source: branches/help/GDE/MUSCLE/src/textfile.cpp

Last change on this file was 10390, checked in by aboeckma, 12 years ago

added muscle sourcles amd makefile

File size: 6.6 KB
Line 
1#include "muscle.h"
2#include "textfile.h"
3#include <errno.h>
4
5TextFile::TextFile(const char szFileName[], bool bWrite)
6        {
7        FILE *ptrFile = 0;
8        if (bWrite)
9                {
10                if (0 == strcmp(szFileName, "-"))
11                        ptrFile = stdout;
12                else
13                        ptrFile = fopen(szFileName, "wb");
14                }
15        else
16                {
17                if (0 == strcmp(szFileName, "-"))
18                        ptrFile = stdin;
19                else
20                        ptrFile = fopen(szFileName, "rb");
21                }
22        if (0 == ptrFile)
23                Quit("Cannot open '%s' errno=%d\n", szFileName, errno);
24        Init(ptrFile, szFileName);
25        }
26
27void TextFile::Init(FILE *ptrFile, const char *ptrFileName)
28        {
29        m_ptrFile = ptrFile;
30        m_ptrName = strdup(ptrFileName);
31        m_uLineNr = 1;
32        m_uColNr = 0;
33        m_bLastCharWasEOL = true;
34        m_cPushedBack = -1;
35#if     DEBUG
36        setbuf(m_ptrFile, 0);
37#endif
38        }
39
40TextFile::TextFile(FILE *ptrFile, const char *ptrFileName)
41        {
42        Init(ptrFile, "-");
43        }
44
45TextFile::~TextFile()
46        {
47        if (m_ptrFile &&
48          m_ptrFile != stdin && m_ptrFile != stdout && m_ptrFile != stderr)
49                fclose(m_ptrFile);
50        free(m_ptrName);
51        }
52
53// Get line from file.
54// Return true if end-of-file, quit if line too long.
55bool TextFile::GetLine(char szLine[], unsigned uBytes)
56        {
57        if (0 == uBytes)
58                Quit("TextFile::GetLine, buffer zero size");
59
60       
61        int FillVal = 0; // suppress warning from gcc that I don't understand
62        memset(szLine, FillVal, (size_t) uBytes);
63
64        unsigned uBytesCopied = 0;
65
66// Loop until end of line or end of file.
67        for (;;)
68                {
69                char c;
70                bool bEof = GetChar(c);
71                if (bEof)
72                        return true;
73                if ('\r' == c)
74                        continue;
75                if ('\n' == c)
76                        return false;
77                if (uBytesCopied < uBytes - 1)
78                        szLine[uBytesCopied++] = (char) c;
79                else
80                        Quit("TextFile::GetLine: input buffer too small, line %u",
81                          m_uLineNr);
82                }
83        }
84
85// As GetLine, but trim leading and trailing blanks; skip empty lines
86bool TextFile::GetTrimLine(char szLine[], unsigned uBytes)
87        {
88        if (uBytes == 0)
89                Quit("GetTrimLine");
90        for (;;)
91                {
92                bool bEOF = GetLine(szLine, uBytes);
93                if (bEOF)
94                        return true;
95                TrimBlanks(szLine);
96                if (0 != szLine[0])
97                        break;
98                }
99        return false;
100        }
101
102void TextFile::Rewind()
103        {
104        fseek(m_ptrFile, 0, SEEK_SET);
105        m_uLineNr = 1;
106        m_bLastCharWasEOL = true;
107        }
108
109void TextFile::PutChar(char c)
110        {
111        int i = fputc(c, m_ptrFile);
112        assert(i == c);
113        if ('\n' == c)
114                {
115                ++m_uLineNr;
116                m_uColNr = 1;
117                }
118        else
119                ++m_uColNr;
120        }
121
122void TextFile::PutString(const char szLine[])
123        {
124        int iError = fputs(szLine, m_ptrFile);
125        assert(iError >= 0);
126        }
127
128void TextFile::PutFormat(const char szFormat[], ...)
129        {
130        char szStr[4096];
131        va_list ArgList;
132        va_start(ArgList, szFormat);
133        vsprintf(szStr, szFormat, ArgList);
134        PutString(szStr);
135        }
136
137void TextFile::GetLineX(char szLine[], unsigned uBytes)
138        {
139        if (uBytes == 0)
140                Quit("GetLineX");
141        bool bEof = GetLine(szLine, uBytes);
142        if (bEof)
143                Quit("end-of-file in GetLineX");
144        }
145
146bool TextFile::GetToken(char szToken[], unsigned uBytes, const char szCharTokens[])
147        {
148// Skip leading white space
149        char c;
150        for (;;)
151                {
152                bool bEof = GetChar(c);
153                if (bEof)
154                        return true;
155                if (!isspace(c))
156                        break;
157                }
158
159// Check for special case single-character tokens
160        if (0 != strchr(szCharTokens, c))
161                {
162                assert(uBytes >= 2);
163                szToken[0] = c;
164                szToken[1] = 0;
165                return false;
166                }
167
168// Loop until token terminated by white space, EOF or special
169        unsigned uBytesCopied = 0;
170        for (;;)
171                {
172                if (uBytesCopied < uBytes - 1)
173                        szToken[uBytesCopied++] = c;
174                else
175                        Quit("TextFile::GetToken: input buffer too small, line %u",
176                          m_uLineNr);
177                bool bEof = GetChar(c);
178                if (bEof)
179                        {
180                        szToken[uBytesCopied] = 0;
181                        return true;
182                        }
183        // Check for special case single-character tokens
184                if (0 != strchr(szCharTokens, c))
185                        {
186                        PushBack(c);
187                        assert(uBytesCopied > 0 && uBytesCopied < uBytes);
188                        szToken[uBytesCopied] = 0;
189                        return false;
190                        }
191                if (isspace(c))
192                        {
193                        assert(uBytesCopied > 0 && uBytesCopied < uBytes);
194                        szToken[uBytesCopied] = 0;
195                        return false;
196                        }
197                }
198        }
199
200void TextFile::GetTokenX(char szToken[], unsigned uBytes, const char szCharTokens[])
201        {
202        bool bEof = GetToken(szToken, uBytes, szCharTokens);
203        if (bEof)
204                Quit("End-of-file in GetTokenX");
205        }
206
207void TextFile::Skip()
208        {
209        for (;;)
210                {
211                char c;
212                bool bEof = GetChar(c);
213                if (bEof || '\n' == c)
214                        return;
215                assert(isspace(c));
216                }
217        }
218
219#ifdef _WIN32
220
221TEXTFILEPOS TextFile::GetPos()
222        {
223        fpos_t p;
224        int i = fgetpos(m_ptrFile, &p);
225        assert(0 == i);
226        assert(p >= 0);
227        TEXTFILEPOS Pos;
228        Pos.uOffset = (unsigned) p;
229        Pos.uLineNr = m_uLineNr;
230        Pos.uColNr = m_uColNr;
231        return Pos;
232        }
233
234void TextFile::SetPos(TEXTFILEPOS Pos)
235        {
236        fpos_t p = (fpos_t) Pos.uOffset;
237        int i = fsetpos(m_ptrFile, &p);
238        assert(0 == i);
239        m_uLineNr = Pos.uLineNr;
240        m_uColNr = Pos.uColNr;
241        }
242
243#else
244
245TEXTFILEPOS TextFile::GetPos()
246        {
247        TEXTFILEPOS Pos;
248        Pos.uOffset = ftell(m_ptrFile);
249        Pos.uLineNr = m_uLineNr;
250        Pos.uColNr = m_uColNr;
251        return Pos;
252        }
253
254void TextFile::SetPos(TEXTFILEPOS Pos)
255        {
256        fseek(m_ptrFile, Pos.uOffset, SEEK_SET);
257        m_uLineNr = Pos.uLineNr;
258        m_uColNr = Pos.uColNr;
259        }
260
261#endif
262
263bool TextFile::GetChar(char &c)
264        {
265        if (-1 != m_cPushedBack)
266                {
267                c = (char) m_cPushedBack;
268                m_cPushedBack = -1;
269                return false;
270                }
271
272        int ic = fgetc(m_ptrFile);
273        if (ic < 0)
274                {
275                if (feof(m_ptrFile))
276                        {
277                // Hack to fix up a non-empty text file that is missing
278                // and end-of-line character in the last line.
279                        if (!m_bLastCharWasEOL && m_uLineNr > 0)
280                                {
281                                c = '\n';
282                                m_bLastCharWasEOL = true;
283                                return false;
284                                }
285                        return true;
286                        }
287                Quit("TextFile::GetChar, error %s", strerror(errno));
288                }
289        c = (char) ic;
290        if ('\n' == c)
291                {
292                m_bLastCharWasEOL = true;
293                ++m_uLineNr;
294                m_uColNr = 1;
295                }
296        else
297                {
298                m_bLastCharWasEOL = false;
299                ++m_uColNr;
300                }
301        return false;
302        }
303
304void TextFile::GetCharX(char &c)
305        {
306        bool bEof = GetChar(c);
307        if (bEof)
308                Quit("End-of-file in GetCharX");
309        }
310
311void TextFile::GetNonblankChar(char &c)
312        {
313        do
314                {
315                bool bEof = GetChar(c);
316                if (bEof)
317                        Quit("End-of-file in GetCharX");
318                }
319        while (isspace(c));
320        }
321
322void TextFile::SkipLine()
323        {
324        if (m_bLastCharWasEOL)
325                return;
326        for (;;)
327                {
328                char c;
329                bool bEof = GetChar(c);
330                if (bEof)
331                        Quit("End-of-file in SkipLine");
332                if ('\n' == c)
333                        break;
334                }
335        }
336
337void TextFile::SkipWhite()
338        {
339        bool bEof = SkipWhiteX();
340        if (bEof)
341                Quit("End-of-file skipping white space");
342        }
343
344bool TextFile::SkipWhiteX()
345        {
346        for (;;)
347                {
348                char c;
349                bool bEof = GetChar(c);
350                if (bEof)
351                        return true;
352                if (!isspace(c))
353                        {
354                        PushBack(c);
355                        break;
356                        }
357                }
358        return false;
359        }
Note: See TracBrowser for help on using the repository browser.