From 5f1e86cb55c48949d8a25eb8e03e6930c4179ed9 Mon Sep 17 00:00:00 2001 From: Shahbaz Youssefi Date: Mon, 28 Oct 2024 13:31:54 -0400 Subject: [PATCH] tools: Move io utils to cpp (#5869) In preparation for more code in that file, which would get unwieldy in a header. --- BUILD.bazel | 1 + BUILD.gn | 17 ++++ test/fuzz/CMakeLists.txt | 3 +- test/reduce/CMakeLists.txt | 1 + tools/CMakeLists.txt | 19 ++-- tools/as/as.cpp | 2 +- tools/cfg/cfg.cpp | 2 +- tools/diff/diff.cpp | 4 +- tools/dis/dis.cpp | 2 +- tools/fuzz/fuzz.cpp | 5 +- tools/io.cpp | 175 +++++++++++++++++++++++++++++++++++++ tools/io.h | 163 +++------------------------------- tools/link/linker.cpp | 2 +- tools/opt/opt.cpp | 2 +- tools/reduce/reduce.cpp | 2 +- tools/val/val.cpp | 2 +- 16 files changed, 229 insertions(+), 173 deletions(-) create mode 100644 tools/io.cpp diff --git a/BUILD.bazel b/BUILD.bazel index 7dc73d0811..e6ff97dd6e 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -269,6 +269,7 @@ cc_library( cc_library( name = "tools_io", hdrs = ["tools/io.h"], + srcs = ["tools/io.cpp"], copts = COMMON_COPTS, ) diff --git a/BUILD.gn b/BUILD.gn index 23610262ea..533cca37fd 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1466,6 +1466,15 @@ source_set("spvtools_tools_util") { configs += [ ":spvtools_internal_config" ] } +source_set("spvtools_tools_io") { + sources = [ + "tools/io.cpp", + "tools/io.h", + ] + deps = [ ":spvtools_headers" ] + configs += [ ":spvtools_internal_config" ] +} + if (spvtools_build_executables) { executable("spirv-as") { sources = [ "tools/as/as.cpp" ] @@ -1473,6 +1482,7 @@ if (spvtools_build_executables) { ":spvtools", ":spvtools_software_version", ":spvtools_tools_util", + ":spvtools_tools_io", ] configs += [ ":spvtools_internal_config" ] } @@ -1483,6 +1493,7 @@ if (spvtools_build_executables) { ":spvtools", ":spvtools_software_version", ":spvtools_tools_util", + ":spvtools_tools_io", ] configs += [ ":spvtools_internal_config" ] } @@ -1493,6 +1504,7 @@ if (spvtools_build_executables) { ":spvtools", ":spvtools_software_version", ":spvtools_tools_util", + ":spvtools_tools_io", ":spvtools_val", ] configs += [ ":spvtools_internal_config" ] @@ -1508,6 +1520,7 @@ if (spvtools_build_executables) { ":spvtools", ":spvtools_software_version", ":spvtools_tools_util", + ":spvtools_tools_io", ] configs += [ ":spvtools_internal_config" ] } @@ -1519,6 +1532,7 @@ if (spvtools_build_executables) { ":spvtools_opt", ":spvtools_software_version", ":spvtools_tools_util", + ":spvtools_tools_io", ":spvtools_val", ] configs += [ ":spvtools_internal_config" ] @@ -1532,6 +1546,7 @@ if (spvtools_build_executables) { ":spvtools_opt", ":spvtools_software_version", ":spvtools_tools_util", + ":spvtools_tools_io", ":spvtools_val", ] configs += [ ":spvtools_internal_config" ] @@ -1552,6 +1567,7 @@ if (!is_ios && !spirv_is_winuwp && build_with_chromium && spvtools_build_executa ":spvtools_reduce", ":spvtools_software_version", ":spvtools_tools_util", + ":spvtools_tools_io", ":spvtools_val", "//third_party/protobuf:protobuf_full", ] @@ -1571,6 +1587,7 @@ if (!is_ios && !spirv_is_winuwp && spvtools_build_executables) { ":spvtools_reduce", ":spvtools_software_version", ":spvtools_tools_util", + ":spvtools_tools_io", ":spvtools_val", ] configs += [ ":spvtools_internal_config" ] diff --git a/test/fuzz/CMakeLists.txt b/test/fuzz/CMakeLists.txt index 56af0b9dd6..6232d6c4dd 100644 --- a/test/fuzz/CMakeLists.txt +++ b/test/fuzz/CMakeLists.txt @@ -123,7 +123,8 @@ if (${SPIRV_BUILD_FUZZER}) transformation_wrap_early_terminator_in_function_test.cpp transformation_wrap_region_in_selection_test.cpp transformation_wrap_vector_synonym_test.cpp - uniform_buffer_element_descriptor_test.cpp) + uniform_buffer_element_descriptor_test.cpp + ${spirv-tools_SOURCE_DIR}/tools/io.cpp) if (${SPIRV_ENABLE_LONG_FUZZER_TESTS}) # These are long-running tests that depend on random seeds. We do not want diff --git a/test/reduce/CMakeLists.txt b/test/reduce/CMakeLists.txt index 121cd4f08a..d3eaa84642 100644 --- a/test/reduce/CMakeLists.txt +++ b/test/reduce/CMakeLists.txt @@ -31,6 +31,7 @@ add_spvtools_unittest(TARGET reduce structured_construct_to_block_test.cpp structured_loop_to_selection_test.cpp validation_during_reduction_test.cpp + ${spirv-tools_SOURCE_DIR}/tools/io.cpp LIBS SPIRV-Tools-reduce ) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index a93f640432..a6736ca3ca 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -42,17 +42,18 @@ endfunction() set(COMMON_TOOLS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/util/flags.cpp") if (NOT ${SPIRV_SKIP_EXECUTABLES}) - add_spvtools_tool(TARGET spirv-diff SRCS ${COMMON_TOOLS_SRCS} diff/diff.cpp util/cli_consumer.cpp LIBS SPIRV-Tools-diff SPIRV-Tools-opt ${SPIRV_TOOLS_FULL_VISIBILITY}) - add_spvtools_tool(TARGET spirv-dis SRCS ${COMMON_TOOLS_SRCS} dis/dis.cpp LIBS ${SPIRV_TOOLS_FULL_VISIBILITY}) - add_spvtools_tool(TARGET spirv-val SRCS ${COMMON_TOOLS_SRCS} val/val.cpp util/cli_consumer.cpp LIBS ${SPIRV_TOOLS_FULL_VISIBILITY}) - add_spvtools_tool(TARGET spirv-opt SRCS ${COMMON_TOOLS_SRCS} opt/opt.cpp util/cli_consumer.cpp LIBS SPIRV-Tools-opt ${SPIRV_TOOLS_FULL_VISIBILITY}) + add_spvtools_tool(TARGET spirv-diff SRCS ${COMMON_TOOLS_SRCS} diff/diff.cpp util/cli_consumer.cpp io.cpp LIBS SPIRV-Tools-diff SPIRV-Tools-opt ${SPIRV_TOOLS_FULL_VISIBILITY}) + add_spvtools_tool(TARGET spirv-dis SRCS ${COMMON_TOOLS_SRCS} dis/dis.cpp io.cpp LIBS ${SPIRV_TOOLS_FULL_VISIBILITY}) + add_spvtools_tool(TARGET spirv-val SRCS ${COMMON_TOOLS_SRCS} val/val.cpp util/cli_consumer.cpp io.cpp LIBS ${SPIRV_TOOLS_FULL_VISIBILITY}) + add_spvtools_tool(TARGET spirv-opt SRCS ${COMMON_TOOLS_SRCS} opt/opt.cpp util/cli_consumer.cpp io.cpp LIBS SPIRV-Tools-opt ${SPIRV_TOOLS_FULL_VISIBILITY}) if(NOT (${CMAKE_SYSTEM_NAME} STREQUAL "iOS")) # iOS does not allow std::system calls which spirv-reduce requires - add_spvtools_tool(TARGET spirv-reduce SRCS ${COMMON_TOOLS_SRCS} reduce/reduce.cpp util/cli_consumer.cpp LIBS SPIRV-Tools-reduce ${SPIRV_TOOLS_FULL_VISIBILITY}) + add_spvtools_tool(TARGET spirv-reduce SRCS ${COMMON_TOOLS_SRCS} reduce/reduce.cpp util/cli_consumer.cpp io.cpp LIBS SPIRV-Tools-reduce ${SPIRV_TOOLS_FULL_VISIBILITY}) endif() - add_spvtools_tool(TARGET spirv-link SRCS ${COMMON_TOOLS_SRCS} link/linker.cpp LIBS SPIRV-Tools-link ${SPIRV_TOOLS_FULL_VISIBILITY}) - add_spvtools_tool(TARGET spirv-lint SRCS ${COMMON_TOOLS_SRCS} lint/lint.cpp util/cli_consumer.cpp LIBS SPIRV-Tools-lint SPIRV-Tools-opt ${SPIRV_TOOLS_FULL_VISIBILITY}) + add_spvtools_tool(TARGET spirv-link SRCS ${COMMON_TOOLS_SRCS} link/linker.cpp io.cpp LIBS SPIRV-Tools-link ${SPIRV_TOOLS_FULL_VISIBILITY}) + add_spvtools_tool(TARGET spirv-lint SRCS ${COMMON_TOOLS_SRCS} lint/lint.cpp util/cli_consumer.cpp io.cpp LIBS SPIRV-Tools-lint SPIRV-Tools-opt ${SPIRV_TOOLS_FULL_VISIBILITY}) add_spvtools_tool(TARGET spirv-as SRCS as/as.cpp + io.cpp ${COMMON_TOOLS_SRCS} LIBS ${SPIRV_TOOLS_FULL_VISIBILITY}) target_include_directories(spirv-as PRIVATE ${spirv-tools_SOURCE_DIR} @@ -61,6 +62,7 @@ if (NOT ${SPIRV_SKIP_EXECUTABLES}) SRCS cfg/cfg.cpp cfg/bin_to_dot.h cfg/bin_to_dot.cpp + io.cpp ${COMMON_TOOLS_SRCS} LIBS ${SPIRV_TOOLS_FULL_VISIBILITY}) target_include_directories(spirv-cfg PRIVATE ${spirv-tools_SOURCE_DIR} @@ -73,6 +75,7 @@ if (NOT ${SPIRV_SKIP_EXECUTABLES}) SRCS objdump/objdump.cpp objdump/extract_source.cpp util/cli_consumer.cpp + io.cpp ${COMMON_TOOLS_SRCS} LIBS ${SPIRV_TOOLS_FULL_VISIBILITY}) target_include_directories(spirv-objdump PRIVATE ${spirv-tools_SOURCE_DIR} @@ -85,7 +88,7 @@ if (NOT ${SPIRV_SKIP_EXECUTABLES}) endif() if(SPIRV_BUILD_FUZZER) - add_spvtools_tool(TARGET spirv-fuzz SRCS fuzz/fuzz.cpp util/cli_consumer.cpp LIBS SPIRV-Tools-fuzz ${SPIRV_TOOLS_FULL_VISIBILITY}) + add_spvtools_tool(TARGET spirv-fuzz SRCS fuzz/fuzz.cpp util/cli_consumer.cpp io.cpp LIBS SPIRV-Tools-fuzz ${SPIRV_TOOLS_FULL_VISIBILITY}) set(SPIRV_INSTALL_TARGETS ${SPIRV_INSTALL_TARGETS} spirv-fuzz) endif(SPIRV_BUILD_FUZZER) diff --git a/tools/as/as.cpp b/tools/as/as.cpp index 2a000cf09b..ab18aeb359 100644 --- a/tools/as/as.cpp +++ b/tools/as/as.cpp @@ -106,7 +106,7 @@ int main(int, const char** argv) { std::string inFile = flags::positional_arguments[0]; std::vector contents; - if (!ReadTextFile(inFile.c_str(), &contents)) return 1; + if (!ReadTextFile(inFile.c_str(), &contents)) return 1; spv_binary binary; spv_diagnostic diagnostic = nullptr; diff --git a/tools/cfg/cfg.cpp b/tools/cfg/cfg.cpp index 2d11e6fb06..2c68904227 100644 --- a/tools/cfg/cfg.cpp +++ b/tools/cfg/cfg.cpp @@ -75,7 +75,7 @@ int main(int, const char** argv) { // Read the input binary. std::vector contents; - if (!ReadBinaryFile(inFile.c_str(), &contents)) return 1; + if (!ReadBinaryFile(inFile.c_str(), &contents)) return 1; spv_context context = spvContextCreate(kDefaultEnvironment); spv_diagnostic diagnostic = nullptr; diff --git a/tools/diff/diff.cpp b/tools/diff/diff.cpp index 2217896c3b..d60edb2e13 100644 --- a/tools/diff/diff.cpp +++ b/tools/diff/diff.cpp @@ -82,7 +82,7 @@ bool is_assembly(const char* path) { std::unique_ptr load_module(const char* path) { if (is_assembly(path)) { std::vector contents; - if (!ReadTextFile(path, &contents)) return {}; + if (!ReadTextFile(path, &contents)) return {}; return spvtools::BuildModule( kDefaultEnvironment, spvtools::utils::CLIMessageConsumer, @@ -92,7 +92,7 @@ std::unique_ptr load_module(const char* path) { } std::vector contents; - if (!ReadBinaryFile(path, &contents)) return {}; + if (!ReadBinaryFile(path, &contents)) return {}; return spvtools::BuildModule(kDefaultEnvironment, spvtools::utils::CLIMessageConsumer, diff --git a/tools/dis/dis.cpp b/tools/dis/dis.cpp index b8ce3e36ec..6b8a1ae637 100644 --- a/tools/dis/dis.cpp +++ b/tools/dis/dis.cpp @@ -153,7 +153,7 @@ int main(int, const char** argv) { // Read the input binary. std::vector contents; - if (!ReadBinaryFile(inFile.c_str(), &contents)) return 1; + if (!ReadBinaryFile(inFile.c_str(), &contents)) return 1; // If printing to standard output, then spvBinaryToText should // do the printing. In particular, colour printing on Windows is diff --git a/tools/fuzz/fuzz.cpp b/tools/fuzz/fuzz.cpp index 5f2a0080d4..e671e31eb9 100644 --- a/tools/fuzz/fuzz.cpp +++ b/tools/fuzz/fuzz.cpp @@ -584,8 +584,7 @@ bool Fuzz(const spv_target_env& target_env, [donor_filename, message_consumer, target_env]() -> std::unique_ptr { std::vector donor_binary; - if (!ReadBinaryFile(donor_filename.c_str(), - &donor_binary)) { + if (!ReadBinaryFile(donor_filename.c_str(), &donor_binary)) { return nullptr; } return spvtools::BuildModule(target_env, message_consumer, @@ -712,7 +711,7 @@ int main(int argc, const char** argv) { } std::vector binary_in; - if (!ReadBinaryFile(in_binary_file.c_str(), &binary_in)) { + if (!ReadBinaryFile(in_binary_file.c_str(), &binary_in)) { return 1; } diff --git a/tools/io.cpp b/tools/io.cpp new file mode 100644 index 0000000000..288f380ad8 --- /dev/null +++ b/tools/io.cpp @@ -0,0 +1,175 @@ +// Copyright (c) 2024 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. + +#include "io.h" + +#include + +#if defined(SPIRV_WINDOWS) +#include +#include + +#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 + +namespace { +// Appends the contents of the |file| to |data|, assuming each element in the +// file is of type |T|. +template +void ReadFile(FILE* file, std::vector* 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 +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; +} +} // namespace + +bool ReadBinaryFile(const char* filename, std::vector* data) { + assert(data->empty()); + + 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(fp, filename); + if (use_file && fp) fclose(fp); + return succeeded; +} + +bool ReadTextFile(const char* filename, std::vector* data) { + assert(data->empty()); + + 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(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) : old_mode_(0) { + 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) { + fflush(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 + +template +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; +} + +template bool WriteFile(const char* filename, const char* mode, + const uint32_t* data, size_t count); +template bool WriteFile(const char* filename, const char* mode, + const char* data, size_t count); diff --git a/tools/io.h b/tools/io.h index a48e3c325e..3c87fcc0d1 100644 --- a/tools/io.h +++ b/tools/io.h @@ -20,145 +20,19 @@ #include #include -#if defined(SPIRV_WINDOWS) -#include -#include - -#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 -void ReadFile(FILE* file, std::vector* 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 -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 +// Sets the contents of the file named |filename| in |data|, assuming each +// element in the file is of type |uint32_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 -bool ReadBinaryFile(const char* filename, std::vector* 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(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 -bool ReadTextFile(const char* filename, std::vector* 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(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) : old_mode_(0) { - 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); - } - } +bool ReadBinaryFile(const char* filename, std::vector* data); - ~OutputFile() { - if (fp_ == stdout) { - fflush(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 +// Sets the contents of the file named |filename| in |data|, assuming each +// element in the file is of type |char|. 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. +bool ReadTextFile(const char* filename, std::vector* data); // 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 @@ -166,21 +40,6 @@ class OutputFile { // returns false and outputs error message to standard error. template 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; -} + size_t count); #endif // TOOLS_IO_H_ diff --git a/tools/link/linker.cpp b/tools/link/linker.cpp index 7dbd8596fa..2f47dd4bb1 100644 --- a/tools/link/linker.cpp +++ b/tools/link/linker.cpp @@ -143,7 +143,7 @@ int main(int, const char* argv[]) { std::vector> contents(inFiles.size()); for (size_t i = 0u; i < inFiles.size(); ++i) { - if (!ReadBinaryFile(inFiles[i].c_str(), &contents[i])) return 1; + if (!ReadBinaryFile(inFiles[i].c_str(), &contents[i])) return 1; } const spvtools::MessageConsumer consumer = [](spv_message_level_t level, diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index 52e5448989..07a57252d4 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -876,7 +876,7 @@ int main(int argc, const char** argv) { } std::vector binary; - if (!ReadBinaryFile(in_file, &binary)) { + if (!ReadBinaryFile(in_file, &binary)) { return 1; } diff --git a/tools/reduce/reduce.cpp b/tools/reduce/reduce.cpp index 959f5a2f27..143779989e 100644 --- a/tools/reduce/reduce.cpp +++ b/tools/reduce/reduce.cpp @@ -307,7 +307,7 @@ int main(int argc, const char** argv) { reducer.SetMessageConsumer(spvtools::utils::CLIMessageConsumer); std::vector binary_in; - if (!ReadBinaryFile(in_binary_file.c_str(), &binary_in)) { + if (!ReadBinaryFile(in_binary_file.c_str(), &binary_in)) { return 1; } diff --git a/tools/val/val.cpp b/tools/val/val.cpp index 33d1ddedfb..c75c6177fd 100644 --- a/tools/val/val.cpp +++ b/tools/val/val.cpp @@ -193,7 +193,7 @@ int main(int argc, char** argv) { } std::vector contents; - if (!ReadBinaryFile(inFile, &contents)) return 1; + if (!ReadBinaryFile(inFile, &contents)) return 1; spvtools::SpirvTools tools(target_env); tools.SetMessageConsumer(spvtools::utils::CLIMessageConsumer);