Fix epicsStrnEscapedFromRaw() and epicsStrnRawFromEscaped()
Major rewrites; the original epicsStrnRawFromEscaped() could read beyond the end of the input buffer if the input count ended in the middle of an octal or hex escape sequence. Zero termination did not always match the return count, and hex escapes were always 2 digits, contrary to the C standard. New versions don't use epicsSnprintf() or sscanf() for hex and octal conversions, so should be slightly faster. Added 81 new tests to check the above issues.
This commit is contained in:
@@ -14,6 +14,11 @@
|
||||
<h2 align="center">Changes between 3.15.0.2 and 3.15.1</h2>
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
<h3>epicsStrnEscapedFromRaw() and epicsStrnRawFromEscaped()</h3>
|
||||
|
||||
<p>These routines have been rewritten; the previous implementations did not
|
||||
always behave exactly as specified.</p>
|
||||
|
||||
<h3>Shared Library Versions</h3>
|
||||
|
||||
<p>On architectures that can support it, the shared library version number for
|
||||
|
||||
@@ -29,148 +29,165 @@
|
||||
#include "epicsString.h"
|
||||
|
||||
/* Deprecated, use epicsStrnRawFromEscaped() instead */
|
||||
int dbTranslateEscape(char *to, const char *from)
|
||||
int dbTranslateEscape(char *dst, const char *src)
|
||||
{
|
||||
size_t big_enough = strlen(from)+1;
|
||||
return epicsStrnRawFromEscaped(to, big_enough, from, big_enough);
|
||||
size_t big_enough = strlen(src) + 1;
|
||||
|
||||
return epicsStrnRawFromEscaped(dst, big_enough, src, big_enough);
|
||||
}
|
||||
|
||||
int epicsStrnRawFromEscaped(char *to, size_t outsize, const char *from,
|
||||
size_t inlen)
|
||||
int epicsStrnRawFromEscaped(char *dst, size_t dstlen, const char *src,
|
||||
size_t srclen)
|
||||
{
|
||||
const char *pfrom = from;
|
||||
char *pto = to;
|
||||
char c;
|
||||
size_t nto = 0, nfrom = 0;
|
||||
int rem = dstlen;
|
||||
int ndst = 0;
|
||||
|
||||
if (outsize == 0)
|
||||
return 0;
|
||||
while (srclen--) {
|
||||
int c = *src++;
|
||||
#define OUT(chr) if (--rem > 0) ndst++, *dst++ = chr
|
||||
|
||||
while ((c = *pfrom++) && nto < outsize && nfrom < inlen) {
|
||||
nfrom++;
|
||||
if (c == '\\') {
|
||||
if (nfrom >= inlen || *pfrom == '\0') break;
|
||||
switch (*pfrom) {
|
||||
case 'a': pfrom++; nfrom++; *pto++ = '\a' ; nto++; break;
|
||||
case 'b': pfrom++; nfrom++; *pto++ = '\b' ; nto++; break;
|
||||
case 'f': pfrom++; nfrom++; *pto++ = '\f' ; nto++; break;
|
||||
case 'n': pfrom++; nfrom++; *pto++ = '\n' ; nto++; break;
|
||||
case 'r': pfrom++; nfrom++; *pto++ = '\r' ; nto++; break;
|
||||
case 't': pfrom++; nfrom++; *pto++ = '\t' ; nto++; break;
|
||||
case 'v': pfrom++; nfrom++; *pto++ = '\v' ; nto++; break;
|
||||
case '\\': pfrom++; nfrom++; *pto++ = '\\' ; nto++; break;
|
||||
case '\?': pfrom++; nfrom++; *pto++ = '\?' ; nto++; break;
|
||||
case '\'': pfrom++; nfrom++; *pto++ = '\'' ; nto++; break;
|
||||
case '\"': pfrom++; nfrom++; *pto++ = '\"' ; nto++; break;
|
||||
case '0' :case '1' :case '2' :case '3' :
|
||||
case '4' :case '5' :case '6' :case '7' :
|
||||
{
|
||||
int i;
|
||||
char strval[4] = {0,0,0,0};
|
||||
unsigned int ival;
|
||||
unsigned char *pchar;
|
||||
if (!c) break;
|
||||
|
||||
for (i=0; i<3; i++) {
|
||||
if ((*pfrom < '0') || (*pfrom > '7')) break;
|
||||
strval[i] = *pfrom++; nfrom++;
|
||||
}
|
||||
sscanf(strval,"%o",&ival);
|
||||
pchar = (unsigned char *)(pto++); nto++;
|
||||
*pchar = (unsigned char)(ival);
|
||||
}
|
||||
break;
|
||||
case 'x' :
|
||||
{
|
||||
int i;
|
||||
char strval[3] = {0,0,0};
|
||||
unsigned int ival;
|
||||
unsigned char *pchar;
|
||||
|
||||
pfrom++; /*skip the x*/
|
||||
for (i=0; i<2; i++) {
|
||||
if (!isxdigit((int)*pfrom)) break;
|
||||
strval[i] = *pfrom++; nfrom++;
|
||||
}
|
||||
sscanf(strval,"%x",&ival);
|
||||
pchar = (unsigned char *)(pto++); nto++;
|
||||
*pchar = (unsigned char)(ival);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*pto++ = *pfrom++; nfrom++; nto++;
|
||||
}
|
||||
} else {
|
||||
*pto++ = c; nto++;
|
||||
input:
|
||||
if (c != '\\') {
|
||||
OUT(c);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (nto == outsize)
|
||||
pto--;
|
||||
*pto = '\0';
|
||||
return nto;
|
||||
}
|
||||
|
||||
int epicsStrnEscapedFromRaw(char *outbuf, size_t outsize, const char *inbuf,
|
||||
size_t inlen)
|
||||
{
|
||||
int maxout = outsize;
|
||||
int nout = 0;
|
||||
int len;
|
||||
char *outpos = outbuf;
|
||||
if (!srclen-- || !(c = *src++)) break;
|
||||
|
||||
while (inlen--) {
|
||||
char c = *inbuf++;
|
||||
switch (c) {
|
||||
case '\a': len = epicsSnprintf(outpos, maxout, "\\a"); break;
|
||||
case '\b': len = epicsSnprintf(outpos, maxout, "\\b"); break;
|
||||
case '\f': len = epicsSnprintf(outpos, maxout, "\\f"); break;
|
||||
case '\n': len = epicsSnprintf(outpos, maxout, "\\n"); break;
|
||||
case '\r': len = epicsSnprintf(outpos, maxout, "\\r"); break;
|
||||
case '\t': len = epicsSnprintf(outpos, maxout, "\\t"); break;
|
||||
case '\v': len = epicsSnprintf(outpos, maxout, "\\v"); break;
|
||||
case '\\': len = epicsSnprintf(outpos, maxout, "\\\\"); ; break;
|
||||
case '\'': len = epicsSnprintf(outpos, maxout, "\\'"); break;
|
||||
case '\"': len = epicsSnprintf(outpos, maxout, "\\\""); break;
|
||||
default:
|
||||
if (isprint((int)c))
|
||||
len = epicsSnprintf(outpos, maxout, "%c", c);
|
||||
else
|
||||
len = epicsSnprintf(outpos, maxout, "\\%03o",
|
||||
(unsigned char)c);
|
||||
break;
|
||||
}
|
||||
if (len<0) return -1;
|
||||
nout += len;
|
||||
if (nout < outsize) {
|
||||
maxout -= len;
|
||||
outpos += len;
|
||||
} else {
|
||||
outpos = outpos + maxout -1;
|
||||
maxout = 1;
|
||||
case 'a': OUT('\a'); break;
|
||||
case 'b': OUT('\b'); break;
|
||||
case 'f': OUT('\f'); break;
|
||||
case 'n': OUT('\n'); break;
|
||||
case 'r': OUT('\r'); break;
|
||||
case 't': OUT('\t'); break;
|
||||
case 'v': OUT('\v'); break;
|
||||
case '\\': OUT('\\'); break;
|
||||
case '\'': OUT('\''); break;
|
||||
case '\"': OUT('\"'); break;
|
||||
|
||||
case '0' :case '1' :case '2' :case '3' :
|
||||
case '4' :case '5' :case '6' :case '7' :
|
||||
{ /* \ooo */
|
||||
unsigned int u = c - '0';
|
||||
|
||||
if (!srclen-- || !(c = *src++)) {
|
||||
OUT(u); goto done;
|
||||
}
|
||||
if (c < '0' || c > '7') {
|
||||
OUT(u); goto input;
|
||||
}
|
||||
u = u << 3 | (c - '0');
|
||||
|
||||
if (!srclen-- || !(c = *src++)) {
|
||||
OUT(u); goto done;
|
||||
}
|
||||
if (c < '0' || c > '7') {
|
||||
OUT(u); goto input;
|
||||
}
|
||||
u = u << 3 | (c - '0');
|
||||
|
||||
if (u > 0377) {
|
||||
/* Undefined behaviour! */
|
||||
}
|
||||
OUT(u);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'x' :
|
||||
{ /* \xXXX... */
|
||||
unsigned int u = 0;
|
||||
|
||||
if (!srclen-- || !(c = *src++))
|
||||
goto done;
|
||||
|
||||
while (isxdigit(c)) {
|
||||
u = u << 4 | ((c > '9') ? toupper(c) - 'A' + 10 : c - '0');
|
||||
if (u > 0xff) {
|
||||
/* Undefined behaviour! */
|
||||
}
|
||||
if (!srclen-- || !(c = *src++)) {
|
||||
OUT(u);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
OUT(u);
|
||||
goto input;
|
||||
}
|
||||
|
||||
default:
|
||||
OUT(c);
|
||||
}
|
||||
#undef OUT
|
||||
}
|
||||
*outpos = '\0';
|
||||
return nout;
|
||||
done:
|
||||
if (dstlen)
|
||||
*dst = '\0';
|
||||
return ndst;
|
||||
}
|
||||
|
||||
size_t epicsStrnEscapedFromRawSize(const char *inbuf, size_t inlen)
|
||||
int epicsStrnEscapedFromRaw(char *dst, size_t dstlen, const char *src,
|
||||
size_t srclen)
|
||||
{
|
||||
size_t nout = inlen;
|
||||
int rem = dstlen;
|
||||
int ndst = 0;
|
||||
|
||||
while (inlen--) {
|
||||
char c = *inbuf++;
|
||||
if (dst == src)
|
||||
return -1;
|
||||
|
||||
while (srclen--) {
|
||||
int c = *src++;
|
||||
#define OUT(chr) ndst++; if (--rem > 0) *dst++ = chr
|
||||
|
||||
switch (c) {
|
||||
case '\a': OUT('\\'); OUT('a'); break;
|
||||
case '\b': OUT('\\'); OUT('b'); break;
|
||||
case '\f': OUT('\\'); OUT('f'); break;
|
||||
case '\n': OUT('\\'); OUT('n'); break;
|
||||
case '\r': OUT('\\'); OUT('r'); break;
|
||||
case '\t': OUT('\\'); OUT('t'); break;
|
||||
case '\v': OUT('\\'); OUT('v'); break;
|
||||
case '\\': OUT('\\'); OUT('\\'); break;
|
||||
case '\'': OUT('\\'); OUT('\''); break;
|
||||
case '\"': OUT('\\'); OUT('\"'); break;
|
||||
default:
|
||||
if (isprint(c)) {
|
||||
OUT(c);
|
||||
break;
|
||||
}
|
||||
OUT('\\');
|
||||
OUT('0' + ((c & 0300) >> 6));
|
||||
OUT('0' + ((c & 0070) >> 3));
|
||||
OUT('0' + (c & 0007));
|
||||
}
|
||||
#undef OUT
|
||||
}
|
||||
if (dstlen)
|
||||
*dst = '\0';
|
||||
return ndst;
|
||||
}
|
||||
|
||||
size_t epicsStrnEscapedFromRawSize(const char *src, size_t srclen)
|
||||
{
|
||||
size_t ndst = srclen;
|
||||
|
||||
while (srclen--) {
|
||||
int c = *src++;
|
||||
|
||||
switch (c) {
|
||||
case '\a': case '\b': case '\f': case '\n':
|
||||
case '\r': case '\t': case '\v': case '\\':
|
||||
case '\'': case '\"':
|
||||
nout++;
|
||||
ndst++;
|
||||
break;
|
||||
default:
|
||||
if (!isprint((int)c))
|
||||
nout += 3;
|
||||
if (!isprint(c))
|
||||
ndst += 3;
|
||||
}
|
||||
}
|
||||
return nout;
|
||||
return ndst;
|
||||
}
|
||||
|
||||
int epicsStrCaseCmp(const char *s1, const char *s2)
|
||||
|
||||
@@ -88,7 +88,7 @@ MAIN(epicsStringTest)
|
||||
char *s;
|
||||
int status;
|
||||
|
||||
testPlan(323);
|
||||
testPlan(402);
|
||||
|
||||
testChars();
|
||||
|
||||
@@ -125,41 +125,199 @@ MAIN(epicsStringTest)
|
||||
|
||||
testGlob();
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnEscapedFromRaw(result, 0, ABCD, 4);
|
||||
testOk(status == 4, "epicsStrnEscapedFromRaw(out, 0) -> %d (exp. 4)", status);
|
||||
testOk(result[0] == 'x', " No output");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 0, ABCD, 4);
|
||||
testOk(status == 0, "epicsStrnRawFromEscaped(out, 0) -> %d (exp. 0)", status);
|
||||
testOk(result[0] == 'x', " No output");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnEscapedFromRaw(result, 1, ABCD, 4);
|
||||
testOk(status == 4, "epicsStrnEscapedFromRaw(out, 1) -> %d (exp. 4)", status);
|
||||
testOk(result[0] == 0, " 0-terminated");
|
||||
testOk(result[1] == 'x', " No overrun");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 1, ABCD, 4);
|
||||
testOk(status == 0, "epicsStrnRawFromEscaped(out, 1) -> %d (exp. 0)", status);
|
||||
testOk(result[0] == 0, " 0-terminated");
|
||||
testOk(result[1] == 'x', " No overrun");
|
||||
|
||||
testDiag("Testing size = epicsStrnEscapedFromRawSize");
|
||||
|
||||
status = epicsStrnEscapedFromRawSize(ABCD, 3);
|
||||
testOk(status == 3, "size(\"ABCD\", 3) -> %d (exp. 3)", status);
|
||||
status = epicsStrnEscapedFromRawSize(ABCD, 4);
|
||||
testOk(status == 4, "size(\"ABCD\", 4) -> %d (exp. 4)", status);
|
||||
status = epicsStrnEscapedFromRawSize(ABCD, 5);
|
||||
testOk(status == 8, "size(\"ABCD\", 5) -> %d (exp. 8)", status);
|
||||
|
||||
testDiag("Testing esc = epicsStrnEscapedFromRaw(out, 4, ...)");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnEscapedFromRaw(result, 4, ABCD, 3);
|
||||
testOk(status == 3, "epicsStrnEscapedFromRaw returned %d (exp. 3)", status);
|
||||
testOk(result[4] == 'x', "epicsStrnEscapedFromRaw no buffer overrun");
|
||||
testOk(result[3] == 0, "epicsStrnEscapedFromRaw 0-terminated");
|
||||
testOk(status == 3, "esc(\"ABCD\", 3) -> %d (exp. 3)", status);
|
||||
testOk(result[3] == 0, " 0-terminated");
|
||||
testOk(result[4] == 'x', " No overrun");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnEscapedFromRaw(result, 4, ABCD, 4);
|
||||
testOk(status == 4, "epicsStrnEscapedFromRaw returned %d (exp. 4)", status);
|
||||
testOk(result[4] == 'x', "epicsStrnEscapedFromRaw no buffer overrun");
|
||||
testOk(result[3] == 0, "epicsStrnEscapedFromRaw 0-terminated");
|
||||
testOk(status == 4, "esc(\"ABCD\", 4) -> %d (exp. 4)", status);
|
||||
testOk(result[3] == 0, " 0-terminated");
|
||||
testOk(result[4] == 'x', " No overrun");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnEscapedFromRaw(result, 4, ABCDE, 5);
|
||||
testOk(status == 5, "epicsStrnEscapedFromRaw returned %d (exp. 5)", status);
|
||||
testOk(result[4] == 'x', "epicsStrnEscapedFromRaw no buffer overrun");
|
||||
testOk(result[3] == 0, "epicsStrnEscapedFromRaw 0-terminated");
|
||||
status = epicsStrnEscapedFromRaw(result, 4, ABCD, 5);
|
||||
testOk(status == 8, "esc(\"ABCD\", 5) -> %d (exp. 8)", status);
|
||||
testOk(result[3] == 0, " 0-terminated");
|
||||
testOk(result[4] == 'x', " No overrun");
|
||||
|
||||
testDiag("Testing raw = epicsStrnRawFromEscaped(out, 4, ...)");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, ABCD, 0);
|
||||
testOk(status == 0, "raw(\"ABCD\", 0) -> %d (exp. 0)", status);
|
||||
testOk(result[0] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, ABCD, 1);
|
||||
testOk(status == 1, "raw(\"ABCD\", 1) -> %d (exp. 1)", status);
|
||||
testOk(result[0] == 'A', " Char '%c' (exp. 'A')", result[0]);
|
||||
testOk(result[1] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, ABCD, 2);
|
||||
testOk(status == 2, "raw(\"ABCD\", 2) -> %d (exp. 2)", status);
|
||||
testOk(result[0] == 'A', " Char '%c' (exp. 'A')", result[0]);
|
||||
testOk(result[1] == 'B', " Char '%c' (exp. 'B')", result[1]);
|
||||
testOk(result[2] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, ABCD, 3);
|
||||
testOk(status == 3, "epicsStrnRawFromEscaped returned %d (exp. 3)", status);
|
||||
testOk(result[4] == 'x', "epicsStrnRawFromEscaped no buffer overrun");
|
||||
testOk(result[3] == 0, "epicsStrnRawFromEscaped 0-terminated");
|
||||
testOk(status == 3, "raw(\"ABCD\", 3) -> %d (exp. 3)", status);
|
||||
testOk(result[0] == 'A', " Char '%c' (exp. 'A')", result[0]);
|
||||
testOk(result[1] == 'B', " Char '%c' (exp. 'B')", result[1]);
|
||||
testOk(result[2] == 'C', " Char '%c' (exp. 'C')", result[2]);
|
||||
testOk(result[3] == 0, " 0-terminated");
|
||||
testOk(result[4] == 'x', " No write outside buffer");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, ABCD, 4);
|
||||
testOk(status == 4, "epicsStrnRawFromEscaped returned %d (exp. 4)", status);
|
||||
testOk(result[4] == 'x', "epicsStrnRawFromEscaped no buffer overrun");
|
||||
testOk(result[3] == 0, "epicsStrnRawFromEscaped 0-terminated");
|
||||
testOk(status == 3, "raw(\"ABCD\", 4) -> %d (exp. 3)", status);
|
||||
testOk(result[0] == 'A', " Char '%c' (exp. 'A')", result[0]);
|
||||
testOk(result[1] == 'B', " Char '%c' (exp. 'B')", result[1]);
|
||||
testOk(result[2] == 'C', " Char '%c' (exp. 'C')", result[2]);
|
||||
testOk(result[3] == 0, " 0-terminated");
|
||||
testOk(result[4] == 'x', " No write outside buffer");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, ABCDE, 5);
|
||||
testOk(status == 4, "epicsStrnRawFromEscaped returned %d (exp. 4)", status);
|
||||
testOk(result[4] == 'x', "epicsStrnRawFromEscaped no buffer overrun");
|
||||
testOk(result[3] == 0, "epicsStrnRawFromEscaped 0-terminated");
|
||||
testOk(status == 3, "raw(\"ABCDE\", 5) -> %d (exp. 3)", status);
|
||||
testOk(result[0] == 'A', " Char '%c' (exp. 'A')", result[0]);
|
||||
testOk(result[1] == 'B', " Char '%c' (exp. 'B')", result[1]);
|
||||
testOk(result[2] == 'C', " Char '%c' (exp. 'C')", result[2]);
|
||||
testOk(result[3] == 0, " 0-terminated");
|
||||
testOk(result[4] == 'x', " No write outside buffer");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "A", 2);
|
||||
testOk(status == 1, "raw(\"A\", 2) -> %d (exp. 1)", status);
|
||||
testOk(result[0] == 'A', " Char '%c' (exp. 'A')", result[0]);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "\\123", 1);
|
||||
testOk(status == 0, "raw(\"\\123\", 1) -> %d (exp. 0)", status);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "\\123", 2);
|
||||
testOk(status == 1, "raw(\"\\123\", 2) -> %d (exp. 1)", status);
|
||||
testOk(result[0] == 1, " Octal escape (got \\%03o)", result[0]);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "\\123", 3);
|
||||
testOk(status == 1, "raw(\"\\123\", 3) -> %d (exp. 1)", status);
|
||||
testOk(result[0] == 012, " Octal escape (got \\%03o)", result[0]);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "\\123", 4);
|
||||
testOk(status == 1, "raw(\"\\123\", 4) -> %d (exp. 1)", status);
|
||||
testOk(result[0] == 0123, " Octal escape (got \\%03o)", result[0]);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "\\812", 2);
|
||||
testOk(status == 1, "raw(\"\\812\", 2) -> %d (exp. 1)", status);
|
||||
testOk(result[0] == '8', " Escaped '%c')", result[0]);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "\\182", 3);
|
||||
testOk(status == 2, "raw(\"\\182\", 3) -> %d (exp. 2)", status);
|
||||
testOk(result[0] == 1, " Octal escape (got \\%03o)", result[0]);
|
||||
testOk(result[1] == '8', " Terminated with '%c'", result[1]);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "\\128", 4);
|
||||
testOk(status == 2, "raw(\"\\128\", 4) -> %d (exp. 2)", status);
|
||||
testOk(result[0] == 012, " Octal escape (got \\%03o)", result[0]);
|
||||
testOk(result[1] == '8', " Terminator char got '%c'", result[1]);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "\\x12", 1);
|
||||
testOk(status == 0, "raw(\"\\x12\", 1) -> %d (exp. 0)", status);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "\\x12", 2);
|
||||
testOk(status == 0, "raw(\"\\x12\", 2) -> %d (exp. 0)", status);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "\\x12", 3);
|
||||
testOk(status == 1, "raw(\"\\x12\", 3) -> %d (exp. 1)", status);
|
||||
testOk(result[0] == 1, " Hex escape (got \\x%x)", result[0]);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "\\x12", 4);
|
||||
testOk(status == 1, "raw(\"\\x12\", 4) -> %d (exp. 1)", status);
|
||||
testOk(result[0] == 0x12," Hex escape (got \\x%x)", result[0]);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "\\xaF", 4);
|
||||
testOk(status == 1, "raw(\"\\xaF\", 4) -> %d (exp. 1)", status);
|
||||
testOk(result[0] == '\xaF'," Hex escape (got \\x%x)", result[0] & 0xFF);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "\\x012", 5);
|
||||
testOk(status == 1, "raw(\"\\x012\", 5) -> %d (exp. 1)", status);
|
||||
testOk(result[0] == 0x12," Hex escape (got \\x%x)", result[0]);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "\\x0012", 6);
|
||||
testOk(status == 1, "raw(\"\\x0012\", 6) -> %d (exp. 1)", status);
|
||||
testOk(result[0] == 0x12," Hex escape (got \\x%x)", result[0]);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
status = epicsStrnRawFromEscaped(result, 4, "\\x1g", 4);
|
||||
testOk(status == 2, "raw(\"\\x1g\", 4) -> %d (exp. 2)", status);
|
||||
testOk(result[0] == 1, " Hex escape (got \\x%x)", result[0]);
|
||||
testOk(result[1] == 'g', " Terminator char got '%c'", result[1]);
|
||||
testOk(result[status] == 0, " 0-terminated");
|
||||
|
||||
return testDone();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user