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,6 +29,7 @@
29 #include <list> 29 #include <list>
30 #include <vector> 30 #include <vector>
31 #include <stdexcept> 31 #include <stdexcept>
  32 +#include <functional>
32 #include <stdio.h> 33 #include <stdio.h>
33 #include <time.h> 34 #include <time.h>
34 35
@@ -90,8 +91,9 @@ namespace QUtil @@ -90,8 +91,9 @@ namespace QUtil
90 QPDF_DLL 91 QPDF_DLL
91 int os_wrapper(std::string const& description, int status); 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 QPDF_DLL 97 QPDF_DLL
96 FILE* safe_fopen(char const* filename, char const* mode); 98 FILE* safe_fopen(char const* filename, char const* mode);
97 99
@@ -308,10 +310,29 @@ namespace QUtil @@ -308,10 +310,29 @@ namespace QUtil
308 QPDF_DLL 310 QPDF_DLL
309 RandomDataProvider* getRandomDataProvider(); 311 RandomDataProvider* getRandomDataProvider();
310 312
  313 + // Filename is UTF-8 encoded, even on Windows, as described in the
  314 + // comments for safe_fopen.
311 QPDF_DLL 315 QPDF_DLL
312 std::list<std::string> read_lines_from_file(char const* filename); 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 QPDF_DLL 321 QPDF_DLL
314 std::list<std::string> read_lines_from_file(std::istream&); 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 QPDF_DLL 336 QPDF_DLL
316 void read_file_into_memory( 337 void read_file_into_memory(
317 char const* filename, PointerHolder<char>& file_buf, size_t& size); 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,6 +234,23 @@ static unsigned short mac_roman_to_unicode[] = {
234 0x02c7, // 0xff 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 template <typename T> 254 template <typename T>
238 static 255 static
239 std::string 256 std::string
@@ -987,19 +1004,6 @@ QUtil::is_number(char const* p) @@ -987,19 +1004,6 @@ QUtil::is_number(char const* p)
987 return found_digit; 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 void 1007 void
1004 QUtil::read_file_into_memory( 1008 QUtil::read_file_into_memory(
1005 char const* filename, 1009 char const* filename,
@@ -1040,18 +1044,69 @@ QUtil::read_file_into_memory( @@ -1040,18 +1044,69 @@ QUtil::read_file_into_memory(
1040 } 1044 }
1041 1045
1042 std::list<std::string> 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 QUtil::read_lines_from_file(std::istream& in) 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 char c; 1103 char c;
1049 - while (in.get(c)) 1104 + while (next_char(c))
1050 { 1105 {
1051 if (buf == 0) 1106 if (buf == 0)
1052 { 1107 {
1053 - result.push_back("");  
1054 - buf = &(result.back()); 1108 + lines.push_back("");
  1109 + buf = &(lines.back());
1055 buf->reserve(80); 1110 buf->reserve(80);
1056 } 1111 }
1057 1112
@@ -1074,8 +1129,6 @@ QUtil::read_lines_from_file(std::istream&amp; in) @@ -1074,8 +1129,6 @@ QUtil::read_lines_from_file(std::istream&amp; in)
1074 buf->append(1, c); 1129 buf->append(1, c);
1075 } 1130 }
1076 } 1131 }
1077 -  
1078 - return result;  
1079 } 1132 }
1080 1133
1081 int 1134 int
libtests/qutil.cc
@@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
9 #include <string.h> 9 #include <string.h>
10 #include <limits.h> 10 #include <limits.h>
11 #include <assert.h> 11 #include <assert.h>
  12 +#include <fstream>
12 13
13 #ifdef _WIN32 14 #ifdef _WIN32
14 # include <io.h> 15 # include <io.h>
@@ -408,6 +409,15 @@ void read_from_file_test() @@ -408,6 +409,15 @@ void read_from_file_test()
408 { 409 {
409 std::cout << *iter << std::endl; 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 PointerHolder<char> buf; 421 PointerHolder<char> buf;
412 size_t size = 0; 422 size_t size = 0;
413 QUtil::read_file_into_memory("other-file", buf, size); 423 QUtil::read_file_into_memory("other-file", buf, size);