llstreamtools.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /**
  2. * @file llstreamtools.cpp
  3. * @brief some helper functions for parsing legacy simstate and asset files.
  4. *
  5. * $LicenseInfo:firstyear=2005&license=viewergpl$
  6. *
  7. * Copyright (c) 2005-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "linden_common.h"
  33. #include "llstreamtools.h"
  34. // Skips whitespace, newlines, and carriage returns
  35. static bool skip_emptyspace(std::istream& input_stream)
  36. {
  37. int c = input_stream.peek();
  38. while (input_stream.good() &&
  39. ('\t' == c || ' ' == c || '\n' == c || '\r' == c))
  40. {
  41. input_stream.get();
  42. c = input_stream.peek();
  43. }
  44. return input_stream.good();
  45. }
  46. // Skips emptyspace and lines that start with a #
  47. bool skip_comments_and_emptyspace(std::istream& input_stream)
  48. {
  49. while (skip_emptyspace(input_stream))
  50. {
  51. int c = input_stream.peek();
  52. if ('#' == c )
  53. {
  54. while ('\n' != c && input_stream.good())
  55. {
  56. c = input_stream.get();
  57. }
  58. }
  59. else
  60. {
  61. break;
  62. }
  63. }
  64. return input_stream.good();
  65. }
  66. static bool skip_line(std::istream& input_stream)
  67. {
  68. int c;
  69. do
  70. {
  71. c = input_stream.get();
  72. }
  73. while ('\n' != c && input_stream.good());
  74. return input_stream.good();
  75. }
  76. bool skip_to_end_of_next_keyword(const char* keyword,
  77. std::istream& input_stream)
  78. {
  79. size_t key_length = strlen(keyword);
  80. if (!key_length)
  81. {
  82. return false;
  83. }
  84. while (input_stream.good())
  85. {
  86. skip_emptyspace(input_stream);
  87. int c = input_stream.get();
  88. if (keyword[0] != c)
  89. {
  90. skip_line(input_stream);
  91. }
  92. else
  93. {
  94. size_t key_index = 1;
  95. while (key_index < key_length && keyword[key_index - 1] == c &&
  96. input_stream.good())
  97. {
  98. ++key_index;
  99. c = input_stream.get();
  100. }
  101. if (key_index == key_length && keyword[key_index - 1] == c)
  102. {
  103. c = input_stream.peek();
  104. if (' ' == c || '\t' == c || '\r' == c || '\n' == c)
  105. {
  106. return true;
  107. }
  108. else
  109. {
  110. skip_line(input_stream);
  111. }
  112. }
  113. else
  114. {
  115. skip_line(input_stream);
  116. }
  117. }
  118. }
  119. return false;
  120. }
  121. // Gets everything up to and including the next newline up to the next n
  122. // characters. Adds a newline on the end if bail before actual line ending
  123. bool get_line(std::string& output_string, std::istream& input_stream, int n)
  124. {
  125. output_string.clear();
  126. int char_count = 0;
  127. int c = input_stream.get();
  128. while (input_stream.good() && char_count < n)
  129. {
  130. ++char_count;
  131. output_string += c;
  132. if (c == '\n')
  133. {
  134. break;
  135. }
  136. if (char_count >= n)
  137. {
  138. output_string.append("\n");
  139. break;
  140. }
  141. c = input_stream.get();
  142. }
  143. return input_stream.good();
  144. }
  145. // The 'keyword' is defined as the first word on a line. The 'value' is
  146. // everything after the keyword on the same line starting at the first non-
  147. // whitespace and ending right before the newline
  148. void get_keyword_and_value(std::string& keyword, std::string& value,
  149. const std::string& line)
  150. {
  151. char c;
  152. size_t line_index = 0;
  153. size_t line_size = line.size();
  154. keyword.clear();
  155. value.clear();
  156. // Skip initial white spaces
  157. while (line_index < line_size)
  158. {
  159. c = line[line_index];
  160. if (!LLStringOps::isSpace(c))
  161. {
  162. break;
  163. }
  164. ++line_index;
  165. }
  166. // Get the keyword
  167. while (line_index < line_size)
  168. {
  169. c = line[line_index];
  170. if (LLStringOps::isSpace(c) || c == '\r' || c == '\n')
  171. {
  172. break;
  173. }
  174. keyword += c;
  175. ++line_index;
  176. }
  177. if (keyword.empty())
  178. {
  179. return; // No keyword, no value !
  180. }
  181. // Get the value
  182. c = line[line_index];
  183. if (c != '\r' && c != '\n')
  184. {
  185. // Discard initial white spaces
  186. while (line_index < line_size)
  187. {
  188. c = line[line_index];
  189. if (c == ' ' || c == '\t')
  190. {
  191. break;
  192. }
  193. ++line_index;
  194. }
  195. while (line_index < line_size)
  196. {
  197. c = line[line_index];
  198. if (c == '\r' || c == '\n')
  199. {
  200. break;
  201. }
  202. value += c;
  203. ++line_index;
  204. }
  205. }
  206. }
  207. std::streamsize fullread(std::istream& istr, char* buf,
  208. std::streamsize requested)
  209. {
  210. std::streamsize got;
  211. std::streamsize total = 0;
  212. istr.read(buf, requested);
  213. got = istr.gcount();
  214. total += got;
  215. while (got && total < requested)
  216. {
  217. if (istr.fail())
  218. {
  219. // If bad is true, not much we can do; it implies loss of stream
  220. // integrity. Bail in that case, and otherwise clear and attempt to
  221. // continue.
  222. if (istr.bad())
  223. {
  224. return total;
  225. }
  226. istr.clear();
  227. }
  228. istr.read(buf + total, requested - total);
  229. got = istr.gcount();
  230. total += got;
  231. }
  232. return total;
  233. }
  234. std::istream& operator>>(std::istream& str, const char* tocheck)
  235. {
  236. char c = '\0';
  237. const char* p = tocheck;
  238. while (*p && !str.bad())
  239. {
  240. str.get(c);
  241. if (c != *p)
  242. {
  243. str.setstate(std::ios::failbit);
  244. break;
  245. }
  246. ++p;
  247. }
  248. return str;
  249. }
  250. int cat_streambuf::underflow()
  251. {
  252. if (gptr() == egptr())
  253. {
  254. // Here because our buffer is empty
  255. std::streamsize sz = 0;
  256. // Until we have run out of mInputs, try reading the first of them into
  257. // mBuffer. If that fetches some characters, break the loop.
  258. while (!mInputs.empty() &&
  259. !(sz = mInputs.front()->sgetn(mBuffer.data(), mBuffer.size())))
  260. {
  261. // We tried to read mInputs.front() but got zero characters.
  262. // Discard the first streambuf and try the next one.
  263. mInputs.pop_front();
  264. }
  265. // Either we ran out of mInputs or we succeeded in reading some
  266. // characters, that is, sz != 0. Tell base class what we have.
  267. setg(mBuffer.data(), mBuffer.data(), mBuffer.data() + sz);
  268. }
  269. // If we fell out of the above loop with mBuffer still empty, return
  270. // eof(), otherwise return the next character.
  271. return gptr() == egptr() ? std::char_traits<char>::eof()
  272. : std::char_traits<char>::to_int_type(*gptr());
  273. }