source: box/trunk/lib/common/GetLine.cpp @ 2935

Revision 2935, 3.8 KB checked in by chris, 13 months ago (diff)

Refactor GetLines? to share common code, fix whitespace removal at end of line.

  • Property svn:eol-style set to native
Line 
1// --------------------------------------------------------------------------
2//
3// File
4//              Name:    GetLine.cpp
5//              Purpose: Common base class for line based file descriptor reading
6//              Created: 2011/04/22
7//
8// --------------------------------------------------------------------------
9
10#include "Box.h"
11
12#include <sys/types.h>
13
14#ifdef HAVE_UNISTD_H
15        #include <unistd.h>
16#endif
17
18#include "GetLine.h"
19#include "CommonException.h"
20
21#include "MemLeakFindOn.h"
22
23// utility whitespace function
24inline bool iw(int c)
25{
26        return (c == ' ' || c == '\t' || c == '\v' || c == '\f'); // \r, \n are already excluded
27}
28
29
30// --------------------------------------------------------------------------
31//
32// Function
33//              Name:    GetLine::GetLine(int)
34//              Purpose: Constructor, taking file descriptor
35//              Created: 2011/04/22
36//
37// --------------------------------------------------------------------------
38GetLine::GetLine()
39: mLineNumber(0),
40  mBufferBegin(0),
41  mBytesInBuffer(0),
42  mPendingEOF(false),
43  mEOF(false)
44{ }
45
46// --------------------------------------------------------------------------
47//
48// Function
49//              Name:    GetLine::GetLineInternal(std::string &, bool, int)
50//              Purpose: Gets a line from the file, returning it in rOutput.
51//                       If Preprocess is true, leading and trailing
52//                       whitespace is removed, and comments (after #)  are
53//                       deleted. Returns true if a line is available now,
54//                       false if retrying may get a line (eg timeout,
55//                       signal), and exceptions if it's EOF.
56//              Created: 2011/04/22
57//
58// --------------------------------------------------------------------------
59bool GetLine::GetLineInternal(std::string &rOutput, bool Preprocess,
60        int Timeout)
61{
62        // EOF?
63        if(mEOF) {THROW_EXCEPTION(CommonException, GetLineEOF)}
64       
65        // Initialise string to stored into
66        rOutput = mPendingString;
67        mPendingString.erase();
68
69        bool foundLineEnd = false;
70
71        while(!foundLineEnd && !mEOF)
72        {
73                // Use any bytes left in the buffer
74                while(mBufferBegin < mBytesInBuffer)
75                {
76                        int c = mBuffer[mBufferBegin++];
77                        if(c == '\r')
78                        {
79                                // Ignore nasty Windows line ending extra chars
80                        }
81                        else if(c == '\n')
82                        {
83                                // Line end!
84                                foundLineEnd = true;
85                                break;
86                        }
87                        else
88                        {
89                                // Add to string
90                                rOutput += c;
91                        }
92                       
93                        // Implicit line ending at EOF
94                        if(mBufferBegin >= mBytesInBuffer && mPendingEOF)
95                        {
96                                foundLineEnd = true;
97                        }
98                }
99               
100                // Check size
101                if(rOutput.size() > GETLINE_MAX_LINE_SIZE)
102                {
103                        THROW_EXCEPTION(CommonException, GetLineTooLarge)
104                }
105               
106                // Read more in?
107                if(!foundLineEnd && mBufferBegin >= mBytesInBuffer && !mPendingEOF)
108                {
109                        int bytes = ReadMore(Timeout);
110                       
111                        // Error?
112                        if(bytes == -1)
113                        {
114                                THROW_EXCEPTION(CommonException, OSFileError)
115                        }
116                       
117                        // Adjust buffer info
118                        mBytesInBuffer = bytes;
119                        mBufferBegin = 0;
120                       
121                        // No data returned?
122                        if(bytes == 0 && IsStreamDataLeft())
123                        {
124                               // store string away
125                               mPendingString = rOutput;
126                               // Return false;
127                               return false;
128                        }
129                }
130               
131                // EOF?
132                if(mPendingEOF && mBufferBegin >= mBytesInBuffer)
133                {
134                        // File is EOF, and now we've depleted the buffer completely, so tell caller as well.
135                        mEOF = true;
136                }
137        }
138
139        if(Preprocess)
140        {
141                // Check for comment char, but char before must be whitespace
142                // end points to a gap between characters, may equal start if
143                // the string to be extracted has zero length, and indexes the
144                // first character not in the string (== length, or a # mark
145                // or whitespace)
146                int end = 0;
147                int size = rOutput.size();
148                while(end < size)
149                {
150                        if(rOutput[end] == '#' && (end == 0 || (iw(rOutput[end-1]))))
151                        {
152                                break;
153                        }
154                        end++;
155                }
156               
157                // Remove whitespace
158                int begin = 0;
159                while(begin < size && iw(rOutput[begin]))
160                {
161                        begin++;
162                }
163
164                while(end > begin && end <= size && iw(rOutput[end-1]))
165                {
166                        end--;
167                }
168               
169                // Return a sub string
170                rOutput = rOutput.substr(begin, end - begin);
171        }
172
173        return true;
174}
175
176
Note: See TracBrowser for help on using the repository browser.