1 ///###////////////////////////////////////////////////////////////////////////
2 //
3 // Burton Computer Corporation
4 // http://www.burton-computer.com
5 // http://www.cooldevtools.com
6 // $Id: SimpleMultiLineStringCharReader.cc 272 2007-01-06 19:37:27Z brian $
7 //
8 // Copyright (C) 2007 Burton Computer Corporation
9 // ALL RIGHTS RESERVED
10 //
11 // This program is open source software; you can redistribute it
12 // and/or modify it under the terms of the Q Public License (QPL)
13 // version 1.0. Use of this software in whole or in part, including
14 // linking it (modified or unmodified) into other programs is
15 // subject to the terms of the QPL.
16 //
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // Q Public License for more details.
21 //
22 // You should have received a copy of the Q Public License
23 // along with this program; see the file LICENSE.txt. If not, visit
24 // the Burton Computer Corporation or CoolDevTools web site
25 // QPL pages at:
26 //
27 // http://www.burton-computer.com/qpl.html
28 // http://www.cooldevtools.com/qpl.html
29 //
30
31 #include "AbstractMultiLineString.h"
32 #include "SimpleMultiLineStringCharReader.h"
33
34 class SimpleMultiLineStringCharReaderPosition : public AbstractCharReaderPosition
35 {
36 public:
SimpleMultiLineStringCharReaderPosition(const string * terminator,const AbstractMultiLineString * target)37 SimpleMultiLineStringCharReaderPosition(const string *terminator,
38 const AbstractMultiLineString *target)
39 : m_terminator(terminator),
40 m_target(target)
41 {
42 assert(m_terminator);
43 assert(m_target);
44 m_haveTerminator = m_terminator->size() > 0;
45 reset();
46 }
47
~SimpleMultiLineStringCharReaderPosition()48 ~SimpleMultiLineStringCharReaderPosition()
49 {
50 }
51
copyPosition(const SimpleMultiLineStringCharReaderPosition * other)52 void copyPosition(const SimpleMultiLineStringCharReaderPosition *other)
53 {
54 assert(other);
55 m_terminator = other->m_terminator;
56 m_target = other->m_target;
57 m_lineIndex = other->m_lineIndex;
58 m_charIndex = other->m_charIndex;
59 m_inTerminator = other->m_inTerminator;
60 m_haveTerminator = other->m_haveTerminator;
61 m_atEnd = other->m_atEnd;
62 m_currentChar = other->m_currentChar;
63 m_currentLine = other->m_currentLine;
64 m_currentLineLength = other->m_currentLineLength;
65 }
66
reset()67 void reset()
68 {
69 m_lineIndex = 0;
70 m_charIndex = -1;
71 m_inTerminator = false;
72 m_atEnd = m_lineIndex >= m_target->lineCount();
73 m_currentChar = ' ';
74 m_currentLine = 0;
75 m_currentLineLength = 0;
76 }
77
skip(int nchars)78 bool skip(int nchars)
79 {
80 m_charIndex += nchars;
81 return ensureCharReady();
82 }
83
currentLine()84 const string *currentLine()
85 {
86 if (!m_currentLine) {
87 m_currentLine = m_inTerminator ? m_terminator : &m_target->line(m_lineIndex);
88 m_currentLineLength = (int)m_currentLine->size();
89 }
90 return m_currentLine;
91 }
92
hasChar()93 bool hasChar()
94 {
95 return m_lineIndex >= 0 && !m_atEnd;
96 }
97
atEnd() const98 bool atEnd() const
99 {
100 return m_atEnd;
101 }
102
currentChar() const103 char currentChar() const
104 {
105 return m_currentChar;
106 }
107
108 bool ensureCharReady();
109
currentLineLength() const110 int currentLineLength() const
111 {
112 assert(m_currentLine);
113 return m_currentLineLength;
114 }
115
116 private:
117 const AbstractMultiLineString *m_target;
118 const string *m_terminator;
119 int m_lineIndex;
120 int m_charIndex;
121 bool m_inTerminator;
122 bool m_haveTerminator;
123 bool m_atEnd;
124 char m_currentChar;
125 const string *m_currentLine;
126 int m_currentLineLength;
127 };
128
ensureCharReady()129 bool SimpleMultiLineStringCharReaderPosition::ensureCharReady()
130 {
131 if (m_atEnd) {
132 return false;
133 }
134
135 assert(m_lineIndex < m_target->lineCount());
136 for (;;) {
137 const string *line = currentLine();
138 if (m_charIndex < m_currentLineLength) {
139 m_currentChar = (*line)[m_charIndex];
140 return true;
141 }
142
143 m_charIndex -= m_currentLineLength;
144 m_currentLine = 0;
145 if (m_inTerminator || !m_haveTerminator) {
146 m_inTerminator = false;
147 ++m_lineIndex;
148 if (m_lineIndex >= m_target->lineCount()) {
149 break;
150 }
151 } else {
152 m_inTerminator = true;
153 }
154 }
155
156 m_atEnd = true;
157 return false;
158 }
159
SimpleMultiLineStringCharReader(const AbstractMultiLineString * target)160 SimpleMultiLineStringCharReader::SimpleMultiLineStringCharReader(const AbstractMultiLineString *target)
161 : m_target(target),
162 m_position(new SimpleMultiLineStringCharReaderPosition(&m_terminator, target))
163 {
164 reset();
165 }
166
SimpleMultiLineStringCharReader(const AbstractMultiLineString * target,const string & terminator)167 SimpleMultiLineStringCharReader::SimpleMultiLineStringCharReader(const AbstractMultiLineString *target,
168 const string &terminator)
169 : m_target(target),
170 m_terminator(terminator),
171 m_position(new SimpleMultiLineStringCharReaderPosition(&m_terminator, target))
172 {
173 reset();
174 }
175
~SimpleMultiLineStringCharReader()176 SimpleMultiLineStringCharReader::~SimpleMultiLineStringCharReader()
177 {
178 }
179
forward()180 bool SimpleMultiLineStringCharReader::forward()
181 {
182 return skip(1);
183 }
184
skip(int nchars)185 bool SimpleMultiLineStringCharReader::skip(int nchars)
186 {
187 bool answer = m_position->skip(nchars);
188 if (answer) {
189 setCurrentChar(m_position->currentChar());
190 }
191 return answer;
192 }
193
hasChar()194 bool SimpleMultiLineStringCharReader::hasChar()
195 {
196 return m_position->hasChar();
197 }
198
atEnd()199 bool SimpleMultiLineStringCharReader::atEnd()
200 {
201 return m_position->atEnd();
202 }
203
reset()204 void SimpleMultiLineStringCharReader::reset()
205 {
206 m_position->reset();
207 }
208
createMark()209 AbstractCharReaderPosition *SimpleMultiLineStringCharReader::createMark()
210 {
211 return new SimpleMultiLineStringCharReaderPosition(*m_position.get());
212 }
213
returnToMark(AbstractCharReaderPosition * position)214 void SimpleMultiLineStringCharReader::returnToMark(AbstractCharReaderPosition *position)
215 {
216 m_position->copyPosition(dynamic_cast<SimpleMultiLineStringCharReaderPosition *>(position));
217 setCurrentChar(m_position->currentChar());
218 }
219
getCurrentLine()220 const string *SimpleMultiLineStringCharReader::getCurrentLine()
221 {
222 return m_position->currentLine();
223 }
224
ensureCharReady()225 bool SimpleMultiLineStringCharReader::ensureCharReady()
226 {
227 bool answer = m_position->ensureCharReady();
228 if (answer) {
229 setCurrentChar(m_position->currentChar());
230 }
231 return answer;
232 }
233