1 /** tests for strXXX
2 */
3 #include <testfwk.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199409L
7 #include <wchar.h>
8 #endif
9 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
10 #include <uchar.h>
11 #endif
12
13 /** tests for strcmp
14 */
15 static void
do_teststrcmp(void)16 do_teststrcmp (void)
17 {
18 #ifndef __SDCC_pdk14 // Lack of memory
19 #if !(defined (__SDCC_pdk15) && defined(__SDCC_STACK_AUTO)) // Lack of code memory
20 int result = strcmp ("", "");
21 ASSERT (result == 0);
22
23 result = strcmp ("", "a");
24 ASSERT (result < 0);
25
26 result = strcmp ("a", "");
27 ASSERT (result > 0);
28
29 result = strcmp ("ab", "ab");
30 ASSERT (result == 0);
31
32 result = strcmp ("aa", "ab");
33 ASSERT (result < 0);
34 #endif
35 #endif
36 }
37
38 /** tests for strcpy
39 */
40 static void
do_teststrcpy(void)41 do_teststrcpy (void)
42 {
43 #ifndef __SDCC_pdk14 // Lack of memory
44 #if !(defined (__SDCC_pdk15) && defined(__SDCC_STACK_AUTO)) // Lack of code memory
45 static char empty[] = "";
46 static char string[] = "\1\2\0\3";
47 char buf[40] = "abcdefghijklmnopqrstuvwxyz";
48
49 char * result = strcpy (buf, empty);
50 ASSERT (strlen (buf) == 0);
51 ASSERT (result == buf);
52
53 result = strcpy (buf, string);
54 ASSERT (result == buf);
55 ASSERT (strlen (buf) == 2);
56 ASSERT (buf[0] == '\1');
57 ASSERT (buf[1] == '\2');
58 ASSERT (buf[3] == 'd');
59 #endif
60 #endif
61 }
62
63 /** tests for strncmp
64 */
65 static void
do_teststrncmp(void)66 do_teststrncmp (void)
67 {
68 #ifndef __SDCC_pdk14 // Lack of memory
69 #if !(defined (__SDCC_pdk15) && defined(__SDCC_STACK_AUTO)) // Lack of code memory
70 ASSERT (strncmp ("", "", 0) == 0);
71 ASSERT (strncmp ("ab", "ab", 0) == 0);
72 ASSERT (strncmp ("a", "a", 2) == 0);
73 ASSERT (strncmp ("aa", "ab", 1) == 0);
74 ASSERT (strncmp ("aa", "ab", 2) < 0);
75 ASSERT (strncmp ("abc", "abd", 2) == 0);
76 ASSERT (strncmp ("abc", "abc", 3) == 0);
77 #endif
78 #endif
79 }
80
81 /** tests for strpbrk
82 * related to bug #2908537
83 */
84 static void
do_teststrpbrk(void)85 do_teststrpbrk (void)
86 {
87 #if !defined(__SDCC_pdk14) && !defined(__SDCC_pdk15) // Lack of memory
88 const char *a = "test";
89
90 ASSERT (strpbrk (a, "e") == &a[1] );
91 ASSERT (strpbrk (a, "z") == NULL );
92 ASSERT (strpbrk (a, "et") == &a[0] );
93 ASSERT (strpbrk (a, "ze") == &a[1] );
94 ASSERT (strpbrk (a, "") == NULL );
95 ASSERT (strpbrk ("", "e") == NULL );
96 ASSERT (*strpbrk ("test2", "s") == 's' );
97 #endif
98 }
99
100 /** tests for strrchr
101 */
102 static void
do_teststrrchr(void)103 do_teststrrchr (void)
104 {
105 #if !defined(__SDCC_pdk14) && !defined(__SDCC_pdk15) // Lack of memory
106 const char *test = "test";
107
108 ASSERT (strrchr (test, 0) == test + 4);
109 ASSERT (strrchr (test, 't') == test + 3);
110 ASSERT (strrchr (test, 'e') == test + 1);
111 #endif
112 }
113
114 /** tests for strstr
115 */
116 static void
do_teststrstr(void)117 do_teststrstr (void)
118 {
119 #if !defined(__SDCC_pdk14) && !defined(__SDCC_pdk15) // Lack of memory
120 const char *a = "aabbcd";
121 ASSERT (strstr (a, "\0\1") == a);
122 ASSERT (strstr (a, "") == a);
123 ASSERT (strstr (a, "ab") == &a[1]);
124 ASSERT (strstr (a, "abc") == NULL);
125 ASSERT (strstr (a, "abbc") == &a[1]);
126 ASSERT (strstr ("", "abbc") == NULL);
127 /* ASSERT (strstr ("", "") == a); should work, but it doesn't */
128 ASSERT (strstr (a, "cd") == &a[4]);
129 #endif
130 }
131
132 /** tests for strspn
133 */
134 static void
do_teststrspn(void)135 do_teststrspn (void)
136 {
137 #if !defined(__SDCC_pdk14) && !defined(__SDCC_pdk15) // Lack of memory
138 ASSERT (strspn("aabbcd", "ab") == 4);
139 ASSERT (strspn("abbacd", "") == 0);
140 ASSERT (strspn("abbacd", "ac") == 1);
141 ASSERT (strspn("abbacd", "x") == 0);
142 ASSERT (strspn("abbacd", "c") == 0);
143 ASSERT (strspn("abbacd", "cba") == 5);
144 ASSERT (strspn("abbacd", "cdba") == 6);
145 #endif
146 }
147
148 /** tests for strtok
149 */
150 static void
do_teststrtok(void)151 do_teststrtok (void)
152 {
153 #if !defined(__SDCC_pdk14) && !defined(__SDCC_pdk15) // Lack of memory
154 static char str[] = "?a???b,,,#c";
155 char str2[] = "axaaba";
156 char *token = strtok (str, "?"); // 'token' points to the token "a"
157 ASSERT (token == &str[1] && 0 == strcmp (token,"a"));
158 token = strtok (NULL, ","); // 'token' points to the token "??b"
159 ASSERT (token == &str[3] && 0 == strcmp (token,"??b"));
160 token = strtok (NULL, "#,"); // 'token' points to the token "c"
161 ASSERT (token == &str[10] && 0 == strcmp (token,"c"));
162 token = strtok (NULL, "?"); // 'token' is a null pointer
163 ASSERT (token == NULL);
164
165 token = strtok (str2, "ab");
166 ASSERT (token && 0 == strcmp (token, "x"));
167 token = strtok (NULL, "ab");
168 ASSERT (token == NULL);
169 #if !defined (__SUNPRO_C) && !defined (__sun__)
170 /* SunPro C compiler and GCC on Solaris have problem with strtok-ing after NULL */
171 token = strtok (NULL, "a");
172 ASSERT (token == NULL);
173 #endif
174 #endif
175 }
176
177 #if !defined (__APPLE__) // uchar.h/char16_t/char32_t are not supported on MacOS/Clang
178
179 // Test C11 UTF-8 behaviour.
180 static void
do_utf_8(void)181 do_utf_8 (void)
182 {
183 #ifndef __SDCC_pdk14 // Lack of memory
184 #if defined(__STDC_VERSION) && __STDC_VERSION >= 201112L
185 const char *str1 = u8"Ä ä";
186 const char *str2 = u8"\u00c4 ä";
187 const char *str3 = u8"Ä " "ä";
188 const char *str4 = u8"Ä " u8"ä";
189 const char *str5 = "Ä " u8"ä";
190
191 ASSERT (str1[0] == 0xc3);
192 ASSERT (str2[1] == 0x84);
193 ASSERT (!strcmp (str1, str2));
194 ASSERT (!strcmp (str1, str3));
195 ASSERT (!strcmp (str1, str4));
196 ASSERT (!strcmp (str1, str5));
197 #endif
198 #endif
199 }
200
201 // Test SDCC implementation-defined UTF-8 behaviour
202 // string literals are UTF-8 (as nearly all implementations out there)
203 static void
do_utf_8_sdcc(void)204 do_utf_8_sdcc (void)
205 {
206 #ifndef __SDCC_pdk14 // Lack of memory
207 #if !(defined (__SDCC_pdk15) && defined(__SDCC_STACK_AUTO)) // Lack of code memory
208 #ifdef __SDCC
209 const char *str1 = "Ä ä";
210 const char *str2 = "\u00c4 ä";
211 const char *str3 = u8"Ä " "ä";
212 const char *str4 = "Ä " "ä";
213 const char *str5 = u8"Ä " u8"ä";
214
215 ASSERT (str1[0] == 0xc3);
216 ASSERT (str2[1] == 0x84);
217 ASSERT (!strcmp (str1, str2));
218 ASSERT (!strcmp (str1, str3));
219 ASSERT (!strcmp (str1, str4));
220 ASSERT (!strcmp (str1, str5));
221
222 ASSERT (!mblen(0, 0));
223 ASSERT (mblen(str1, 3) == 2);
224 ASSERT (mblen("test", 3) == 1);
225 ASSERT (mblen("", 3) == 0);
226 #endif
227 #endif
228 #endif
229 }
230
231 // Test C11 UTF-16 behaviour
232 static void
do_utf_16(void)233 do_utf_16 (void)
234 {
235 #if defined(__STDC_UTF_16__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
236 const char16_t *str1 = u"Ä ä";
237 const char16_t *str2 = u"\u00c4 ä";
238 const char16_t *str3 = u"Ä " "ä";
239 const char16_t *str4 = "Ä " u"ä";
240 const char16_t *str5 = u"Ä " u"ä";
241
242 ASSERT (str1[0] == 0xc4);
243 ASSERT (str2[2] == 0xe4);
244 ASSERT (!memcmp (str1, str2, 4 * sizeof(char16_t)));
245 ASSERT (!memcmp (str1, str3, 4 * sizeof(char16_t)));
246 ASSERT (!memcmp (str1, str4, 4 * sizeof(char16_t)));
247 ASSERT (!memcmp (str1, str5, 4 * sizeof(char16_t)));
248 #endif
249 }
250
251 // Test C95 UTF-32 behaviour
252 static void
do_utf_32_c95(void)253 do_utf_32_c95 (void)
254 {
255 #ifndef __SDCC_pdk14 // Lack of memory
256 #if !(defined (__SDCC_pdk15) && defined(__SDCC_STACK_AUTO)) // Lack of code memory
257 #ifdef __STDC_ISO_10646__
258 const wchar_t *str1 = L"Ä ä";
259 const wchar_t *str2 = L"\u00c4 ä";
260 const wchar_t *str3 = L"Ä " "ä";
261 const wchar_t *str4 = "Ä " L"ä";
262 const wchar_t *str5 = L"Ä " L"ä";
263
264 ASSERT (str1[0] == 0xc4);
265 ASSERT (str2[2] == 0xe4);
266 ASSERT (wcslen (str1) == 3);
267 ASSERT (!memcmp (str1, str2, 4 * sizeof(wchar_t)));
268 ASSERT (!memcmp (str1, str3, 4 * sizeof(wchar_t)));
269 ASSERT (!memcmp (str1, str4, 4 * sizeof(wchar_t)));
270 ASSERT (!memcmp (str1, str5, 4 * sizeof(wchar_t)));
271 #endif
272 #endif
273 #endif
274 }
275
276 // Test C11 UTF-32 behaviour
277 static void
do_utf_32_c11(void)278 do_utf_32_c11 (void)
279 {
280 #if defined(__STDC_UTF_32__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
281 const char32_t *str1 = U"Ä ä";
282 const char32_t *str2 = U"\u00c4 ä";
283 const char32_t *str3 = U"Ä " "ä";
284 const char32_t *str4 = "Ä " U"ä";
285 const char32_t *str5 = U"Ä " U"ä";
286
287 ASSERT (str1[0] == 0xc4);
288 ASSERT (str2[2] == 0xe4);
289 ASSERT (!memcmp (str1, str2, 4 * sizeof(char32_t)));
290 ASSERT (!memcmp (str1, str3, 4 * sizeof(char32_t)));
291 ASSERT (!memcmp (str1, str4, 4 * sizeof(char32_t)));
292 ASSERT (!memcmp (str1, str5, 4 * sizeof(char32_t)));
293 #endif
294 }
295
296 static void
do_chinese(void)297 do_chinese (void)
298 {
299 #if defined(__STDC_UTF_32__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
300 const char32_t *p0 = U"史斌";
301 #endif
302 #ifdef __STDC_ISO_10646__
303 const wchar_t *p1 = L"史庭芳";
304 #endif
305 #if defined(__STDC_UTF_16__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
306 const char16_t *p2 = u"天津";
307 #endif
308 #if defined(__STDC_UTF_32__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
309 ASSERT (p0[0] == 0x53f2);
310 #endif
311 #ifdef __STDC_ISO_10646__
312 ASSERT (p1[2] == 0x82b3);
313 #endif
314 #if defined(__STDC_UTF_16__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
315 ASSERT (p2[1] == 0x6d25);
316 #endif
317 }
318
319 #endif // __APPLE__
320
321 static void
teststr(void)322 teststr (void)
323 {
324 do_teststrcmp ();
325 do_teststrcpy ();
326 do_teststrncmp ();
327 do_teststrpbrk ();
328 do_teststrrchr ();
329 do_teststrstr ();
330 do_teststrspn ();
331 do_teststrtok ();
332 #if !defined (__APPLE__)
333 do_utf_8 ();
334 do_utf_8_sdcc ();
335 do_utf_16 ();
336 do_utf_32_c95 ();
337 do_utf_32_c11 ();
338 do_chinese ();
339 #endif // __APPLE__
340 }
341
342