说明:

(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.
// 译文:这些是支持的压缩文件类型的签名
86 87 static int xzsig[] = { 0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00, 0x00, EOF }; 88 static int bz2sig[] = { 0x42, 0x5A, 0x68, EOF }; 89 static int gzsig[] = { 0x1F, 0x8B, EOF }; 90 static int sig7z[] = { 0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C, EOF }; 91 static int lzmasig[] = { 0x5D, 0x00, 0x00, 0x80, 0x00, EOF }; 92 93 bool File::match (Internal * internal, 94 const char * path, const int * sig) { 95 assert (path); 96 FILE * tmp = fopen (path, "r"); 97 if (!tmp) { 98 WARNING ("failed to open '%s' to check signature", path); 99 return false; 100 } 101 bool res = true; 102 for (const int *p = sig; res && (*p != EOF); p++) 103 res = (cadical_getc_unlocked (tmp) == *p); 104 fclose (tmp); 105 if (!res) WARNING ("file type signature check for '%s' failed", path); 106 return res; 107 } 108 109 size_t File::size (const char * path) { 110 struct stat buf; 111 if (stat (path, &buf)) return 0; 112 return (size_t) buf.st_size; 113 } 114 115 // Check that 'prg' is in the 'PATH' and thus can be found if executed 116 // through 'popen'. 117 118 char * File::find (const char * prg) { 119 size_t prglen = strlen (prg); 120 const char * c = getenv ("PATH"); 121 if (!c) return 0;; 122 size_t len = strlen (c); 123 char * e = new char[len + 1]; 124 strcpy (e, c); 125 char * res = 0; 126 for (char * p = e, * q; !res && p < e + len; p = q) { 127 for (q = p; *q && *q != ':'; q++) 128 ; 129 *q++ = 0; 130 size_t pathlen = (q - p) + prglen; 131 char * path = new char [pathlen + 1]; 132 sprintf (path, "%s/%s", p, prg); 133 assert (strlen (path) == pathlen); 134 if (exists (path)) res = path; 135 else delete [] path; 136 } 137 delete [] e; 138 return res; 139 } 140 141 /*------------------------------------------------------------------------*/ 142 143 FILE * File::open_file (Internal * internal, const char * path, 144 const char * mode) { 145 (void) internal; 146 return fopen (path, mode); 147 } 148 149 FILE * File::read_file (Internal * internal, const char * path) { 150 MSG ("opening file to read '%s'", path); 151 return open_file (internal, path, "r"); 152 } 153 154 FILE * File::write_file (Internal * internal, const char * path) { 155 MSG ("opening file to write '%s'", path); 156 return open_file (internal, path, "w"); 157 } 158 159 /*------------------------------------------------------------------------*/ 160 161 FILE * File::open_pipe (Internal * internal, 162 const char * fmt, const char * path, 163 const char * mode) { 164 #ifdef QUIET 165 (void) internal; 166 #endif 167 size_t prglen = 0; 168 while (fmt[prglen] && fmt[prglen] != ' ') prglen++; 169 char * prg = new char [prglen + 1]; 170 strncpy (prg, fmt, prglen); 171 prg[prglen] = 0; 172 char * found = find (prg); 173 if (found) MSG ("found '%s' in path for '%s'", found, prg); 174 if (!found) MSG ("did not find '%s' in path", prg); 175 delete [] prg; 176 if (!found) return 0; 177 delete [] found; 178 char * cmd = new char [strlen (fmt) + strlen (path)]; 179 sprintf (cmd, fmt, path); 180 FILE * res = popen (cmd, mode); 181 delete [] cmd; 182 return res; 183 } 184 185 FILE * File::read_pipe (Internal * internal, 186 const char * fmt, 187 const int * sig, 188 const char * path) { 189 if (!File::exists (path)) { 190 LOG ("file '%s' does not exist", path); 191 return 0; 192 } 193 LOG ("file '%s' exists", path); 194 if (sig && !File::match (internal, path, sig)) return 0; 195 LOG ("file '%s' matches signature for '%s'", path, fmt); 196 MSG ("opening pipe to read '%s'", path); 197 return open_pipe (internal, fmt, path, "r"); 198 } 199 200 FILE * File::write_pipe (Internal * internal, 201 const char * fmt, const char * path) { 202 MSG ("opening pipe to write '%s'", path); 203 return open_pipe (internal, fmt, path, "w"); 204 } 205 206 /*------------------------------------------------------------------------*/ 207 208 File * File::read (Internal * internal, FILE * f, const char * n) { 209 return new File (internal, false, 0, f, n); 210 } 211 212 File * File::write (Internal * internal, FILE * f, const char * n) { 213 return new File (internal, true, 0, f, n); 214 } 215 216 File * File::read (Internal * internal, const char * path) { 217 FILE * file; 218 int close_input = 2; 219 if (has_suffix (path, ".xz")) { 220 file = read_pipe (internal, "xz -c -d %s", xzsig, path); 221 if (!file) goto READ_FILE; 222 } else if (has_suffix (path, ".lzma")) { 223 file = read_pipe (internal, "lzma -c -d %s", lzmasig, path); 224 if (!file) goto READ_FILE; 225 } else if (has_suffix (path, ".bz2")) { 226 file = read_pipe (internal, "bzip2 -c -d %s", bz2sig, path); 227 if (!file) goto READ_FILE; 228 } else if (has_suffix (path, ".gz")) { 229 file = read_pipe (internal, "gzip -c -d %s", gzsig, path); 230 if (!file) goto READ_FILE; 231 } else if (has_suffix (path, ".7z")) { 232 file = read_pipe (internal, "7z x -so %s 2>/dev/null", sig7z, path); 233 if (!file) goto READ_FILE; 234 } else { 235 READ_FILE: 236 file = read_file (internal, path); 237 close_input = 1; 238 } 239 240 return file ? new File (internal, false, close_input, file, path) : 0; 241 } 242 243 File * File::write (Internal * internal, const char * path) { 244 FILE * file; 245 int close_input = 2; 246 if (has_suffix (path, ".xz")) 247 file = write_pipe (internal, "xz -c > %s", path); 248 else if (has_suffix (path, ".bz2")) 249 file = write_pipe (internal, "bzip2 -c > %s", path); 250 else if (has_suffix (path, ".gz")) 251 file = write_pipe (internal, "gzip -c > %s", path); 252 else if (has_suffix (path, ".7z")) 253 file = write_pipe (internal, 254 "7z a -an -txz -si -so > %s 2>/dev/null", path); 255 else 256 file = write_file (internal, path), close_input = 1; 257 258 return file ? new File (internal, true, close_input, file, path) : 0; 259 } 260 261 void File::close () { 262 assert (file); 263 if (close_file == 0) { 264 MSG ("disconnecting from '%s'", name ()); 265 } 266 if (close_file == 1) { 267 MSG ("closing file '%s'", name ()); 268 fclose (file); 269 } 270 if (close_file == 2) { 271 MSG ("closing pipe command on '%s'", name ()); 272 pclose (file); 273 } 274 275 file = 0; // mark as closed 276 277 #ifndef QUIET 278 if (internal->opts.verbose > 1) return; 279 double mb = bytes () / (double) (1 << 20); 280 if (writing) 281 MSG ("after writing %" PRIu64 " bytes %.1f MB", bytes (), mb); 282 else 283 MSG ("after reading %" PRIu64 " bytes %.1f MB", bytes (), mb); 284 if (close_file == 2) { 285 int64_t s = size (name ()); 286 double mb = s / (double) (1<<20); 287 if (writing) 288 MSG ("deflated to %" PRId64 " bytes %.1f MB by factor %.2f " 289 "(%.2f%% compression)", 290 s, mb, relative (bytes (), s), percent (bytes () - s, bytes ())); 291 else 292 MSG ("inflated from %" PRId64 " bytes %.1f MB by factor %.2f " 293 "(%.2f%% compression)", 294 s, mb, relative (bytes (), s), percent (bytes () - s, bytes ())); 295 } 296 #endif 297 } 298 299 void File::flush () { 300 assert (file); 301 fflush (file); 302 } 303 304 File::~File () { if (file) close (); } 305 306 }

 

   

 


posted on 2020-07-31 16:51  海阔凭鱼跃越  阅读(202)  评论(0)    收藏  举报