summaryrefslogtreecommitdiff
path: root/indra/llcommon/llstreamtools.h
blob: 599484361bfcd674cf1adf1be97c4733ed6da679 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/**
 * @file llstreamtools.h
 * @brief some helper functions for parsing legacy simstate and asset files.
 *
 * $LicenseInfo:firstyear=2005&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#ifndef LL_STREAM_TOOLS_H
#define LL_STREAM_TOOLS_H

#include <deque>
#include <iostream>
#include <string>
#include <vector>

// unless specifed otherwise these all return input_stream.good()

// skips spaces and tabs
LL_COMMON_API bool skip_whitespace(std::istream& input_stream);

// skips whitespace and newlines
LL_COMMON_API bool skip_emptyspace(std::istream& input_stream);

// skips emptyspace and lines that start with a #
LL_COMMON_API bool skip_comments_and_emptyspace(std::istream& input_stream);

// skips to character after next newline
LL_COMMON_API bool skip_line(std::istream& input_stream);

// skips to beginning of next non-emptyspace
LL_COMMON_API bool skip_to_next_word(std::istream& input_stream);

// skips to character after the end of next keyword
// a 'keyword' is defined as the first word on a line
LL_COMMON_API bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream);

// skip_to_start_of_next_keyword() is disabled -- might tickle corruption bug
// in windows iostream
// skips to beginning of next keyword
// a 'keyword' is defined as the first word on a line
//bool skip_to_start_of_next_keyword(const char* keyword, std::istream& input_stream);

// characters are pulled out of input_stream and appended to output_string
// returns result of input_stream.good() after characters are pulled
LL_COMMON_API bool get_word(std::string& output_string, std::istream& input_stream);
LL_COMMON_API bool get_line(std::string& output_string, std::istream& input_stream);

// characters are pulled out of input_stream (up to a max of 'n')
// and appended to output_string
// returns result of input_stream.good() after characters are pulled
LL_COMMON_API bool get_word(std::string& output_string, std::istream& input_stream, int n);
LL_COMMON_API bool get_line(std::string& output_string, std::istream& input_stream, int n);

// unget_line() is disabled -- might tickle corruption 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);

// TODO -- move these string manipulator functions to a different file

// removes the last char in 'line' if it matches 'c'
// returns true if removed last char
LL_COMMON_API bool remove_last_char(char c, std::string& line);

// replaces escaped characters with the correct characters from left to right
// "\\" ---> '\\'
// "\n" ---> '\n'
LL_COMMON_API void unescape_string(std::string& line);

// replaces unescaped characters with expanded equivalents from left to right
// '\\' ---> "\\"
// '\n' ---> "\n"
LL_COMMON_API void escape_string(std::string& line);

// replaces each '\n' character with ' '
LL_COMMON_API void replace_newlines_with_whitespace(std::string& line);

// erases any double-quote characters in line
LL_COMMON_API void remove_double_quotes(std::string& line);

// 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
LL_COMMON_API void get_keyword_and_value(std::string& keyword,
                           std::string& value,
                           const std::string& line);

// continue to read from the stream until you really can't
// read anymore or until we hit the count.  Some istream
// implimentations have a max that they will read.
// Returns the number of bytes read.
LL_COMMON_API std::streamsize fullread(
    std::istream& istr,
    char* buf,
    std::streamsize requested);


LL_COMMON_API std::istream& operator>>(std::istream& str, const char *tocheck);

/**
 * cat_streambuf is a std::streambuf subclass that accepts a variadic number
 * of std::streambuf* (e.g. some_istream.rdbuf()) and virtually concatenates
 * their contents.
 */
// derived from https://stackoverflow.com/a/49441066/5533635
class cat_streambuf: public std::streambuf
{
private:
    std::deque<std::streambuf*> mInputs;
    std::vector<char> mBuffer;

public:
    // only valid for std::streambuf* arguments
    template <typename... Inputs>
    cat_streambuf(Inputs... inputs):
        mInputs{inputs...},
        mBuffer(1024)
    {}

    int underflow() override;
};

#endif