ARB
MultiFileReader.cxx
Go to the documentation of this file.
1 // ============================================================= //
2 // //
3 // File : MultiFileReader.cxx //
4 // Purpose : Read multiple files like one concatenated file //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in March 2014 //
7 // http://www.arb-home.de/ //
8 // //
9 // ============================================================= //
10 
11 #include "MultiFileReader.h"
12 #include "arb_msg.h"
13 
14 const string& MultiFileReader::getFilename() const {
15  if (!reader) {
16  if (last_reader) return last_reader->getFilename();
17  arb_assert(0);
18  static string nf = "unknown-source";
19  return nf;
20  }
21  return reader->getFilename();
22 }
23 bool MultiFileReader::getLine_intern(string& line) {
24  bool gotLine = false;
25  if (reader) {
26  gotLine = reader->getLine(line);
27  if (!gotLine) {
28  nextReader();
29  gotLine = getLine_intern(line);
30  if (gotLine) setLineNumber(reader->getLineNumber());
31  }
32  }
33  return gotLine;
34 }
35 
36 FILE *MultiFileReader::open(int i) {
37  FILE *in = fopen(files[i], "rt");
38  if (!in) error = new string(GB_IO_error("reading", files[i]));
39  return in;
40 }
41 
42 void MultiFileReader::nextReader() {
43  if (reader) {
44  if (last_reader) {
45  delete last_reader;
46  last_reader = NULp;
47  }
48  last_reader = reader;
49  reader = NULp;
50  }
51  ++at;
52  if (at<files.size()) {
53  FILE *in = open(at);
54  if (in) {
55  reader = new BufferedFileReader(files[at], in);
56  }
57  }
58 }
59 
60 MultiFileReader::MultiFileReader(const CharPtrArray& files_) :
61  files(files_),
62  reader(NULp),
63  last_reader(NULp),
64  error(NULp),
65  at(-1)
66 {
67  for (size_t i = 0; i<files.size() && !error; ++i) {
68  // test open all files
69  FILE *in = open(i);
70  if (in) fclose(in);
71  }
72  if (!error) nextReader();
73 }
74 
75 MultiFileReader::~MultiFileReader() {
76  delete reader;
77  delete last_reader;
78  delete error;
79 }
80 
81 // --------------------------------------------------------------------------------
82 
83 #ifdef UNIT_TESTS
84 #ifndef TEST_UNIT_H
85 #include <test_unit.h>
86 #endif
87 
88 void TEST_MultiFileReader() {
89  ConstStrArray files;
90  files.put("general/broken_LF.input"); // 6 lines
91  files.put("general/dos.input"); // 6 lines
92  files.put("general/mac.input"); // 6 lines
93  files.put("general/empty.input"); // 1 line
94  files.put("general/text.input"); // 6 lines
95 
96  {
97  MultiFileReader reader(files);
98 
99  TEST_EXPECT_NO_ERROR(reader.get_error());
100 
101  string line;
102  string emptyLineError;
103  string db_found_msgs;
104  int lineCount = 0;
105  int emptyLineCount = 0;
106 
107  while (reader.getLine(line)) {
108  lineCount++;
109  if (line.empty()) {
110  emptyLineCount++;
111  emptyLineError = reader.lineError("seen empty line");
112  }
113  else if (strstr(line.c_str(), "database")) {
114  db_found_msgs += reader.lineError("DB") + "\n";
115  }
116  }
117 
118  TEST_EXPECT_NO_ERROR(reader.get_error());
119  TEST_EXPECT_EQUAL(lineCount, 25);
120  TEST_EXPECT_EQUAL(emptyLineCount, 1);
121  TEST_EXPECT_EQUAL(emptyLineError, "general/empty.input:1: seen empty line");
122  TEST_EXPECT_EQUAL(db_found_msgs,
123  "general/broken_LF.input:2: DB\n"
124  "general/dos.input:2: DB\n"
125  "general/mac.input:2: DB\n"
126  "general/text.input:2: DB\n");
127  }
128 
129  files.put("general/nosuch.input");
130  {
131  MultiFileReader reader(files);
132  TEST_EXPECT_EQUAL(reader.get_error(), "While reading 'general/nosuch.input': No such file or directory");
133  }
134 }
135 TEST_PUBLISH(TEST_MultiFileReader);
136 
137 #endif // UNIT_TESTS
138 
139 // --------------------------------------------------------------------------------
140 
#define arb_assert(cond)
Definition: arb_assert.h:245
void put(const char *elem)
Definition: arb_strarray.h:188
return string(buffer, length)
GB_ERROR GB_IO_error(const char *action, const char *filename)
Definition: arb_msg.cxx:285
#define TEST_PUBLISH(testfunction)
Definition: test_unit.h:1517
static void error(const char *msg)
Definition: mkptypes.cxx:96
#define TEST_EXPECT_NO_ERROR(call)
Definition: test_unit.h:1118
static int line
Definition: arb_a2ps.c:296
#define NULp
Definition: cxxforward.h:116
#define TEST_EXPECT_EQUAL(expr, want)
Definition: test_unit.h:1294