|
reSIProcate/rutil
9694
|
00001 #include <cassert> 00002 00003 #include "rutil/Logger.hxx" 00004 #include "rutil/ParseBuffer.hxx" 00005 #include "rutil/ParseException.hxx" 00006 #include "rutil/DataStream.hxx" 00007 #include "rutil/WinLeakCheck.hxx" 00008 00009 using namespace resip; 00010 00011 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP 00012 00013 const char* ParseBuffer::ParamTerm = ";?"; // maybe include "@>,"? 00014 const char* ParseBuffer::Whitespace = " \t\r\n"; 00015 const Data ParseBuffer::Pointer::msg("dereferenced ParseBuffer eof"); 00016 00017 ParseBuffer::ParseBuffer(const char* buff, size_t len, 00018 const Data& errorContext) 00019 : mBuff(buff), 00020 mPosition(buff), 00021 mEnd(buff+len), 00022 mErrorContext(errorContext) 00023 {} 00024 00025 ParseBuffer::ParseBuffer(const Data& data, 00026 const Data& errorContext) 00027 : mBuff(data.data()), 00028 mPosition(mBuff), 00029 mEnd(mBuff + data.size()), 00030 mErrorContext(errorContext) 00031 {} 00032 00033 ParseBuffer::ParseBuffer(const ParseBuffer& rhs) 00034 : mBuff(rhs.mBuff), 00035 mPosition(rhs.mPosition), 00036 mEnd(rhs.mEnd), 00037 mErrorContext(rhs.mErrorContext) 00038 {} 00039 00040 ParseBuffer& 00041 ParseBuffer::operator=(const ParseBuffer& rhs) 00042 { 00043 mBuff = rhs.mBuff; 00044 mPosition = rhs.mPosition; 00045 mEnd = rhs.mEnd; 00046 00047 return *this; 00048 } 00049 00050 ParseBuffer::CurrentPosition 00051 ParseBuffer::skipChar(char c) 00052 { 00053 if (eof()) 00054 { 00055 fail(__FILE__, __LINE__,"skipped over eof"); 00056 } 00057 if (*mPosition != c) 00058 { 00059 Data msg("expected '"); 00060 msg += c; 00061 msg += "'"; 00062 fail(__FILE__, __LINE__,msg); 00063 } 00064 ++mPosition; 00065 return CurrentPosition(*this); 00066 } 00067 00068 ParseBuffer::CurrentPosition 00069 ParseBuffer::skipChars(const char* cs) 00070 { 00071 const char* match = cs; 00072 while (*match != 0) 00073 { 00074 if (eof() || (*match != *mPosition)) 00075 { 00076 Data msg("Expected \""); 00077 msg += cs; 00078 msg += "\""; 00079 fail(__FILE__, __LINE__,msg); 00080 } 00081 match++; 00082 mPosition++; 00083 } 00084 return CurrentPosition(*this); 00085 } 00086 00087 ParseBuffer::CurrentPosition 00088 ParseBuffer::skipChars(const Data& cs) 00089 { 00090 const char* match = cs.data(); 00091 for(Data::size_type i = 0; i < cs.size(); i++) 00092 { 00093 if (eof() || (*match != *mPosition)) 00094 { 00095 Data msg( "Expected \""); 00096 msg += cs; 00097 msg += "\""; 00098 fail(__FILE__, __LINE__,msg); 00099 } 00100 match++; 00101 mPosition++; 00102 } 00103 return CurrentPosition(*this); 00104 } 00105 00106 ParseBuffer::CurrentPosition 00107 ParseBuffer::skipNonWhitespace() 00108 { 00109 assertNotEof(); 00110 while (mPosition < mEnd) 00111 { 00112 switch (*mPosition) 00113 { 00114 case ' ' : 00115 case '\t' : 00116 case '\r' : 00117 case '\n' : 00118 return CurrentPosition(*this); 00119 default : 00120 mPosition++; 00121 } 00122 } 00123 return CurrentPosition(*this); 00124 } 00125 00126 ParseBuffer::CurrentPosition 00127 ParseBuffer::skipWhitespace() 00128 { 00129 while (mPosition < mEnd) 00130 { 00131 switch (*mPosition) 00132 { 00133 case ' ' : 00134 case '\t' : 00135 case '\r' : 00136 case '\n' : 00137 { 00138 mPosition++; 00139 break; 00140 } 00141 default : 00142 return CurrentPosition(*this); 00143 } 00144 } 00145 return CurrentPosition(*this); 00146 } 00147 00148 // "SIP header field values can be folded onto multiple lines if the 00149 // continuation line begins with a space or horizontal tab" 00150 00151 // CR can be quote with \ within "" and comments -- treat \CR as whitespace 00152 ParseBuffer::CurrentPosition 00153 ParseBuffer::skipLWS() 00154 { 00155 enum State {WS, CR, LF}; 00156 State state = WS; 00157 while (mPosition < mEnd) 00158 { 00159 char c = *mPosition++; 00160 if (c == '\\') 00161 { 00162 // treat escaped CR and LF as space 00163 c = *mPosition++; 00164 if (c == '\r' || c == '\n') 00165 { 00166 c = ' '; 00167 } 00168 } 00169 switch (*mPosition++) 00170 { 00171 case ' ' : 00172 case '\t' : 00173 { 00174 state = WS; 00175 break; 00176 } 00177 case '\r' : 00178 { 00179 state = CR; 00180 break; 00181 } 00182 case '\n' : 00183 { 00184 if (state == CR) 00185 { 00186 state = LF; 00187 } 00188 else 00189 { 00190 state = WS; 00191 } 00192 break; 00193 } 00194 default : 00195 { 00196 // terminating CRLF not skipped 00197 if (state == LF) 00198 { 00199 mPosition -= 3; 00200 } 00201 else 00202 { 00203 mPosition--; 00204 } 00205 return CurrentPosition(*this); 00206 } 00207 } 00208 } 00209 return CurrentPosition(*this); 00210 } 00211 00212 static Data CRLF("\r\n"); 00213 ParseBuffer::CurrentPosition 00214 ParseBuffer::skipToTermCRLF() 00215 { 00216 while (mPosition < mEnd) 00217 { 00218 skipToChars(CRLF); 00219 mPosition += 2; 00220 if ((*mPosition != ' ' && 00221 *mPosition != '\t' && 00222 // check for \CRLF -- not terminating 00223 // \\CRLF -- terminating 00224 ((mPosition-3 < mBuff || *(mPosition-3) != '\\') || 00225 (mPosition-4 > mBuff && *(mPosition-4) == '\\')))) 00226 { 00227 mPosition -= 2; 00228 return CurrentPosition(*this); 00229 } 00230 } 00231 return CurrentPosition(*this); 00232 } 00233 00234 ParseBuffer::CurrentPosition 00235 ParseBuffer::skipToChars(const char* cs) 00236 { 00237 assert(cs); 00238 unsigned int l = (unsigned int)strlen(cs); 00239 00240 const char* rpos; 00241 const char* cpos; 00242 while (mPosition < mEnd) 00243 { 00244 rpos = mPosition; 00245 cpos = cs; 00246 for (unsigned int i = 0; i < l; i++) 00247 { 00248 if (*cpos++ != *rpos++) 00249 { 00250 mPosition++; 00251 goto skip; 00252 } 00253 } 00254 return CurrentPosition(*this); 00255 skip: ; 00256 } 00257 return CurrentPosition(*this); 00258 } 00259 00260 ParseBuffer::CurrentPosition 00261 ParseBuffer::skipToChars(const Data& sub) 00262 { 00263 const char* begSub = sub.mBuf; 00264 const char* endSub = sub.mBuf + sub.mSize; 00265 if(begSub == endSub) 00266 { 00267 fail(__FILE__, __LINE__, "ParseBuffer::skipToChars() called with an " 00268 "empty string. Don't do this!"); 00269 } 00270 00271 while (true) 00272 { 00273 next: 00274 const char* searchPos = mPosition; 00275 const char* subPos = sub.mBuf; 00276 00277 while (subPos != endSub) 00278 { 00279 if (searchPos == mEnd) 00280 { 00281 // nope 00282 mPosition = mEnd; 00283 return CurrentPosition(*this); 00284 } 00285 if (*subPos++ != *searchPos++) 00286 { 00287 // nope, but try the next position 00288 ++mPosition; 00289 goto next; 00290 } 00291 } 00292 // found a match 00293 return CurrentPosition(*this); 00294 } 00295 } 00296 00297 bool 00298 ParseBuffer::oneOf(char c, const char* cs) 00299 { 00300 while (*cs) 00301 { 00302 if (c == *(cs++)) 00303 { 00304 return true; 00305 } 00306 } 00307 return false; 00308 } 00309 00310 bool 00311 ParseBuffer::oneOf(char c, const Data& cs) 00312 { 00313 for (Data::size_type i = 0; i < cs.size(); i++) 00314 { 00315 if (c == cs[i]) 00316 { 00317 return true; 00318 } 00319 } 00320 return false; 00321 } 00322 00323 ParseBuffer::CurrentPosition 00324 ParseBuffer::skipToOneOf(const char* cs) 00325 { 00326 while (mPosition < mEnd) 00327 { 00328 if (oneOf(*mPosition, cs)) 00329 { 00330 return CurrentPosition(*this); 00331 } 00332 else 00333 { 00334 mPosition++; 00335 } 00336 } 00337 return CurrentPosition(*this); 00338 } 00339 00340 ParseBuffer::CurrentPosition 00341 ParseBuffer::skipToOneOf(const char* cs1, 00342 const char* cs2) 00343 { 00344 while (mPosition < mEnd) 00345 { 00346 if (oneOf(*mPosition, cs1) || 00347 oneOf(*mPosition, cs2)) 00348 { 00349 return CurrentPosition(*this); 00350 } 00351 else 00352 { 00353 mPosition++; 00354 } 00355 } 00356 return CurrentPosition(*this); 00357 } 00358 00359 ParseBuffer::CurrentPosition 00360 ParseBuffer::skipToOneOf(const Data& cs) 00361 { 00362 while (mPosition < mEnd) 00363 { 00364 if (oneOf(*mPosition, cs)) 00365 { 00366 return CurrentPosition(*this); 00367 } 00368 else 00369 { 00370 mPosition++; 00371 } 00372 } 00373 return CurrentPosition(*this); 00374 } 00375 00376 ParseBuffer::CurrentPosition 00377 ParseBuffer::skipToOneOf(const Data& cs1, 00378 const Data& cs2) 00379 { 00380 while (mPosition < mEnd) 00381 { 00382 if (oneOf(*mPosition, cs1) || 00383 oneOf(*mPosition, cs2)) 00384 { 00385 return CurrentPosition(*this); 00386 } 00387 else 00388 { 00389 mPosition++; 00390 } 00391 } 00392 return CurrentPosition(*this); 00393 } 00394 00395 const char* 00396 ParseBuffer::skipToEndQuote(char quote) 00397 { 00398 while (mPosition < mEnd) 00399 { 00400 // !dlb! mark character encoding 00401 if (*mPosition == '\\') 00402 { 00403 mPosition += 2; 00404 } 00405 else if (*mPosition == quote) 00406 { 00407 return mPosition; 00408 } 00409 else 00410 { 00411 mPosition++; 00412 } 00413 } 00414 00415 { 00416 Data msg("Missing '"); 00417 msg += quote; 00418 msg += "'"; 00419 fail(__FILE__,__LINE__,msg); 00420 } 00421 return 0; 00422 } 00423 00424 const char* 00425 ParseBuffer::skipBackChar() 00426 { 00427 if (bof()) 00428 { 00429 fail(__FILE__, __LINE__,"backed over beginning of buffer"); 00430 } 00431 mPosition--; 00432 return mPosition; 00433 } 00434 00435 const char* 00436 ParseBuffer::skipBackWhitespace() 00437 { 00438 while (!bof()) 00439 { 00440 switch (*(--mPosition)) 00441 { 00442 case ' ' : 00443 case '\t' : 00444 case '\r' : 00445 case '\n' : 00446 { 00447 break; 00448 } 00449 default : 00450 return ++mPosition; 00451 } 00452 } 00453 return mBuff; 00454 } 00455 00456 // abcde 00457 // ^ 00458 // skipBackChar('d'); 00459 // abcde 00460 // ^ 00461 // skipChar('d'); 00462 // abcde 00463 // ^ 00464 const char* 00465 ParseBuffer::skipBackChar(char c) 00466 { 00467 if (bof()) 00468 { 00469 fail(__FILE__, __LINE__,"backed over beginning of buffer"); 00470 } 00471 if (*(--mPosition) != c) 00472 { 00473 Data msg( "Expected '"); 00474 msg += c; 00475 msg += "'"; 00476 fail(__FILE__, __LINE__,msg); 00477 } 00478 return mPosition; 00479 } 00480 00481 // abcde 00482 // ^ 00483 // skipBackToChar('c'); 00484 // abcde 00485 // ^ 00486 const char* 00487 ParseBuffer::skipBackToChar(char c) 00488 { 00489 while (!bof()) 00490 { 00491 if (*(--mPosition) == c) 00492 { 00493 return ++mPosition; 00494 } 00495 } 00496 return mBuff; 00497 } 00498 00499 const char* 00500 ParseBuffer::skipBackToOneOf(const char* cs) 00501 { 00502 while (!bof()) 00503 { 00504 if (oneOf(*(--mPosition),cs)) 00505 { 00506 return ++mPosition; 00507 } 00508 } 00509 return mBuff; 00510 } 00511 00512 void 00513 ParseBuffer::data(Data& data, const char* start) const 00514 { 00515 if (!(mBuff <= start && start <= mPosition)) 00516 { 00517 fail(__FILE__, __LINE__,"Bad anchor position"); 00518 } 00519 00520 if (data.mShareEnum == Data::Take) 00521 { 00522 delete[] data.mBuf; 00523 } 00524 data.mSize = (unsigned int)(mPosition - start); 00525 data.mBuf = const_cast<char*>(start); 00526 data.mCapacity = data.mSize; 00527 data.mShareEnum = Data::Share; 00528 } 00529 00530 static const unsigned char hexToByte[256] = 00531 { 00532 // 0 1 2 3 4 5 6 7 8 9 a b c d e f 00533 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//0 00534 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//1 00535 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//2 00536 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'k','k','k','k','k','k', //3 00537 'k',0xA,0xB,0xC,0xD,0xE,0xF,'k','k','k','k','k','k','k','k','k', //4 00538 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//5 00539 'k',0xA,0xB,0xC,0xD,0xE,0xF,'k','k','k','k','k','k','k','k','k', //6 00540 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//8 00541 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//9 00542 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//a 00543 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//b 00544 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//c 00545 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//d 00546 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//e 00547 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k' //f 00548 00549 }; 00550 00551 void 00552 ParseBuffer::dataUnescaped(Data& dataToUse, const char* start) const 00553 { 00554 if (!(mBuff <= start && start <= mPosition)) 00555 { 00556 fail(__FILE__, __LINE__, "Bad anchor position"); 00557 } 00558 00559 { 00560 const char* current = start; 00561 while (current < mPosition) 00562 { 00563 if (*current == '%') 00564 { 00565 // needs to be unencoded 00566 goto copy; 00567 } 00568 current++; 00569 } 00570 // can use an overlay 00571 data(dataToUse, start); 00572 return; 00573 } 00574 00575 copy: 00576 if ((size_t)(mPosition-start) > dataToUse.mCapacity) 00577 { 00578 dataToUse.resize(mPosition-start, false); 00579 } 00580 00581 char* target = dataToUse.mBuf; 00582 const char* current = start; 00583 while (current < mPosition) 00584 { 00585 if (*current == '%') 00586 { 00587 current++; 00588 if (mPosition - current < 2) 00589 { 00590 fail(__FILE__, __LINE__,"Illegal escaping"); 00591 } 00592 const char high = hexToByte[(unsigned char)*current]; 00593 const char low = hexToByte[(unsigned char)*(current + 1)]; 00594 if (high!='k' && low!='k') 00595 { 00596 unsigned char escaped = 0; 00597 escaped = high << 4 | low; 00598 // !bwc! I think this check is bogus, especially the ':' (58) check 00599 // You could maybe argue that the point of %-escaping is to allow 00600 // the use of UTF-8 data (including ASCII that is not allowed in an 00601 // on-the-wire representation of whatever it is we're unescaping), 00602 // and not unprintable characters (the unprintable codes are not 00603 // used by UTF-8). 00604 if (escaped > 31 && escaped != 127 && escaped != 58) 00605 { 00606 *target++ = escaped; 00607 current+= 2; 00608 } 00609 else 00610 { 00611 *target++ = '%'; 00612 *target++ = *current++; 00613 *target++ = *current++; 00614 } 00615 } 00616 else 00617 { 00618 fail(__FILE__, __LINE__,"Illegal escaping, not hex"); 00619 } 00620 } 00621 else 00622 { 00623 *target++ = *current++; 00624 } 00625 } 00626 *target = 0; 00627 dataToUse.mSize = target - dataToUse.mBuf; 00628 } 00629 00630 Data 00631 ParseBuffer::data(const char* start) const 00632 { 00633 if (!(mBuff <= start && start <= mPosition)) 00634 { 00635 00636 fail(__FILE__, __LINE__,"Bad anchor position"); 00637 } 00638 00639 Data data(start, mPosition - start); 00640 return data; 00641 } 00642 00643 int 00644 ParseBuffer::integer() 00645 { 00646 if (this->eof()) 00647 { 00648 fail(__FILE__, __LINE__,"Expected a digit, got eof "); 00649 } 00650 00651 int signum = 1; 00652 if (*mPosition == '-') 00653 { 00654 signum = -1; 00655 ++mPosition; 00656 assertNotEof(); 00657 } 00658 else if (*mPosition == '+') 00659 { 00660 ++mPosition; 00661 assertNotEof(); 00662 } 00663 00664 if (!isdigit(*mPosition)) 00665 { 00666 Data msg("Expected a digit, got: "); 00667 msg += Data(mPosition, (mEnd - mPosition)); 00668 fail(__FILE__, __LINE__,msg); 00669 } 00670 00671 int num = 0; 00672 int last=0; 00673 while (!eof() && isdigit(*mPosition)) 00674 { 00675 last=num; 00676 num = num*10 + (*mPosition-'0'); 00677 if(last > num) 00678 { 00679 fail(__FILE__, __LINE__,"Overflow detected."); 00680 } 00681 ++mPosition; 00682 } 00683 00684 return signum*num; 00685 } 00686 00687 UInt8 00688 ParseBuffer::uInt8() 00689 { 00690 const char* begin=mPosition; 00691 UInt8 num = 0; 00692 UInt8 last = 0; 00693 while (!eof() && isdigit(*mPosition)) 00694 { 00695 last = num; 00696 num = num*10 + (*mPosition-'0'); 00697 if(last>num) 00698 { 00699 fail(__FILE__, __LINE__,"Overflow detected."); 00700 } 00701 ++mPosition; 00702 } 00703 00704 if(mPosition==begin) 00705 { 00706 fail(__FILE__, __LINE__,"Expected a digit"); 00707 } 00708 return num; 00709 } 00710 00711 00713 UInt32 00714 ParseBuffer::uInt32() 00715 { 00716 const char* begin=mPosition; 00717 UInt32 num = 0; 00718 while (!eof() && isdigit(*mPosition)) 00719 { 00720 num = num*10 + (*mPosition-'0'); 00721 ++mPosition; 00722 } 00723 00724 switch(mPosition-begin) 00725 { 00726 case 0: 00727 fail(__FILE__, __LINE__,"Expected a digit"); 00728 case 1: 00729 case 2: 00730 case 3: 00731 case 4: 00732 case 5: 00733 case 6: 00734 case 7: 00735 case 8: 00736 case 9: 00737 break; 00738 case 10: 00739 if(*begin<'4') 00740 { 00741 break; 00742 } 00743 else if(*begin=='4' && num >= 4000000000UL) 00744 { 00745 break; 00746 } 00747 default: 00748 fail(__FILE__, __LINE__,"Overflow detected"); 00749 } 00750 00751 return num; 00752 } 00753 00754 UInt64 00755 ParseBuffer::uInt64() 00756 { 00757 const char* begin=mPosition; 00758 UInt64 num = 0; 00759 while (!eof() && isdigit(*mPosition)) 00760 { 00761 num = num*10 + (*mPosition-'0'); 00762 ++mPosition; 00763 } 00764 00765 switch(mPosition-begin) 00766 { 00767 case 0: 00768 fail(__FILE__, __LINE__,"Expected a digit"); 00769 case 1: 00770 case 2: 00771 case 3: 00772 case 4: 00773 case 5: 00774 case 6: 00775 case 7: 00776 case 8: 00777 case 9: 00778 case 10: 00779 case 11: 00780 case 12: 00781 case 13: 00782 case 14: 00783 case 15: 00784 case 16: 00785 case 17: 00786 case 18: 00787 case 19: 00788 break; 00789 case 20: 00790 if(*begin=='1' && num >= 10000000000000000000ULL) 00791 { 00792 break; 00793 } 00794 default: 00795 fail(__FILE__, __LINE__,"Overflow detected"); 00796 } 00797 00798 return num; 00799 } 00800 00801 #ifndef RESIP_FIXED_POINT 00802 float 00803 ParseBuffer::floatVal() 00804 { 00805 const char* s = mPosition; 00806 try 00807 { 00808 float mant = 0.0; 00809 int num = integer(); 00810 00811 if (*mPosition == '.') 00812 { 00813 skipChar(); 00814 const char* pos = mPosition; 00815 mant = float(integer()); 00816 int s = int(mPosition - pos); 00817 while (s--) 00818 { 00819 mant /= 10.0; 00820 } 00821 } 00822 return num + mant; 00823 } 00824 catch (ParseException&) 00825 { 00826 Data msg("Expected a floating point value, got: "); 00827 msg += Data(s, mPosition - s); 00828 fail(__FILE__, __LINE__,msg); 00829 return 0.0; 00830 } 00831 } 00832 #endif 00833 00834 int 00835 ParseBuffer::qVal() 00836 { 00837 // parse a qvalue into an integer between 0 and 1000 (ex: 1.0 -> 1000, 0.8 -> 800, 0.05 -> 50) 00838 const char* s = mPosition; 00839 try 00840 { 00841 int num = integer(); 00842 if (num == 1) 00843 { 00844 num = 1000; 00845 } 00846 else if (num != 0) 00847 { 00848 // error: qvalue must start with 1 or 0 00849 return 0; 00850 } 00851 00852 if (*mPosition == '.') 00853 { 00854 skipChar(); 00855 00856 int i = 100; 00857 while(!eof() && isdigit(*mPosition) && i) 00858 { 00859 num += (*mPosition-'0') * i; 00860 i /= 10; 00861 skipChar(); 00862 } 00863 } 00864 return num; 00865 } 00866 catch (ParseException&) 00867 { 00868 Data msg("Expected a floating point value, got: "); 00869 msg += Data(s, mPosition - s); 00870 fail(__FILE__, __LINE__,msg); 00871 return 0; 00872 } 00873 } 00874 00875 00876 Data 00877 spaces(unsigned int numSpaces) 00878 { 00879 Data sps(numSpaces, Data::Preallocate); 00880 for (unsigned int i = 0; i < numSpaces; i++) 00881 { 00882 sps += ' '; 00883 } 00884 return sps; 00885 } 00886 00887 Data 00888 escapeAndAnnotate(const char* buffer, 00889 Data::size_type size, 00890 const char* position) 00891 { 00892 Data ret(2*size+16, Data::Preallocate); 00893 00894 const char* lastReturn = buffer; 00895 int lineCount = 0; 00896 bool doneAt = false; 00897 00898 const char* p = buffer; 00899 for (unsigned int i = 0; i < size; i++) 00900 { 00901 unsigned char c = *p++; 00902 00903 switch (c) 00904 { 00905 case 0x0D: // CR 00906 { 00907 continue; 00908 } 00909 case 0x0A: // LF 00910 { 00911 if (!doneAt && p >= position) 00912 { 00913 ret += "[CRLF]\n"; 00914 ret += spaces((unsigned int)(position - lastReturn)); 00915 ret += "^[CRLF]\n"; 00916 doneAt = true; 00917 } 00918 else 00919 { 00920 lastReturn = p; 00921 ret += c; 00922 } 00923 lineCount++; 00924 continue; 00925 } 00926 } 00927 00928 if (iscntrl(c) || (c >= 0x7F)) 00929 { 00930 ret +='*'; // indicates unprintable character 00931 continue; 00932 } 00933 00934 ret += c; 00935 } 00936 if (!doneAt && p >= position) 00937 { 00938 ret += "\n"; 00939 ret += spaces((unsigned int)(position - lastReturn)); 00940 ret += "^\n"; 00941 } 00942 00943 return ret; 00944 } 00945 00946 void 00947 ParseBuffer::fail(const char* file, unsigned int line, const Data& detail) const 00948 { 00949 Data errmsg; 00950 { 00951 DataStream ds(errmsg); 00952 ds << file << ":" << line 00953 << ", Parse failed "; 00954 00955 if (detail != Data::Empty) ds << detail << ' ' ; 00956 00957 ds << "in context: " << mErrorContext 00958 << std::endl 00959 << escapeAndAnnotate(mBuff, mEnd - mBuff, mPosition); 00960 00961 ds.flush(); 00962 } 00963 DebugLog(<<errmsg); 00964 throw ParseException(errmsg, mErrorContext, file, line); 00965 } 00966 00967 ParseBuffer::Pointer::Pointer(const ParseBuffer& pb, 00968 const char* position, 00969 bool atEof) 00970 : mPb(pb), 00971 mPosition(position), 00972 mIsValid(!atEof) 00973 {} 00974 00975 ParseBuffer::Pointer::Pointer(const CurrentPosition& pos) : 00976 mPb(pos.mPb), 00977 mPosition(pos), 00978 mIsValid(pos.mPb.valid()) 00979 {} 00980 00981 const char& 00982 ParseBuffer::Pointer::operator*() const 00983 { 00984 if (mIsValid) 00985 { 00986 return *mPosition; 00987 } 00988 else 00989 { 00990 throw ParseException(msg, mPb.getContext(), __FILE__, __LINE__); 00991 } 00992 } 00993 00994 /* ==================================================================== 00995 * The Vovida Software License, Version 1.0 00996 * 00997 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00998 * 00999 * Redistribution and use in source and binary forms, with or without 01000 * modification, are permitted provided that the following conditions 01001 * are met: 01002 * 01003 * 1. Redistributions of source code must retain the above copyright 01004 * notice, this list of conditions and the following disclaimer. 01005 * 01006 * 2. Redistributions in binary form must reproduce the above copyright 01007 * notice, this list of conditions and the following disclaimer in 01008 * the documentation and/or other materials provided with the 01009 * distribution. 01010 * 01011 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 01012 * and "Vovida Open Communication Application Library (VOCAL)" must 01013 * not be used to endorse or promote products derived from this 01014 * software without prior written permission. For written 01015 * permission, please contact vocal@vovida.org. 01016 * 01017 * 4. Products derived from this software may not be called "VOCAL", nor 01018 * may "VOCAL" appear in their name, without prior written 01019 * permission of Vovida Networks, Inc. 01020 * 01021 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 01022 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 01023 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 01024 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 01025 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 01026 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 01027 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 01028 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 01029 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 01030 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 01031 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 01032 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 01033 * DAMAGE. 01034 * 01035 * ==================================================================== 01036 * 01037 * This software consists of voluntary contributions made by Vovida 01038 * Networks, Inc. and many individuals on behalf of Vovida Networks, 01039 * Inc. For more information on Vovida Networks, Inc., please see 01040 * <http://www.vovida.org/>. 01041 * 01042 */
1.7.5.1