]> pd.if.org Git - pdclib/blob - opt/basecodecs/_PDCLIB_ascii.c
7c73d1baf613dc9d8a15511831ff613e014a2c6c
[pdclib] / opt / basecodecs / _PDCLIB_ascii.c
1 /* ASCII codec
2
3    This file is part of the Public Domain C Library (PDCLib).
4    Permission is granted to use, modify, and / or redistribute at will.
5 */
6
7 #include <stdbool.h>
8 #ifndef REGTEST
9 #include <uchar.h>
10 #include <_PDCLIB_encoding.h>
11
12 static bool ascii_mbsinit( const mbstate_t *ps )
13 { return 1; }
14
15 static bool asciitoc32(
16     char32_t       *restrict *restrict   p_outbuf,
17     size_t                   *restrict   p_outsz,
18     const char     *restrict *restrict   p_inbuf,
19     size_t                   *restrict   p_insz,
20     mbstate_t                *restrict   p_ps
21 )
22 {
23     while(*p_outsz && *p_insz) {
24         unsigned char c = **p_inbuf;
25         if(c > 127)
26             return false;
27         
28         if(p_outbuf) {
29             **p_outbuf = c;
30             (*p_outbuf)++; 
31         }
32
33         (*p_inbuf)++;
34         (*p_insz)--; 
35         (*p_outsz)--;
36     }
37     return true;
38 }
39
40 static bool c32toascii(
41     char           *restrict *restrict  p_outbuf,
42     size_t                   *restrict  p_outsz,
43     const char32_t *restrict *restrict  p_inbuf,
44     size_t                   *restrict  p_insz,
45     mbstate_t                *restrict  p_ps
46 )
47 {
48     while(*p_outsz && *p_insz) {
49         char32_t c = **p_inbuf;
50         if(c > 127)
51             return false;
52
53         if(p_outbuf) {
54             **p_outbuf = c;
55             (*p_outbuf)++; 
56         }
57
58         (*p_inbuf)++;
59         (*p_insz)--; 
60         (*p_outsz)--;        
61     }
62     return true;
63 }
64
65 const struct _PDCLIB_charcodec _PDCLIB_ascii_codec = {
66     .__mbsinit   = ascii_mbsinit,
67     .__mbstoc32s = asciitoc32,
68     .__c32stombs = c32toascii,
69     .__mb_max    = 1,
70 };
71
72 #endif
73
74 #ifdef TEST
75 #include <_PDCLIB_test.h>
76
77 int main( void )
78 {
79 #ifndef REGTEST
80     // Valid conversion & back
81
82     char32_t c32out[5];
83
84     char32_t *c32ptr = &c32out[0];
85     size_t    c32rem = 5;
86     char     *chrptr = (char*) &abcde[0];
87     size_t    chrrem = 5;
88     mbstate_t mbs = { 0 };
89
90     TESTCASE(asciitoc32(&c32ptr, &c32rem, &chrptr, &chrrem, &mbs) == true);
91     TESTCASE(c32rem == 0);
92     TESTCASE(chrrem == 0);
93     TESTCASE(c32ptr == &c32out[5]);
94     TESTCASE(chrptr == &abcde[5]);
95     TESTCASE(c32out[0] == 'a' && c32out[1] == 'b' && c32out[2] == 'c' && \
96              c32out[3] == 'd' && c32out[4] == 'e');
97
98     char chrout[5];
99     c32ptr = &c32out[0];
100     c32rem = 5;
101     chrptr = &chrout[0];
102     chrrem = 5;
103
104
105     TESTCASE(c32toascii(&chrptr, &chrrem, &c32ptr, &c32rem, &mbs) == true);
106     TESTCASE(c32rem == 0);
107     TESTCASE(chrrem == 0);
108     TESTCASE(c32ptr == &c32out[5]);
109     TESTCASE(chrptr == &chrout[5]);
110     TESTCASE(memcmp(chrout, abcde, 5) == 0);
111
112     // Invalid conversions
113     char badascii = '\xC0';
114     c32ptr = &c32out[0];
115     c32rem = 5;
116     chrptr = &badascii;
117     chrrem = 1;
118     TESTCASE(asciitoc32(&c32ptr, &c32rem, &chrptr, &chrrem, &mbs) == false);
119     TESTCASE(c32ptr == &c32out[0]);
120     TESTCASE(c32rem == 5);
121     TESTCASE(chrptr == &badascii);
122     TESTCASE(chrrem == 1);
123
124     char32_t baduni = 0xC0;
125     c32ptr = &baduni;
126     c32rem = 1;
127     chrptr = &chrout[0];
128     chrrem = 5;
129     TESTCASE(c32toascii(&chrptr, &chrrem, &c32ptr, &c32rem, &mbs) == false);
130     TESTCASE(c32ptr == &baduni);
131     TESTCASE(c32rem == 1);
132     TESTCASE(chrptr == &chrout[0]);
133     TESTCASE(chrrem == 5);
134 #endif
135     return TEST_RESULTS;
136 }
137
138 #endif
139