PageRenderTime 52ms CodeModel.GetById 22ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/llcommon/llstreamtools.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 525 lines | 397 code | 20 blank | 108 comment | 96 complexity | d099df39103d2f8fac46d278dfd0fd34 MD5 | raw file
  1/** 
  2 * @file llstreamtools.cpp
  3 * @brief some helper functions for parsing legacy simstate and asset files.
  4 *
  5 * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "linden_common.h"
 28
 29#include <iostream>
 30#include <string>
 31
 32#include "llstreamtools.h"
 33
 34
 35// ----------------------------------------------------------------------------
 36// some std::istream helper functions
 37// ----------------------------------------------------------------------------
 38
 39// skips spaces and tabs
 40bool skip_whitespace(std::istream& input_stream)
 41{
 42	int c = input_stream.peek();
 43	while (('\t' == c || ' ' == c) && input_stream.good())
 44	{
 45		input_stream.get();
 46		c = input_stream.peek();
 47	}
 48	return input_stream.good();
 49}
 50
 51// skips whitespace, newlines, and carriage returns
 52bool skip_emptyspace(std::istream& input_stream)
 53{
 54	int c = input_stream.peek();
 55	while ( input_stream.good()
 56			&& ('\t' == c || ' ' == c || '\n' == c || '\r' == c) )
 57	{
 58		input_stream.get();
 59		c = input_stream.peek();
 60	}
 61	return input_stream.good();
 62}
 63
 64// skips emptyspace and lines that start with a #
 65bool skip_comments_and_emptyspace(std::istream& input_stream)
 66{
 67	while (skip_emptyspace(input_stream))
 68	{
 69		int c = input_stream.peek();
 70		if ('#' == c )
 71		{
 72			while ('\n' != c && input_stream.good())
 73			{
 74				c = input_stream.get();
 75			}
 76		}
 77		else
 78		{
 79			break;
 80		}
 81	}
 82	return input_stream.good();
 83}
 84
 85bool skip_line(std::istream& input_stream)
 86{
 87	int c;
 88	do
 89	{
 90		c = input_stream.get();
 91	} while ('\n' != c  &&  input_stream.good());
 92	return input_stream.good();
 93}
 94
 95bool skip_to_next_word(std::istream& input_stream)
 96{
 97	int c = input_stream.peek();
 98	while ( input_stream.good()
 99			&& (   (c >= 'a' && c <= 'z')
100		   		|| (c >= 'A' && c <= 'Z')
101				|| (c >= '0' && c <= '9')
102				|| '_' == c ) )
103	{
104		input_stream.get();
105		c = input_stream.peek();
106	}
107	while ( input_stream.good()
108			&& !(   (c >= 'a' && c <= 'z')
109		   		 || (c >= 'A' && c <= 'Z')
110				 || (c >= '0' && c <= '9')
111				 || '_' == c ) )
112	{
113		input_stream.get();
114		c = input_stream.peek();
115	}
116	return input_stream.good();
117}
118
119bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream)
120{
121	int key_length = strlen(keyword);	 /*Flawfinder: ignore*/
122	if (0 == key_length)
123	{
124		return false;
125	}
126	while (input_stream.good())
127	{
128		skip_emptyspace(input_stream);
129		int c = input_stream.get();
130		if (keyword[0] != c)
131		{
132			skip_line(input_stream);
133		}
134		else
135		{
136			int key_index = 1;
137			while ( key_index < key_length
138					&&	keyword[key_index - 1] == c 
139			   		&& input_stream.good())
140			{
141				key_index++;
142				c = input_stream.get();
143			} 
144
145			if (key_index == key_length
146				&& keyword[key_index-1] == c)
147			{
148				c = input_stream.peek();
149				if (' ' == c || '\t' == c || '\r' == c || '\n' == c)
150				{ 
151					return true;
152				}
153				else
154				{
155					skip_line(input_stream);
156				}
157			}
158			else
159			{
160				skip_line(input_stream);
161			}
162		}
163	}
164	return false;
165}
166
167/* skip_to_start_of_next_keyword() is disabled -- might tickle corruption bug in windows iostream
168bool skip_to_start_of_next_keyword(const char* keyword, std::istream& input_stream)
169{
170	int key_length = strlen(keyword);
171	if (0 == key_length)
172	{
173		return false;
174	}
175	while (input_stream.good())
176	{
177		skip_emptyspace(input_stream);
178		int c = input_stream.get();
179		if (keyword[0] != c)
180		{
181			skip_line(input_stream);
182		}
183		else
184		{
185			int key_index = 1;
186			while ( key_index < key_length
187					&&	keyword[key_index - 1] == c 
188			   		&& input_stream.good())
189			{
190				key_index++;
191				c = input_stream.get();
192			} 
193
194			if (key_index == key_length
195				&& keyword[key_index-1] == c)
196			{
197				c = input_stream.peek();
198				if (' ' == c || '\t' == c || '\r' == c || '\n' == c)
199				{ 
200					// put the keyword back onto the stream
201					for (int index = key_length - 1; index >= 0; index--)
202					{
203						input_stream.putback(keyword[index]);
204					}
205					return true;
206				}
207				else
208				{
209					skip_line(input_stream);
210					break;
211				}
212			}
213			else
214			{
215				skip_line(input_stream);
216			}
217		}
218	}
219	return false;
220}
221*/
222
223bool get_word(std::string& output_string, std::istream& input_stream)
224{
225	skip_emptyspace(input_stream);
226	int c = input_stream.peek();
227	while ( !isspace(c) 
228			&& '\n' != c 
229			&& '\r' != c 
230			&& input_stream.good() )
231	{
232		output_string += c;
233		input_stream.get();
234		c = input_stream.peek();
235	}
236	return input_stream.good();
237}
238
239bool get_word(std::string& output_string, std::istream& input_stream, int n)
240{
241	skip_emptyspace(input_stream);
242	int char_count = 0;
243	int c = input_stream.peek();
244	while (!isspace(c) 
245			&& '\n' != c 
246			&& '\r' != c 
247			&& input_stream.good() 
248			&& char_count < n)
249	{
250		char_count++;
251		output_string += c;
252		input_stream.get();
253		c = input_stream.peek();
254	}
255	return input_stream.good();
256}
257
258// get everything up to and including the next newline
259bool get_line(std::string& output_string, std::istream& input_stream)
260{
261	output_string.clear();
262	int c = input_stream.get();
263	while (input_stream.good())
264	{
265		output_string += c;
266		if ('\n' == c)
267		{
268			break;
269		}
270		c = input_stream.get();
271	} 
272	return input_stream.good();
273}
274
275// get everything up to and including the next newline
276// up to the next n characters.  
277// add a newline on the end if bail before actual line ending
278bool get_line(std::string& output_string, std::istream& input_stream, int n)
279{
280	output_string.clear();
281	int char_count = 0;
282	int c = input_stream.get();
283	while (input_stream.good() && char_count < n)
284	{
285		char_count++;
286		output_string += c;
287		if ('\n' == c)
288		{
289			break;
290		}
291		if (char_count >= n)
292		{
293			output_string.append("\n");
294			break;
295		}
296		c = input_stream.get();
297	} 
298	return input_stream.good();
299}
300
301/* disabled -- might tickle bug in windows iostream
302// backs up the input_stream by line_size + 1 characters
303bool unget_line(const std::string& line, std::istream& input_stream)
304{
305	input_stream.putback('\n');	// unget the newline
306	for (int line_index = line.size()-1; line_index >= 0; line_index--)
307	{ 
308		input_stream.putback(line[line_index]);
309	}
310	return input_stream.good();
311}
312*/
313
314// removes the last char in 'line' if it matches 'c'
315// returns true if removed last char
316bool remove_last_char(char c, std::string& line)
317{
318	int line_size = line.size();
319	if (line_size > 1
320		&& c == line[line_size - 1])
321	{
322		line.replace(line_size - 1, 1, "");
323		return true;
324	}
325	return false;
326}
327
328// replaces escaped characters with the correct characters from left to right
329// "\\\\" ---> '\\' (two backslahes become one)
330// "\\n" ---> '\n' (backslash n becomes carriage return)
331void unescape_string(std::string& line)
332{
333	int line_size = line.size();
334	int index = 0;
335	while (index < line_size - 1)
336	{
337		if ('\\' == line[index])
338		{
339			if ('\\' == line[index + 1])
340			{
341				line.replace(index, 2, "\\");
342				line_size--;
343			}
344			else if ('n' == line[index + 1])
345			{
346				line.replace(index, 2, "\n");
347				line_size--;
348			}
349		}
350		index++;
351	}
352}
353
354// replaces unescaped characters with expanded equivalents from left to right
355// '\\' ---> "\\\\" (one backslash becomes two)
356// '\n' ---> "\\n"  (carriage return becomes backslash n)
357void escape_string(std::string& line)
358{
359	int line_size = line.size();
360	int index = 0;
361	while (index < line_size)
362	{
363		if ('\\' == line[index])
364		{
365			line.replace(index, 1, "\\\\");
366			line_size++;
367			index++;
368		}
369		else if ('\n' == line[index])
370		{
371			line.replace(index, 1, "\\n"); 
372			line_size++;
373			index++;
374		}
375		index++;
376	}
377}
378
379// removes '\n' characters
380void replace_newlines_with_whitespace(std::string& line)
381{
382	int line_size = line.size();
383	int index = 0;
384	while (index < line_size)
385	{
386		if ('\n' == line[index])
387		{
388			line.replace(index, 1, " ");
389		}
390		index++;
391	}
392}
393
394// erases any double-quote characters in 'line'
395void remove_double_quotes(std::string& line)
396{
397	int index = 0;
398	int line_size = line.size();
399	while (index < line_size)
400	{
401		if ('"' == line[index])
402		{
403			int count = 1;
404			while (index + count < line_size
405				   && '"' == line[index + count])
406			{
407				count++;
408			}
409			line.replace(index, count, "");
410			line_size -= count;
411		}
412		else
413		{
414			index++;
415		}
416	}
417}
418
419// the 'keyword' is defined as the first word on a line
420// the 'value' is everything after the keyword on the same line
421// starting at the first non-whitespace and ending right before the newline
422void get_keyword_and_value(std::string& keyword, 
423						   std::string& value, 
424						   const std::string& line)
425{
426	// skip initial whitespace
427	int line_size = line.size();
428	int line_index = 0;
429	char c;
430	while (line_index < line_size)
431	{
432		c = line[line_index];
433		if (!LLStringOps::isSpace(c))
434		{
435			break;
436		}
437		line_index++;
438	}
439
440	// get the keyword
441	keyword.clear();
442	while (line_index < line_size)
443	{
444		c = line[line_index];
445		if (LLStringOps::isSpace(c) || '\r' == c || '\n' == c)
446		{
447			break;
448		}
449		keyword += c;
450		line_index++;
451	}
452
453	// get the value
454	value.clear();
455	if (keyword.size() > 0
456		&& '\r' != line[line_index]
457		&& '\n' != line[line_index])
458
459	{
460		// discard initial white spaces
461		while (line_index < line_size
462				&& (' ' == line[line_index] 
463					|| '\t' == line[line_index]) )
464		{
465			line_index++;
466		}
467
468		while (line_index < line_size)
469		{
470			c = line[line_index];
471			if ('\r' == c || '\n' == c)
472			{
473				break;
474			}
475			value += c;
476			line_index++;
477		}
478	}
479}
480
481std::streamsize fullread(
482	std::istream& istr,
483	char* buf,
484	std::streamsize requested)
485{
486	std::streamsize got;
487	std::streamsize total = 0;
488
489	istr.read(buf, requested);	 /*Flawfinder: ignore*/
490	got = istr.gcount();
491	total += got;
492	while(got && total < requested)
493	{
494		if(istr.fail())
495		{
496			// If bad is true, not much we can doo -- it implies loss
497			// of stream integrity. Bail in that case, and otherwise
498			// clear and attempt to continue.
499			if(istr.bad()) return total;
500			istr.clear();
501		}
502		istr.read(buf + total, requested - total);	 /*Flawfinder: ignore*/
503		got = istr.gcount();
504		total += got;
505	}
506	return total;
507}
508
509std::istream& operator>>(std::istream& str, const char *tocheck)
510{
511	char c = '\0';
512	const char *p;
513	p = tocheck;
514	while (*p && !str.bad())
515	{
516		str.get(c);
517		if (c != *p)
518		{
519			str.setstate(std::ios::failbit);		/*Flawfinder: ignore*/
520			break;
521		}
522		p++;
523	}
524	return str;
525}