Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
locale_core.cpp
Go to the documentation of this file.
1
29#define _RWSTD_LIB_SRC
30
31#include <rw/_defs.h>
32
33#ifdef __SUNPRO_CC
34 // working around SunPro bug 568
35# include <time.h>
36#endif
37
38#include <loc/_facet.h>
39#include <loc/_locale.h>
40
41#include "locale_body.h"
42
43#include <stdlib.h> // for getenv(), size_t
44#include <string.h> // for strchr()
45#include <sys/stat.h> // for stat()
46
47
49
50
51// outlined to hide implementation details
52locale::locale () _THROWS (())
53 : _C_body (_RW::__rw_locale::_C_manage (0, 0))
54{
55 _RWSTD_ASSERT (0 != _C_body);
56}
57
58
59// outlined to hide implementation details
60locale::locale (const locale &rhs) _THROWS (())
61 : _C_body (rhs._C_body)
62{
63 _RWSTD_ATOMIC_PREINCREMENT (_C_body->_C_ref, false);
64
65 _RWSTD_ASSERT (0 != _C_body);
66}
67
68
69locale::~locale () _THROWS (())
70{
71 _RWSTD_ASSERT (0 != _C_body);
72
73 if (_C_body->_C_is_managed (_RW::__rw_cat_none)) {
74 // body is globally managed, let manager dispose of it
75 _RW::__rw_locale::_C_manage (_C_body, _C_body->_C_name);
76 }
77 else {
78 // body is not globally managed, delete it
79 // only when its ref count drops down to 0
80 if (!_RWSTD_ATOMIC_PREDECREMENT (_C_body->_C_ref, false))
81 delete _C_body;
82
83 }
84}
85
86
87const locale::facet*
88locale::_C_get_std_facet (facet::_C_facet_type type,
89 facet::_C_ctor_t *ctor) const
90{
91 _RWSTD_ASSERT (0 != _C_body);
92
93 const size_t inx = size_t (type / 2);
94
95 // for standard facets, the index also identifies the facet's type
96 // (including its specialization, but excluding whether its an ordinary
97 // or byname facet), and the facet's LC_XXX category
98
99 _RWSTD_ASSERT (0 != _C_body->_C_name);
100
101 // determine whether locale name is simple or combined
102 const char *nm = _C_body->_C_name;
103 const char *next = strchr (nm, *_RWSTD_CAT_SEP);
104
105 if (*_RWSTD_CAT_SEP == _RWSTD_PATH_SEP && next) {
106
107#ifndef _RWSTD_LOCALE_ROOT_ENVVAR
108# define _RWSTD_LOCALE_ROOT_ENVVAR "RWSTD_LOCALE_ROOT"
109#endif
110 _RW::__rw_chararray pathname;
111
112 if (next != nm) {
113 // look up the value of the environment variable
114 const char *root = getenv (_RWSTD_LOCALE_ROOT_ENVVAR);
115
116 // use the cwd if none given
117 if (!root || !*root)
118 root = "." _RWSTD_CAT_SEP;
119
120 // compose the absolute pathname
121 pathname.append (root);
122 if (pathname.data () [pathname.size () - 1] != _RWSTD_PATH_SEP)
123 pathname.append (_RWSTD_CAT_SEP, 1);
124
125 pathname.append (nm);
126 nm = pathname.data ();
127 }
128
129 struct stat sb;
130 if (-1 != stat (nm, &sb))
131 next = 0;
132 }
133
134 nm = _C_body->_C_name;
135
136 _RW::__rw_chararray locname;
137
138 if (next && *next) {
139
140 // compute the facet category from the value of its id
141 const int facet_cat = _RW::__rw_get_cat (int (inx + 1));
142
143 // determine the locale name of the given category
144 size_t i = 0;
145 for (; i != sizeof _RW::__rw_cats / sizeof *_RW::__rw_cats; ++i) {
146 if (_RW::__rw_cats [i].cat == facet_cat) {
147
148 const size_t nmlen = size_t (next - nm);
149
150 locname.assign (nm, nmlen);
151 locname.append ("", 1); // append a terminating NUL
152 break;
153 }
154 nm = next + !!*next;
155 next = ::strchr (nm, *_RWSTD_CAT_SEP);
156 if (!next)
157 next = nm + ::strlen (nm);
158 }
159
160 nm = locname.data ();
161 }
162
163 _RWSTD_ASSERT (0 != nm);
164
165 const bool byname = !_RW::__rw_is_C (nm);
166
167 type = facet::_C_facet_type (type + byname);
168
169 if ( type == 1 + _RW::__rw_facet::_C_money_get
170 || type == 1 + _RW::__rw_facet::_C_money_put
171 || type == 1 + _RW::__rw_facet::_C_num_get
172 || type == 1 + _RW::__rw_facet::_C_num_put
173 || type == 1 + _RW::__rw_facet::_C_wmoney_get
174 || type == 1 + _RW::__rw_facet::_C_wmoney_put
175 || type == 1 + _RW::__rw_facet::_C_wnum_get
176 || type == 1 + _RW::__rw_facet::_C_wnum_put) {
177 type = facet::_C_facet_type (type - 1);
178 nm = 0;
179 }
180
181 // add facet for the simple named locale (or retrieve existing)
182 typedef _RW::__rw_facet::_C_facet_type FacetType;
183
184 facet* const pfacet =
185 _RW::__rw_facet::_C_manage (0, FacetType (type), nm, ctor);
186
187 _RWSTD_ASSERT (0 != pfacet);
188
189#ifndef _RWSTD_REENTRANT
190
191 // verify that initialization happens exactly once per thread
192 // i.e., multiple threads may safely assign the same `pfacet'
193 // to the same slot
194 _RWSTD_ASSERT (!_C_body->_C_std_facets [inx]);
195
196#endif // _RWSTD_REENTRANT
197
198 _C_body->_C_std_facets [inx] = pfacet;
199
200 return pfacet;
201}
202
203
204} // namespace std
#define i
Definition 17.names.cpp:126
#define rhs
Definition 17.names.cpp:536
#define sb
Definition 17.names.cpp:542
#define inx
Definition 17.names.cpp:484
#define _THROWS()
#define _RWSTD_PATH_SEP
Definition _config.h:297
#define _RWSTD_ATOMIC_PREINCREMENT(x, ignore)
Definition _defs.h:699
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
#define _RWSTD_ATOMIC_PREDECREMENT(x, ignore)
Definition _defs.h:700
#define _RWSTD_ASSERT(ignore)
Definition _defs.h:1108
#define _RWSTD_CAT_SEP
#define _RWSTD_LOCALE_ROOT_ENVVAR
Definition json.h:5363