llstreamtools.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:11k
源码类别:

游戏引擎

开发平台:

C++ Builder

  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-2010, 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 <iostream>
  34. #include <string>
  35. #include "llstreamtools.h"
  36. // ----------------------------------------------------------------------------
  37. // some std::istream helper functions
  38. // ----------------------------------------------------------------------------
  39. // skips spaces and tabs
  40. bool 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. // skips whitespace, newlines, and carriage returns
  51. bool skip_emptyspace(std::istream& input_stream)
  52. {
  53. int 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. // skips emptyspace and lines that start with a #
  63. bool skip_comments_and_emptyspace(std::istream& input_stream)
  64. {
  65. while (skip_emptyspace(input_stream))
  66. {
  67. int c = input_stream.peek();
  68. if ('#' == c )
  69. {
  70. while ('n' != c && input_stream.good())
  71. {
  72. c = input_stream.get();
  73. }
  74. }
  75. else
  76. {
  77. break;
  78. }
  79. }
  80. return input_stream.good();
  81. }
  82. bool skip_line(std::istream& input_stream)
  83. {
  84. int c;
  85. do
  86. {
  87. c = input_stream.get();
  88. } while ('n' != c  &&  input_stream.good());
  89. return input_stream.good();
  90. }
  91. bool skip_to_next_word(std::istream& input_stream)
  92. {
  93. int c = input_stream.peek();
  94. while ( input_stream.good()
  95. && (   (c >= 'a' && c <= 'z')
  96.     || (c >= 'A' && c <= 'Z')
  97. || (c >= '0' && c <= '9')
  98. || '_' == c ) )
  99. {
  100. input_stream.get();
  101. c = input_stream.peek();
  102. }
  103. while ( input_stream.good()
  104. && !(   (c >= 'a' && c <= 'z')
  105.      || (c >= 'A' && c <= 'Z')
  106.  || (c >= '0' && c <= '9')
  107.  || '_' == c ) )
  108. {
  109. input_stream.get();
  110. c = input_stream.peek();
  111. }
  112. return input_stream.good();
  113. }
  114. bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream)
  115. {
  116. int key_length = strlen(keyword);  /*Flawfinder: ignore*/
  117. if (0 == key_length)
  118. {
  119. return false;
  120. }
  121. while (input_stream.good())
  122. {
  123. skip_emptyspace(input_stream);
  124. int c = input_stream.get();
  125. if (keyword[0] != c)
  126. {
  127. skip_line(input_stream);
  128. }
  129. else
  130. {
  131. int key_index = 1;
  132. while ( key_index < key_length
  133. && keyword[key_index - 1] == c 
  134.     && input_stream.good())
  135. {
  136. key_index++;
  137. c = input_stream.get();
  138. if (key_index == key_length
  139. && keyword[key_index-1] == c)
  140. {
  141. c = input_stream.peek();
  142. if (' ' == c || 't' == c || 'r' == c || 'n' == c)
  143. return true;
  144. }
  145. else
  146. {
  147. skip_line(input_stream);
  148. }
  149. }
  150. else
  151. {
  152. skip_line(input_stream);
  153. }
  154. }
  155. }
  156. return false;
  157. }
  158. /* skip_to_start_of_next_keyword() is disabled -- might tickle corruption bug in windows iostream
  159. bool skip_to_start_of_next_keyword(const char* keyword, std::istream& input_stream)
  160. {
  161. int key_length = strlen(keyword);
  162. if (0 == key_length)
  163. {
  164. return false;
  165. }
  166. while (input_stream.good())
  167. {
  168. skip_emptyspace(input_stream);
  169. int c = input_stream.get();
  170. if (keyword[0] != c)
  171. {
  172. skip_line(input_stream);
  173. }
  174. else
  175. {
  176. int key_index = 1;
  177. while ( key_index < key_length
  178. && keyword[key_index - 1] == c 
  179.     && input_stream.good())
  180. {
  181. key_index++;
  182. c = input_stream.get();
  183. if (key_index == key_length
  184. && keyword[key_index-1] == c)
  185. {
  186. c = input_stream.peek();
  187. if (' ' == c || 't' == c || 'r' == c || 'n' == c)
  188. // put the keyword back onto the stream
  189. for (int index = key_length - 1; index >= 0; index--)
  190. {
  191. input_stream.putback(keyword[index]);
  192. }
  193. return true;
  194. }
  195. else
  196. {
  197. skip_line(input_stream);
  198. break;
  199. }
  200. }
  201. else
  202. {
  203. skip_line(input_stream);
  204. }
  205. }
  206. }
  207. return false;
  208. }
  209. */
  210. bool get_word(std::string& output_string, std::istream& input_stream)
  211. {
  212. skip_emptyspace(input_stream);
  213. int c = input_stream.peek();
  214. while ( !isspace(c) 
  215. && 'n' != c 
  216. && 'r' != c 
  217. && input_stream.good() )
  218. {
  219. output_string += c;
  220. input_stream.get();
  221. c = input_stream.peek();
  222. }
  223. return input_stream.good();
  224. }
  225. bool get_word(std::string& output_string, std::istream& input_stream, int n)
  226. {
  227. skip_emptyspace(input_stream);
  228. int char_count = 0;
  229. int c = input_stream.peek();
  230. while (!isspace(c) 
  231. && 'n' != c 
  232. && 'r' != c 
  233. && input_stream.good() 
  234. && char_count < n)
  235. {
  236. char_count++;
  237. output_string += c;
  238. input_stream.get();
  239. c = input_stream.peek();
  240. }
  241. return input_stream.good();
  242. }
  243. // get everything up to and including the next newline
  244. bool get_line(std::string& output_string, std::istream& input_stream)
  245. {
  246. output_string.clear();
  247. int c = input_stream.get();
  248. while (input_stream.good())
  249. {
  250. output_string += c;
  251. if ('n' == c)
  252. {
  253. break;
  254. }
  255. c = input_stream.get();
  256. return input_stream.good();
  257. }
  258. // get everything up to and including the next newline
  259. // up to the next n characters.  
  260. // add a newline on the end if bail before actual line ending
  261. bool get_line(std::string& output_string, std::istream& input_stream, int n)
  262. {
  263. output_string.clear();
  264. int char_count = 0;
  265. int c = input_stream.get();
  266. while (input_stream.good() && char_count < n)
  267. {
  268. char_count++;
  269. output_string += c;
  270. if ('n' == c)
  271. {
  272. break;
  273. }
  274. if (char_count >= n)
  275. {
  276. output_string.append("n");
  277. break;
  278. }
  279. c = input_stream.get();
  280. return input_stream.good();
  281. }
  282. /* disabled -- might tickle bug in windows iostream
  283. // backs up the input_stream by line_size + 1 characters
  284. bool unget_line(const std::string& line, std::istream& input_stream)
  285. {
  286. input_stream.putback('n'); // unget the newline
  287. for (int line_index = line.size()-1; line_index >= 0; line_index--)
  288. input_stream.putback(line[line_index]);
  289. }
  290. return input_stream.good();
  291. }
  292. */
  293. // removes the last char in 'line' if it matches 'c'
  294. // returns true if removed last char
  295. bool remove_last_char(char c, std::string& line)
  296. {
  297. int line_size = line.size();
  298. if (line_size > 1
  299. && c == line[line_size - 1])
  300. {
  301. line.replace(line_size - 1, 1, "");
  302. return true;
  303. }
  304. return false;
  305. }
  306. // replaces escaped characters with the correct characters from left to right
  307. // "\\" ---> '\' (two backslahes become one)
  308. // "\n" ---> 'n' (backslash n becomes carriage return)
  309. void unescape_string(std::string& line)
  310. {
  311. int line_size = line.size();
  312. int index = 0;
  313. while (index < line_size - 1)
  314. {
  315. if ('\' == line[index])
  316. {
  317. if ('\' == line[index + 1])
  318. {
  319. line.replace(index, 2, "\");
  320. line_size--;
  321. }
  322. else if ('n' == line[index + 1])
  323. {
  324. line.replace(index, 2, "n");
  325. line_size--;
  326. }
  327. }
  328. index++;
  329. }
  330. }
  331. // replaces unescaped characters with expanded equivalents from left to right
  332. // '\' ---> "\\" (one backslash becomes two)
  333. // 'n' ---> "\n"  (carriage return becomes backslash n)
  334. void escape_string(std::string& line)
  335. {
  336. int line_size = line.size();
  337. int index = 0;
  338. while (index < line_size)
  339. {
  340. if ('\' == line[index])
  341. {
  342. line.replace(index, 1, "\\");
  343. line_size++;
  344. index++;
  345. }
  346. else if ('n' == line[index])
  347. {
  348. line.replace(index, 1, "\n"); 
  349. line_size++;
  350. index++;
  351. }
  352. index++;
  353. }
  354. }
  355. // removes 'n' characters
  356. void replace_newlines_with_whitespace(std::string& line)
  357. {
  358. int line_size = line.size();
  359. int index = 0;
  360. while (index < line_size)
  361. {
  362. if ('n' == line[index])
  363. {
  364. line.replace(index, 1, " ");
  365. }
  366. index++;
  367. }
  368. }
  369. // erases any double-quote characters in 'line'
  370. void remove_double_quotes(std::string& line)
  371. {
  372. int index = 0;
  373. int line_size = line.size();
  374. while (index < line_size)
  375. {
  376. if ('"' == line[index])
  377. {
  378. int count = 1;
  379. while (index + count < line_size
  380.    && '"' == line[index + count])
  381. {
  382. count++;
  383. }
  384. line.replace(index, count, "");
  385. line_size -= count;
  386. }
  387. else
  388. {
  389. index++;
  390. }
  391. }
  392. }
  393. // the 'keyword' is defined as the first word on a line
  394. // the 'value' is everything after the keyword on the same line
  395. // starting at the first non-whitespace and ending right before the newline
  396. void get_keyword_and_value(std::string& keyword, 
  397.    std::string& value, 
  398.    const std::string& line)
  399. {
  400. // skip initial whitespace
  401. int line_size = line.size();
  402. int line_index = 0;
  403. char c;
  404. while (line_index < line_size)
  405. {
  406. c = line[line_index];
  407. if (!LLStringOps::isSpace(c))
  408. {
  409. break;
  410. }
  411. line_index++;
  412. }
  413. // get the keyword
  414. keyword.clear();
  415. while (line_index < line_size)
  416. {
  417. c = line[line_index];
  418. if (LLStringOps::isSpace(c) || 'r' == c || 'n' == c)
  419. {
  420. break;
  421. }
  422. keyword += c;
  423. line_index++;
  424. }
  425. // get the value
  426. value.clear();
  427. if (keyword.size() > 0
  428. && 'r' != line[line_index]
  429. && 'n' != line[line_index])
  430. {
  431. // discard initial white spaces
  432. while (line_index < line_size
  433. && (' ' == line[line_index] 
  434. || 't' == line[line_index]) )
  435. {
  436. line_index++;
  437. }
  438. while (line_index < line_size)
  439. {
  440. c = line[line_index];
  441. if ('r' == c || 'n' == c)
  442. {
  443. break;
  444. }
  445. value += c;
  446. line_index++;
  447. }
  448. }
  449. }
  450. std::streamsize fullread(
  451. std::istream& istr,
  452. char* buf,
  453. std::streamsize requested)
  454. {
  455. std::streamsize got;
  456. std::streamsize total = 0;
  457. istr.read(buf, requested);  /*Flawfinder: ignore*/
  458. got = istr.gcount();
  459. total += got;
  460. while(got && total < requested)
  461. {
  462. if(istr.fail())
  463. {
  464. // If bad is true, not much we can doo -- it implies loss
  465. // of stream integrity. Bail in that case, and otherwise
  466. // clear and attempt to continue.
  467. if(istr.bad()) return total;
  468. istr.clear();
  469. }
  470. istr.read(buf + total, requested - total);  /*Flawfinder: ignore*/
  471. got = istr.gcount();
  472. total += got;
  473. }
  474. return total;
  475. }
  476. std::istream& operator>>(std::istream& str, const char *tocheck)
  477. {
  478. char c = '';
  479. const char *p;
  480. p = tocheck;
  481. while (*p && !str.bad())
  482. {
  483. str.get(c);
  484. if (c != *p)
  485. {
  486. str.setstate(std::ios::failbit); /*Flawfinder: ignore*/
  487. break;
  488. }
  489. p++;
  490. }
  491. return str;
  492. }