Commit 9a398504ca869e00de15c713108264e0beead504
1 parent
75241655
Refactor QUtil::read_lines_from_file
This commit adds the preserve_eol flags but doesn't implement EOL preservation yet.
Showing
3 changed files
with
106 additions
and
22 deletions
include/qpdf/QUtil.hh
| ... | ... | @@ -29,6 +29,7 @@ |
| 29 | 29 | #include <list> |
| 30 | 30 | #include <vector> |
| 31 | 31 | #include <stdexcept> |
| 32 | +#include <functional> | |
| 32 | 33 | #include <stdio.h> |
| 33 | 34 | #include <time.h> |
| 34 | 35 | |
| ... | ... | @@ -90,8 +91,9 @@ namespace QUtil |
| 90 | 91 | QPDF_DLL |
| 91 | 92 | int os_wrapper(std::string const& description, int status); |
| 92 | 93 | |
| 93 | - // If the open fails, throws std::runtime_error. Otherwise, the | |
| 94 | - // FILE* is returned. | |
| 94 | + // If the open fails, throws std::runtime_error. Otherwise, the | |
| 95 | + // FILE* is returned. The filename should be UTF-8 encoded, even | |
| 96 | + // on Windows. It will be converted as needed on Windows. | |
| 95 | 97 | QPDF_DLL |
| 96 | 98 | FILE* safe_fopen(char const* filename, char const* mode); |
| 97 | 99 | |
| ... | ... | @@ -308,10 +310,29 @@ namespace QUtil |
| 308 | 310 | QPDF_DLL |
| 309 | 311 | RandomDataProvider* getRandomDataProvider(); |
| 310 | 312 | |
| 313 | + // Filename is UTF-8 encoded, even on Windows, as described in the | |
| 314 | + // comments for safe_fopen. | |
| 311 | 315 | QPDF_DLL |
| 312 | 316 | std::list<std::string> read_lines_from_file(char const* filename); |
| 317 | + // ABI: make preserve_eol an optional arg and remove single-arg version | |
| 318 | + QPDF_DLL | |
| 319 | + std::list<std::string> read_lines_from_file( | |
| 320 | + char const* filename, bool preserve_eol); | |
| 313 | 321 | QPDF_DLL |
| 314 | 322 | std::list<std::string> read_lines_from_file(std::istream&); |
| 323 | + // ABI: make preserve_eol an optional arg and remove single-arg version | |
| 324 | + QPDF_DLL | |
| 325 | + std::list<std::string> read_lines_from_file( | |
| 326 | + std::istream&, bool preserve_eol); | |
| 327 | + QPDF_DLL | |
| 328 | + std::list<std::string> read_lines_from_file( | |
| 329 | + FILE*, bool preserve_eol = false); | |
| 330 | + QPDF_DLL | |
| 331 | + void read_lines_from_file( | |
| 332 | + std::function<bool(char&)> next_char, | |
| 333 | + std::list<std::string>& lines, | |
| 334 | + bool preserve_eol = false); | |
| 335 | + | |
| 315 | 336 | QPDF_DLL |
| 316 | 337 | void read_file_into_memory( |
| 317 | 338 | char const* filename, PointerHolder<char>& file_buf, size_t& size); | ... | ... |
libqpdf/QUtil.cc
| ... | ... | @@ -234,6 +234,23 @@ static unsigned short mac_roman_to_unicode[] = { |
| 234 | 234 | 0x02c7, // 0xff |
| 235 | 235 | }; |
| 236 | 236 | |
| 237 | +class FileCloser | |
| 238 | +{ | |
| 239 | + public: | |
| 240 | + FileCloser(FILE* f) : | |
| 241 | + f(f) | |
| 242 | + { | |
| 243 | + } | |
| 244 | + | |
| 245 | + ~FileCloser() | |
| 246 | + { | |
| 247 | + fclose(f); | |
| 248 | + } | |
| 249 | + | |
| 250 | + private: | |
| 251 | + FILE* f; | |
| 252 | +}; | |
| 253 | + | |
| 237 | 254 | template <typename T> |
| 238 | 255 | static |
| 239 | 256 | std::string |
| ... | ... | @@ -987,19 +1004,6 @@ QUtil::is_number(char const* p) |
| 987 | 1004 | return found_digit; |
| 988 | 1005 | } |
| 989 | 1006 | |
| 990 | -std::list<std::string> | |
| 991 | -QUtil::read_lines_from_file(char const* filename) | |
| 992 | -{ | |
| 993 | - std::ifstream in(filename, std::ios_base::binary); | |
| 994 | - if (! in.is_open()) | |
| 995 | - { | |
| 996 | - throw_system_error(std::string("open ") + filename); | |
| 997 | - } | |
| 998 | - std::list<std::string> lines = read_lines_from_file(in); | |
| 999 | - in.close(); | |
| 1000 | - return lines; | |
| 1001 | -} | |
| 1002 | - | |
| 1003 | 1007 | void |
| 1004 | 1008 | QUtil::read_file_into_memory( |
| 1005 | 1009 | char const* filename, |
| ... | ... | @@ -1040,18 +1044,69 @@ QUtil::read_file_into_memory( |
| 1040 | 1044 | } |
| 1041 | 1045 | |
| 1042 | 1046 | std::list<std::string> |
| 1047 | +QUtil::read_lines_from_file(char const* filename) | |
| 1048 | +{ | |
| 1049 | + // ABI: remove this method | |
| 1050 | + std::list<std::string> lines; | |
| 1051 | + FILE* f = safe_fopen(filename, "rb"); | |
| 1052 | + FileCloser fc(f); | |
| 1053 | + auto next_char = [&f](char& ch) { return (fread(&ch, 1, 1, f) > 0); }; | |
| 1054 | + read_lines_from_file(next_char, lines, false); | |
| 1055 | + return lines; | |
| 1056 | +} | |
| 1057 | + | |
| 1058 | +std::list<std::string> | |
| 1059 | +QUtil::read_lines_from_file(char const* filename, bool preserve_eol) | |
| 1060 | +{ | |
| 1061 | + std::list<std::string> lines; | |
| 1062 | + FILE* f = safe_fopen(filename, "rb"); | |
| 1063 | + FileCloser fc(f); | |
| 1064 | + auto next_char = [&f](char& ch) { return (fread(&ch, 1, 1, f) > 0); }; | |
| 1065 | + read_lines_from_file(next_char, lines, preserve_eol); | |
| 1066 | + return lines; | |
| 1067 | +} | |
| 1068 | + | |
| 1069 | +std::list<std::string> | |
| 1043 | 1070 | QUtil::read_lines_from_file(std::istream& in) |
| 1044 | 1071 | { |
| 1045 | - std::list<std::string> result; | |
| 1046 | - std::string* buf = 0; | |
| 1072 | + // ABI: remove this method | |
| 1073 | + std::list<std::string> lines; | |
| 1074 | + auto next_char = [&in](char& ch) { return (in.get(ch)) ? true: false; }; | |
| 1075 | + read_lines_from_file(next_char, lines, false); | |
| 1076 | + return lines; | |
| 1077 | +} | |
| 1078 | + | |
| 1079 | +std::list<std::string> | |
| 1080 | +QUtil::read_lines_from_file(std::istream& in, bool preserve_eol) | |
| 1081 | +{ | |
| 1082 | + std::list<std::string> lines; | |
| 1083 | + auto next_char = [&in](char& ch) { return (in.get(ch)) ? true: false; }; | |
| 1084 | + read_lines_from_file(next_char, lines, preserve_eol); | |
| 1085 | + return lines; | |
| 1086 | +} | |
| 1087 | + | |
| 1088 | +std::list<std::string> | |
| 1089 | +QUtil::read_lines_from_file(FILE* f, bool preserve_eol) | |
| 1090 | +{ | |
| 1091 | + std::list<std::string> lines; | |
| 1092 | + auto next_char = [&f](char& ch) { return (fread(&ch, 1, 1, f) > 0); }; | |
| 1093 | + read_lines_from_file(next_char, lines, preserve_eol); | |
| 1094 | + return lines; | |
| 1095 | +} | |
| 1047 | 1096 | |
| 1097 | +void | |
| 1098 | +QUtil::read_lines_from_file(std::function<bool(char&)> next_char, | |
| 1099 | + std::list<std::string>& lines, | |
| 1100 | + bool preserve_eol) | |
| 1101 | +{ | |
| 1102 | + std::string* buf = 0; | |
| 1048 | 1103 | char c; |
| 1049 | - while (in.get(c)) | |
| 1104 | + while (next_char(c)) | |
| 1050 | 1105 | { |
| 1051 | 1106 | if (buf == 0) |
| 1052 | 1107 | { |
| 1053 | - result.push_back(""); | |
| 1054 | - buf = &(result.back()); | |
| 1108 | + lines.push_back(""); | |
| 1109 | + buf = &(lines.back()); | |
| 1055 | 1110 | buf->reserve(80); |
| 1056 | 1111 | } |
| 1057 | 1112 | |
| ... | ... | @@ -1074,8 +1129,6 @@ QUtil::read_lines_from_file(std::istream& in) |
| 1074 | 1129 | buf->append(1, c); |
| 1075 | 1130 | } |
| 1076 | 1131 | } |
| 1077 | - | |
| 1078 | - return result; | |
| 1079 | 1132 | } |
| 1080 | 1133 | |
| 1081 | 1134 | int | ... | ... |
libtests/qutil.cc
| ... | ... | @@ -9,6 +9,7 @@ |
| 9 | 9 | #include <string.h> |
| 10 | 10 | #include <limits.h> |
| 11 | 11 | #include <assert.h> |
| 12 | +#include <fstream> | |
| 12 | 13 | |
| 13 | 14 | #ifdef _WIN32 |
| 14 | 15 | # include <io.h> |
| ... | ... | @@ -408,6 +409,15 @@ void read_from_file_test() |
| 408 | 409 | { |
| 409 | 410 | std::cout << *iter << std::endl; |
| 410 | 411 | } |
| 412 | + // Test the other versions and make sure we get the same results | |
| 413 | + { | |
| 414 | + std::ifstream infs("other-file", std::ios_base::binary); | |
| 415 | + assert(QUtil::read_lines_from_file(infs) == lines); | |
| 416 | + FILE* fp = QUtil::safe_fopen("other-file", "rb"); | |
| 417 | + assert(QUtil::read_lines_from_file(fp) == lines); | |
| 418 | + fclose(fp); | |
| 419 | + } | |
| 420 | + | |
| 411 | 421 | PointerHolder<char> buf; |
| 412 | 422 | size_t size = 0; |
| 413 | 423 | QUtil::read_file_into_memory("other-file", buf, size); | ... | ... |