/* Unescape the buffer pointed to by s 'in-place' using the (un)escape mechanizm described at http://www.postgresql.org/docs/9.0/static/datatype-binary.html The new size of s is assigned to r. Returns s. See PostgresqlResultSet_getBlob() below for usage and further info. See also Postgres' PQunescapeBytea() function which this function mirrors except it does not allocate a new string. */ static inline const void *unescape_bytea(uchar_t *s, int len, int *r) { assert(s); register int i, j; if (s[0] == '\\' && s[1] == 'x') { // bytea hex format static const uchar_t hex[128] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; for (i = 0, j = 2; j < len; j++) { /* According to the doc, whitespace between hex pairs are allowed. Blarg!! */ if (isxdigit(s[j])) { s[i] = hex[s[j]] << 4; s[i] |= hex[s[j + 1]]; i++; j++; } } } else { // bytea escaped format uchar_t byte; for (i = j = 0; j < len; i++, j++) { if ((s[i] = s[j]) == '\\') { if (s[j + 1] == '\\') j++; else if ((ISFIRSTOCTDIGIT(s[j + 1])) && (ISOCTDIGIT(s[j + 2])) && (ISOCTDIGIT(s[j + 3]))) { byte = OCTVAL(s[j + 1]); byte = (byte << 3) + OCTVAL(s[j + 2]); byte = (byte << 3) + OCTVAL(s[j + 3]); s[i] = byte; j += 3; } } } } *r = i; if (i < j) s[i] = 0; // If unescape was performed, terminate the buffer to mirror postgres behavior return s; }
int esc( const tchar * * s) { /* Map escape sequences into their equivalent symbols. Return * the equivalent ASCII character. *s is advanced past the * escape sequence. If no escape sequence is present, the * current character is returned and the string is advanced by * one. The following are recognized: * * \b backspace * \f formfeed * \n newline * \r carriage return * \s space * \t tab * \e ASCII ESC character ('\033') * \DDD number formed of 1-3 octal digits * \xDDD number formed of 1-3 hex digits * \^C C = any letter. Control code */ int rval; if( **s != _T('\\') ) rval = *( (*s)++ ); else { ++(*s); /* Skip the \ */ switch( toupper(**s) ) { case _T('\0'): rval = _T('\\'); break; case _T('B'): rval = _T('\b') ; break; case _T('F'): rval = _T('\f') ; break; case _T('N'): rval = _T('\n') ; break; case _T('R'): rval = _T('\r') ; break; case _T('S'): rval = _T(' ') ; break; case _T('T'): rval = _T('\t') ; break; case _T('E'): rval = _T('\033'); break; case _T('^'): rval = *++(*s) ; rval = _toupper(rval) - _T('@') ; break; case _T('X'): rval = 0; ++(*s); if( ISHEXDIGIT(**s) ) { rval = hex2bin( *(*s)++ ); } if( ISHEXDIGIT(**s) ) { rval <<= 4; rval |= hex2bin( *(*s)++ ); } if( ISHEXDIGIT(**s) ) { rval <<= 4; rval |= hex2bin( *(*s)++ ); } --(*s); break; default: if( !ISOCTDIGIT(**s) ) rval = **s; else { ++(*s); rval = oct2bin( *(*s)++ ); if( ISOCTDIGIT(**s) ) { rval <<= 3; rval |= oct2bin( *(*s)++ ); } if( ISOCTDIGIT(**s) ) { rval <<= 3; rval |= oct2bin( *(*s)++ ); } --(*s); } break; } ++(*s); } return rval; }