rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 Open Asset Import Library (assimp)
|
nuclear@0
|
3 ----------------------------------------------------------------------
|
nuclear@0
|
4
|
nuclear@0
|
5 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
6 All rights reserved.
|
nuclear@0
|
7
|
nuclear@0
|
8 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
9 with or without modification, are permitted provided that the
|
nuclear@0
|
10 following conditions are met:
|
nuclear@0
|
11
|
nuclear@0
|
12 * Redistributions of source code must retain the above
|
nuclear@0
|
13 copyright notice, this list of conditions and the
|
nuclear@0
|
14 following disclaimer.
|
nuclear@0
|
15
|
nuclear@0
|
16 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
17 copyright notice, this list of conditions and the
|
nuclear@0
|
18 following disclaimer in the documentation and/or other
|
nuclear@0
|
19 materials provided with the distribution.
|
nuclear@0
|
20
|
nuclear@0
|
21 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
22 contributors may be used to endorse or promote products
|
nuclear@0
|
23 derived from this software without specific prior
|
nuclear@0
|
24 written permission of the assimp team.
|
nuclear@0
|
25
|
nuclear@0
|
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
37
|
nuclear@0
|
38 ----------------------------------------------------------------------
|
nuclear@0
|
39 */
|
nuclear@0
|
40
|
nuclear@0
|
41 /** @file LineSplitter.h
|
nuclear@0
|
42 * @brief LineSplitter, a helper class to iterate through all lines
|
nuclear@0
|
43 * of a file easily. Works with StreamReader.
|
nuclear@0
|
44 */
|
nuclear@0
|
45 #ifndef INCLUDED_LINE_SPLITTER_H
|
nuclear@0
|
46 #define INCLUDED_LINE_SPLITTER_H
|
nuclear@0
|
47
|
nuclear@0
|
48 #include <stdexcept>
|
nuclear@0
|
49
|
nuclear@0
|
50 #include "StreamReader.h"
|
nuclear@0
|
51 #include "ParsingUtils.h"
|
nuclear@0
|
52
|
nuclear@0
|
53 namespace Assimp {
|
nuclear@0
|
54
|
nuclear@0
|
55 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
56 /** Usage:
|
nuclear@0
|
57 @code
|
nuclear@0
|
58 for(LineSplitter splitter(stream);splitter;++splitter) {
|
nuclear@0
|
59
|
nuclear@0
|
60 if (*splitter == "hi!") {
|
nuclear@0
|
61 ...
|
nuclear@0
|
62 }
|
nuclear@0
|
63 else if (splitter->substr(0,5) == "hello") {
|
nuclear@0
|
64 ...
|
nuclear@0
|
65 // access the third token in the line (tokens are space-separated)
|
nuclear@0
|
66 if (strtol(splitter[2]) > 5) { .. }
|
nuclear@0
|
67 }
|
nuclear@0
|
68
|
nuclear@0
|
69 std::cout << "Current line is: " << splitter.get_index() << std::endl;
|
nuclear@0
|
70 }
|
nuclear@0
|
71 @endcode */
|
nuclear@0
|
72 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
73 class LineSplitter
|
nuclear@0
|
74 {
|
nuclear@0
|
75 public:
|
nuclear@0
|
76
|
nuclear@0
|
77 typedef size_t line_idx;
|
nuclear@0
|
78
|
nuclear@0
|
79 public:
|
nuclear@0
|
80
|
nuclear@0
|
81 // -----------------------------------------
|
nuclear@0
|
82 /** construct from existing stream reader
|
nuclear@0
|
83 note: trim is *always* assumed true if skyp_empty_lines==true
|
nuclear@0
|
84 */
|
nuclear@0
|
85 LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true)
|
nuclear@0
|
86 : stream(stream)
|
nuclear@0
|
87 , swallow()
|
nuclear@0
|
88 , skip_empty_lines(skip_empty_lines)
|
nuclear@0
|
89 , trim(trim)
|
nuclear@0
|
90 {
|
nuclear@0
|
91 cur.reserve(1024);
|
nuclear@0
|
92 operator++();
|
nuclear@0
|
93
|
nuclear@0
|
94 idx = 0;
|
nuclear@0
|
95 }
|
nuclear@0
|
96
|
nuclear@0
|
97 public:
|
nuclear@0
|
98
|
nuclear@0
|
99 // -----------------------------------------
|
nuclear@0
|
100 /** pseudo-iterator increment */
|
nuclear@0
|
101 LineSplitter& operator++() {
|
nuclear@0
|
102 if(swallow) {
|
nuclear@0
|
103 swallow = false;
|
nuclear@0
|
104 return *this;
|
nuclear@0
|
105 }
|
nuclear@0
|
106
|
nuclear@0
|
107 if (!*this) {
|
nuclear@0
|
108 throw std::logic_error("End of file, no more lines to be retrieved.");
|
nuclear@0
|
109 }
|
nuclear@0
|
110
|
nuclear@0
|
111 char s;
|
nuclear@0
|
112
|
nuclear@0
|
113 cur.clear();
|
nuclear@0
|
114 while(stream.GetRemainingSize() && (s = stream.GetI1(),1)) {
|
nuclear@0
|
115 if (s == '\n' || s == '\r') {
|
nuclear@0
|
116 if (skip_empty_lines) {
|
nuclear@0
|
117 while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\r' || s == '\n'));
|
nuclear@0
|
118 if (stream.GetRemainingSize()) {
|
nuclear@0
|
119 stream.IncPtr(-1);
|
nuclear@0
|
120 }
|
nuclear@0
|
121 }
|
nuclear@0
|
122 else {
|
nuclear@0
|
123 // skip both potential line terminators but don't read past this line.
|
nuclear@0
|
124 if (stream.GetRemainingSize() && (s == '\r' && stream.GetI1() != '\n')) {
|
nuclear@0
|
125 stream.IncPtr(-1);
|
nuclear@0
|
126 }
|
nuclear@0
|
127
|
nuclear@0
|
128 if (trim) {
|
nuclear@0
|
129 while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\t'));
|
nuclear@0
|
130 if (stream.GetRemainingSize()) {
|
nuclear@0
|
131 stream.IncPtr(-1);
|
nuclear@0
|
132 }
|
nuclear@0
|
133 }
|
nuclear@0
|
134 }
|
nuclear@0
|
135
|
nuclear@0
|
136 break;
|
nuclear@0
|
137 }
|
nuclear@0
|
138 cur += s;
|
nuclear@0
|
139 }
|
nuclear@0
|
140
|
nuclear@0
|
141 ++idx;
|
nuclear@0
|
142 return *this;
|
nuclear@0
|
143 }
|
nuclear@0
|
144
|
nuclear@0
|
145 // -----------------------------------------
|
nuclear@0
|
146 LineSplitter& operator++(int) {
|
nuclear@0
|
147 return ++(*this);
|
nuclear@0
|
148 }
|
nuclear@0
|
149
|
nuclear@0
|
150 // -----------------------------------------
|
nuclear@0
|
151 /** get a pointer to the beginning of a particular token */
|
nuclear@0
|
152 const char* operator[] (size_t idx) const {
|
nuclear@0
|
153 const char* s = operator->()->c_str();
|
nuclear@0
|
154
|
nuclear@0
|
155 SkipSpaces(&s);
|
nuclear@0
|
156 for(size_t i = 0; i < idx; ++i) {
|
nuclear@0
|
157
|
nuclear@0
|
158 for(;!IsSpace(*s); ++s) {
|
nuclear@0
|
159 if(IsLineEnd(*s)) {
|
nuclear@0
|
160 throw std::range_error("Token index out of range, EOL reached");
|
nuclear@0
|
161 }
|
nuclear@0
|
162 }
|
nuclear@0
|
163 SkipSpaces(&s);
|
nuclear@0
|
164 }
|
nuclear@0
|
165 return s;
|
nuclear@0
|
166 }
|
nuclear@0
|
167
|
nuclear@0
|
168 // -----------------------------------------
|
nuclear@0
|
169 /** extract the start positions of N tokens from the current line*/
|
nuclear@0
|
170 template <size_t N>
|
nuclear@0
|
171 void get_tokens(const char* (&tokens)[N]) const {
|
nuclear@0
|
172 const char* s = operator->()->c_str();
|
nuclear@0
|
173
|
nuclear@0
|
174 SkipSpaces(&s);
|
nuclear@0
|
175 for(size_t i = 0; i < N; ++i) {
|
nuclear@0
|
176 if(IsLineEnd(*s)) {
|
nuclear@0
|
177 throw std::range_error("Token count out of range, EOL reached");
|
nuclear@0
|
178 }
|
nuclear@0
|
179 tokens[i] = s;
|
nuclear@0
|
180
|
nuclear@0
|
181 for(;*s && !IsSpace(*s); ++s);
|
nuclear@0
|
182 SkipSpaces(&s);
|
nuclear@0
|
183 }
|
nuclear@0
|
184 }
|
nuclear@0
|
185
|
nuclear@0
|
186 // -----------------------------------------
|
nuclear@0
|
187 /** member access */
|
nuclear@0
|
188 const std::string* operator -> () const {
|
nuclear@0
|
189 return &cur;
|
nuclear@0
|
190 }
|
nuclear@0
|
191
|
nuclear@0
|
192 std::string operator* () const {
|
nuclear@0
|
193 return cur;
|
nuclear@0
|
194 }
|
nuclear@0
|
195
|
nuclear@0
|
196 // -----------------------------------------
|
nuclear@0
|
197 /** boolean context */
|
nuclear@0
|
198 operator bool() const {
|
nuclear@0
|
199 return stream.GetRemainingSize()>0;
|
nuclear@0
|
200 }
|
nuclear@0
|
201
|
nuclear@0
|
202 // -----------------------------------------
|
nuclear@0
|
203 /** line indices are zero-based, empty lines are included */
|
nuclear@0
|
204 operator line_idx() const {
|
nuclear@0
|
205 return idx;
|
nuclear@0
|
206 }
|
nuclear@0
|
207
|
nuclear@0
|
208 line_idx get_index() const {
|
nuclear@0
|
209 return idx;
|
nuclear@0
|
210 }
|
nuclear@0
|
211
|
nuclear@0
|
212 // -----------------------------------------
|
nuclear@0
|
213 /** access the underlying stream object */
|
nuclear@0
|
214 StreamReaderLE& get_stream() {
|
nuclear@0
|
215 return stream;
|
nuclear@0
|
216 }
|
nuclear@0
|
217
|
nuclear@0
|
218 // -----------------------------------------
|
nuclear@0
|
219 /** !strcmp((*this)->substr(0,strlen(check)),check) */
|
nuclear@0
|
220 bool match_start(const char* check) {
|
nuclear@0
|
221 const size_t len = strlen(check);
|
nuclear@0
|
222
|
nuclear@0
|
223 return len <= cur.length() && std::equal(check,check+len,cur.begin());
|
nuclear@0
|
224 }
|
nuclear@0
|
225
|
nuclear@0
|
226
|
nuclear@0
|
227 // -----------------------------------------
|
nuclear@0
|
228 /** swallow the next call to ++, return the previous value. */
|
nuclear@0
|
229 void swallow_next_increment() {
|
nuclear@0
|
230 swallow = true;
|
nuclear@0
|
231 }
|
nuclear@0
|
232
|
nuclear@0
|
233 private:
|
nuclear@0
|
234
|
nuclear@0
|
235 line_idx idx;
|
nuclear@0
|
236 std::string cur;
|
nuclear@0
|
237 StreamReaderLE& stream;
|
nuclear@0
|
238 bool swallow, skip_empty_lines, trim;
|
nuclear@0
|
239 };
|
nuclear@0
|
240
|
nuclear@0
|
241 }
|
nuclear@0
|
242 #endif // INCLUDED_LINE_SPLITTER_H
|