Home | History | Annotate | Download | only in tools
      1 // Copyright (c) 2016 Google Inc.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #ifndef TOOLS_IO_H_
     16 #define TOOLS_IO_H_
     17 
     18 #include <cstdint>
     19 #include <cstdio>
     20 #include <vector>
     21 
     22 // Appends the content from the file named as |filename| to |data|, assuming
     23 // each element in the file is of type |T|. The file is opened with the given
     24 // |mode|. If |filename| is nullptr or "-", reads from the standard input, but
     25 // reopened with the given mode. If any error occurs, writes error messages to
     26 // standard error and returns false.
     27 template <typename T>
     28 bool ReadFile(const char* filename, const char* mode, std::vector<T>* data) {
     29   const int buf_size = 1024;
     30   const bool use_file = filename && strcmp("-", filename);
     31   if (FILE* fp =
     32           (use_file ? fopen(filename, mode) : freopen(nullptr, mode, stdin))) {
     33     T buf[buf_size];
     34     while (size_t len = fread(buf, sizeof(T), buf_size, fp)) {
     35       data->insert(data->end(), buf, buf + len);
     36     }
     37     if (ftell(fp) == -1L) {
     38       if (ferror(fp)) {
     39         fprintf(stderr, "error: error reading file '%s'\n", filename);
     40         return false;
     41       }
     42     } else {
     43       if (sizeof(T) != 1 && (ftell(fp) % sizeof(T))) {
     44         fprintf(
     45             stderr,
     46             "error: file size should be a multiple of %zd; file '%s' corrupt\n",
     47             sizeof(T), filename);
     48         return false;
     49       }
     50     }
     51     if (use_file) fclose(fp);
     52   } else {
     53     fprintf(stderr, "error: file does not exist '%s'\n", filename);
     54     return false;
     55   }
     56   return true;
     57 }
     58 
     59 // Writes the given |data| into the file named as |filename| using the given
     60 // |mode|, assuming |data| is an array of |count| elements of type |T|. If
     61 // |filename| is nullptr or "-", writes to standard output. If any error occurs,
     62 // returns false and outputs error message to standard error.
     63 template <typename T>
     64 bool WriteFile(const char* filename, const char* mode, const T* data,
     65                size_t count) {
     66   const bool use_stdout =
     67       !filename || (filename[0] == '-' && filename[1] == '\0');
     68   if (FILE* fp = (use_stdout ? stdout : fopen(filename, mode))) {
     69     size_t written = fwrite(data, sizeof(T), count, fp);
     70     if (count != written) {
     71       fprintf(stderr, "error: could not write to file '%s'\n", filename);
     72       return false;
     73     }
     74     if (!use_stdout) fclose(fp);
     75   } else {
     76     fprintf(stderr, "error: could not open file '%s'\n", filename);
     77     return false;
     78   }
     79   return true;
     80 }
     81 
     82 #endif  // TOOLS_IO_H_
     83