说明:
(1)file.hpp中包含了相关的输入输出函数;
(2)File类型内部有一个Internal指针,该指针用于衔接;
Internal * internal;
(3)可以接受读取各种压缩个格式的cnf输入文件
(4)打开文件函数open有两个,关闭文件函数close只有一个;
(5)
file.hpp代码解读
1 #ifndef _file_hpp_INCLUDED 2 #define _file_hpp_INCLUDED 3 4 #include <cstdio> 5 #include <cassert> 6 #include <cstdlib> 7 8 #ifndef NDEBUG 9 #include <climits> 10 #endif 11 12 /*------------------------------------------------------------------------*/ 13 #ifndef NUNLOCKED 14 #define cadical_putc_unlocked putc_unlocked 15 #define cadical_getc_unlocked getc_unlocked 16 #else 17 #define cadical_putc_unlocked putc 18 #define cadical_getc_unlocked getc 19 #endif 20 /*------------------------------------------------------------------------*/ 21 22 namespace CaDiCaL { 23 24 // Wraps a 'C' file 'FILE' with name and supports zipped reading and writing 25 // through 'popen' using external helper tools. Reading has line numbers. 26 // Compression and decompression relies on external utilities, e.g., 'gzip', 27 // 'bzip2', 'xz', and '7z', which should be in the 'PATH'. 28 29 struct Internal; //前置声明 30 31 class File { 32 33 #ifndef QUIET 34 Internal * internal; //该指针用于与整体衔接 35 #endif 36 #if !defined(QUIET) || !defined(NDEBUG) 37 bool writing; 38 #endif 39 40 int close_file; // need to close file (1=fclose, 2=pclose) 41 FILE * file; 42 const char * _name; 43 uint64_t _lineno; 44 uint64_t _bytes; 45 46 File (Internal *, bool, int, FILE *, const char *); 47 48 static FILE * open_file (Internal *, 49 const char * path, const char * mode); 50 static FILE * read_file (Internal *, const char * path); 51 static FILE * write_file (Internal *, const char * path); 52 53 static FILE * open_pipe (Internal *, 54 const char * fmt, 55 const char * path, 56 const char * mode); 57 static FILE * read_pipe (Internal *, 58 const char * fmt, 59 const int * sig, 60 const char * path); 61 static FILE * write_pipe (Internal *, 62 const char * fmt, const char * path); 63 public: 64 65 static char* find (const char * prg); // search in 'PATH' 66 static bool exists (const char * path); // file exists? 67 static bool writable (const char * path);// can write to that file? 68 static size_t size (const char * path); // file size in bytes 69 70 // Does the file match the file type signature. 71 // 72 static bool match (Internal *, const char * path, const int * sig); 73 74 // Read from existing file. Assume given name. 75 // 76 static File * read (Internal *, FILE * f, const char * name); 77 78 // Open file from path name for reading (possibly through opening a pipe 79 // to a decompression utility, based on the suffix). 80 // 81 static File * read (Internal *, const char * path); 82 83 // Same for writing as for reading above. 84 // 85 static File * write (Internal *, FILE *, const char * name); 86 static File * write (Internal *, const char * path); 87 88 ~File (); 89 90 // Using the 'unlocked' versions here is way faster but 91 // not thread safe if the same file is used by different 92 // threads, which on the other hand currently is impossible. 93 94 int get () { 95 assert (!writing); 96 int res = cadical_getc_unlocked (file); 97 if (res == '\n') _lineno++; 98 if (res != EOF) _bytes++; 99 return res; 100 } 101 102 bool put (char ch) { 103 assert (writing); 104 if (cadical_putc_unlocked (ch, file) == EOF) return false; 105 _bytes++; 106 return true; 107 } 108 109 bool put (unsigned char ch) { 110 assert (writing); 111 if (cadical_putc_unlocked (ch, file) == EOF) return false; 112 _bytes++; 113 return true; 114 } 115 116 bool put (const char * s) { 117 for (const char * p = s; *p; p++) 118 if (!put (*p)) return false; 119 return true; 120 } 121 122 bool put (int lit) { 123 assert (writing); 124 if (!lit) return put ('0'); 125 else if (lit == -2147483648) { 126 assert (lit == INT_MIN); 127 return put ("-2147483648"); 128 } else { 129 char buffer[11]; 130 int i = sizeof buffer; 131 buffer[--i] = 0; 132 assert (lit != INT_MIN); 133 unsigned idx = abs (lit); 134 while (idx) { 135 assert (i > 0); 136 buffer[--i] = '0' + idx % 10; 137 idx /= 10; 138 } 139 if (lit < 0 && !put ('-')) return false; 140 return put (buffer + i); 141 } 142 } 143 144 bool put (int64_t l) { 145 assert (writing); 146 if (!l) return put ('0'); 147 else if (l == INT64_MIN) { 148 assert (sizeof l == 8); 149 return put ("-9223372036854775808"); 150 } else { 151 char buffer[21]; 152 int i = sizeof buffer; 153 buffer[--i] = 0; 154 assert (l != INT64_MIN); 155 uint64_t k = l < 0 ? -l : l; 156 while (k) { 157 assert (i > 0); 158 buffer[--i] = '0' + k % 10; 159 k /= 10; 160 } 161 if (l < 0 && !put ('-')) return false; 162 return put (buffer + i); 163 } 164 } 165 166 const char * name () const { return _name; } 167 uint64_t lineno () const { return _lineno; } 168 uint64_t bytes () const { return _bytes; } 169 170 bool closed () { return !file; } 171 void close (); //open函数有两个(open_file,open_pipe),close函数只有一个 172 void flush (); 173 }; 174 175 } 176 177 #endif
|
|
file.cpp代码解读
1 #include "internal.hpp" //没有直接包含file.hpp头文件,该头文件在internal.hpp之中 2 3 /*------------------------------------------------------------------------*/ 4 5 // Some more low-level 'C' headers. 6 7 extern "C" { 8 #include <string.h> 9 #include <errno.h> 10 #include <sys/stat.h> 11 #include <sys/types.h> 12 #include <unistd.h> 13 #include <stdlib.h> 14 } 15 16 /*------------------------------------------------------------------------*/ 17 18 namespace CaDiCaL { 19 20 /*------------------------------------------------------------------------*/ 21 22 // Private constructor. 23 24 File::File (Internal *i, bool w, int c, FILE * f, const char * n) 25 : 26 #ifndef QUIET 27 internal (i), 28 #endif 29 #if !defined(QUIET) || !defined(NDEBUG) 30 writing (w), 31 #endif 32 close_file (c), file (f), 33 _name (n), _lineno (1), _bytes (0) 34 { 35 (void) i, (void) w; 36 assert (f), assert (n); 37 } 38 39 /*------------------------------------------------------------------------*/ 40 41 bool File::exists (const char * path) { 42 struct stat buf; 43 if (stat (path, &buf)) return false; 44 if (access (path, R_OK)) return false; 45 return true; 46 } 47 48 bool File::writable (const char * path) { 49 int res; 50 if (!path) res = 1; 51 else if (!strcmp (path, "/dev/null")) res = 0; 52 else { 53 if (!*path) res = 2; 54 else { 55 struct stat buf; 56 const char * p = strrchr (path, '/'); 57 if (!p) { 58 if (stat (path, &buf)) res = ((errno == ENOENT) ? 0 : -2); 59 else if (S_ISDIR (buf.st_mode)) res = 3; 60 else res = (access (path, W_OK) ? 4 : 0); 61 } else if (!p[1]) res = 5; 62 else { 63 size_t len = p - path; 64 char * dirname = new char[len + 1]; 65 strncpy (dirname, path, len); 66 dirname[len] = 0; 67 if (stat (dirname, &buf)) res = 6; 68 else if (!S_ISDIR (buf.st_mode)) res = 7; 69 else if (access (dirname, W_OK)) res = 8; 70 else if (stat (path, &buf)) res = (errno == ENOENT) ? 0 : -3; 71 else res = access (path, W_OK) ? 9 : 0; 72 delete [] dirname; 73 } 74 } 75 } 76 return !res; 77 } 78 79 // These are signatures for supported compressed file types. In 2018 the 80 // SAT Competition was running on StarExec and used internally 'bzip2' 81 // compressed files, but gave them uncompressed to the solver using exactly 82 // the same path (with '.bz2' suffix). Then 'CaDiCaL' tried to read that 83 // actually uncompressed file through 'bzip2', which of course failed. Now 84 // we double check and fall back to reading the file as is, if the signature 85 // does not match after issuing a warning.
|
|
浙公网安备 33010602011771号