/*=export_func ao_string_cook_escape_char * private: * * what: escape-process a string fragment * arg: + char const * + pzScan + points to character after the escape + * arg: + char * + pRes + Where to put the result byte + * arg: + unsigned int + nl_ch + replacement char if scanned char is \n + * * ret-type: unsigned int * ret-desc: The number of bytes consumed processing the escaped character. * * doc: * * This function converts "t" into "\t" and all your other favorite * escapes, including numeric ones: hex and ocatal, too. * The returned result tells the caller how far to advance the * scan pointer (passed in). The default is to just pass through the * escaped character and advance the scan by one. * * Some applications need to keep an escaped newline, others need to * suppress it. This is accomplished by supplying a '\n' replacement * character that is different from \n, if need be. For example, use * 0x7F and never emit a 0x7F. * * err: @code{NULL} is returned if the string is mal-formed. =*/ unsigned int ao_string_cook_escape_char(char const * pzIn, char * pRes, uint_t nl) { unsigned int res = 1; switch (*pRes = *pzIn++) { case NUL: /* NUL - end of input string */ return 0; case '\r': if (*pzIn != NL) return 1; res++; /* FALLTHROUGH */ case NL: /* NL - emit newline */ *pRes = (char)nl; return res; case 'a': *pRes = '\a'; break; case 'b': *pRes = '\b'; break; case 'f': *pRes = '\f'; break; case 'n': *pRes = NL; break; case 'r': *pRes = '\r'; break; case 't': *pRes = '\t'; break; case 'v': *pRes = '\v'; break; case 'x': case 'X': /* HEX Escape */ if (IS_HEX_DIGIT_CHAR(*pzIn)) { char z[4]; unsigned int ct = 0; do { z[ct] = pzIn[ct]; if (++ct >= 2) break; } while (IS_HEX_DIGIT_CHAR(pzIn[ct])); z[ct] = NUL; *pRes = (char)strtoul(z, NULL, 16); return ct + 1; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { /* * IF the character copied was an octal digit, * THEN set the output character to an octal value. * The 3 octal digit result might exceed 0xFF, so check it. */ char z[4]; unsigned long val; unsigned int ct = 0; z[ct++] = *--pzIn; while (IS_OCT_DIGIT_CHAR(pzIn[ct])) { z[ct] = pzIn[ct]; if (++ct >= 3) break; } z[ct] = NUL; val = strtoul(z, NULL, 8); if (val > 0xFF) val = 0xFF; *pRes = (char)val; return ct; } default: /* quoted character is result character */; } return res; }
/*=export_func ao_string_cook_escape_char * private: * * what: escape-process a string fragment * arg: + char const* + pzScan + points to character after the escape + * arg: + char* + pRes + Where to put the result byte + * arg: + unsigned int + nl_ch + replacement char if scanned char is \n + * * ret-type: unsigned int * ret-desc: The number of bytes consumed processing the escaped character. * * doc: * * This function converts "t" into "\t" and all your other favorite * escapes, including numeric ones: hex and ocatal, too. * The returned result tells the caller how far to advance the * scan pointer (passed in). The default is to just pass through the * escaped character and advance the scan by one. * * Some applications need to keep an escaped newline, others need to * suppress it. This is accomplished by supplying a '\n' replacement * character that is different from \n, if need be. For example, use * 0x7F and never emit a 0x7F. * * err: @code{NULL} is returned if the string is mal-formed. =*/ unsigned int ao_string_cook_escape_char( char const* pzIn, char* pRes, u_int nl ) { unsigned int res = 1; switch (*pRes = *pzIn++) { case NUL: /* NUL - end of input string */ return 0; case '\r': if (*pzIn != '\n') return 1; res++; /* FALLTHROUGH */ case '\n': /* NL - emit newline */ *pRes = (char)nl; return res; case 'a': *pRes = '\a'; break; case 'b': *pRes = '\b'; break; case 'f': *pRes = '\f'; break; case 'n': *pRes = '\n'; break; case 'r': *pRes = '\r'; break; case 't': *pRes = '\t'; break; case 'v': *pRes = '\v'; break; case 'x': case 'X': /* HEX Escape */ if (IS_HEX_DIGIT_CHAR(*pzIn)) { char z[4], *pz = z; do *(pz++) = *(pzIn++); while (IS_HEX_DIGIT_CHAR(*pzIn) && (pz < z + 2)); *pz = NUL; *pRes = (unsigned char)strtoul(z, NULL, 16); res += pz - z; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { /* * IF the character copied was an octal digit, * THEN set the output character to an octal value */ char z[4], *pz = z + 1; unsigned long val; z[0] = *pRes; while (IS_OCT_DIGIT_CHAR(*pzIn) && (pz < z + 3)) *(pz++) = *(pzIn++); *pz = NUL; val = strtoul(z, NULL, 8); if (val > 0xFF) val = 0xFF; *pRes = (unsigned char)val; res = pz - z; break; } default: ; } return res; }