Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6743a87

Browse files
committed
Support more locale-specific formatting options in cash_out().
The POSIX spec defines locale fields for controlling the ordering of thevalue, sign, and currency symbol in monetary output, but cash_out onlysupported a small subset of these options. Fully implement p/n_sign_posn,p/n_cs_precedes, and p/n_sep_by_space per spec. Fix up cash_in so thatit will accept all these format variants.Also, make sure that thousands_sep is only inserted to the left of thedecimal point, as required by spec.Per bug #6144 from Eduard Kracmar and discussion of bug #6277. This patchincludes some ideas from Alexander Lakhin's proposed patch, though it isvery different in detail.
1 parenteb5834d commit6743a87

File tree

1 file changed

+134
-32
lines changed

1 file changed

+134
-32
lines changed

‎src/backend/utils/adt/cash.c

Lines changed: 134 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ cash_in(PG_FUNCTION_ARGS)
150150
s++;
151151
if (strncmp(s,csymbol,strlen(csymbol))==0)
152152
s+=strlen(csymbol);
153+
while (isspace((unsignedchar)*s))
154+
s++;
153155

154156
#ifdefCASHDEBUG
155157
printf("cashin- string is '%s'\n",s);
@@ -180,6 +182,8 @@ cash_in(PG_FUNCTION_ARGS)
180182
s++;
181183
if (strncmp(s,csymbol,strlen(csymbol))==0)
182184
s+=strlen(csymbol);
185+
while (isspace((unsignedchar)*s))
186+
s++;
183187

184188
#ifdefCASHDEBUG
185189
printf("cashin- string is '%s'\n",s);
@@ -218,10 +222,11 @@ cash_in(PG_FUNCTION_ARGS)
218222

219223
/*
220224
* should only be trailing digits followed by whitespace, right paren,
221-
*or possibly a trailingminus sign
225+
*trailing sign, and/or trailingcurrency symbol
222226
*/
223227
while (isdigit((unsignedchar)*s))
224228
s++;
229+
225230
while (*s)
226231
{
227232
if (isspace((unsignedchar)*s)||*s==')')
@@ -231,6 +236,10 @@ cash_in(PG_FUNCTION_ARGS)
231236
sgn=-1;
232237
s+=strlen(nsymbol);
233238
}
239+
elseif (strncmp(s,psymbol,strlen(psymbol))==0)
240+
s+=strlen(psymbol);
241+
elseif (strncmp(s,csymbol,strlen(csymbol))==0)
242+
s+=strlen(csymbol);
234243
else
235244
ereport(ERROR,
236245
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
@@ -259,15 +268,16 @@ cash_out(PG_FUNCTION_ARGS)
259268
char*result;
260269
charbuf[128];
261270
char*bufptr;
262-
boolminus= false;
263271
intdigit_pos;
264272
intpoints,
265273
mon_group;
266274
chardsymbol;
267275
constchar*ssymbol,
268276
*csymbol,
269-
*nsymbol;
270-
charconvention;
277+
*signsymbol;
278+
charsign_posn,
279+
cs_precedes,
280+
sep_by_space;
271281
structlconv*lconvert=PGLC_localeconv();
272282

273283
/* see comments about frac_digits in cash_in() */
@@ -283,8 +293,6 @@ cash_out(PG_FUNCTION_ARGS)
283293
if (mon_group <=0||mon_group>6)
284294
mon_group=3;
285295

286-
convention=lconvert->n_sign_posn;
287-
288296
/* we restrict dsymbol to be a single byte, but not the other symbols */
289297
if (*lconvert->mon_decimal_point!='\0'&&
290298
lconvert->mon_decimal_point[1]=='\0')
@@ -296,16 +304,26 @@ cash_out(PG_FUNCTION_ARGS)
296304
else/* ssymbol should not equal dsymbol */
297305
ssymbol= (dsymbol!=',') ?"," :".";
298306
csymbol= (*lconvert->currency_symbol!='\0') ?lconvert->currency_symbol :"$";
299-
nsymbol= (*lconvert->negative_sign!='\0') ?lconvert->negative_sign :"-";
300307

301-
/* we work with positive amounts and add the minus sign at the end */
302308
if (value<0)
303309
{
304-
minus= true;
310+
/* make the amount positive for digit-reconstruction loop */
305311
value=-value;
312+
/* set up formatting data */
313+
signsymbol= (*lconvert->negative_sign!='\0') ?lconvert->negative_sign :"-";
314+
sign_posn=lconvert->n_sign_posn;
315+
cs_precedes=lconvert->n_cs_precedes;
316+
sep_by_space=lconvert->n_sep_by_space;
317+
}
318+
else
319+
{
320+
signsymbol=lconvert->positive_sign;
321+
sign_posn=lconvert->p_sign_posn;
322+
cs_precedes=lconvert->p_cs_precedes;
323+
sep_by_space=lconvert->p_sep_by_space;
306324
}
307325

308-
/* we build theresult string right-to-left in buf[] */
326+
/* we build thedigits+decimal-point+sep string right-to-left in buf[] */
309327
bufptr=buf+sizeof(buf)-1;
310328
*bufptr='\0';
311329

@@ -320,12 +338,12 @@ cash_out(PG_FUNCTION_ARGS)
320338
{
321339
if (points&&digit_pos==0)
322340
{
323-
/* insert decimal point */
341+
/* insert decimal point, but not if value cannot be fractional */
324342
*(--bufptr)=dsymbol;
325343
}
326-
elseif (digit_pos<points&& (digit_pos %mon_group)==0)
344+
elseif (digit_pos<0&& (digit_pos %mon_group)==0)
327345
{
328-
/* insert thousands sep */
346+
/* insert thousands sep, but only to left of radix point */
329347
bufptr-=strlen(ssymbol);
330348
memcpy(bufptr,ssymbol,strlen(ssymbol));
331349
}
@@ -335,27 +353,111 @@ cash_out(PG_FUNCTION_ARGS)
335353
digit_pos--;
336354
}while (value||digit_pos >=0);
337355

338-
/* prepend csymbol */
339-
bufptr-=strlen(csymbol);
340-
memcpy(bufptr,csymbol,strlen(csymbol));
341-
342-
/* see if we need to signify negative amount */
343-
if (minus)
344-
{
345-
result=palloc(strlen(bufptr)+strlen(nsymbol)+3);
356+
/*----------
357+
* Now, attach currency symbol and sign symbol in the correct order.
358+
*
359+
* The POSIX spec defines these values controlling this code:
360+
*
361+
* p/n_sign_posn:
362+
*0Parentheses enclose the quantity and the currency_symbol.
363+
*1The sign string precedes the quantity and the currency_symbol.
364+
*2The sign string succeeds the quantity and the currency_symbol.
365+
*3The sign string precedes the currency_symbol.
366+
*4The sign string succeeds the currency_symbol.
367+
*
368+
* p/n_cs_precedes: 0 means currency symbol after value, else before it.
369+
*
370+
* p/n_sep_by_space:
371+
*0No <space> separates the currency symbol and value.
372+
*1If the currency symbol and sign string are adjacent, a <space>
373+
*separates them from the value; otherwise, a <space> separates
374+
*the currency symbol from the value.
375+
*2If the currency symbol and sign string are adjacent, a <space>
376+
*separates them; otherwise, a <space> separates the sign string
377+
*from the value.
378+
*----------
379+
*/
380+
result=palloc(strlen(bufptr)+strlen(csymbol)+strlen(signsymbol)+4);
346381

347-
/* Position code of 0 means use parens */
348-
if (convention==0)
349-
sprintf(result,"(%s)",bufptr);
350-
elseif (convention==2)
351-
sprintf(result,"%s%s",bufptr,nsymbol);
352-
else
353-
sprintf(result,"%s%s",nsymbol,bufptr);
354-
}
355-
else
382+
switch (sign_posn)
356383
{
357-
/* just emit what we have */
358-
result=pstrdup(bufptr);
384+
case0:
385+
if (cs_precedes)
386+
sprintf(result,"(%s%s%s)",
387+
csymbol,
388+
(sep_by_space==1) ?" " :"",
389+
bufptr);
390+
else
391+
sprintf(result,"(%s%s%s)",
392+
bufptr,
393+
(sep_by_space==1) ?" " :"",
394+
csymbol);
395+
break;
396+
case1:
397+
default:
398+
if (cs_precedes)
399+
sprintf(result,"%s%s%s%s%s",
400+
signsymbol,
401+
(sep_by_space==2) ?" " :"",
402+
csymbol,
403+
(sep_by_space==1) ?" " :"",
404+
bufptr);
405+
else
406+
sprintf(result,"%s%s%s%s%s",
407+
signsymbol,
408+
(sep_by_space==2) ?" " :"",
409+
bufptr,
410+
(sep_by_space==1) ?" " :"",
411+
csymbol);
412+
break;
413+
case2:
414+
if (cs_precedes)
415+
sprintf(result,"%s%s%s%s%s",
416+
csymbol,
417+
(sep_by_space==1) ?" " :"",
418+
bufptr,
419+
(sep_by_space==2) ?" " :"",
420+
signsymbol);
421+
else
422+
sprintf(result,"%s%s%s%s%s",
423+
bufptr,
424+
(sep_by_space==1) ?" " :"",
425+
csymbol,
426+
(sep_by_space==2) ?" " :"",
427+
signsymbol);
428+
break;
429+
case3:
430+
if (cs_precedes)
431+
sprintf(result,"%s%s%s%s%s",
432+
signsymbol,
433+
(sep_by_space==2) ?" " :"",
434+
csymbol,
435+
(sep_by_space==1) ?" " :"",
436+
bufptr);
437+
else
438+
sprintf(result,"%s%s%s%s%s",
439+
bufptr,
440+
(sep_by_space==1) ?" " :"",
441+
signsymbol,
442+
(sep_by_space==2) ?" " :"",
443+
csymbol);
444+
break;
445+
case4:
446+
if (cs_precedes)
447+
sprintf(result,"%s%s%s%s%s",
448+
csymbol,
449+
(sep_by_space==2) ?" " :"",
450+
signsymbol,
451+
(sep_by_space==1) ?" " :"",
452+
bufptr);
453+
else
454+
sprintf(result,"%s%s%s%s%s",
455+
bufptr,
456+
(sep_by_space==1) ?" " :"",
457+
csymbol,
458+
(sep_by_space==2) ?" " :"",
459+
signsymbol);
460+
break;
359461
}
360462

361463
PG_RETURN_CSTRING(result);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp