PostgreSQL Source Code: src/port/pg_localeconv_r.c Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16#include "c.h"

17

18#if !defined(WIN32)

19#include <langinfo.h>

20#include <pthread.h>

21#endif

22

23#include <limits.h>

24

25#ifdef MON_THOUSANDS_SEP

26

27

28

29

30#define TRANSLATE_FROM_LANGINFO

31#endif

32

34{

38#ifdef TRANSLATE_FROM_LANGINFO

39 nl_item item;

40#endif

41};

42

43

44#ifdef TRANSLATE_FROM_LANGINFO

45#define LCONV_M(is_string, category, name, item) \

46 { is_string, category, offsetof(struct lconv, name), item }

47#else

48#define LCONV_M(is_string, category, name, item) \

49 { is_string, category, offsetof(struct lconv, name) }

50#endif

51#define LCONV_S(c, n, i) LCONV_M(true, c, n, i)

52#define LCONV_C(c, n, i) LCONV_M(false, c, n, i)

53

54

55

56

57

58

59

60

61

62

64

67 LCONV_S(LC_NUMERIC, grouping, GROUPING),

68 LCONV_S(LC_MONETARY, int_curr_symbol, INT_CURR_SYMBOL),

69 LCONV_S(LC_MONETARY, currency_symbol, CURRENCY_SYMBOL),

70 LCONV_S(LC_MONETARY, mon_decimal_point, MON_DECIMAL_POINT),

71 LCONV_S(LC_MONETARY, mon_thousands_sep, MON_THOUSANDS_SEP),

72 LCONV_S(LC_MONETARY, mon_grouping, MON_GROUPING),

73 LCONV_S(LC_MONETARY, positive_sign, POSITIVE_SIGN),

74 LCONV_S(LC_MONETARY, negative_sign, NEGATIVE_SIGN),

75

76

77 LCONV_C(LC_MONETARY, int_frac_digits, INT_FRAC_DIGITS),

78 LCONV_C(LC_MONETARY, frac_digits, FRAC_DIGITS),

79 LCONV_C(LC_MONETARY, p_cs_precedes, P_CS_PRECEDES),

80 LCONV_C(LC_MONETARY, p_sep_by_space, P_SEP_BY_SPACE),

81 LCONV_C(LC_MONETARY, n_cs_precedes, N_CS_PRECEDES),

82 LCONV_C(LC_MONETARY, n_sep_by_space, N_SEP_BY_SPACE),

83 LCONV_C(LC_MONETARY, p_sign_posn, P_SIGN_POSN),

84 LCONV_C(LC_MONETARY, n_sign_posn, N_SIGN_POSN),

85};

86

87static inline char **

89{

90 return (char **) ((char *) lconv + table[i].offset);

91}

92

93static inline char *

95{

97}

98

99

100

101

102

103void

105{

109}

110

111#ifdef TRANSLATE_FROM_LANGINFO

112

113

114

115static int

116pg_localeconv_from_langinfo(struct lconv *dst,

119{

121 {

123

125 numeric_locale : monetary_locale;

126

128 {

130

131 string = nl_langinfo_l(table[i].item, locale);

132 if (!(string = strdup(string)))

133 {

135 errno = ENOMEM;

136 return -1;

137 }

139 }

140 else

141 {

144 }

145 }

146

147 return 0;

148}

149#else

150

151

152

153

154static int

156 struct lconv *src,

158{

160 {

162 continue;

163

165 {

167

169 if (!(string = strdup(string)))

170 {

172 errno = ENOMEM;

173 return -1;

174 }

176 }

177 else

178 {

180 }

181 }

182

183 return 0;

184}

185#endif

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230int

233 struct lconv *output)

234{

235#ifdef WIN32

236 wchar_t *save_lc_ctype = NULL;

237 wchar_t *save_lc_monetary = NULL;

238 wchar_t *save_lc_numeric = NULL;

239 int save_config_thread_locale;

240 int result = -1;

241

242

243 save_config_thread_locale = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);

244

245

246

247

248

249

250

251

252 save_lc_ctype = _wsetlocale(LC_CTYPE, NULL);

253 if (!save_lc_ctype || !(save_lc_ctype = wcsdup(save_lc_ctype)))

254 goto exit;

255 save_lc_monetary = _wsetlocale(LC_MONETARY, NULL);

256 if (!save_lc_monetary || !(save_lc_monetary = wcsdup(save_lc_monetary)))

257 goto exit;

258 save_lc_numeric = _wsetlocale(LC_NUMERIC, NULL);

259 if (!save_lc_numeric || !(save_lc_numeric = wcsdup(save_lc_numeric)))

260 goto exit;

261

263

264

266 goto exit;

268 if (result != 0)

269 goto exit;

270

271

273 goto exit;

275

276exit:

277

278 if (save_lc_ctype)

279 {

280 _wsetlocale(LC_CTYPE, save_lc_ctype);

281 free(save_lc_ctype);

282 }

283 if (save_lc_monetary)

284 {

285 _wsetlocale(LC_MONETARY, save_lc_monetary);

286 free(save_lc_monetary);

287 }

288 if (save_lc_numeric)

289 {

290 _wsetlocale(LC_NUMERIC, save_lc_numeric);

291 free(save_lc_numeric);

292 }

293 _configthreadlocale(save_config_thread_locale);

294

295 return result;

296

297#else

300 int result;

301

302

303

304

305

306

307

308 errno = ENOENT;

309 monetary_locale = newlocale(LC_ALL_MASK, lc_monetary, 0);

310 if (monetary_locale == 0)

311 return -1;

312 numeric_locale = newlocale(LC_ALL_MASK, lc_numeric, 0);

313 if (numeric_locale == 0)

314 {

315 freelocale(monetary_locale);

316 return -1;

317 }

318

320#if defined(TRANSLATE_FROM_LANGINFO)

321

322 result = pg_localeconv_from_langinfo(output,

323 monetary_locale,

324 numeric_locale);

325#elif defined(HAVE_LOCALECONV_L)

326

328 localeconv_l(monetary_locale),

329 LC_MONETARY);

330 if (result == 0)

331 {

332

334 localeconv_l(numeric_locale),

335 LC_NUMERIC);

336 }

337#else

338

339 {

342

344

345 save_locale = uselocale(monetary_locale);

347 localeconv(),

348 LC_MONETARY);

349 if (result == 0)

350 {

351

352 uselocale(numeric_locale);

354 localeconv(),

355 LC_NUMERIC);

356 }

358

359 uselocale(save_locale);

360 }

361#endif

362

363 freelocale(monetary_locale);

364 freelocale(numeric_locale);

365

366 return result;

367#endif

368}

static char * thousands_sep

static char * decimal_point

static char * lc_monetary

static char * lconv_char_member(struct lconv *lconv, int i)

int pg_localeconv_r(const char *lc_monetary, const char *lc_numeric, struct lconv *output)

static int pg_localeconv_copy_members(struct lconv *dst, struct lconv *src, int category)

static char ** lconv_string_member(struct lconv *lconv, int i)

static const struct lconv_member_info table[]

void pg_localeconv_free(struct lconv *lconv)

int pthread_mutex_unlock(pthread_mutex_t *mp)

int pthread_mutex_lock(pthread_mutex_t *mp)

#define PTHREAD_MUTEX_INITIALIZER