reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
ParseBuffer.cxx
Go to the documentation of this file.
1#include <ctype.h>
2
3#include "rutil/ResipAssert.h"
4
5#include "rutil/Logger.hxx"
10
11using namespace resip;
12
13#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
14
15const char* ParseBuffer::ParamTerm = ";?"; // maybe include "@>,"?
16const char* ParseBuffer::Whitespace = " \t\r\n";
17const Data ParseBuffer::Pointer::msg("dereferenced ParseBuffer eof");
18
19ParseBuffer::ParseBuffer(const char* buff, size_t len,
20 const Data& errorContext)
21 : mBuff(buff),
22 mPosition(buff),
23 mEnd(buff+len),
24 mErrorContext(errorContext)
25{}
26
27ParseBuffer::ParseBuffer(const char* buff,
28 const Data& errorContext)
29 : mBuff(buff),
30 mPosition(buff),
31 mEnd(buff+strlen(buff)),
32 mErrorContext(errorContext)
33{}
34
36 const Data& errorContext)
37 : mBuff(data.data()),
38 mPosition(mBuff),
39 mEnd(mBuff + data.size()),
40 mErrorContext(errorContext)
41{}
42
44 : mBuff(rhs.mBuff),
45 mPosition(rhs.mPosition),
46 mEnd(rhs.mEnd),
47 mErrorContext(rhs.mErrorContext)
48{}
49
52{
53 if (&rhs != this)
54 {
55 mBuff = rhs.mBuff;
56 mPosition = rhs.mPosition;
57 mEnd = rhs.mEnd;
58 }
59
60 return *this;
61}
62
63ParseBuffer::CurrentPosition
65{
66 if (eof())
67 {
68 fail(__FILE__, __LINE__,"skipped over eof");
69 }
70 if (*mPosition != c)
71 {
72 Data msg("expected '");
73 msg += c;
74 msg += "'";
75 fail(__FILE__, __LINE__,msg);
76 }
77 ++mPosition;
78 return CurrentPosition(*this);
79}
80
81ParseBuffer::CurrentPosition
83{
84 const char* match = cs;
85 while (*match != 0)
86 {
87 if (eof() || (*match != *mPosition))
88 {
89 Data msg("Expected \"");
90 msg += cs;
91 msg += "\"";
92 fail(__FILE__, __LINE__,msg);
93 }
94 match++;
95 mPosition++;
96 }
97 return CurrentPosition(*this);
98}
99
100ParseBuffer::CurrentPosition
102{
103 const char* match = cs.data();
104 for(Data::size_type i = 0; i < cs.size(); i++)
105 {
106 if (eof() || (*match != *mPosition))
107 {
108 Data msg( "Expected \"");
109 msg += cs;
110 msg += "\"";
111 fail(__FILE__, __LINE__,msg);
112 }
113 match++;
114 mPosition++;
115 }
116 return CurrentPosition(*this);
117}
118
119ParseBuffer::CurrentPosition
121{
122 assertNotEof();
123 while (mPosition < mEnd)
124 {
125 switch (*mPosition)
126 {
127 case ' ' :
128 case '\t' :
129 case '\r' :
130 case '\n' :
131 return CurrentPosition(*this);
132 default :
133 mPosition++;
134 }
135 }
136 return CurrentPosition(*this);
137}
138
139ParseBuffer::CurrentPosition
141{
142 while (mPosition < mEnd)
143 {
144 switch (*mPosition)
145 {
146 case ' ' :
147 case '\t' :
148 case '\r' :
149 case '\n' :
150 {
151 mPosition++;
152 break;
153 }
154 default :
155 return CurrentPosition(*this);
156 }
157 }
158 return CurrentPosition(*this);
159}
160
161// "SIP header field values can be folded onto multiple lines if the
162// continuation line begins with a space or horizontal tab"
163
164// CR can be quote with \ within "" and comments -- treat \CR as whitespace
165ParseBuffer::CurrentPosition
167{
168 enum State {WS, CR, LF};
169 State state = WS;
170 while (mPosition < mEnd)
171 {
172 char c = *mPosition++;
173 if (c == '\\')
174 {
175 // treat escaped CR and LF as space
176 c = *mPosition++;
177 if (c == '\r' || c == '\n')
178 {
179 c = ' ';
180 }
181 }
182 switch (*mPosition++)
183 {
184 case ' ' :
185 case '\t' :
186 {
187 state = WS;
188 break;
189 }
190 case '\r' :
191 {
192 state = CR;
193 break;
194 }
195 case '\n' :
196 {
197 if (state == CR)
198 {
199 state = LF;
200 }
201 else
202 {
203 state = WS;
204 }
205 break;
206 }
207 default :
208 {
209 // terminating CRLF not skipped
210 if (state == LF)
211 {
212 mPosition -= 3;
213 }
214 else
215 {
216 mPosition--;
217 }
218 return CurrentPosition(*this);
219 }
220 }
221 }
222 return CurrentPosition(*this);
223}
224
225static Data CRLF("\r\n");
226ParseBuffer::CurrentPosition
228{
229 while (mPosition < mEnd)
230 {
232 mPosition += 2;
233 if ((*mPosition != ' ' &&
234 *mPosition != '\t' &&
235 // check for \CRLF -- not terminating
236 // \\CRLF -- terminating
237 ((mPosition-3 < mBuff || *(mPosition-3) != '\\') ||
238 (mPosition-4 > mBuff && *(mPosition-4) == '\\'))))
239 {
240 mPosition -= 2;
241 return CurrentPosition(*this);
242 }
243 }
244 return CurrentPosition(*this);
245}
246
247ParseBuffer::CurrentPosition
249{
250 resip_assert(cs);
251 unsigned int l = (unsigned int)strlen(cs);
252
253 const char* rpos;
254 const char* cpos;
255 // Checking mPosition >= mEnd - l +1 is unnecessary because there won't be
256 // enough bytes left to find [cs].
257 while (mPosition < mEnd - l + 1)
258 {
259 rpos = mPosition;
260 cpos = cs;
261 for (unsigned int i = 0; i < l; i++)
262 {
263 if (*cpos++ != *rpos++)
264 {
265 mPosition++;
266 goto skip;
267 }
268 }
269 return CurrentPosition(*this);
270 skip: ;
271 }
272 // Advance to the end since we didn't find a match.
273 mPosition = mEnd;
274 return CurrentPosition(*this);
275}
276
277ParseBuffer::CurrentPosition
279{
280 const char* begSub = sub.mBuf;
281 const char* endSub = sub.mBuf + sub.mSize;
282 if(begSub == endSub)
283 {
284 fail(__FILE__, __LINE__, "ParseBuffer::skipToChars() called with an "
285 "empty string. Don't do this!");
286 }
287
288 while (true)
289 {
290next:
291 const char* searchPos = mPosition;
292 const char* subPos = sub.mBuf;
293
294 while (subPos != endSub)
295 {
296 if (searchPos == mEnd)
297 {
298 // nope
299 mPosition = mEnd;
300 return CurrentPosition(*this);
301 }
302 if (*subPos++ != *searchPos++)
303 {
304 // nope, but try the next position
305 ++mPosition;
306 goto next;
307 }
308 }
309 // found a match
310 return CurrentPosition(*this);
311 }
312}
313
314bool
315ParseBuffer::oneOf(char c, const char* cs)
316{
317 while (*cs)
318 {
319 if (c == *(cs++))
320 {
321 return true;
322 }
323 }
324 return false;
325}
326
327bool
328ParseBuffer::oneOf(char c, const Data& cs)
329{
330 for (Data::size_type i = 0; i < cs.size(); i++)
331 {
332 if (c == cs[i])
333 {
334 return true;
335 }
336 }
337 return false;
338}
339
340ParseBuffer::CurrentPosition
342{
343 while (mPosition < mEnd)
344 {
345 if (oneOf(*mPosition, cs))
346 {
347 return CurrentPosition(*this);
348 }
349 else
350 {
351 mPosition++;
352 }
353 }
354 return CurrentPosition(*this);
355}
356
357ParseBuffer::CurrentPosition
359 const char* cs2)
360{
361 while (mPosition < mEnd)
362 {
363 if (oneOf(*mPosition, cs1) ||
364 oneOf(*mPosition, cs2))
365 {
366 return CurrentPosition(*this);
367 }
368 else
369 {
370 mPosition++;
371 }
372 }
373 return CurrentPosition(*this);
374}
375
376ParseBuffer::CurrentPosition
378{
379 while (mPosition < mEnd)
380 {
381 if (oneOf(*mPosition, cs))
382 {
383 return CurrentPosition(*this);
384 }
385 else
386 {
387 mPosition++;
388 }
389 }
390 return CurrentPosition(*this);
391}
392
393ParseBuffer::CurrentPosition
395 const Data& cs2)
396{
397 while (mPosition < mEnd)
398 {
399 if (oneOf(*mPosition, cs1) ||
400 oneOf(*mPosition, cs2))
401 {
402 return CurrentPosition(*this);
403 }
404 else
405 {
406 mPosition++;
407 }
408 }
409 return CurrentPosition(*this);
410}
411
412const char*
414{
415 while (mPosition < mEnd)
416 {
417 // !dlb! mark character encoding
418 if (*mPosition == '\\')
419 {
420 mPosition += 2;
421 }
422 else if (*mPosition == quote)
423 {
424 return mPosition;
425 }
426 else
427 {
428 mPosition++;
429 }
430 }
431
432 {
433 Data msg("Missing '");
434 msg += quote;
435 msg += "'";
436 fail(__FILE__,__LINE__,msg);
437 }
438 return 0;
439}
440
441const char*
443{
444 if (bof())
445 {
446 fail(__FILE__, __LINE__,"backed over beginning of buffer");
447 }
448 mPosition--;
449 return mPosition;
450}
451
452const char*
454{
455 while (!bof())
456 {
457 switch (*(--mPosition))
458 {
459 case ' ' :
460 case '\t' :
461 case '\r' :
462 case '\n' :
463 {
464 break;
465 }
466 default :
467 return ++mPosition;
468 }
469 }
470 return mBuff;
471}
472
473// abcde
474// ^
475// skipBackChar('d');
476// abcde
477// ^
478// skipChar('d');
479// abcde
480// ^
481const char*
483{
484 if (bof())
485 {
486 fail(__FILE__, __LINE__,"backed over beginning of buffer");
487 }
488 if (*(--mPosition) != c)
489 {
490 Data msg( "Expected '");
491 msg += c;
492 msg += "'";
493 fail(__FILE__, __LINE__,msg);
494 }
495 return mPosition;
496}
497
498// abcde
499// ^
500// skipBackToChar('c');
501// abcde
502// ^
503const char*
505{
506 while (!bof())
507 {
508 if (*(--mPosition) == c)
509 {
510 return ++mPosition;
511 }
512 }
513 return mBuff;
514}
515
516const char*
518{
519 while (!bof())
520 {
521 if (oneOf(*(--mPosition),cs))
522 {
523 return ++mPosition;
524 }
525 }
526 return mBuff;
527}
528
529void
530ParseBuffer::data(Data& data, const char* start) const
531{
532 if (!(mBuff <= start && start <= mPosition))
533 {
534 fail(__FILE__, __LINE__,"Bad anchor position");
535 }
536
537 if (data.mShareEnum == Data::Take)
538 {
539 delete[] data.mBuf;
540 }
541 data.mSize = (unsigned int)(mPosition - start);
542 data.mBuf = const_cast<char*>(start);
543 data.mCapacity = data.mSize;
544 data.mShareEnum = Data::Share;
545}
546
547static const unsigned char hexToByte[256] =
548{
549// 0 1 2 3 4 5 6 7 8 9 a b c d e f
550 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//0
551 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//1
552 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//2
553 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'k','k','k','k','k','k', //3
554 'k',0xA,0xB,0xC,0xD,0xE,0xF,'k','k','k','k','k','k','k','k','k', //4
555 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//5
556 'k',0xA,0xB,0xC,0xD,0xE,0xF,'k','k','k','k','k','k','k','k','k', //6
557 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//8
558 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//9
559 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//a
560 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//b
561 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//c
562 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//d
563 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k',//e
564 'k','k','k','k','k','k','k','k','k','k','k','k','k','k','k','k' //f
565
566};
567
568void
569ParseBuffer::dataUnescaped(Data& dataToUse, const char* start) const
570{
571 if (!(mBuff <= start && start <= mPosition))
572 {
573 fail(__FILE__, __LINE__, "Bad anchor position");
574 }
575
576 {
577 const char* current = start;
578 while (current < mPosition)
579 {
580 if (*current == '%')
581 {
582 // needs to be unencoded
583 goto copy;
584 }
585 current++;
586 }
587 // can use an overlay
588 data(dataToUse, start);
589 return;
590 }
591
592 copy:
593 if ((size_t)(mPosition-start) > dataToUse.mCapacity)
594 {
595 dataToUse.resize((Data::size_type)(mPosition-start), false);
596 }
597
598 char* target = dataToUse.mBuf;
599 const char* current = start;
600 while (current < mPosition)
601 {
602 if (*current == '%')
603 {
604 current++;
605 if (mPosition - current < 2)
606 {
607 fail(__FILE__, __LINE__,"Illegal escaping");
608 }
609 const char high = hexToByte[(unsigned char)*current];
610 const char low = hexToByte[(unsigned char)*(current + 1)];
611 if (high!='k' && low!='k')
612 {
613 unsigned char escaped = 0;
614 escaped = high << 4 | low;
615 // !bwc! I think this check is bogus, especially the ':' (58) check
616 // You could maybe argue that the point of %-escaping is to allow
617 // the use of UTF-8 data (including ASCII that is not allowed in an
618 // on-the-wire representation of whatever it is we're unescaping),
619 // and not unprintable characters (the unprintable codes are not
620 // used by UTF-8).
621 if (escaped > 31 && escaped != 127 && escaped != 58)
622 {
623 *target++ = escaped;
624 current+= 2;
625 }
626 else
627 {
628 *target++ = '%';
629 *target++ = *current++;
630 *target++ = *current++;
631 }
632 }
633 else
634 {
635 fail(__FILE__, __LINE__,"Illegal escaping, not hex");
636 }
637 }
638 else
639 {
640 *target++ = *current++;
641 }
642 }
643 *target = 0;
644 dataToUse.mSize = (Data::size_type)(target - dataToUse.mBuf);
645}
646
647Data
648ParseBuffer::data(const char* start) const
649{
650 if (!(mBuff <= start && start <= mPosition))
651 {
652
653 fail(__FILE__, __LINE__,"Bad anchor position");
654 }
655
656 Data data(start, (Data::size_type)(mPosition - start));
657 return data;
658}
659
660int
662{
663 if (this->eof())
664 {
665 fail(__FILE__, __LINE__,"Expected a digit, got eof ");
666 }
667
668 bool negative = false;
669 if (*mPosition == '-')
670 {
671 negative = true;
672 ++mPosition;
673 assertNotEof();
674 }
675 else if (*mPosition == '+')
676 {
677 ++mPosition;
678 assertNotEof();
679 }
680
681 if (!isdigit(static_cast< unsigned char >(*mPosition)))
682 {
683 Data msg("Expected a digit, got: ");
684 msg += Data(mPosition, (Data::size_type)(mEnd - mPosition));
685 fail(__FILE__, __LINE__,msg);
686 }
687
688#ifdef _MSC_VER
689#pragma warning( push )
690#pragma warning( disable : 4146)
691#endif
692 // The absolute value limit depending on the detected sign
693 const unsigned int absoluteLimit = negative ? -(unsigned int)INT_MIN : INT_MAX;
694 // maximum value for full number except last digit
695 const unsigned int border = absoluteLimit / 10;
696 // value the last digit must not exceed
697 const unsigned int digitLimit = absoluteLimit % 10;
698
699 unsigned int num = 0;
700 while (!eof() && isdigit(static_cast< unsigned char >(*mPosition)))
701 {
702 const unsigned int c = *mPosition++ - '0';
703 if (num > border || (num == border && c > digitLimit)) {
704 fail(__FILE__, __LINE__,"Overflow detected.");
705 }
706 num *= 10;
707 num += c;
708 }
709 if (negative)
710 {
711 num = -num;
712 }
713 return num;
714#ifdef _MSC_VER
715#pragma warning( pop )
716#endif
717}
718
721{
722 const char* begin=mPosition;
723 uint8_t num = 0;
724 uint8_t last = 0;
725 while (!eof() && isdigit(static_cast< unsigned char >(*mPosition)))
726 {
727 last = num;
728 num = num*10 + (*mPosition-'0');
729 if(last>num)
730 {
731 fail(__FILE__, __LINE__,"Overflow detected.");
732 }
733 ++mPosition;
734 }
735
736 if(mPosition==begin)
737 {
738 fail(__FILE__, __LINE__,"Expected a digit");
739 }
740 return num;
741}
742
743
747{
748 const char* begin=mPosition;
749 uint32_t num = 0;
750 while (!eof() && isdigit(static_cast< unsigned char >(*mPosition)))
751 {
752 num = num*10 + (*mPosition-'0');
753 ++mPosition;
754 }
755
756 switch(mPosition-begin)
757 {
758 case 0:
759 fail(__FILE__, __LINE__,"Expected a digit");
760 case 1:
761 case 2:
762 case 3:
763 case 4:
764 case 5:
765 case 6:
766 case 7:
767 case 8:
768 case 9:
769 break;
770 case 10:
771 if(*begin<'4')
772 {
773 break;
774 }
775 else if(*begin=='4' && num >= 4000000000UL)
776 {
777 break;
778 }
779 default:
780 fail(__FILE__, __LINE__,"Overflow detected");
781 }
782
783 return num;
784}
785
788{
789 const char* begin=mPosition;
790 uint64_t num = 0;
791 while (!eof() && isdigit(static_cast< unsigned char >(*mPosition)))
792 {
793 num = num*10 + (*mPosition-'0');
794 ++mPosition;
795 }
796
797 switch(mPosition-begin)
798 {
799 case 0:
800 fail(__FILE__, __LINE__,"Expected a digit");
801 case 1:
802 case 2:
803 case 3:
804 case 4:
805 case 5:
806 case 6:
807 case 7:
808 case 8:
809 case 9:
810 case 10:
811 case 11:
812 case 12:
813 case 13:
814 case 14:
815 case 15:
816 case 16:
817 case 17:
818 case 18:
819 case 19:
820 break;
821 case 20:
822 if(*begin=='1' && num >= 10000000000000000000ULL)
823 {
824 break;
825 }
826 default:
827 fail(__FILE__, __LINE__,"Overflow detected");
828 }
829
830 return num;
831}
832
833#ifndef RESIP_FIXED_POINT
834float
836{
837 const char* s = mPosition;
838 try
839 {
840 float mant = 0.0;
841 int num = integer();
842
843 if (*mPosition == '.')
844 {
845 skipChar();
846 const char* pos = mPosition;
847 mant = float(integer());
848 int s = int(mPosition - pos);
849 while (s--)
850 {
851 mant /= 10.0;
852 }
853 }
854 return num + mant;
855 }
856 catch (ParseException&)
857 {
858 Data msg("Expected a floating point value, got: ");
859 msg += Data(s, (Data::size_type)(mPosition - s));
860 fail(__FILE__, __LINE__,msg);
861 return 0.0;
862 }
863}
864#endif
865
866int
868{
869 // parse a qvalue into an integer between 0 and 1000 (ex: 1.0 -> 1000, 0.8 -> 800, 0.05 -> 50)
870 const char* s = mPosition;
871 try
872 {
873 int num = integer();
874 if (num == 1)
875 {
876 num = 1000;
877 }
878 else if (num != 0)
879 {
880 // error: qvalue must start with 1 or 0
881 return 0;
882 }
883
884 if (!eof() && *mPosition == '.')
885 {
886 skipChar();
887
888 int i = 100;
889 while(!eof() && isdigit(static_cast< unsigned char >(*mPosition)) && i)
890 {
891 num += (*mPosition-'0') * i;
892 i /= 10;
893 skipChar();
894 }
895 }
896 return num;
897 }
898 catch (ParseException&)
899 {
900 Data msg("Expected a floating point value, got: ");
901 msg += Data(s, (Data::size_type)(mPosition - s));
902 fail(__FILE__, __LINE__,msg);
903 return 0;
904 }
905}
906
907
908Data
909spaces(unsigned int numSpaces)
910{
911 Data sps(numSpaces, Data::Preallocate);
912 for (unsigned int i = 0; i < numSpaces; i++)
913 {
914 sps += ' ';
915 }
916 return sps;
917}
918
919Data
920escapeAndAnnotate(const char* buffer,
921 Data::size_type size,
922 const char* position)
923{
924 Data ret(2*size+16, Data::Preallocate);
925
926 const char* lastReturn = buffer;
927 int lineCount = 0;
928 bool doneAt = false;
929
930 const char* p = buffer;
931 for (unsigned int i = 0; i < size; i++)
932 {
933 unsigned char c = *p++;
934
935 switch (c)
936 {
937 case 0x0D: // CR
938 {
939 continue;
940 }
941 case 0x0A: // LF
942 {
943 if (!doneAt && p >= position)
944 {
945 ret += "[CRLF]\n";
946 ret += spaces((unsigned int)(position - lastReturn));
947 ret += "^[CRLF]\n";
948 doneAt = true;
949 }
950 else
951 {
952 lastReturn = p;
953 ret += c;
954 }
955 lineCount++;
956 continue;
957 }
958 }
959
960 if (iscntrl(static_cast< unsigned char >(c)) || (c >= 0x7F))
961 {
962 ret +='*'; // indicates unprintable character
963 continue;
964 }
965
966 ret += c;
967 }
968 if (!doneAt && p >= position)
969 {
970 ret += "\n";
971 ret += spaces((unsigned int)(position - lastReturn));
972 ret += "^\n";
973 }
974
975 return ret;
976}
977
978void
979ParseBuffer::fail(const char* file, unsigned int line, const Data& detail) const
980{
981 Data errmsg;
982 {
983 DataStream ds(errmsg);
984 ds << file << ":" << line
985 << ", Parse failed ";
986
987 if (detail != Data::Empty) ds << detail << ' ' ;
988
989 ds << "in context: " << mErrorContext
990 << std::endl
991 << escapeAndAnnotate(mBuff, (Data::size_type)(mEnd - mBuff), mPosition);
992
993 ds.flush();
994 }
995 DebugLog(<<errmsg);
996 throw ParseException(errmsg, mErrorContext, file, line);
997}
998
999ParseBuffer::Pointer::Pointer(const ParseBuffer& pb,
1000 const char* position,
1001 bool atEof)
1002 : mPb(pb),
1003 mPosition(position),
1004 mIsValid(!atEof)
1005{}
1006
1007ParseBuffer::Pointer::Pointer(const CurrentPosition& pos) :
1008 mPb(pos.mPb),
1009 mPosition(pos),
1010 mIsValid(pos.mPb.valid())
1011{}
1012
1013const char&
1014ParseBuffer::Pointer::operator*() const
1015{
1016 if (mIsValid)
1017 {
1018 return *mPosition;
1019 }
1020 else
1021 {
1022 throw ParseException(msg, mPb.getContext(), __FILE__, __LINE__);
1023 }
1024}
1025
1026/* ====================================================================
1027 * The Vovida Software License, Version 1.0
1028 *
1029 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
1030 *
1031 * Redistribution and use in source and binary forms, with or without
1032 * modification, are permitted provided that the following conditions
1033 * are met:
1034 *
1035 * 1. Redistributions of source code must retain the above copyright
1036 * notice, this list of conditions and the following disclaimer.
1037 *
1038 * 2. Redistributions in binary form must reproduce the above copyright
1039 * notice, this list of conditions and the following disclaimer in
1040 * the documentation and/or other materials provided with the
1041 * distribution.
1042 *
1043 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1044 * and "Vovida Open Communication Application Library (VOCAL)" must
1045 * not be used to endorse or promote products derived from this
1046 * software without prior written permission. For written
1047 * permission, please contact vocal@vovida.org.
1048 *
1049 * 4. Products derived from this software may not be called "VOCAL", nor
1050 * may "VOCAL" appear in their name, without prior written
1051 * permission of Vovida Networks, Inc.
1052 *
1053 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1054 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1055 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1056 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1057 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1058 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1059 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1060 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1061 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1062 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1063 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1064 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1065 * DAMAGE.
1066 *
1067 * ====================================================================
1068 *
1069 * This software consists of voluntary contributions made by Vovida
1070 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1071 * Inc. For more information on Vovida Networks, Inc., please see
1072 * <http://www.vovida.org/>.
1073 *
1074 */
#define DebugLog(args_)
Definition Logger.hxx:128
static const unsigned char hexToByte[256]
Data spaces(unsigned int numSpaces)
static Data CRLF("\r\n")
Data escapeAndAnnotate(const char *buffer, Data::size_type size, const char *position)
#define resip_assert(x)
This file needs to work for both C and C++ code.
An iostream that operates on an existing Data.
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
static const Data Empty
Constant that represents a zero-length data.
Definition Data.hxx:882
@ Share
The Data instance will use the buffer in a read-only mode.
Definition Data.hxx:266
@ Take
The Data instance takes complete ownership of the buffer.
Definition Data.hxx:272
static const PreallocateType Preallocate
used only to disambiguate constructors
Definition Data.hxx:116
size_t size_type
Definition Data.hxx:94
size_type size() const noexcept
Returns the number of bytes in this Data.
Definition Data.hxx:599
const char * data() const noexcept
Returns a pointer to the contents of this Data.
Definition Data.hxx:608
Provides string-parsing functionality with protection from buffer overflow.
CurrentPosition skipLWS()
CurrentPosition skipNonWhitespace()
void dataUnescaped(Data &data, const char *start) const
const char * skipBackToChar(char c)
uint32_t uInt32()
dcm! – merge these, ask about length checks
Pointer start() const
ParseBuffer & operator=(const ParseBuffer &other)
ParseBuffer(const char *buff, size_t len, const Data &errorContext=Data::Empty)
static const char * ParamTerm
const char * skipBackChar()
CurrentPosition skipWhitespace()
CurrentPosition skipToChars(const char *cs)
static bool oneOf(char c, const char *cs)
CurrentPosition skipChars(const char *cs)
void assertNotEof() const
CurrentPosition skipToOneOf(const char *cs)
CurrentPosition skipChar()
CurrentPosition skipToTermCRLF()
void fail(const char *file, unsigned int line, const Data &errmsg=Data::Empty) const
void data(Data &data, const char *start) const
make the passed in data share memory with the buffer (uses Data::Share)
const char * skipToEndQuote(char quote='"')
const char * skipBackWhitespace()
const char * skipBackToOneOf(const char *cs)
static const char * Whitespace
BaseException used to indicate parse failures.
dcm! – add UnusedChecking(_enum) below;
unsigned long long uint64_t
Definition Stun.hxx:39
unsigned int uint32_t
Definition Stun.hxx:34
unsigned char uint8_t
Definition Stun.hxx:29