1 | #include "reader.h" |
---|
2 | #include <unistd.h> |
---|
3 | |
---|
4 | Reader::Reader(const char *inf) |
---|
5 | : fp(fopen(inf, "rt")), |
---|
6 | file(NULL), |
---|
7 | curr(NULL), |
---|
8 | failure(false) |
---|
9 | { |
---|
10 | reset(); |
---|
11 | try { |
---|
12 | if (!fp) { |
---|
13 | throw_errorf(1, "can't read input file '%s' (Reason: %s)", inf, strerror(errno)); |
---|
14 | } |
---|
15 | file = new BufferedFileReader(inf, fp); |
---|
16 | file->showFilenameInLineError(true); |
---|
17 | read(); |
---|
18 | } |
---|
19 | catch (Convaln_exception& exc) { |
---|
20 | failure = true; |
---|
21 | curr = NULL; |
---|
22 | throw; |
---|
23 | } |
---|
24 | } |
---|
25 | |
---|
26 | Reader::~Reader() { |
---|
27 | // if kicked by exception, decorate error-msg with current reader position |
---|
28 | if (const Convaln_exception *exc = Convaln_exception::exception_thrown()) { |
---|
29 | exc->replace_msg(file->lineError(exc->get_msg()).c_str()); |
---|
30 | } |
---|
31 | else { |
---|
32 | ca_assert(!curr); // reader did NOT read till EOF, why ? |
---|
33 | } |
---|
34 | delete file; |
---|
35 | } |
---|
36 | |
---|
37 | void Reader::read() { |
---|
38 | if (!curr) { |
---|
39 | failure = true; // read _beyond_ EOF |
---|
40 | } |
---|
41 | else { |
---|
42 | ca_assert(!failure); // attempt to read after failure |
---|
43 | |
---|
44 | string next_line; |
---|
45 | if (!file->getLine(next_line)) { |
---|
46 | curr = NULL; |
---|
47 | } |
---|
48 | else { |
---|
49 | size_t len = next_line.length(); |
---|
50 | |
---|
51 | if (len >= (LINESIZE-1)) { |
---|
52 | char lbuf[200]; |
---|
53 | memcpy(lbuf, next_line.c_str(), 200-4); |
---|
54 | strcpy(lbuf+200-4, "..."); |
---|
55 | throw_errorf(148, "Line too long: '%s'", lbuf); |
---|
56 | } |
---|
57 | memcpy(linebuf, next_line.c_str(), len); |
---|
58 | linebuf[len] = '\n'; |
---|
59 | linebuf[len + 1] = 0; |
---|
60 | |
---|
61 | curr = linebuf; |
---|
62 | } |
---|
63 | } |
---|
64 | } |
---|
65 | |
---|
66 | |
---|
67 | // -------------------------------------------------------------------------------- |
---|
68 | |
---|
69 | FileWriter::FileWriter(const char *outname) |
---|
70 | : ofp(NULL), |
---|
71 | filename(NULL), |
---|
72 | written(0) |
---|
73 | #if defined(ENFORCE_CHECKED_WRITTEN) |
---|
74 | , checked_written(false) |
---|
75 | #endif |
---|
76 | { |
---|
77 | ofp = fopen(outname, "wt"); |
---|
78 | if (!ofp) { |
---|
79 | throw_errorf(2, "can't write output file '%s' (Reason: %s)", outname, strerror(errno)); |
---|
80 | } |
---|
81 | filename = strdup(outname); |
---|
82 | } |
---|
83 | FileWriter::~FileWriter() { |
---|
84 | bool fine = is_fine(); |
---|
85 | |
---|
86 | #if defined(ENFORCE_CHECKED_WRITTEN) |
---|
87 | ca_assert(implicated(fine, checked_written)); // you have to call expect_written() on FileWriter before destruction |
---|
88 | #endif |
---|
89 | |
---|
90 | if (ofp) fclose(ofp); |
---|
91 | if (!fine) unlink(filename); |
---|
92 | free(filename); |
---|
93 | |
---|
94 | log_processed(written); |
---|
95 | } |
---|
96 | |
---|
97 | void FileWriter::expect_written() { |
---|
98 | #if defined(ENFORCE_CHECKED_WRITTEN) |
---|
99 | ca_assert(!checked_written); // checking twice is nonsense |
---|
100 | checked_written = true; |
---|
101 | #endif |
---|
102 | if (is_fine() && !written) { |
---|
103 | throw_errorf(42, "No sequence has been written"); |
---|
104 | } |
---|
105 | } |
---|
106 | |
---|
107 | void Writer::throw_write_error() const { |
---|
108 | throw_errorf(41, "Write error: %s(=%i) while writing %s", |
---|
109 | strerror(errno), errno, name()); |
---|
110 | } |
---|
111 | void FileWriter::out(char ch) { |
---|
112 | if (fputc(ch, ofp) == EOF) throw_write_error(); |
---|
113 | } |
---|
114 | |
---|
115 | int FileWriter::outf(const char *format, ...) { |
---|
116 | va_list parg; |
---|
117 | va_start(parg, format); |
---|
118 | int printed = vfprintf(ofp, format, parg); |
---|
119 | va_end(parg); |
---|
120 | if (printed<0) throw_write_error(); |
---|
121 | return printed; |
---|
122 | } |
---|
123 | |
---|
124 | int Writer::outf(const char *format, ...) { |
---|
125 | va_list parg; |
---|
126 | va_start(parg, format); |
---|
127 | char buffer[LINESIZE]; |
---|
128 | int printed = vsprintf(buffer, format, parg); |
---|
129 | ca_assert(printed <= LINESIZE); |
---|
130 | va_end(parg); |
---|
131 | |
---|
132 | out(buffer); |
---|
133 | return printed; |
---|
134 | } |
---|
135 | |
---|
136 | int Writer::out(const char *text) { |
---|
137 | int i = 0; |
---|
138 | while (text[i]) { |
---|
139 | out(text[i++]); |
---|
140 | } |
---|
141 | return i; |
---|
142 | } |
---|
143 | |
---|