llstreamtools.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 #include <iostream>
00035 #include <string>
00036 
00037 #include "llstreamtools.h"
00038 
00039 
00040 // ----------------------------------------------------------------------------
00041 // some std::istream helper functions
00042 // ----------------------------------------------------------------------------
00043 
00044 // skips spaces and tabs
00045 bool skip_whitespace(std::istream& input_stream)
00046 {
00047         char c = input_stream.peek();
00048         while (('\t' == c || ' ' == c) && input_stream.good())
00049         {
00050                 input_stream.get();
00051                 c = input_stream.peek();
00052         }
00053         return input_stream.good();
00054 }
00055 
00056 // skips whitespace, newlines, and carriage returns
00057 bool skip_emptyspace(std::istream& input_stream)
00058 {
00059         char c = input_stream.peek();
00060         while ( input_stream.good()
00061                         && ('\t' == c || ' ' == c || '\n' == c || '\r' == c) )
00062         {
00063                 input_stream.get();
00064                 c = input_stream.peek();
00065         }
00066         return input_stream.good();
00067 }
00068 
00069 // skips emptyspace and lines that start with a #
00070 bool skip_comments_and_emptyspace(std::istream& input_stream)
00071 {
00072         while (skip_emptyspace(input_stream))
00073         {
00074                 char c = input_stream.peek();
00075                 if ('#' == c )
00076                 {
00077                         while ('\n' != c && input_stream.good())
00078                         {
00079                                 c = input_stream.get();
00080                         }
00081                 }
00082                 else
00083                 {
00084                         break;
00085                 }
00086         }
00087         return input_stream.good();
00088 }
00089 
00090 bool skip_line(std::istream& input_stream)
00091 {
00092         char c;
00093         do
00094         {
00095                 c = input_stream.get();
00096         } while ('\n' != c  &&  input_stream.good());
00097         return input_stream.good();
00098 }
00099 
00100 bool skip_to_next_word(std::istream& input_stream)
00101 {
00102         char c = input_stream.peek();
00103         while ( input_stream.good()
00104                         && (   (c >= 'a' && c <= 'z')
00105                                 || (c >= 'A' && c <= 'Z')
00106                                 || (c >= '0' && c <= '9')
00107                                 || '_' == c ) )
00108         {
00109                 input_stream.get();
00110                 c = input_stream.peek();
00111         }
00112         while ( input_stream.good()
00113                         && !(   (c >= 'a' && c <= 'z')
00114                                  || (c >= 'A' && c <= 'Z')
00115                                  || (c >= '0' && c <= '9')
00116                                  || '_' == c ) )
00117         {
00118                 input_stream.get();
00119                 c = input_stream.peek();
00120         }
00121         return input_stream.good();
00122 }
00123 
00124 bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream)
00125 {
00126         int key_length = strlen(keyword);        /*Flawfinder: ignore*/
00127         if (0 == key_length)
00128         {
00129                 return false;
00130         }
00131         while (input_stream.good())
00132         {
00133                 skip_emptyspace(input_stream);
00134                 char c = input_stream.get();
00135                 if (keyword[0] != c)
00136                 {
00137                         skip_line(input_stream);
00138                 }
00139                 else
00140                 {
00141                         int key_index = 1;
00142                         while ( key_index < key_length
00143                                         &&      keyword[key_index - 1] == c 
00144                                         && input_stream.good())
00145                         {
00146                                 key_index++;
00147                                 c = input_stream.get();
00148                         } 
00149 
00150                         if (key_index == key_length
00151                                 && keyword[key_index-1] == c)
00152                         {
00153                                 c = input_stream.peek();
00154                                 if (' ' == c || '\t' == c || '\r' == c || '\n' == c)
00155                                 { 
00156                                         return true;
00157                                 }
00158                                 else
00159                                 {
00160                                         skip_line(input_stream);
00161                                 }
00162                         }
00163                         else
00164                         {
00165                                 skip_line(input_stream);
00166                         }
00167                 }
00168         }
00169         return false;
00170 }
00171 
00172 /* skip_to_start_of_next_keyword() is disabled -- might tickle corruption bug in windows iostream
00173 bool skip_to_start_of_next_keyword(const char* keyword, std::istream& input_stream)
00174 {
00175         int key_length = strlen(keyword);
00176         if (0 == key_length)
00177         {
00178                 return false;
00179         }
00180         while (input_stream.good())
00181         {
00182                 skip_emptyspace(input_stream);
00183                 char c = input_stream.get();
00184                 if (keyword[0] != c)
00185                 {
00186                         skip_line(input_stream);
00187                 }
00188                 else
00189                 {
00190                         int key_index = 1;
00191                         while ( key_index < key_length
00192                                         &&      keyword[key_index - 1] == c 
00193                                         && input_stream.good())
00194                         {
00195                                 key_index++;
00196                                 c = input_stream.get();
00197                         } 
00198 
00199                         if (key_index == key_length
00200                                 && keyword[key_index-1] == c)
00201                         {
00202                                 c = input_stream.peek();
00203                                 if (' ' == c || '\t' == c || '\r' == c || '\n' == c)
00204                                 { 
00205                                         // put the keyword back onto the stream
00206                                         for (int index = key_length - 1; index >= 0; index--)
00207                                         {
00208                                                 input_stream.putback(keyword[index]);
00209                                         }
00210                                         return true;
00211                                 }
00212                                 else
00213                                 {
00214                                         skip_line(input_stream);
00215                                         break;
00216                                 }
00217                         }
00218                         else
00219                         {
00220                                 skip_line(input_stream);
00221                         }
00222                 }
00223         }
00224         return false;
00225 }
00226 */
00227 
00228 bool get_word(std::string& output_string, std::istream& input_stream)
00229 {
00230         skip_emptyspace(input_stream);
00231         char c = input_stream.peek();
00232         while ( !isspace(c) 
00233                         && '\n' != c 
00234                         && '\r' != c 
00235                         && input_stream.good() )
00236         {
00237                 output_string += c;
00238                 input_stream.get();
00239                 c = input_stream.peek();
00240         }
00241         return input_stream.good();
00242 }
00243 
00244 bool get_word(std::string& output_string, std::istream& input_stream, int n)
00245 {
00246         skip_emptyspace(input_stream);
00247         int char_count = 0;
00248         char c = input_stream.peek();
00249         while (!isspace(c) 
00250                         && '\n' != c 
00251                         && '\r' != c 
00252                         && input_stream.good() 
00253                         && char_count < n)
00254         {
00255                 char_count++;
00256                 output_string += c;
00257                 input_stream.get();
00258                 c = input_stream.peek();
00259         }
00260         return input_stream.good();
00261 }
00262 
00263 // get everything up to and including the next newline
00264 bool get_line(std::string& output_string, std::istream& input_stream)
00265 {
00266         char c = input_stream.get();
00267         while (input_stream.good())
00268         {
00269                 if ('\r' == c)
00270                 {
00271                         // skip carriage returns
00272                 }
00273                 else
00274                 {
00275                         output_string += c;
00276                         if ('\n' == c)
00277                         {
00278                                 break;
00279                         }
00280                 }
00281                 c = input_stream.get();
00282         } 
00283         return input_stream.good();
00284 }
00285 
00286 // get everything up to and including the next newline
00287 // up to the next n characters.  
00288 // add a newline on the end if bail before actual line ending
00289 bool get_line(std::string& output_string, std::istream& input_stream, int n)
00290 {
00291         int char_count = 0;
00292         char c = input_stream.get();
00293         while (input_stream.good() && char_count < n)
00294         {
00295                 char_count++;
00296                 output_string += c;
00297                 if ('\r' == c)
00298                 {
00299                         // skip carriage returns
00300                 }
00301                 else
00302                 {
00303                         if ('\n' == c)
00304                         {
00305                                 break;
00306                         }
00307                         if (char_count >= n)
00308                         {
00309                                 output_string.append("\n");
00310                                 break;
00311                         }
00312                 }
00313                 c = input_stream.get();
00314         } 
00315         return input_stream.good();
00316 }
00317 
00318 /* disabled -- might tickle bug in windows iostream
00319 // backs up the input_stream by line_size + 1 characters
00320 bool unget_line(const std::string& line, std::istream& input_stream)
00321 {
00322         input_stream.putback('\n');     // unget the newline
00323         for (int line_index = line.size()-1; line_index >= 0; line_index--)
00324         { 
00325                 input_stream.putback(line[line_index]);
00326         }
00327         return input_stream.good();
00328 }
00329 */
00330 
00331 // removes the last char in 'line' if it matches 'c'
00332 // returns true if removed last char
00333 bool remove_last_char(char c, std::string& line)
00334 {
00335         int line_size = line.size();
00336         if (line_size > 1
00337                 && c == line[line_size - 1])
00338         {
00339                 line.replace(line_size - 1, 1, "");
00340                 return true;
00341         }
00342         return false;
00343 }
00344 
00345 // replaces escaped characters with the correct characters from left to right
00346 // "\\\\" ---> '\\' (two backslahes become one)
00347 // "\\n" ---> '\n' (backslash n becomes carriage return)
00348 void unescape_string(std::string& line)
00349 {
00350         int line_size = line.size();
00351         int index = 0;
00352         while (index < line_size - 1)
00353         {
00354                 if ('\\' == line[index])
00355                 {
00356                         if ('\\' == line[index + 1])
00357                         {
00358                                 line.replace(index, 2, "\\");
00359                                 line_size--;
00360                         }
00361                         else if ('n' == line[index + 1])
00362                         {
00363                                 line.replace(index, 2, "\n");
00364                                 line_size--;
00365                         }
00366                 }
00367                 index++;
00368         }
00369 }
00370 
00371 // replaces unescaped characters with expanded equivalents from left to right
00372 // '\\' ---> "\\\\" (one backslash becomes two)
00373 // '\n' ---> "\\n"  (carriage return becomes backslash n)
00374 void escape_string(std::string& line)
00375 {
00376         int line_size = line.size();
00377         int index = 0;
00378         while (index < line_size)
00379         {
00380                 if ('\\' == line[index])
00381                 {
00382                         line.replace(index, 1, "\\\\");
00383                         line_size++;
00384                         index++;
00385                 }
00386                 else if ('\n' == line[index])
00387                 {
00388                         line.replace(index, 1, "\\n"); 
00389                         line_size++;
00390                         index++;
00391                 }
00392                 index++;
00393         }
00394 }
00395 
00396 // removes '\n' characters
00397 void replace_newlines_with_whitespace(std::string& line)
00398 {
00399         int line_size = line.size();
00400         int index = 0;
00401         while (index < line_size)
00402         {
00403                 if ('\n' == line[index])
00404                 {
00405                         line.replace(index, 1, " ");
00406                 }
00407                 index++;
00408         }
00409 }
00410 
00411 // returns 1 for solitary "{"
00412 // returns -1 for solitary "}"
00413 // otherwise returns 0
00414 int get_brace_count(const std::string& line)
00415 {
00416         int index = 0;
00417         int line_size = line.size();
00418         char c = 0;
00419         while (index < line_size)
00420         {
00421                 c = line[index];
00422                 index++;
00423                 if (!isspace(c))
00424                 {
00425                         break;
00426                 }
00427         }
00428         char brace = c;
00429         // make sure the rest of the line is whitespace
00430         while (index < line_size)
00431         {
00432                 c = line[index];
00433                 if (!isspace(c))
00434                 {
00435                         break;
00436                 }
00437                 index++;
00438         }
00439         if ('\n' != c)
00440         {
00441                 return 0;
00442         }
00443         if ('{' == brace)
00444         {
00445                 return 1;
00446         }
00447         else if ('}' == brace)
00448         {
00449                 return -1;
00450         }
00451         return 0;
00452 }
00453 
00454 // erases any double-quote characters in 'line'
00455 void remove_double_quotes(std::string& line)
00456 {
00457         int index = 0;
00458         int line_size = line.size();
00459         while (index < line_size)
00460         {
00461                 if ('"' == line[index])
00462                 {
00463                         int count = 1;
00464                         while (index + count < line_size
00465                                    && '"' == line[index + count])
00466                         {
00467                                 count++;
00468                         }
00469                         line.replace(index, count, "");
00470                         line_size -= count;
00471                 }
00472                 else
00473                 {
00474                         index++;
00475                 }
00476         }
00477 }
00478 
00479 // the 'keyword' is defined as the first word on a line
00480 // the 'value' is everything after the keyword on the same line
00481 // starting at the first non-whitespace and ending right before the newline
00482 void get_keyword_and_value(std::string& keyword, 
00483                                                    std::string& value, 
00484                                                    const std::string& line)
00485 {
00486         // skip initial whitespace
00487         int line_size = line.size();
00488         int line_index = 0;
00489         char c;
00490         while (line_index < line_size)
00491         {
00492                 c = line[line_index];
00493                 if (!isspace(c))
00494                 {
00495                         break;
00496                 }
00497                 line_index++;
00498         }
00499 
00500         // get the keyword
00501         keyword.assign("");
00502         while (line_index < line_size)
00503         {
00504                 c = line[line_index];
00505                 if (isspace(c) || '\r' == c || '\n' == c)
00506                 {
00507                         break;
00508                 }
00509                 keyword += c;
00510                 line_index++;
00511         }
00512 
00513         if (keyword.size() > 0
00514                 && '\r' != line[line_index]
00515                 && '\n' != line[line_index])
00516 
00517         {
00518                 // discard initial white spaces
00519                 while (line_index < line_size
00520                                 && (' ' == line[line_index] 
00521                                         || '\t' == line[line_index]) )
00522                 {
00523                         line_index++;
00524                 }
00525 
00526                 // get the value
00527                 value.assign("");
00528                 while (line_index < line_size)
00529                 {
00530                         c = line[line_index];
00531                         if ('\r' == c || '\n' == c)
00532                         {
00533                                 break;
00534                         }
00535                         value += c;
00536                         line_index++;
00537                 }
00538         }
00539 }
00540 
00541 std::istream& fullread(std::istream& str, char *buf, std::streamsize requested)
00542 {
00543         std::streamsize got;
00544         std::streamsize total = 0;
00545 
00546         str.read(buf, requested);        /*Flawfinder: ignore*/
00547         got = str.gcount();
00548         total += got;
00549         while (got && total < requested)
00550         {
00551                 if (str.fail())
00552                         str.clear();
00553                 str.read(buf + total, requested - total);        /*Flawfinder: ignore*/
00554                 got = str.gcount();
00555                 total += got;
00556         }
00557         return str;
00558 }
00559 
00560 std::istream& operator>>(std::istream& str, const char *tocheck)
00561 {
00562         char c = '\0';
00563         const char *p;
00564         p = tocheck;
00565         while (*p && !str.bad())
00566         {
00567                 str.get(c);
00568                 if (c != *p)
00569                 {
00570                         str.setstate(std::ios::failbit);                /*Flawfinder: ignore*/
00571                         break;
00572                 }
00573                 p++;
00574         }
00575         return str;
00576 }

Generated on Thu Jul 1 06:09:13 2010 for Second Life Viewer by  doxygen 1.4.7