io.h 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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. #ifndef TOOLS_IO_H_
  15. #define TOOLS_IO_H_
  16. #include <cstdint>
  17. #include <cstdio>
  18. #include <vector>
  19. // Appends the content from the file named as |filename| to |data|, assuming
  20. // each element in the file is of type |T|. The file is opened with the given
  21. // |mode|. If |filename| is nullptr or "-", reads from the standard input, but
  22. // reopened with the given mode. If any error occurs, writes error messages to
  23. // standard error and returns false.
  24. template <typename T>
  25. bool ReadFile(const char* filename, const char* mode, std::vector<T>* data) {
  26. const int buf_size = 1024;
  27. const bool use_file = filename && strcmp("-", filename);
  28. if (FILE* fp =
  29. (use_file ? fopen(filename, mode) : freopen(nullptr, mode, stdin))) {
  30. T buf[buf_size];
  31. while (size_t len = fread(buf, sizeof(T), buf_size, fp)) {
  32. data->insert(data->end(), buf, buf + len);
  33. }
  34. if (ftell(fp) == -1L) {
  35. if (ferror(fp)) {
  36. fprintf(stderr, "error: error reading file '%s'\n", filename);
  37. return false;
  38. }
  39. } else {
  40. if (sizeof(T) != 1 && (ftell(fp) % sizeof(T))) {
  41. fprintf(
  42. stderr,
  43. "error: file size should be a multiple of %zd; file '%s' corrupt\n",
  44. sizeof(T), filename);
  45. return false;
  46. }
  47. }
  48. if (use_file) fclose(fp);
  49. } else {
  50. fprintf(stderr, "error: file does not exist '%s'\n", filename);
  51. return false;
  52. }
  53. return true;
  54. }
  55. // Writes the given |data| into the file named as |filename| using the given
  56. // |mode|, assuming |data| is an array of |count| elements of type |T|. If
  57. // |filename| is nullptr or "-", writes to standard output. If any error occurs,
  58. // returns false and outputs error message to standard error.
  59. template <typename T>
  60. bool WriteFile(const char* filename, const char* mode, const T* data,
  61. size_t count) {
  62. const bool use_stdout =
  63. !filename || (filename[0] == '-' && filename[1] == '\0');
  64. if (FILE* fp = (use_stdout ? stdout : fopen(filename, mode))) {
  65. size_t written = fwrite(data, sizeof(T), count, fp);
  66. if (count != written) {
  67. fprintf(stderr, "error: could not write to file '%s'\n", filename);
  68. return false;
  69. }
  70. if (!use_stdout) fclose(fp);
  71. } else {
  72. fprintf(stderr, "error: could not open file '%s'\n", filename);
  73. return false;
  74. }
  75. return true;
  76. }
  77. #endif // TOOLS_IO_H_