summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common.h11
-rw-r--r--libnumtext_num2text.c28
-rw-r--r--swedish.c52
3 files changed, 48 insertions, 43 deletions
diff --git a/common.h b/common.h
index e3c9912..e23ebb7 100644
--- a/common.h
+++ b/common.h
@@ -27,4 +27,13 @@
#define IS_UTF8_CHAR_CONTINUATION(B) (((B) & 0xC0) == 0x80)
-ssize_t libnumtext_num2text_swedish__(char *outbuf, size_t outbuf_size, const char *num, size_t num_len, uint32_t flags);
+struct common_num2text_params {
+ char *outbuf;
+ size_t outbuf_size;
+ size_t sign_length;
+ size_t number_offset;
+ size_t trailing_zeroes;
+};
+
+
+ssize_t libnumtext_num2text_swedish__(struct common_num2text_params *params, const char *num, size_t num_len, uint32_t flags);
diff --git a/libnumtext_num2text.c b/libnumtext_num2text.c
index fafe436..50dc6ca 100644
--- a/libnumtext_num2text.c
+++ b/libnumtext_num2text.c
@@ -6,25 +6,43 @@ ssize_t
libnumtext_num2text(char *outbuf, size_t outbuf_size, const char *num, size_t num_len,
enum libnumtext_language lang, uint32_t flags, ...)
{
+ struct common_num2text_params params;
size_t i;
+ params.outbuf = outbuf;
+ params.outbuf_size = outbuf_size;
+ params.trailing_zeroes = 0;
+
i = 0;
if (i < num_len) {
- if (num[i] == '+' || num[i] == '-')
+ if (num[i] == '+' || num[i] == '-') {
i += 1;
- else if (!strncmp(&num[0], UNICODE_MINUS, sizeof(UNICODE_MINUS) - 1))
- i += sizeof(UNICODE_MINUS) - 1;
+ } else if (num_len >= sizeof(UNICODE_MINUS)) {
+ if (!strncmp(&num[0], UNICODE_MINUS, sizeof(UNICODE_MINUS) - 1))
+ i += sizeof(UNICODE_MINUS) - 1;
+ }
}
+ params.sign_length = i;
if (i == num_len)
goto einval;
- for (; i < num_len; i++)
+
+ while (i + 1 < num_len && num[i] == '0')
+ i += 1;
+ params.number_offset = i;
+
+ for (; i < num_len; i++) {
if (!isdigit(num[i]))
goto einval;
+ else if (num[i] == '0')
+ params.trailing_zeroes += 1;
+ else
+ params.trailing_zeroes = 0;
+ }
switch (lang) {
case LIBNUMTEXT_SWEDISH:
- return libnumtext_num2text_swedish__(outbuf, outbuf_size, num, num_len, flags);
+ return libnumtext_num2text_swedish__(&params, num, num_len, flags);
default:
einval:
diff --git a/swedish.c b/swedish.c
index 89047ee..fa404a7 100644
--- a/swedish.c
+++ b/swedish.c
@@ -396,13 +396,12 @@ adjust_case(struct state *state)
ssize_t
-libnumtext_num2text_swedish__(char *outbuf, size_t outbuf_size, const char *num, size_t num_len, uint32_t flags)
+libnumtext_num2text_swedish__(struct common_num2text_params *params, const char *num, size_t num_len, uint32_t flags)
{
int hundred_thousands, ten_thousands, one_thousands, hundreds, ones;
int great_plurality;
+ size_t great_order, great_order_suffix, small_order;
int32_t small_num;
- size_t great_order, great_order_suffix;
- size_t i, small_order, trailing_zeroes;
struct state state;
if (INVALID_BITS(flags) || X_INVALID_TRIPLETS(flags))
@@ -411,46 +410,26 @@ libnumtext_num2text_swedish__(char *outbuf, size_t outbuf_size, const char *num,
if (!ORDINAL(flags) && !DENOMINATOR(flags))
goto einval;
- state.outbuf = outbuf;
- state.outbuf_size = outbuf_size;
+ state.outbuf = params->outbuf;
+ state.outbuf_size = params->outbuf_size;
state.len = 0;
state.flags = flags;
state.double_char = 0;
state.first = 1;
state.append_for_ordinal = NULL;
- if (!isdigit(num[0])) {
+ if (params->sign_length)
append(&state, signs[num[0] == '+'][TYPE_INDEX(flags)]);
- do {
- num++;
- num_len--;
- } while (IS_UTF8_CHAR_CONTINUATION(*num));
- }
-
- while (num_len > 1 && num[0] == '0') {
- num++;
- num_len--;
- }
- if (num_len == 1) {
- if (num[0] == '0') {
- append_final_digit(&state, 0);
- goto out_and_suffix;
- } else if (num[0] <= '2' && DENOMINATOR(flags)) {
- if (ORDINAL(flags))
- append(&state, wholes_and_halves[num[0] - '1'].ordinal);
- else
- append(&state, wholes_and_halves[num[0] - '1'].cardinal[FORM_INDEX(flags)]);
- goto out;
- }
- }
+ num += params->number_offset;
+ num_len -= params->number_offset;
- trailing_zeroes = 0;
- for (i = 0; i < num_len; i += 1) {
- if (num[i] == '0')
- trailing_zeroes += 1;
+ if (num_len == 1 && '1' <= num[0] && num[0] <= '2' && DENOMINATOR(flags)) {
+ if (ORDINAL(flags))
+ append(&state, wholes_and_halves[num[0] - '1'].ordinal);
else
- trailing_zeroes = 0;
+ append(&state, wholes_and_halves[num[0] - '1'].cardinal[FORM_INDEX(flags)]);
+ goto out;
}
while (num_len) {
@@ -528,7 +507,7 @@ libnumtext_num2text_swedish__(char *outbuf, size_t outbuf_size, const char *num,
small_num *= 10;
small_num += (int32_t)(*num - '0');
ones += *num++ - '0';
- if (ones) {
+ if (ones || (state.first && !great_order)) {
state.append_for_ordinal = NULL;
if (!great_order)
append_final_digit(&state, ones);
@@ -542,14 +521,13 @@ libnumtext_num2text_swedish__(char *outbuf, size_t outbuf_size, const char *num,
}
if (great_order && small_num) {
- great_plurality = (num_len > trailing_zeroes || (CARDINAL(flags) && NUMERATOR(flags)));
- great_plurality = great_plurality && (small_num != 1);
+ great_plurality = (num_len > params->trailing_zeroes || (CARDINAL(flags) && NUMERATOR(flags)));
+ great_plurality = (great_plurality && small_num != 1);
if (append_great(&state, great_order, great_order_suffix, great_plurality))
return -1;
}
}
-out_and_suffix:
if (DENOMINATOR(flags))
append(&state, ORDINAL(flags) ? denominator_suffixes.ordinal : denominator_suffixes.cardinal[FORM_INDEX(flags)]);
else if (ORDINAL(flags) && state.append_for_ordinal)