Commit 9a398504ca869e00de15c713108264e0beead504

Authored by Jay Berkenbilt
1 parent 75241655

Refactor QUtil::read_lines_from_file

This commit adds the preserve_eol flags but doesn't implement EOL
preservation yet.
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&amp; 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);
... ...