X-Git-Url: https://pd.if.org/git/?p=pdclib;a=blobdiff_plain;f=functions%2F_PDCLIB%2F_PDCLIB_ascii.c;fp=functions%2F_PDCLIB%2F_PDCLIB_ascii.c;h=ac5a593d963266367c61b18f814b834eda2fff08;hp=0000000000000000000000000000000000000000;hb=f60269dfbb4671b3bea11d1257de54bef0c9ffef;hpb=261086b873397b437ad024d44e9467f0fb2586ba diff --git a/functions/_PDCLIB/_PDCLIB_ascii.c b/functions/_PDCLIB/_PDCLIB_ascii.c new file mode 100644 index 0000000..ac5a593 --- /dev/null +++ b/functions/_PDCLIB/_PDCLIB_ascii.c @@ -0,0 +1,139 @@ +/* ASCII codec + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include +#ifndef REGTEST +#include +#include "_PDCLIB_encoding.h" + +static bool ascii_mbsinit( const mbstate_t *ps ) +{ return 1; } + +static bool asciitoc32( + char32_t *restrict *restrict p_outbuf, + size_t *restrict p_outsz, + const char *restrict *restrict p_inbuf, + size_t *restrict p_insz, + mbstate_t *restrict p_ps +) +{ + while(*p_outsz && *p_insz) { + unsigned char c = **p_inbuf; + if(c > 127) + return false; + + if(p_outbuf) { + **p_outbuf = c; + (*p_outbuf)++; + } + + (*p_inbuf)++; + (*p_insz)--; + (*p_outsz)--; + } + return true; +} + +static bool c32toascii( + char *restrict *restrict p_outbuf, + size_t *restrict p_outsz, + const char32_t *restrict *restrict p_inbuf, + size_t *restrict p_insz, + mbstate_t *restrict p_ps +) +{ + while(*p_outsz && *p_insz) { + char32_t c = **p_inbuf; + if(c > 127) + return false; + + if(p_outbuf) { + **p_outbuf = c; + (*p_outbuf)++; + } + + (*p_inbuf)++; + (*p_insz)--; + (*p_outsz)--; + } + return true; +} + +const struct _PDCLIB_charcodec_t _PDCLIB_ascii_codec = { + .__mbsinit = ascii_mbsinit, + .__mbstoc32s = asciitoc32, + .__c32stombs = c32toascii, + .__mb_max = 1, +}; + +#endif + +#ifdef TEST +#include "_PDCLIB_test.h" + +int main( void ) +{ +#ifndef REGTEST + // Valid conversion & back + + char32_t c32out[5]; + + char32_t *c32ptr = &c32out[0]; + size_t c32rem = 5; + char *chrptr = (char*) &abcde[0]; + size_t chrrem = 5; + mbstate_t mbs = { 0 }; + + TESTCASE(asciitoc32(&c32ptr, &c32rem, &chrptr, &chrrem, &mbs) == true); + TESTCASE(c32rem == 0); + TESTCASE(chrrem == 0); + TESTCASE(c32ptr == &c32out[5]); + TESTCASE(chrptr == &abcde[5]); + TESTCASE(c32out[0] == 'a' && c32out[1] == 'b' && c32out[2] == 'c' && \ + c32out[3] == 'd' && c32out[4] == 'e'); + + char chrout[5]; + c32ptr = &c32out[0]; + c32rem = 5; + chrptr = &chrout[0]; + chrrem = 5; + + + TESTCASE(c32toascii(&chrptr, &chrrem, &c32ptr, &c32rem, &mbs) == true); + TESTCASE(c32rem == 0); + TESTCASE(chrrem == 0); + TESTCASE(c32ptr == &c32out[5]); + TESTCASE(chrptr == &chrout[5]); + TESTCASE(memcmp(chrout, abcde, 5) == 0); + + // Invalid conversions + char badascii = '\xC0'; + c32ptr = &c32out[0]; + c32rem = 5; + chrptr = &badascii; + chrrem = 1; + TESTCASE(asciitoc32(&c32ptr, &c32rem, &chrptr, &chrrem, &mbs) == false); + TESTCASE(c32ptr == &c32out[0]); + TESTCASE(c32rem == 5); + TESTCASE(chrptr == &badascii); + TESTCASE(chrrem == 1); + + char32_t baduni = 0xC0; + c32ptr = &baduni; + c32rem = 1; + chrptr = &chrout[0]; + chrrem = 5; + TESTCASE(c32toascii(&chrptr, &chrrem, &c32ptr, &c32rem, &mbs) == false); + TESTCASE(c32ptr == &baduni); + TESTCASE(c32rem == 1); + TESTCASE(chrptr == &chrout[0]); + TESTCASE(chrrem == 5); +#endif + return TEST_RESULTS; +} + +#endif +