aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon/llstreamtools.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/llcommon/llstreamtools.cpp570
1 files changed, 570 insertions, 0 deletions
diff --git a/linden/indra/llcommon/llstreamtools.cpp b/linden/indra/llcommon/llstreamtools.cpp
new file mode 100644
index 0000000..b68edd3
--- /dev/null
+++ b/linden/indra/llcommon/llstreamtools.cpp
@@ -0,0 +1,570 @@
1/**
2 * @file llstreamtools.cpp
3 * @brief some helper functions for parsing legacy simstate and asset files.
4 *
5 * Copyright (c) 2005-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include <iostream>
29#include <string>
30
31#include "llstreamtools.h"
32
33
34// ----------------------------------------------------------------------------
35// some std::istream helper functions
36// ----------------------------------------------------------------------------
37
38// skips spaces and tabs
39bool skip_whitespace(std::istream& input_stream)
40{
41 char c = input_stream.peek();
42 while (('\t' == c || ' ' == c) && input_stream.good())
43 {
44 input_stream.get();
45 c = input_stream.peek();
46 }
47 return input_stream.good();
48}
49
50// skips whitespace, newlines, and carriage returns
51bool skip_emptyspace(std::istream& input_stream)
52{
53 char c = input_stream.peek();
54 while ( input_stream.good()
55 && ('\t' == c || ' ' == c || '\n' == c || '\r' == c) )
56 {
57 input_stream.get();
58 c = input_stream.peek();
59 }
60 return input_stream.good();
61}
62
63// skips emptyspace and lines that start with a #
64bool skip_comments_and_emptyspace(std::istream& input_stream)
65{
66 while (skip_emptyspace(input_stream))
67 {
68 char c = input_stream.peek();
69 if ('#' == c )
70 {
71 while ('\n' != c && input_stream.good())
72 {
73 c = input_stream.get();
74 }
75 }
76 else
77 {
78 break;
79 }
80 }
81 return input_stream.good();
82}
83
84bool skip_line(std::istream& input_stream)
85{
86 char c;
87 do
88 {
89 c = input_stream.get();
90 } while ('\n' != c && input_stream.good());
91 return input_stream.good();
92}
93
94bool skip_to_next_word(std::istream& input_stream)
95{
96 char c = input_stream.peek();
97 while ( input_stream.good()
98 && ( (c >= 'a' && c <= 'z')
99 || (c >= 'A' && c <= 'Z')
100 || (c >= '0' && c <= '9')
101 || '_' == c ) )
102 {
103 input_stream.get();
104 c = input_stream.peek();
105 }
106 while ( input_stream.good()
107 && !( (c >= 'a' && c <= 'z')
108 || (c >= 'A' && c <= 'Z')
109 || (c >= '0' && c <= '9')
110 || '_' == c ) )
111 {
112 input_stream.get();
113 c = input_stream.peek();
114 }
115 return input_stream.good();
116}
117
118bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream)
119{
120 int key_length = strlen(keyword); /*Flawfinder: ignore*/
121 if (0 == key_length)
122 {
123 return false;
124 }
125 while (input_stream.good())
126 {
127 skip_emptyspace(input_stream);
128 char c = input_stream.get();
129 if (keyword[0] != c)
130 {
131 skip_line(input_stream);
132 }
133 else
134 {
135 int key_index = 1;
136 while ( key_index < key_length
137 && keyword[key_index - 1] == c
138 && input_stream.good())
139 {
140 key_index++;
141 c = input_stream.get();
142 }
143
144 if (key_index == key_length
145 && keyword[key_index-1] == c)
146 {
147 c = input_stream.peek();
148 if (' ' == c || '\t' == c || '\r' == c || '\n' == c)
149 {
150 return true;
151 }
152 else
153 {
154 skip_line(input_stream);
155 }
156 }
157 else
158 {
159 skip_line(input_stream);
160 }
161 }
162 }
163 return false;
164}
165
166/* skip_to_start_of_next_keyword() is disabled -- might tickle corruption bug in windows iostream
167bool skip_to_start_of_next_keyword(const char* keyword, std::istream& input_stream)
168{
169 int key_length = strlen(keyword);
170 if (0 == key_length)
171 {
172 return false;
173 }
174 while (input_stream.good())
175 {
176 skip_emptyspace(input_stream);
177 char c = input_stream.get();
178 if (keyword[0] != c)
179 {
180 skip_line(input_stream);
181 }
182 else
183 {
184 int key_index = 1;
185 while ( key_index < key_length
186 && keyword[key_index - 1] == c
187 && input_stream.good())
188 {
189 key_index++;
190 c = input_stream.get();
191 }
192
193 if (key_index == key_length
194 && keyword[key_index-1] == c)
195 {
196 c = input_stream.peek();
197 if (' ' == c || '\t' == c || '\r' == c || '\n' == c)
198 {
199 // put the keyword back onto the stream
200 for (int index = key_length - 1; index >= 0; index--)
201 {
202 input_stream.putback(keyword[index]);
203 }
204 return true;
205 }
206 else
207 {
208 skip_line(input_stream);
209 break;
210 }
211 }
212 else
213 {
214 skip_line(input_stream);
215 }
216 }
217 }
218 return false;
219}
220*/
221
222bool get_word(std::string& output_string, std::istream& input_stream)
223{
224 skip_emptyspace(input_stream);
225 char c = input_stream.peek();
226 while ( !isspace(c)
227 && '\n' != c
228 && '\r' != c
229 && input_stream.good() )
230 {
231 output_string += c;
232 input_stream.get();
233 c = input_stream.peek();
234 }
235 return input_stream.good();
236}
237
238bool get_word(std::string& output_string, std::istream& input_stream, int n)
239{
240 skip_emptyspace(input_stream);
241 int char_count = 0;
242 char c = input_stream.peek();
243 while (!isspace(c)
244 && '\n' != c
245 && '\r' != c
246 && input_stream.good()
247 && char_count < n)
248 {
249 char_count++;
250 output_string += c;
251 input_stream.get();
252 c = input_stream.peek();
253 }
254 return input_stream.good();
255}
256
257// get everything up to and including the next newline
258bool get_line(std::string& output_string, std::istream& input_stream)
259{
260 char c = input_stream.get();
261 while (input_stream.good())
262 {
263 if ('\r' == c)
264 {
265 // skip carriage returns
266 }
267 else
268 {
269 output_string += c;
270 if ('\n' == c)
271 {
272 break;
273 }
274 }
275 c = input_stream.get();
276 }
277 return input_stream.good();
278}
279
280// get everything up to and including the next newline
281// up to the next n characters.
282// add a newline on the end if bail before actual line ending
283bool get_line(std::string& output_string, std::istream& input_stream, int n)
284{
285 int char_count = 0;
286 char c = input_stream.get();
287 while (input_stream.good() && char_count < n)
288 {
289 char_count++;
290 output_string += c;
291 if ('\r' == c)
292 {
293 // skip carriage returns
294 }
295 else
296 {
297 if ('\n' == c)
298 {
299 break;
300 }
301 if (char_count >= n)
302 {
303 output_string.append("\n");
304 break;
305 }
306 }
307 c = input_stream.get();
308 }
309 return input_stream.good();
310}
311
312/* disabled -- might tickle bug in windows iostream
313// backs up the input_stream by line_size + 1 characters
314bool unget_line(const std::string& line, std::istream& input_stream)
315{
316 input_stream.putback('\n'); // unget the newline
317 for (int line_index = line.size()-1; line_index >= 0; line_index--)
318 {
319 input_stream.putback(line[line_index]);
320 }
321 return input_stream.good();
322}
323*/
324
325// removes the last char in 'line' if it matches 'c'
326// returns true if removed last char
327bool remove_last_char(char c, std::string& line)
328{
329 int line_size = line.size();
330 if (line_size > 1
331 && c == line[line_size - 1])
332 {
333 line.replace(line_size - 1, 1, "");
334 return true;
335 }
336 return false;
337}
338
339// replaces escaped characters with the correct characters from left to right
340// "\\\\" ---> '\\' (two backslahes become one)
341// "\\n" ---> '\n' (backslash n becomes carriage return)
342void unescape_string(std::string& line)
343{
344 int line_size = line.size();
345 int index = 0;
346 while (index < line_size - 1)
347 {
348 if ('\\' == line[index])
349 {
350 if ('\\' == line[index + 1])
351 {
352 line.replace(index, 2, "\\");
353 line_size--;
354 }
355 else if ('n' == line[index + 1])
356 {
357 line.replace(index, 2, "\n");
358 line_size--;
359 }
360 }
361 index++;
362 }
363}
364
365// replaces unescaped characters with expanded equivalents from left to right
366// '\\' ---> "\\\\" (one backslash becomes two)
367// '\n' ---> "\\n" (carriage return becomes backslash n)
368void escape_string(std::string& line)
369{
370 int line_size = line.size();
371 int index = 0;
372 while (index < line_size)
373 {
374 if ('\\' == line[index])
375 {
376 line.replace(index, 1, "\\\\");
377 line_size++;
378 index++;
379 }
380 else if ('\n' == line[index])
381 {
382 line.replace(index, 1, "\\n");
383 line_size++;
384 index++;
385 }
386 index++;
387 }
388}
389
390// removes '\n' characters
391void replace_newlines_with_whitespace(std::string& line)
392{
393 int line_size = line.size();
394 int index = 0;
395 while (index < line_size)
396 {
397 if ('\n' == line[index])
398 {
399 line.replace(index, 1, " ");
400 }
401 index++;
402 }
403}
404
405// returns 1 for solitary "{"
406// returns -1 for solitary "}"
407// otherwise returns 0
408int get_brace_count(const std::string& line)
409{
410 int index = 0;
411 int line_size = line.size();
412 char c = 0;
413 while (index < line_size)
414 {
415 c = line[index];
416 index++;
417 if (!isspace(c))
418 {
419 break;
420 }
421 }
422 char brace = c;
423 // make sure the rest of the line is whitespace
424 while (index < line_size)
425 {
426 c = line[index];
427 if (!isspace(c))
428 {
429 break;
430 }
431 index++;
432 }
433 if ('\n' != c)
434 {
435 return 0;
436 }
437 if ('{' == brace)
438 {
439 return 1;
440 }
441 else if ('}' == brace)
442 {
443 return -1;
444 }
445 return 0;
446}
447
448// erases any double-quote characters in 'line'
449void remove_double_quotes(std::string& line)
450{
451 int index = 0;
452 int line_size = line.size();
453 while (index < line_size)
454 {
455 if ('"' == line[index])
456 {
457 int count = 1;
458 while (index + count < line_size
459 && '"' == line[index + count])
460 {
461 count++;
462 }
463 line.replace(index, count, "");
464 line_size -= count;
465 }
466 else
467 {
468 index++;
469 }
470 }
471}
472
473// the 'keyword' is defined as the first word on a line
474// the 'value' is everything after the keyword on the same line
475// starting at the first non-whitespace and ending right before the newline
476void get_keyword_and_value(std::string& keyword,
477 std::string& value,
478 const std::string& line)
479{
480 // skip initial whitespace
481 int line_size = line.size();
482 int line_index = 0;
483 char c;
484 while (line_index < line_size)
485 {
486 c = line[line_index];
487 if (!isspace(c))
488 {
489 break;
490 }
491 line_index++;
492 }
493
494 // get the keyword
495 keyword.assign("");
496 while (line_index < line_size)
497 {
498 c = line[line_index];
499 if (isspace(c) || '\r' == c || '\n' == c)
500 {
501 break;
502 }
503 keyword += c;
504 line_index++;
505 }
506
507 if (keyword.size() > 0
508 && '\r' != line[line_index]
509 && '\n' != line[line_index])
510
511 {
512 // discard initial white spaces
513 while (line_index < line_size
514 && (' ' == line[line_index]
515 || '\t' == line[line_index]) )
516 {
517 line_index++;
518 }
519
520 // get the value
521 value.assign("");
522 while (line_index < line_size)
523 {
524 c = line[line_index];
525 if ('\r' == c || '\n' == c)
526 {
527 break;
528 }
529 value += c;
530 line_index++;
531 }
532 }
533}
534
535std::istream& fullread(std::istream& str, char *buf, std::streamsize requested)
536{
537 std::streamsize got;
538 std::streamsize total = 0;
539
540 str.read(buf, requested); /*Flawfinder: ignore*/
541 got = str.gcount();
542 total += got;
543 while (got && total < requested)
544 {
545 if (str.fail())
546 str.clear();
547 str.read(buf + total, requested - total); /*Flawfinder: ignore*/
548 got = str.gcount();
549 total += got;
550 }
551 return str;
552}
553
554std::istream& operator>>(std::istream& str, const char *tocheck)
555{
556 char c;
557 const char *p;
558 p = tocheck;
559 while (*p && !str.bad())
560 {
561 str.get(c);
562 if (c != *p)
563 {
564 str.setstate(std::ios::failbit); /*Flawfinder: ignore*/
565 break;
566 }
567 p++;
568 }
569 return str;
570}