1 /* $NetBSD: citrus_lc_numeric.c,v 1.4 2010/06/13 04:14:57 tnozaki Exp $ */ 2 3 /*- 4 * Copyright (c)2008 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 <sys/cdefs.h> 30 #if defined(LIBC_SCCS) && !defined(lint) 31 __RCSID("$NetBSD: citrus_lc_numeric.c,v 1.4 2010/06/13 04:14:57 tnozaki Exp $"); 32 #endif /* LIBC_SCCS and not lint */ 33 34 #include "namespace.h" 35 #include "reentrant.h" 36 #include <sys/types.h> 37 #include <sys/localedef.h> 38 #include <sys/queue.h> 39 #include <assert.h> 40 #include <errno.h> 41 #include <langinfo.h> 42 #include <limits.h> 43 #define __SETLOCALE_SOURCE__ 44 #include <locale.h> 45 #include <stddef.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 50 #include "setlocale_local.h" 51 52 #include "citrus_namespace.h" 53 #include "citrus_types.h" 54 #include "citrus_bcs.h" 55 #include "citrus_region.h" 56 #include "citrus_lookup.h" 57 #include "citrus_aliasname_local.h" 58 #include "citrus_module.h" 59 #include "citrus_mmap.h" 60 #include "citrus_hash.h" 61 #include "citrus_db.h" 62 #include "citrus_db_hash.h" 63 #include "citrus_memstream.h" 64 #include "runetype_local.h" 65 66 #include "fix_grouping.h" 67 #include "citrus_fix_grouping.h" 68 69 /* 70 * macro required by all template headers 71 */ 72 #define _PREFIX(name) __CONCAT(_citrus_LC_NUMERIC_, name) 73 74 #include "nb_lc_numeric_misc.h" 75 #include "citrus_lc_template_decl.h" 76 77 static __inline void 78 _citrus_LC_NUMERIC_uninit(_NumericLocale *data) 79 { 80 free(__UNCONST(data->decimal_point)); 81 free(__UNCONST(data->thousands_sep)); 82 free(__UNCONST(data->grouping)); 83 } 84 85 #include "citrus_lc_numeric.h" 86 87 struct _citrus_LC_NUMERIC_key { 88 const char *name; 89 size_t offset; 90 }; 91 92 #define OFFSET(field) (offsetof(_NumericLocale, field)) 93 static const struct _citrus_LC_NUMERIC_key keys[] = { 94 { _CITRUS_LC_NUMERIC_SYM_DECIMAL_POINT, OFFSET(decimal_point) }, 95 { _CITRUS_LC_NUMERIC_SYM_THOUSANDS_SEP, OFFSET(thousands_sep) }, 96 { _CITRUS_LC_NUMERIC_SYM_GROUPING, OFFSET(grouping ) }, 97 { NULL, 0 } 98 }; 99 100 static __inline int 101 _citrus_LC_NUMERIC_init_normal(_NumericLocale * __restrict data, 102 struct _citrus_db * __restrict db) 103 { 104 const struct _citrus_LC_NUMERIC_key *key; 105 char **p; 106 const char *s; 107 108 _DIAGASSERT(data != NULL); 109 _DIAGASSERT(db != NULL); 110 111 memset(data, 0, sizeof(*data)); 112 for (key = &keys[0]; key->name != NULL; ++key) { 113 if (_db_lookupstr_by_s(db, key->name, &s, NULL)) 114 goto fatal; 115 p = (char **)(void *) 116 (((char *)(void *)data) + key->offset); 117 *p = strdup(s); 118 if (*p == NULL) 119 goto fatal; 120 } 121 _CITRUS_FIXUP_CHAR_MAX_MD(data->grouping); 122 123 return 0; 124 125 fatal: 126 _citrus_LC_NUMERIC_uninit(data); 127 return EFTYPE; 128 } 129 130 static __inline int 131 _citrus_LC_NUMERIC_init_fallback(_NumericLocale * __restrict data, 132 struct _memstream * __restrict ms) 133 { 134 const struct _citrus_LC_NUMERIC_key *key; 135 char **p; 136 const char *s; 137 size_t n; 138 139 _DIAGASSERT(data != NULL); 140 _DIAGASSERT(ms != NULL); 141 142 memset(data, 0, sizeof(*data)); 143 for (key = &keys[0]; key->name != NULL; ++key) { 144 if ((s = _memstream_getln(ms, &n)) == NULL) 145 goto fatal; 146 p = (char **)(void *) 147 (((char *)(void *)data) + key->offset); 148 *p = strndup(s, n - 1); 149 if (*p == NULL) 150 goto fatal; 151 } 152 data->grouping = 153 __fix_locale_grouping_str(data->grouping); 154 155 return 0; 156 157 fatal: 158 _citrus_LC_NUMERIC_uninit(data); 159 return EFTYPE; 160 } 161 162 /* 163 * macro required by citrus_lc_template.h 164 */ 165 #define _CATEGORY_DB "LC_NUMERIC" 166 #define _CATEGORY_MAGIC _CITRUS_LC_NUMERIC_MAGIC_1 167 168 #include "citrus_lc_template.h" 169 _LOCALE_CATEGORY_ENTRY(_citrus_LC_NUMERIC_); 170