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