X-Git-Url: https://pd.if.org/git/?p=pdclib;a=blobdiff_plain;f=functions%2Fuchar%2Fc16rtomb.c;h=5070e28f86b5b004a34062a1c7d6300f2834d405;hp=bce172bd00ff070a5095d33747ff273d56b8021b;hb=abc15df6b9fae3374d24c7cf5c3ab94c605b2a6d;hpb=8894c921674bb116d0a7b8f23a55311e7a768019 diff --git a/functions/uchar/c16rtomb.c b/functions/uchar/c16rtomb.c index bce172b..5070e28 100644 --- a/functions/uchar/c16rtomb.c +++ b/functions/uchar/c16rtomb.c @@ -1,104 +1,104 @@ -/* c16rtomb( char *, char16_t, mbstate_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#ifndef REGTEST -#include -#include -#include -#include -#include -#include "_PDCLIB_encoding.h" -#include "_PDCLIB_locale.h" - -size_t c16rtomb_l( - char *restrict s, - char16_t c16, - mbstate_t *restrict ps, - locale_t restrict l -) -{ - const char16_t *restrict psrc = &c16; - char buf[s ? 0 : MB_CUR_MAX]; - s = s ? s : buf; - - if(!l->_Codec->__c16stombs) { - // Codec doesn't support direct conversion - translate via UCS-4 - if(ps->_Surrogate == 0) { - // No pending surrogate - if((c16 & 0xF800) == 0xD800) { - // Surrogate range - if((c16 & 0x0400) == 0) { - // 0xD800 -> 0xDBFF leading surrogate - ps->_Surrogate = c16; - - // Need more data - // Return 0 - we haven't output anything yet - - /* STD: ISO/IEC 9899:2011 is very implcifit about this being - * the correct return value. N1040, from which the - * function was adopted, is explicit about 0 being a - * valid return. - */ - return (size_t) 0; - } else { - // 0xDC00 -> 0xDFFF trailing surrogate - errno = EILSEQ; - return (size_t) -1; - } - } else { - // BMP range - UTF16 == UCS-4, pass through to c32rtomb_l - return c32rtomb_l(s, c16, ps, l); - } - } else { - // We have a stored surrogate - if((c16 & 0xFC00) == 0xDC00) { - // Trailing surrogate - char32_t c32 = (ps->_Surrogate & 0x3FF) << 10 | (c16 & 0x3FF); - ps->_Surrogate = 0; - return c32rtomb_l(s, c32, ps, l); - } else { - // Not a trailing surrogate - encoding error - errno = EILSEQ; - return (size_t) -1; - } - - } - } else { - // Codec supports direct conversion - size_t srcsz = 1; - size_t dstsz = MB_CUR_MAX; - size_t dstrem = dstsz; - - if(l->_Codec->__c16stombs(&s, &dstrem, &psrc, &srcsz, ps)) { - // Successful conversion - return dstsz - dstrem; - } else { - errno = EILSEQ; - return (size_t) -1; - } - } -} - -size_t c16rtomb( - char *restrict s, - char16_t c16, - mbstate_t *restrict ps -) -{ - return c16rtomb_l(s, c16, ps, _PDCLIB_threadlocale()); -} - -#endif - -#ifdef TEST -#include "_PDCLIB_test.h" - -int main( void ) -{ - TESTCASE( NO_TESTDRIVER ); - return TEST_RESULTS; -} -#endif +/* c16rtomb( char *, char16_t, mbstate_t * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST +#include +#include +#include +#include +#include +#include "_PDCLIB_encoding.h" +#include "_PDCLIB_locale.h" + +size_t c16rtomb_l( + char *restrict s, + char16_t c16, + mbstate_t *restrict ps, + locale_t restrict l +) +{ + const char16_t *restrict psrc = &c16; + char buf[s ? 0 : MB_CUR_MAX]; + s = s ? s : buf; + + if(!l->_Codec->__c16stombs) { + // Codec doesn't support direct conversion - translate via UCS-4 + if(ps->_Surrogate == 0) { + // No pending surrogate + if((c16 & 0xF800) == 0xD800) { + // Surrogate range + if((c16 & 0x0400) == 0) { + // 0xD800 -> 0xDBFF leading surrogate + ps->_Surrogate = c16; + + // Need more data + // Return 0 - we haven't output anything yet + + /* STD: ISO/IEC 9899:2011 is very implcifit about this being + * the correct return value. N1040, from which the + * function was adopted, is explicit about 0 being a + * valid return. + */ + return (size_t) 0; + } else { + // 0xDC00 -> 0xDFFF trailing surrogate + errno = EILSEQ; + return (size_t) -1; + } + } else { + // BMP range - UTF16 == UCS-4, pass through to c32rtomb_l + return c32rtomb_l(s, c16, ps, l); + } + } else { + // We have a stored surrogate + if((c16 & 0xFC00) == 0xDC00) { + // Trailing surrogate + char32_t c32 = (ps->_Surrogate & 0x3FF) << 10 | (c16 & 0x3FF); + ps->_Surrogate = 0; + return c32rtomb_l(s, c32, ps, l); + } else { + // Not a trailing surrogate - encoding error + errno = EILSEQ; + return (size_t) -1; + } + + } + } else { + // Codec supports direct conversion + size_t srcsz = 1; + size_t dstsz = MB_CUR_MAX; + size_t dstrem = dstsz; + + if(l->_Codec->__c16stombs(&s, &dstrem, &psrc, &srcsz, ps)) { + // Successful conversion + return dstsz - dstrem; + } else { + errno = EILSEQ; + return (size_t) -1; + } + } +} + +size_t c16rtomb( + char *restrict s, + char16_t c16, + mbstate_t *restrict ps +) +{ + return c16rtomb_l(s, c16, ps, _PDCLIB_threadlocale()); +} + +#endif + +#ifdef TEST +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( NO_TESTDRIVER ); + return TEST_RESULTS; +} +#endif