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         output_string.clear();
00267         char c = input_stream.get();
00268         while (input_stream.good())
00269         {
00270                 output_string += c;
00271                 if ('\n' == c)
00272                 {
00273                         break;
00274                 }
00275                 c = input_stream.get();
00276         } 
00277         return input_stream.good();
00278 }
00279 
00280 // get everything up to and including the next newline
00281 // up to the next n characters.  
00282 // add a newline on the end if bail before actual line ending
00283 bool get_line(std::string& output_string, std::istream& input_stream, int n)
00284 {
00285         output_string.clear();
00286         int char_count = 0;
00287         char c = input_stream.get();
00288         while (input_stream.good() && char_count < n)
00289         {
00290                 char_count++;
00291                 output_string += c;
00292                 if ('\n' == c)
00293                 {
00294                         break;
00295                 }
00296                 if (char_count >= n)
00297                 {
00298                         output_string.append("\n");
00299                         break;
00300                 }
00301                 c = input_stream.get();
00302         } 
00303         return input_stream.good();
00304 }
00305 
00306 /* disabled -- might tickle bug in windows iostream
00307 // backs up the input_stream by line_size + 1 characters
00308 bool unget_line(const std::string& line, std::istream& input_stream)
00309 {
00310         input_stream.putback('\n');     // unget the newline
00311         for (int line_index = line.size()-1; line_index >= 0; line_index--)
00312         { 
00313                 input_stream.putback(line[line_index]);
00314         }
00315         return input_stream.good();
00316 }
00317 */
00318 
00319 // removes the last char in 'line' if it matches 'c'
00320 // returns true if removed last char
00321 bool remove_last_char(char c, std::string& line)
00322 {
00323         int line_size = line.size();
00324         if (line_size > 1
00325                 && c == line[line_size - 1])
00326         {
00327                 line.replace(line_size - 1, 1, "");
00328                 return true;
00329         }
00330         return false;
00331 }
00332 
00333 // replaces escaped characters with the correct characters from left to right
00334 // "\\\\" ---> '\\' (two backslahes become one)
00335 // "\\n" ---> '\n' (backslash n becomes carriage return)
00336 void unescape_string(std::string& line)
00337 {
00338         int line_size = line.size();
00339         int index = 0;
00340         while (index < line_size - 1)
00341         {
00342                 if ('\\' == line[index])
00343                 {
00344                         if ('\\' == line[index + 1])
00345                         {
00346                                 line.replace(index, 2, "\\");
00347                                 line_size--;
00348                         }
00349                         else if ('n' == line[index + 1])
00350                         {
00351                                 line.replace(index, 2, "\n");
00352                                 line_size--;
00353                         }
00354                 }
00355                 index++;
00356         }
00357 }
00358 
00359 // replaces unescaped characters with expanded equivalents from left to right
00360 // '\\' ---> "\\\\" (one backslash becomes two)
00361 // '\n' ---> "\\n"  (carriage return becomes backslash n)
00362 void escape_string(std::string& line)
00363 {
00364         int line_size = line.size();
00365         int index = 0;
00366         while (index < line_size)
00367         {
00368                 if ('\\' == line[index])
00369                 {
00370                         line.replace(index, 1, "\\\\");
00371                         line_size++;
00372                         index++;
00373                 }
00374                 else if ('\n' == line[index])
00375                 {
00376                         line.replace(index, 1, "\\n"); 
00377                         line_size++;
00378                         index++;
00379                 }
00380                 index++;
00381         }
00382 }
00383 
00384 // removes '\n' characters
00385 void replace_newlines_with_whitespace(std::string& line)
00386 {
00387         int line_size = line.size();
00388         int index = 0;
00389         while (index < line_size)
00390         {
00391                 if ('\n' == line[index])
00392                 {
00393                         line.replace(index, 1, " ");
00394                 }
00395                 index++;
00396         }
00397 }
00398 
00399 // erases any double-quote characters in 'line'
00400 void remove_double_quotes(std::string& line)
00401 {
00402         int index = 0;
00403         int line_size = line.size();
00404         while (index < line_size)
00405         {
00406                 if ('"' == line[index])
00407                 {
00408                         int count = 1;
00409                         while (index + count < line_size
00410                                    && '"' == line[index + count])
00411                         {
00412                                 count++;
00413                         }
00414                         line.replace(index, count, "");
00415                         line_size -= count;
00416                 }
00417                 else
00418                 {
00419                         index++;
00420                 }
00421         }
00422 }
00423 
00424 // the 'keyword' is defined as the first word on a line
00425 // the 'value' is everything after the keyword on the same line
00426 // starting at the first non-whitespace and ending right before the newline
00427 void get_keyword_and_value(std::string& keyword, 
00428                                                    std::string& value, 
00429                                                    const std::string& line)
00430 {
00431         // skip initial whitespace
00432         int line_size = line.size();
00433         int line_index = 0;
00434         char c;
00435         while (line_index < line_size)
00436         {
00437                 c = line[line_index];
00438                 if (!isspace(c))
00439                 {
00440                         break;
00441                 }
00442                 line_index++;
00443         }
00444 
00445         // get the keyword
00446         keyword.clear();
00447         while (line_index < line_size)
00448         {
00449                 c = line[line_index];
00450                 if (isspace(c) || '\r' == c || '\n' == c)
00451                 {
00452                         break;
00453                 }
00454                 keyword += c;
00455                 line_index++;
00456         }
00457 
00458         // get the value
00459         value.clear();
00460         if (keyword.size() > 0
00461                 && '\r' != line[line_index]
00462                 && '\n' != line[line_index])
00463 
00464         {
00465                 // discard initial white spaces
00466                 while (line_index < line_size
00467                                 && (' ' == line[line_index] 
00468                                         || '\t' == line[line_index]) )
00469                 {
00470                         line_index++;
00471                 }
00472 
00473                 while (line_index < line_size)
00474                 {
00475                         c = line[line_index];
00476                         if ('\r' == c || '\n' == c)
00477                         {
00478                                 break;
00479                         }
00480                         value += c;
00481                         line_index++;
00482                 }
00483         }
00484 }
00485 
00486 std::streamsize fullread(
00487         std::istream& istr,
00488         char* buf,
00489         std::streamsize requested)
00490 {
00491         std::streamsize got;
00492         std::streamsize total = 0;
00493 
00494         istr.read(buf, requested);       /*Flawfinder: ignore*/
00495         got = istr.gcount();
00496         total += got;
00497         while(got && total < requested)
00498         {
00499                 if(istr.fail())
00500                 {
00501                         // If bad is true, not much we can doo -- it implies loss
00502                         // of stream integrity. Bail in that case, and otherwise
00503                         // clear and attempt to continue.
00504                         if(istr.bad()) return total;
00505                         istr.clear();
00506                 }
00507                 istr.read(buf + total, requested - total);       /*Flawfinder: ignore*/
00508                 got = istr.gcount();
00509                 total += got;
00510         }
00511         return total;
00512 }
00513 
00514 std::istream& operator>>(std::istream& str, const char *tocheck)
00515 {
00516         char c = '\0';
00517         const char *p;
00518         p = tocheck;
00519         while (*p && !str.bad())
00520         {
00521                 str.get(c);
00522                 if (c != *p)
00523                 {
00524                         str.setstate(std::ios::failbit);                /*Flawfinder: ignore*/
00525                         break;
00526                 }
00527                 p++;
00528         }
00529         return str;
00530 }

Generated on Fri May 16 08:32:08 2008 for SecondLife by  doxygen 1.5.5