1 /* $NetBSD: citrus_none.c,v 1.17 2005/12/02 11:14:20 yamt Exp $ */ 2 3 /*- 4 * Copyright (c)2002 Citrus Project, 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <assert.h> 30 #include <errno.h> 31 #include <string.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <stddef.h> 35 #include <locale.h> 36 #include <wchar.h> 37 #include <sys/types.h> 38 39 #include "citrus_namespace.h" 40 #include "citrus_types.h" 41 #include "citrus_module.h" 42 #include "citrus_ctype.h" 43 #include "citrus_none.h" 44 #include "citrus_stdenc.h" 45 46 /* ---------------------------------------------------------------------- */ 47 static int 48 _citrus_NONE_ctype_getops(_citrus_ctype_ops_rec_t *, size_t, uint32_t); 49 static int 50 _citrus_NONE_stdenc_getops(struct _citrus_stdenc_ops *, size_t, uint32_t); 51 52 _CITRUS_CTYPE_DECLS(NONE); 53 _CITRUS_CTYPE_DEF_OPS(NONE); 54 55 56 /* ---------------------------------------------------------------------- */ 57 58 static int 59 _citrus_NONE_ctype_getops(_citrus_ctype_ops_rec_t *ops, size_t lenops, 60 uint32_t expected_version) 61 { 62 if (expected_version<_CITRUS_CTYPE_ABI_VERSION || lenops<sizeof(*ops)) 63 return (EINVAL); 64 65 memcpy(ops, &_citrus_NONE_ctype_ops, sizeof(_citrus_NONE_ctype_ops)); 66 67 return (0); 68 } 69 70 static int 71 _citrus_NONE_stdenc_getops(struct _citrus_stdenc_ops *ops, size_t lenops, 72 uint32_t expected_version) 73 { 74 if (expected_version<_CITRUS_STDENC_ABI_VERSION || lenops<sizeof(*ops)) 75 return (EINVAL); 76 77 memcpy(ops, &_citrus_NONE_stdenc_ops, sizeof(_citrus_NONE_stdenc_ops)); 78 79 return (0); 80 } 81 82 static int 83 /*ARGSUSED*/ 84 _citrus_NONE_ctype_init(void ** __restrict cl, void * __restrict var __unused, 85 size_t lenvar __unused, size_t lenps __unused) 86 { 87 *cl = NULL; 88 return (0); 89 } 90 91 static void 92 /*ARGSUSED*/ 93 _citrus_NONE_ctype_uninit(void *cl __unused) 94 { 95 } 96 97 static unsigned 98 /*ARGSUSED*/ 99 _citrus_NONE_ctype_get_mb_cur_max(void *cl __unused) 100 { 101 return (1); 102 } 103 104 static int 105 /*ARGSUSED*/ 106 _citrus_NONE_ctype_mblen(void * __restrict cl __unused, 107 const char * __restrict s, size_t n, 108 int * __restrict nresult) 109 { 110 if (!s) { 111 *nresult = 0; /* state independent */ 112 return (0); 113 } 114 if (n==0) { 115 *nresult = -1; 116 return (EILSEQ); 117 } 118 *nresult = (*s == 0) ? 0 : 1; 119 return (0); 120 } 121 122 static int 123 /*ARGSUSED*/ 124 _citrus_NONE_ctype_mbrlen(void * __restrict cl __unused, 125 const char * __restrict s, size_t n, 126 void * __restrict pspriv __unused, 127 size_t * __restrict nresult) 128 { 129 if (!s) { 130 *nresult = 0; 131 return (0); 132 } 133 if (n==0) { 134 *nresult = (size_t)-2; 135 return (0); 136 } 137 *nresult = (*s == 0) ? 0 : 1; 138 return (0); 139 } 140 141 static int 142 /*ARGSUSED*/ 143 _citrus_NONE_ctype_mbrtowc(void * __restrict cl __unused, 144 wchar_t * __restrict pwc, 145 const char * __restrict s, size_t n, 146 void * __restrict pspriv __unused, 147 size_t * __restrict nresult) 148 { 149 if (s == NULL) { 150 *nresult = 0; 151 return (0); 152 } 153 if (n == 0) { 154 *nresult = (size_t)-2; 155 return (0); 156 } 157 158 if (pwc != NULL) 159 *pwc = (wchar_t)(unsigned char) *s; 160 161 *nresult = *s == '\0' ? 0 : 1; 162 return (0); 163 } 164 165 static int 166 /*ARGSUSED*/ 167 _citrus_NONE_ctype_mbsinit(void * __restrict cl __unused, 168 const void * __restrict pspriv __unused, 169 int * __restrict nresult) 170 { 171 *nresult = 1; /* always initial state */ 172 return (0); 173 } 174 175 static int 176 /*ARGSUSED*/ 177 _citrus_NONE_ctype_mbsrtowcs(void * __restrict cl __unused, 178 wchar_t * __restrict pwcs, 179 const char ** __restrict s, size_t n, 180 void * __restrict pspriv __unused, 181 size_t * __restrict nresult) 182 { 183 int cnt; 184 const char *s0; 185 186 /* if pwcs is NULL, ignore n */ 187 if (pwcs == NULL) 188 n = 1; /* arbitrary >0 value */ 189 190 cnt = 0; 191 s0 = *s; /* to keep *s unchanged for now, use copy instead. */ 192 while (n > 0) { 193 if (pwcs != NULL) { 194 *pwcs = (wchar_t)(unsigned char)*s0; 195 } 196 if (*s0 == '\0') { 197 s0 = NULL; 198 break; 199 } 200 s0++; 201 if (pwcs != NULL) { 202 pwcs++; 203 n--; 204 } 205 cnt++; 206 } 207 if (pwcs) 208 *s = s0; 209 210 *nresult = (size_t)cnt; 211 212 return (0); 213 } 214 215 static int 216 _citrus_NONE_ctype_mbstowcs(void * __restrict cl, wchar_t * __restrict wcs, 217 const char * __restrict s, size_t n, 218 size_t * __restrict nresult) 219 { 220 const char *tmp_s = __DEQUALIFY(const char *, s); 221 222 return (_citrus_NONE_ctype_mbsrtowcs(cl, wcs, &tmp_s, n, NULL, nresult)); 223 } 224 225 static int 226 /*ARGSUSED*/ 227 _citrus_NONE_ctype_mbtowc(void * __restrict cl __unused, 228 wchar_t * __restrict pwc, 229 const char * __restrict s, size_t n, 230 int * __restrict nresult) 231 { 232 233 if (s == NULL) { 234 *nresult = 0; /* state independent */ 235 return (0); 236 } 237 if (n == 0) { 238 return (EILSEQ); 239 } 240 if (pwc == NULL) { 241 if (*s == '\0') { 242 *nresult = 0; 243 } else { 244 *nresult = 1; 245 } 246 return (0); 247 } 248 249 *pwc = (wchar_t)(unsigned char)*s; 250 *nresult = *s == '\0' ? 0 : 1; 251 252 return (0); 253 } 254 255 static int 256 /*ARGSUSED*/ 257 _citrus_NONE_ctype_wcrtomb(void * __restrict cl __unused, 258 char * __restrict s, wchar_t wc, 259 void * __restrict pspriv __unused, 260 size_t * __restrict nresult) 261 { 262 if ((wc&~0xFFU) != 0) { 263 *nresult = (size_t)-1; 264 return (EILSEQ); 265 } 266 267 *nresult = 1; 268 if (s!=NULL) 269 *s = (char)wc; 270 271 return (0); 272 } 273 274 static int 275 /*ARGSUSED*/ 276 _citrus_NONE_ctype_wcsrtombs(void * __restrict cl __unused, 277 char * __restrict s, 278 const wchar_t ** __restrict pwcs, size_t n, 279 void * __restrict pspriv __unused, 280 size_t * __restrict nresult) 281 { 282 size_t count; 283 const wchar_t *pwcs0; 284 285 pwcs0 = *pwcs; 286 count = 0; 287 288 if (s == NULL) 289 n = 1; 290 291 while (n > 0) { 292 if ((*pwcs0 & ~0xFFU) != 0) { 293 *nresult = (size_t)-1; 294 return (EILSEQ); 295 } 296 if (s != NULL) { 297 *s++ = (char)*pwcs0; 298 n--; 299 } 300 if (*pwcs0 == L'\0') { 301 pwcs0 = NULL; 302 break; 303 } 304 count++; 305 pwcs0++; 306 } 307 if (s != NULL) 308 *pwcs = pwcs0; 309 310 *nresult = count; 311 312 return (0); 313 } 314 315 static int 316 _citrus_NONE_ctype_wcstombs(void * __restrict cl, char * __restrict s, 317 const wchar_t * __restrict pwcs, size_t n, 318 size_t * __restrict nresult) 319 { 320 const wchar_t *tmp_pwcs = __DEQUALIFY(const wchar_t *, pwcs); 321 322 return (_citrus_NONE_ctype_wcsrtombs(cl, s, &tmp_pwcs, n, NULL, nresult)); 323 } 324 325 static int 326 _citrus_NONE_ctype_wctomb(void * __restrict cl, char * __restrict s, 327 wchar_t wc, int * __restrict nresult) 328 { 329 int ret; 330 size_t nr; 331 332 if (s == NULL) { 333 /* 334 * initialize state here. 335 * (nothing to do for us.) 336 */ 337 *nresult = 0; /* we're state independent */ 338 return (0); 339 } 340 341 ret = _citrus_NONE_ctype_wcrtomb(cl, s, wc, NULL, &nr); 342 *nresult = (int)nr; 343 344 return (ret); 345 } 346 347 static int 348 /*ARGSUSED*/ 349 _citrus_NONE_ctype_btowc(_citrus_ctype_rec_t * __restrict cc __unused, 350 int c, wint_t * __restrict wcresult) 351 { 352 if (c == EOF || c & ~0xFF) 353 *wcresult = WEOF; 354 else 355 *wcresult = (wint_t)c; 356 return (0); 357 } 358 359 static int 360 /*ARGSUSED*/ 361 _citrus_NONE_ctype_wctob(_citrus_ctype_rec_t * __restrict cc __unused, 362 wint_t wc, int * __restrict cresult) 363 { 364 if (wc == WEOF || wc & ~0xFF) 365 *cresult = EOF; 366 else 367 *cresult = (int)wc; 368 return (0); 369 } 370 371 /* ---------------------------------------------------------------------- */ 372 373 _CITRUS_STDENC_DECLS(NONE); 374 _CITRUS_STDENC_DEF_OPS(NONE); 375 struct _citrus_stdenc_traits _citrus_NONE_stdenc_traits = { 376 0, /* et_state_size */ 377 1, /* mb_cur_max */ 378 }; 379 380 static int 381 /*ARGSUSED*/ 382 _citrus_NONE_stdenc_init(struct _citrus_stdenc * __restrict ce, 383 const void *var __unused, size_t lenvar __unused, 384 struct _citrus_stdenc_traits * __restrict et) 385 { 386 387 et->et_state_size = 0; 388 et->et_mb_cur_max = 1; 389 390 ce->ce_closure = NULL; 391 392 return (0); 393 } 394 395 static void 396 /*ARGSUSED*/ 397 _citrus_NONE_stdenc_uninit(struct _citrus_stdenc *ce __unused) 398 { 399 } 400 401 static int 402 /*ARGSUSED*/ 403 _citrus_NONE_stdenc_init_state(struct _citrus_stdenc * __restrict ce __unused, 404 void * __restrict ps __unused) 405 { 406 return (0); 407 } 408 409 static int 410 /*ARGSUSED*/ 411 _citrus_NONE_stdenc_mbtocs(struct _citrus_stdenc * __restrict ce __unused, 412 _csid_t *csid, _index_t *idx, 413 const char **s, size_t n, 414 void *ps __unused, size_t *nresult) 415 { 416 417 _DIAGASSERT(csid != NULL && idx != NULL); 418 419 if (n<1) { 420 *nresult = (size_t)-2; 421 return (0); 422 } 423 424 *csid = 0; 425 *idx = (_index_t)(unsigned char)*(*s)++; 426 *nresult = *idx == 0 ? 0 : 1; 427 428 return (0); 429 } 430 431 static int 432 /*ARGSUSED*/ 433 _citrus_NONE_stdenc_cstomb(struct _citrus_stdenc * __restrict ce __unused, 434 char *s, size_t n, 435 _csid_t csid, _index_t idx, 436 void *ps __unused, size_t *nresult) 437 { 438 439 if (csid == _CITRUS_CSID_INVALID) { 440 *nresult = 0; 441 return (0); 442 } 443 if (n<1) { 444 *nresult = (size_t)-1; 445 return (E2BIG); 446 } 447 if (csid != 0 || (idx&0xFF) != idx) 448 return (EILSEQ); 449 450 *s = (char)idx; 451 *nresult = 1; 452 453 return (0); 454 } 455 456 static int 457 /*ARGSUSED*/ 458 _citrus_NONE_stdenc_mbtowc(struct _citrus_stdenc * __restrict ce __unused, 459 _wc_t * __restrict pwc, 460 const char ** __restrict s, size_t n, 461 void * __restrict pspriv __unused, 462 size_t * __restrict nresult) 463 { 464 if (s == NULL) { 465 *nresult = 0; 466 return (0); 467 } 468 if (n == 0) { 469 *nresult = (size_t)-2; 470 return (0); 471 } 472 473 if (pwc != NULL) 474 *pwc = (_wc_t)(unsigned char) **s; 475 476 *nresult = *s == '\0' ? 0 : 1; 477 return (0); 478 } 479 480 static int 481 /*ARGSUSED*/ 482 _citrus_NONE_stdenc_wctomb(struct _citrus_stdenc * __restrict ce __unused, 483 char * __restrict s, size_t n, _wc_t wc, 484 void * __restrict pspriv __unused, 485 size_t * __restrict nresult) 486 { 487 if ((wc&~0xFFU) != 0) { 488 *nresult = (size_t)-1; 489 return (EILSEQ); 490 } 491 if (n==0) { 492 *nresult = (size_t)-1; 493 return (E2BIG); 494 } 495 496 *nresult = 1; 497 if (s!=NULL && n>0) 498 *s = (char)wc; 499 500 return (0); 501 } 502 503 static int 504 /*ARGSUSED*/ 505 _citrus_NONE_stdenc_put_state_reset(struct _citrus_stdenc * __restrict ce __unused, 506 char * __restrict s __unused, 507 size_t n __unused, 508 void * __restrict pspriv __unused, 509 size_t * __restrict nresult) 510 { 511 512 *nresult = 0; 513 514 return (0); 515 } 516 517 static int 518 /*ARGSUSED*/ 519 _citrus_NONE_stdenc_get_state_desc(struct _stdenc * __restrict ce, 520 void * __restrict ps, 521 int id, 522 struct _stdenc_state_desc * __restrict d) 523 { 524 int ret = 0; 525 526 switch (id) { 527 case _STDENC_SDID_GENERIC: 528 d->u.generic.state = _STDENC_SDGEN_INITIAL; 529 break; 530 default: 531 ret = EOPNOTSUPP; 532 } 533 534 return ret; 535 } 536