13#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
17const Data ParseBuffer::Pointer::msg(
"dereferenced ParseBuffer eof");
20 const Data& errorContext)
24 mErrorContext(errorContext)
28 const Data& errorContext)
31 mEnd(buff+strlen(buff)),
32 mErrorContext(errorContext)
36 const Data& errorContext)
39 mEnd(mBuff + data.size()),
40 mErrorContext(errorContext)
45 mPosition(rhs.mPosition),
47 mErrorContext(rhs.mErrorContext)
56 mPosition = rhs.mPosition;
63ParseBuffer::CurrentPosition
68 fail(__FILE__, __LINE__,
"skipped over eof");
72 Data msg(
"expected '");
75 fail(__FILE__, __LINE__,msg);
78 return CurrentPosition(*
this);
81ParseBuffer::CurrentPosition
84 const char* match = cs;
87 if (
eof() || (*match != *mPosition))
89 Data msg(
"Expected \"");
92 fail(__FILE__, __LINE__,msg);
97 return CurrentPosition(*
this);
100ParseBuffer::CurrentPosition
103 const char* match = cs.
data();
106 if (
eof() || (*match != *mPosition))
108 Data msg(
"Expected \"");
111 fail(__FILE__, __LINE__,msg);
116 return CurrentPosition(*
this);
119ParseBuffer::CurrentPosition
123 while (mPosition < mEnd)
131 return CurrentPosition(*
this);
136 return CurrentPosition(*
this);
139ParseBuffer::CurrentPosition
142 while (mPosition < mEnd)
155 return CurrentPosition(*
this);
158 return CurrentPosition(*
this);
165ParseBuffer::CurrentPosition
170 while (mPosition < mEnd)
172 char c = *mPosition++;
177 if (c ==
'\r' || c ==
'\n')
182 switch (*mPosition++)
218 return CurrentPosition(*
this);
222 return CurrentPosition(*
this);
226ParseBuffer::CurrentPosition
229 while (mPosition < mEnd)
233 if ((*mPosition !=
' ' &&
234 *mPosition !=
'\t' &&
237 ((mPosition-3 < mBuff || *(mPosition-3) !=
'\\') ||
238 (mPosition-4 > mBuff && *(mPosition-4) ==
'\\'))))
241 return CurrentPosition(*
this);
244 return CurrentPosition(*
this);
247ParseBuffer::CurrentPosition
251 unsigned int l = (
unsigned int)strlen(cs);
257 while (mPosition < mEnd - l + 1)
261 for (
unsigned int i = 0; i < l; i++)
263 if (*cpos++ != *rpos++)
269 return CurrentPosition(*
this);
274 return CurrentPosition(*
this);
277ParseBuffer::CurrentPosition
280 const char* begSub = sub.mBuf;
281 const char* endSub = sub.mBuf + sub.mSize;
284 fail(__FILE__, __LINE__,
"ParseBuffer::skipToChars() called with an "
285 "empty string. Don't do this!");
291 const char* searchPos = mPosition;
292 const char* subPos = sub.mBuf;
294 while (subPos != endSub)
296 if (searchPos == mEnd)
300 return CurrentPosition(*
this);
302 if (*subPos++ != *searchPos++)
310 return CurrentPosition(*
this);
340ParseBuffer::CurrentPosition
343 while (mPosition < mEnd)
345 if (
oneOf(*mPosition, cs))
347 return CurrentPosition(*
this);
354 return CurrentPosition(*
this);
357ParseBuffer::CurrentPosition
361 while (mPosition < mEnd)
363 if (
oneOf(*mPosition, cs1) ||
364 oneOf(*mPosition, cs2))
366 return CurrentPosition(*
this);
373 return CurrentPosition(*
this);
376ParseBuffer::CurrentPosition
379 while (mPosition < mEnd)
381 if (
oneOf(*mPosition, cs))
383 return CurrentPosition(*
this);
390 return CurrentPosition(*
this);
393ParseBuffer::CurrentPosition
397 while (mPosition < mEnd)
399 if (
oneOf(*mPosition, cs1) ||
400 oneOf(*mPosition, cs2))
402 return CurrentPosition(*
this);
409 return CurrentPosition(*
this);
415 while (mPosition < mEnd)
418 if (*mPosition ==
'\\')
422 else if (*mPosition == quote)
433 Data msg(
"Missing '");
436 fail(__FILE__,__LINE__,msg);
446 fail(__FILE__, __LINE__,
"backed over beginning of buffer");
457 switch (*(--mPosition))
486 fail(__FILE__, __LINE__,
"backed over beginning of buffer");
488 if (*(--mPosition) != c)
490 Data msg(
"Expected '");
493 fail(__FILE__, __LINE__,msg);
508 if (*(--mPosition) == c)
521 if (
oneOf(*(--mPosition),cs))
534 fail(__FILE__, __LINE__,
"Bad anchor position");
541 data.mSize = (
unsigned int)(mPosition -
start);
550 'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
551 'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
552 'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
553 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
'k',
'k',
'k',
'k',
'k',
'k',
554 'k',0xA,0xB,0xC,0xD,0xE,0xF,
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
555 'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
556 'k',0xA,0xB,0xC,0xD,0xE,0xF,
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
557 'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
558 'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
559 'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
560 'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
561 'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
562 'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
563 'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
564 'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k',
'k'
573 fail(__FILE__, __LINE__,
"Bad anchor position");
577 const char* current =
start;
578 while (current < mPosition)
593 if ((
size_t)(mPosition-
start) > dataToUse.mCapacity)
598 char* target = dataToUse.mBuf;
599 const char* current =
start;
600 while (current < mPosition)
605 if (mPosition - current < 2)
607 fail(__FILE__, __LINE__,
"Illegal escaping");
609 const char high =
hexToByte[(
unsigned char)*current];
610 const char low =
hexToByte[(
unsigned char)*(current + 1)];
611 if (high!=
'k' && low!=
'k')
613 unsigned char escaped = 0;
614 escaped = high << 4 | low;
621 if (escaped > 31 && escaped != 127 && escaped != 58)
629 *target++ = *current++;
630 *target++ = *current++;
635 fail(__FILE__, __LINE__,
"Illegal escaping, not hex");
640 *target++ = *current++;
653 fail(__FILE__, __LINE__,
"Bad anchor position");
665 fail(__FILE__, __LINE__,
"Expected a digit, got eof ");
668 bool negative =
false;
669 if (*mPosition ==
'-')
675 else if (*mPosition ==
'+')
681 if (!isdigit(
static_cast< unsigned char >(*mPosition)))
683 Data msg(
"Expected a digit, got: ");
685 fail(__FILE__, __LINE__,msg);
689#pragma warning( push )
690#pragma warning( disable : 4146)
693 const unsigned int absoluteLimit = negative ? -(
unsigned int)INT_MIN : INT_MAX;
695 const unsigned int border = absoluteLimit / 10;
697 const unsigned int digitLimit = absoluteLimit % 10;
699 unsigned int num = 0;
700 while (!
eof() && isdigit(
static_cast< unsigned char >(*mPosition)))
702 const unsigned int c = *mPosition++ -
'0';
703 if (num > border || (num == border && c > digitLimit)) {
704 fail(__FILE__, __LINE__,
"Overflow detected.");
715#pragma warning( pop )
722 const char* begin=mPosition;
725 while (!
eof() && isdigit(
static_cast< unsigned char >(*mPosition)))
728 num = num*10 + (*mPosition-
'0');
731 fail(__FILE__, __LINE__,
"Overflow detected.");
738 fail(__FILE__, __LINE__,
"Expected a digit");
748 const char* begin=mPosition;
750 while (!
eof() && isdigit(
static_cast< unsigned char >(*mPosition)))
752 num = num*10 + (*mPosition-
'0');
756 switch(mPosition-begin)
759 fail(__FILE__, __LINE__,
"Expected a digit");
775 else if(*begin==
'4' && num >= 4000000000UL)
780 fail(__FILE__, __LINE__,
"Overflow detected");
789 const char* begin=mPosition;
791 while (!
eof() && isdigit(
static_cast< unsigned char >(*mPosition)))
793 num = num*10 + (*mPosition-
'0');
797 switch(mPosition-begin)
800 fail(__FILE__, __LINE__,
"Expected a digit");
822 if(*begin==
'1' && num >= 10000000000000000000ULL)
827 fail(__FILE__, __LINE__,
"Overflow detected");
833#ifndef RESIP_FIXED_POINT
837 const char* s = mPosition;
843 if (*mPosition ==
'.')
846 const char* pos = mPosition;
848 int s = int(mPosition - pos);
858 Data msg(
"Expected a floating point value, got: ");
860 fail(__FILE__, __LINE__,msg);
870 const char* s = mPosition;
884 if (!
eof() && *mPosition ==
'.')
889 while(!
eof() && isdigit(
static_cast< unsigned char >(*mPosition)) && i)
891 num += (*mPosition-
'0') * i;
900 Data msg(
"Expected a floating point value, got: ");
902 fail(__FILE__, __LINE__,msg);
912 for (
unsigned int i = 0; i < numSpaces; i++)
922 const char* position)
926 const char* lastReturn = buffer;
930 const char* p = buffer;
931 for (
unsigned int i = 0; i < size; i++)
933 unsigned char c = *p++;
943 if (!doneAt && p >= position)
946 ret +=
spaces((
unsigned int)(position - lastReturn));
960 if (iscntrl(
static_cast< unsigned char >(c)) || (c >= 0x7F))
968 if (!doneAt && p >= position)
971 ret +=
spaces((
unsigned int)(position - lastReturn));
984 ds << file <<
":" << line
985 <<
", Parse failed ";
989 ds <<
"in context: " << mErrorContext
999ParseBuffer::Pointer::Pointer(
const ParseBuffer& pb,
1000 const char* position,
1003 mPosition(position),
1007ParseBuffer::Pointer::Pointer(
const CurrentPosition& pos) :
1010 mIsValid(pos.mPb.valid())
1014ParseBuffer::Pointer::operator*()
const
static const unsigned char hexToByte[256]
Data spaces(unsigned int numSpaces)
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.
static const Data Empty
Constant that represents a zero-length data.
@ Share
The Data instance will use the buffer in a read-only mode.
@ Take
The Data instance takes complete ownership of the buffer.
static const PreallocateType Preallocate
used only to disambiguate constructors
size_type size() const noexcept
Returns the number of bytes in this Data.
const char * data() const noexcept
Returns a pointer to the contents of this Data.
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
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