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