| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- // Copyright (c) 2016 Google Inc.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #ifndef TOOLS_IO_H_
- #define TOOLS_IO_H_
- #include <cstdint>
- #include <cstdio>
- #include <cstring>
- #include <vector>
- #if defined(SPIRV_WINDOWS)
- #include <fcntl.h>
- #include <io.h>
- #define SET_STDIN_TO_BINARY_MODE() _setmode(_fileno(stdin), O_BINARY);
- #define SET_STDIN_TO_TEXT_MODE() _setmode(_fileno(stdin), O_TEXT);
- #define SET_STDOUT_TO_BINARY_MODE() _setmode(_fileno(stdout), O_BINARY);
- #define SET_STDOUT_TO_TEXT_MODE() _setmode(_fileno(stdout), O_TEXT);
- #define SET_STDOUT_MODE(mode) _setmode(_fileno(stdout), mode);
- #else
- #define SET_STDIN_TO_BINARY_MODE()
- #define SET_STDIN_TO_TEXT_MODE()
- #define SET_STDOUT_TO_BINARY_MODE() 0
- #define SET_STDOUT_TO_TEXT_MODE() 0
- #define SET_STDOUT_MODE(mode)
- #endif
- // Appends the contents of the |file| to |data|, assuming each element in the
- // file is of type |T|.
- template <typename T>
- void ReadFile(FILE* file, std::vector<T>* data) {
- if (file == nullptr) return;
- const int buf_size = 1024;
- T buf[buf_size];
- while (size_t len = fread(buf, sizeof(T), buf_size, file)) {
- data->insert(data->end(), buf, buf + len);
- }
- }
- // Returns true if |file| has encountered an error opening the file or reading
- // the file as a series of element of type |T|. If there was an error, writes an
- // error message to standard error.
- template <class T>
- bool WasFileCorrectlyRead(FILE* file, const char* filename) {
- if (file == nullptr) {
- fprintf(stderr, "error: file does not exist '%s'\n", filename);
- return false;
- }
- if (ftell(file) == -1L) {
- if (ferror(file)) {
- fprintf(stderr, "error: error reading file '%s'\n", filename);
- return false;
- }
- } else {
- if (sizeof(T) != 1 && (ftell(file) % sizeof(T))) {
- fprintf(
- stderr,
- "error: file size should be a multiple of %zd; file '%s' corrupt\n",
- sizeof(T), filename);
- return false;
- }
- }
- return true;
- }
- // Appends the contents of the file named |filename| to |data|, assuming
- // each element in the file is of type |T|. The file is opened as a binary file
- // If |filename| is nullptr or "-", reads from the standard input, but
- // reopened as a binary file. If any error occurs, writes error messages to
- // standard error and returns false.
- template <typename T>
- bool ReadBinaryFile(const char* filename, std::vector<T>* data) {
- const bool use_file = filename && strcmp("-", filename);
- FILE* fp = nullptr;
- if (use_file) {
- fp = fopen(filename, "rb");
- } else {
- SET_STDIN_TO_BINARY_MODE();
- fp = stdin;
- }
- ReadFile(fp, data);
- bool succeeded = WasFileCorrectlyRead<T>(fp, filename);
- if (use_file && fp) fclose(fp);
- return succeeded;
- }
- // Appends the contents of the file named |filename| to |data|, assuming
- // each element in the file is of type |T|. The file is opened as a text file
- // If |filename| is nullptr or "-", reads from the standard input, but
- // reopened as a text file. If any error occurs, writes error messages to
- // standard error and returns false.
- template <typename T>
- bool ReadTextFile(const char* filename, std::vector<T>* data) {
- const bool use_file = filename && strcmp("-", filename);
- FILE* fp = nullptr;
- if (use_file) {
- fp = fopen(filename, "r");
- } else {
- SET_STDIN_TO_TEXT_MODE();
- fp = stdin;
- }
- ReadFile(fp, data);
- bool succeeded = WasFileCorrectlyRead<T>(fp, filename);
- if (use_file && fp) fclose(fp);
- return succeeded;
- }
- namespace {
- // A class to create and manage a file for outputting data.
- class OutputFile {
- public:
- // Opens |filename| in the given mode. If |filename| is nullptr, the empty
- // string or "-", stdout will be set to the given mode.
- OutputFile(const char* filename, const char* mode) {
- const bool use_stdout =
- !filename || (filename[0] == '-' && filename[1] == '\0');
- if (use_stdout) {
- if (strchr(mode, 'b')) {
- old_mode_ = SET_STDOUT_TO_BINARY_MODE();
- } else {
- old_mode_ = SET_STDOUT_TO_TEXT_MODE();
- }
- fp_ = stdout;
- } else {
- fp_ = fopen(filename, mode);
- }
- }
- ~OutputFile() {
- if (fp_ == stdout) {
- SET_STDOUT_MODE(old_mode_);
- } else if (fp_ != nullptr) {
- fclose(fp_);
- }
- }
- // Returns a file handle to the file.
- FILE* GetFileHandle() const { return fp_; }
- private:
- FILE* fp_;
- int old_mode_;
- };
- } // namespace
- // Writes the given |data| into the file named as |filename| using the given
- // |mode|, assuming |data| is an array of |count| elements of type |T|. If
- // |filename| is nullptr or "-", writes to standard output. If any error occurs,
- // returns false and outputs error message to standard error.
- template <typename T>
- bool WriteFile(const char* filename, const char* mode, const T* data,
- size_t count) {
- OutputFile file(filename, mode);
- FILE* fp = file.GetFileHandle();
- if (fp == nullptr) {
- fprintf(stderr, "error: could not open file '%s'\n", filename);
- return false;
- }
- size_t written = fwrite(data, sizeof(T), count, fp);
- if (count != written) {
- fprintf(stderr, "error: could not write to file '%s'\n", filename);
- return false;
- }
- return true;
- }
- #endif // TOOLS_IO_H_
|