Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* cash_out()
- * Function to convert cash to a money representation.
- */
- Datum
- cash_out(PG_FUNCTION_ARGS)
- {
- Cash value = PG_GETARG_CASH(0);
- char *result;
- char buf[CASH_BUFSZ];
- int count = LAST_DIGIT,
- dcount = 0;
- int points,
- mon_group;
- const char *dsymbol,
- *ssymbol,
- *csymbol,
- *csymbol_sep,
- *signsymbol;
- char sign_pos,
- csymbol_precedes;
- struct lconv *lconvert = PGLC_localeconv();
- /* see comments about frac_digits in cash_in() */
- points = lconvert->frac_digits;
- if (points < 0 || points > 10)
- points = 2; /* best guess in this case, I think */
- /*
- * As with frac_digits, must apply a range check to mon_grouping to avoid
- * being fooled by variant CHAR_MAX values.
- */
- mon_group = *lconvert->mon_grouping;
- if (mon_group <= 0 || mon_group > 6)
- mon_group = 3;
- dsymbol = ((*lconvert->mon_decimal_point != '\0') ? lconvert->mon_decimal_point : ".");
- /*
- ssymbol = lconvert->mon_thousands_sep;
- to pass regression test must set "," as the separator when it is empty
- */
- if (*lconvert->mon_thousands_sep != '\0')
- ssymbol = lconvert->mon_thousands_sep;
- else
- /* ssymbol should not equal dsymbol */
- ssymbol = (*dsymbol != ',') ? "," : ".";
- csymbol = ((*lconvert->currency_symbol != '\0') ? lconvert->currency_symbol : "$");
- if (value < 0)
- {
- /* we work with positive amounts */
- value = -value;
- signsymbol = ((*lconvert->negative_sign != '\0') ? lconvert->negative_sign : "-");
- /*
- csymbol_sep = ((lconvert->n_sep_by_space) ? " " : "");
- to pass regression test must omit the currency symbol separator
- */
- csymbol_sep = "";
- csymbol_precedes = lconvert->n_cs_precedes;
- sign_pos = lconvert->n_sign_posn;
- }
- else
- {
- signsymbol = lconvert->positive_sign;
- /*
- csymbol_sep = ((lconvert->p_sep_by_space) ? " " : "");
- to pass regression test must omit the currency symbol separator
- */
- csymbol_sep = "";
- csymbol_precedes = lconvert->p_cs_precedes;
- sign_pos = lconvert->p_sign_posn;
- }
- /* allow for trailing negative strings */
- MemSet(buf, ' ', CASH_BUFSZ);
- buf[TERMINATOR] = buf[LAST_PAREN] = '\0';
- while (count >= 0 && (value || dcount <= points))
- {
- if (points && points == dcount)
- {
- if (count < strlen(dsymbol)) break;
- count -= strlen(dsymbol);
- strncpy((buf + count + 1), dsymbol, strlen(dsymbol));
- }
- else if (*ssymbol && dcount > points && (dcount - points) % mon_group == 0)
- {
- if (count < strlen(ssymbol)) break;
- count -= strlen(ssymbol);
- strncpy((buf + count + 1), ssymbol, strlen(ssymbol));
- }
- buf[count--] = ((uint64) value % 10) + '0';
- value = ((uint64) value) / 10;
- dcount++;
- }
- count++;
- if (!sign_pos) {
- result = palloc(CASH_BUFSZ + 2 - count + 2 + strlen(csymbol) + 1);
- if (csymbol_precedes)
- sprintf(result, "(%s%s%s)", csymbol, csymbol_sep, buf + count);
- else
- sprintf(result, "(%s%s%s)", buf + count, csymbol_sep, csymbol);
- } else {
- result = palloc(CASH_BUFSZ + 2 - count + strlen(signsymbol) + strlen(csymbol) + 1);
- switch (sign_pos)
- {
- case 2:
- /* sign after the quantity and currency symbol */
- if (csymbol_precedes)
- sprintf(result, "%s%s%s%s", csymbol, csymbol_sep, buf + count, signsymbol);
- else
- sprintf(result, "%s%s%s%s", buf + count, csymbol_sep, csymbol, signsymbol);
- break;
- case 3:
- /* sign right before currency symbol */
- if (csymbol_precedes)
- sprintf(result, "%s%s%s%s", signsymbol, csymbol, csymbol_sep, buf + count);
- else
- sprintf(result, "%s%s%s%s", buf + count, signsymbol, csymbol_sep, csymbol);
- break;
- case 4:
- /* sign right after currency symbol */
- if (csymbol_precedes)
- sprintf(result, "%s%s%s%s", csymbol, csymbol_sep, signsymbol, buf + count);
- else
- sprintf(result, "%s%s%s%s", buf + count, csymbol_sep, csymbol, signsymbol);
- break;
- case 1:
- /* sign before the quantity and currency symbol */
- default:
- if (csymbol_precedes)
- sprintf(result, "%s%s%s%s", signsymbol, csymbol, csymbol_sep, buf + count);
- else
- sprintf(result, "%s%s%s%s", signsymbol, buf + count, csymbol_sep, csymbol);
- break;
- }
- }
- PG_RETURN_CSTRING(result);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement