From 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 Mon Sep 17 00:00:00 2001 From: Jacek Antonelli Date: Fri, 15 Aug 2008 23:44:46 -0500 Subject: Second Life viewer sources 1.13.2.12 --- linden/indra/llcommon/llstreamtools.cpp | 570 ++++++++++++++++++++++++++++++++ 1 file changed, 570 insertions(+) create mode 100644 linden/indra/llcommon/llstreamtools.cpp (limited to 'linden/indra/llcommon/llstreamtools.cpp') 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 @@ +/** + * @file llstreamtools.cpp + * @brief some helper functions for parsing legacy simstate and asset files. + * + * Copyright (c) 2005-2007, Linden Research, Inc. + * + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#include +#include + +#include "llstreamtools.h" + + +// ---------------------------------------------------------------------------- +// some std::istream helper functions +// ---------------------------------------------------------------------------- + +// skips spaces and tabs +bool skip_whitespace(std::istream& input_stream) +{ + char c = input_stream.peek(); + while (('\t' == c || ' ' == c) && input_stream.good()) + { + input_stream.get(); + c = input_stream.peek(); + } + return input_stream.good(); +} + +// skips whitespace, newlines, and carriage returns +bool skip_emptyspace(std::istream& input_stream) +{ + char c = input_stream.peek(); + while ( input_stream.good() + && ('\t' == c || ' ' == c || '\n' == c || '\r' == c) ) + { + input_stream.get(); + c = input_stream.peek(); + } + return input_stream.good(); +} + +// skips emptyspace and lines that start with a # +bool skip_comments_and_emptyspace(std::istream& input_stream) +{ + while (skip_emptyspace(input_stream)) + { + char c = input_stream.peek(); + if ('#' == c ) + { + while ('\n' != c && input_stream.good()) + { + c = input_stream.get(); + } + } + else + { + break; + } + } + return input_stream.good(); +} + +bool skip_line(std::istream& input_stream) +{ + char c; + do + { + c = input_stream.get(); + } while ('\n' != c && input_stream.good()); + return input_stream.good(); +} + +bool skip_to_next_word(std::istream& input_stream) +{ + char c = input_stream.peek(); + while ( input_stream.good() + && ( (c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || (c >= '0' && c <= '9') + || '_' == c ) ) + { + input_stream.get(); + c = input_stream.peek(); + } + while ( input_stream.good() + && !( (c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || (c >= '0' && c <= '9') + || '_' == c ) ) + { + input_stream.get(); + c = input_stream.peek(); + } + return input_stream.good(); +} + +bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream) +{ + int key_length = strlen(keyword); /*Flawfinder: ignore*/ + if (0 == key_length) + { + return false; + } + while (input_stream.good()) + { + skip_emptyspace(input_stream); + char c = input_stream.get(); + if (keyword[0] != c) + { + skip_line(input_stream); + } + else + { + int key_index = 1; + while ( key_index < key_length + && keyword[key_index - 1] == c + && input_stream.good()) + { + key_index++; + c = input_stream.get(); + } + + if (key_index == key_length + && keyword[key_index-1] == c) + { + c = input_stream.peek(); + if (' ' == c || '\t' == c || '\r' == c || '\n' == c) + { + return true; + } + else + { + skip_line(input_stream); + } + } + else + { + skip_line(input_stream); + } + } + } + return false; +} + +/* skip_to_start_of_next_keyword() is disabled -- might tickle corruption bug in windows iostream +bool skip_to_start_of_next_keyword(const char* keyword, std::istream& input_stream) +{ + int key_length = strlen(keyword); + if (0 == key_length) + { + return false; + } + while (input_stream.good()) + { + skip_emptyspace(input_stream); + char c = input_stream.get(); + if (keyword[0] != c) + { + skip_line(input_stream); + } + else + { + int key_index = 1; + while ( key_index < key_length + && keyword[key_index - 1] == c + && input_stream.good()) + { + key_index++; + c = input_stream.get(); + } + + if (key_index == key_length + && keyword[key_index-1] == c) + { + c = input_stream.peek(); + if (' ' == c || '\t' == c || '\r' == c || '\n' == c) + { + // put the keyword back onto the stream + for (int index = key_length - 1; index >= 0; index--) + { + input_stream.putback(keyword[index]); + } + return true; + } + else + { + skip_line(input_stream); + break; + } + } + else + { + skip_line(input_stream); + } + } + } + return false; +} +*/ + +bool get_word(std::string& output_string, std::istream& input_stream) +{ + skip_emptyspace(input_stream); + char c = input_stream.peek(); + while ( !isspace(c) + && '\n' != c + && '\r' != c + && input_stream.good() ) + { + output_string += c; + input_stream.get(); + c = input_stream.peek(); + } + return input_stream.good(); +} + +bool get_word(std::string& output_string, std::istream& input_stream, int n) +{ + skip_emptyspace(input_stream); + int char_count = 0; + char c = input_stream.peek(); + while (!isspace(c) + && '\n' != c + && '\r' != c + && input_stream.good() + && char_count < n) + { + char_count++; + output_string += c; + input_stream.get(); + c = input_stream.peek(); + } + return input_stream.good(); +} + +// get everything up to and including the next newline +bool get_line(std::string& output_string, std::istream& input_stream) +{ + char c = input_stream.get(); + while (input_stream.good()) + { + if ('\r' == c) + { + // skip carriage returns + } + else + { + output_string += c; + if ('\n' == c) + { + break; + } + } + c = input_stream.get(); + } + return input_stream.good(); +} + +// get everything up to and including the next newline +// up to the next n characters. +// add a newline on the end if bail before actual line ending +bool get_line(std::string& output_string, std::istream& input_stream, int n) +{ + int char_count = 0; + char c = input_stream.get(); + while (input_stream.good() && char_count < n) + { + char_count++; + output_string += c; + if ('\r' == c) + { + // skip carriage returns + } + else + { + if ('\n' == c) + { + break; + } + if (char_count >= n) + { + output_string.append("\n"); + break; + } + } + c = input_stream.get(); + } + return input_stream.good(); +} + +/* disabled -- might tickle bug in windows iostream +// backs up the input_stream by line_size + 1 characters +bool unget_line(const std::string& line, std::istream& input_stream) +{ + input_stream.putback('\n'); // unget the newline + for (int line_index = line.size()-1; line_index >= 0; line_index--) + { + input_stream.putback(line[line_index]); + } + return input_stream.good(); +} +*/ + +// removes the last char in 'line' if it matches 'c' +// returns true if removed last char +bool remove_last_char(char c, std::string& line) +{ + int line_size = line.size(); + if (line_size > 1 + && c == line[line_size - 1]) + { + line.replace(line_size - 1, 1, ""); + return true; + } + return false; +} + +// replaces escaped characters with the correct characters from left to right +// "\\\\" ---> '\\' (two backslahes become one) +// "\\n" ---> '\n' (backslash n becomes carriage return) +void unescape_string(std::string& line) +{ + int line_size = line.size(); + int index = 0; + while (index < line_size - 1) + { + if ('\\' == line[index]) + { + if ('\\' == line[index + 1]) + { + line.replace(index, 2, "\\"); + line_size--; + } + else if ('n' == line[index + 1]) + { + line.replace(index, 2, "\n"); + line_size--; + } + } + index++; + } +} + +// replaces unescaped characters with expanded equivalents from left to right +// '\\' ---> "\\\\" (one backslash becomes two) +// '\n' ---> "\\n" (carriage return becomes backslash n) +void escape_string(std::string& line) +{ + int line_size = line.size(); + int index = 0; + while (index < line_size) + { + if ('\\' == line[index]) + { + line.replace(index, 1, "\\\\"); + line_size++; + index++; + } + else if ('\n' == line[index]) + { + line.replace(index, 1, "\\n"); + line_size++; + index++; + } + index++; + } +} + +// removes '\n' characters +void replace_newlines_with_whitespace(std::string& line) +{ + int line_size = line.size(); + int index = 0; + while (index < line_size) + { + if ('\n' == line[index]) + { + line.replace(index, 1, " "); + } + index++; + } +} + +// returns 1 for solitary "{" +// returns -1 for solitary "}" +// otherwise returns 0 +int get_brace_count(const std::string& line) +{ + int index = 0; + int line_size = line.size(); + char c = 0; + while (index < line_size) + { + c = line[index]; + index++; + if (!isspace(c)) + { + break; + } + } + char brace = c; + // make sure the rest of the line is whitespace + while (index < line_size) + { + c = line[index]; + if (!isspace(c)) + { + break; + } + index++; + } + if ('\n' != c) + { + return 0; + } + if ('{' == brace) + { + return 1; + } + else if ('}' == brace) + { + return -1; + } + return 0; +} + +// erases any double-quote characters in 'line' +void remove_double_quotes(std::string& line) +{ + int index = 0; + int line_size = line.size(); + while (index < line_size) + { + if ('"' == line[index]) + { + int count = 1; + while (index + count < line_size + && '"' == line[index + count]) + { + count++; + } + line.replace(index, count, ""); + line_size -= count; + } + else + { + index++; + } + } +} + +// the 'keyword' is defined as the first word on a line +// the 'value' is everything after the keyword on the same line +// starting at the first non-whitespace and ending right before the newline +void get_keyword_and_value(std::string& keyword, + std::string& value, + const std::string& line) +{ + // skip initial whitespace + int line_size = line.size(); + int line_index = 0; + char c; + while (line_index < line_size) + { + c = line[line_index]; + if (!isspace(c)) + { + break; + } + line_index++; + } + + // get the keyword + keyword.assign(""); + while (line_index < line_size) + { + c = line[line_index]; + if (isspace(c) || '\r' == c || '\n' == c) + { + break; + } + keyword += c; + line_index++; + } + + if (keyword.size() > 0 + && '\r' != line[line_index] + && '\n' != line[line_index]) + + { + // discard initial white spaces + while (line_index < line_size + && (' ' == line[line_index] + || '\t' == line[line_index]) ) + { + line_index++; + } + + // get the value + value.assign(""); + while (line_index < line_size) + { + c = line[line_index]; + if ('\r' == c || '\n' == c) + { + break; + } + value += c; + line_index++; + } + } +} + +std::istream& fullread(std::istream& str, char *buf, std::streamsize requested) +{ + std::streamsize got; + std::streamsize total = 0; + + str.read(buf, requested); /*Flawfinder: ignore*/ + got = str.gcount(); + total += got; + while (got && total < requested) + { + if (str.fail()) + str.clear(); + str.read(buf + total, requested - total); /*Flawfinder: ignore*/ + got = str.gcount(); + total += got; + } + return str; +} + +std::istream& operator>>(std::istream& str, const char *tocheck) +{ + char c; + const char *p; + p = tocheck; + while (*p && !str.bad()) + { + str.get(c); + if (c != *p) + { + str.setstate(std::ios::failbit); /*Flawfinder: ignore*/ + break; + } + p++; + } + return str; +} -- cgit v1.1