summaryrefslogtreecommitdiff
path: root/src/select/format_list_style.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/select/format_list_style.c')
-rw-r--r--src/select/format_list_style.c319
1 files changed, 161 insertions, 158 deletions
diff --git a/src/select/format_list_style.c b/src/select/format_list_style.c
index 8636c03..46861a4 100644
--- a/src/select/format_list_style.c
+++ b/src/select/format_list_style.c
@@ -21,8 +21,12 @@ struct list_counter_style {
const unsigned int length;
const symbol_t value;
} pad;
+ struct {
+ const char *pre;
+ const char *post;
+ } negative;
const char *prefix;
- const char *postfix;
+ const char *suffix;
const symbol_t *symbols; /**< array of symbols which represent this style */
const int *weights; /**< symbol weights for additive schemes */
const size_t items; /**< items in symbol and weight table */
@@ -30,6 +34,16 @@ struct list_counter_style {
};
/**
+ * numeric representation of the value using a system
+ */
+struct numeric {
+ uint8_t *val; /* buffer containing the numeric values */
+ size_t len; /* length of alen */
+ size_t used; /* number of numeric values used */
+ bool negative; /* if the value is negative */
+};
+
+/**
* Copy a null-terminated UTF-8 string to buffer at offset, if there is space
*
* \param[in] buf The output buffer
@@ -82,12 +96,12 @@ copy_symbol(char *buf, const size_t buflen, size_t pos, const symbol_t symbol)
}
/**
- * maps alphabet values to output values with a symbol table
+ * maps numeric values to output values with a symbol table
*
- * Takes a list of alphabet values and for each one outputs the
+ * Takes a list of numeric values and for each one outputs the
* compete symbol (in utf8) to an output buffer.
*
- * \param buf The oputput buffer
+ * \param buf The output buffer
* \param buflen the length of \a buf
* \param aval array of alphabet values
* \param alen The number of values in \a alen
@@ -97,33 +111,53 @@ copy_symbol(char *buf, const size_t buflen, size_t pos, const symbol_t symbol)
* larger than \a buflen but the buffer will not be overrun
*/
static size_t
-map_aval_to_symbols(char *buf, const size_t buflen,
- const uint8_t *aval, const size_t alen,
- const struct list_counter_style *cstyle)
+nval_to_symbols(struct numeric *nval,
+ const struct list_counter_style *cstyle,
+ char *buf, const size_t buflen)
{
size_t oidx = 0;
size_t aidx; /* numeral index */
- const symbol_t postfix = "."; /* default postfix string */
+ const char *suffix = "."; /* default sufffix string */
+ const char *negative_pre = "-"; /* default negative string */
+
+ /* prefix */
+ if (cstyle->prefix != NULL) {
+ oidx += copy_string(buf, buflen, oidx, cstyle->prefix);
+ }
+
+ /* negative pre */
+ if (nval->negative) {
+ if (cstyle->negative.pre != NULL) {
+ negative_pre = cstyle->negative.pre;
+ }
+ oidx += copy_string(buf, buflen, oidx, negative_pre);
+ }
/* add padding if required */
- if (alen < cstyle->pad.length) {
+ if (nval->used < cstyle->pad.length) {
size_t pidx; /* padding index */
- for (pidx=cstyle->pad.length - alen; pidx > 0; pidx--) {
+ for (pidx = cstyle->pad.length - nval->used; pidx > 0; pidx--) {
oidx += copy_symbol(buf, buflen, oidx,
cstyle->pad.value);
}
}
/* map symbols */
- for (aidx=0; aidx < alen; aidx++) {
+ for (aidx=0; aidx < nval->used; aidx++) {
oidx += copy_symbol(buf, buflen, oidx,
- cstyle->symbols[aval[aidx]]);
+ cstyle->symbols[nval->val[aidx]]);
}
- /* postfix */
- oidx += copy_string(buf, buflen, oidx,
- (cstyle->postfix != NULL) ?
- cstyle->postfix : postfix);
+ /* negative post */
+ if ((nval->negative) && (cstyle->negative.post != NULL)) {
+ oidx += copy_string(buf, buflen, oidx, cstyle->negative.post);
+ }
+
+ /* suffix */
+ if (cstyle->suffix != NULL) {
+ suffix = cstyle->suffix;
+ }
+ oidx += copy_string(buf, buflen, oidx, suffix);
return oidx;
}
@@ -150,6 +184,16 @@ calc_numeric_system(uint8_t *ares,
uint8_t *first;
uint8_t *last;
+ if (value == 0) {
+ if (alen >= 1) {
+ ares[0] = 0;
+ }
+ return 1;
+ }
+
+ value = abs(value);
+
+
/* generate alphabet values in ascending order */
while (value > 0) {
if (idx < alen) {
@@ -230,6 +274,16 @@ calc_additive_system(uint8_t *ares,
size_t idx;
size_t times; /* number of times a weight occours */
+ /* ensure value is within acceptable range of this system */
+ if ((value < cstyle->range.start) || (value > cstyle->range.end)) {
+ return 0;
+ }
+
+ /* implementation cannot cope with negatives */
+ if (value < 1) {
+ return 0;
+ }
+
/* iterate over the available weights */
for (widx = 0; widx < cstyle->items;widx++) {
times = value / cstyle->weights[widx];
@@ -525,7 +579,7 @@ static const struct list_counter_style lcs_disc = {
.name = "disc",
.symbols = disc_symbols,
.items = (sizeof(disc_symbols) / SYMBOL_SIZE),
- .postfix = " ",
+ .suffix = " ",
.calc = calc_cyclic_system,
};
@@ -534,7 +588,7 @@ static const struct list_counter_style lcs_circle = {
.name = "circle",
.symbols = circle_symbols,
.items = (sizeof(circle_symbols) / SYMBOL_SIZE),
- .postfix = " ",
+ .suffix = " ",
.calc = calc_cyclic_system,
};
@@ -543,7 +597,7 @@ static const struct list_counter_style lcs_square = {
.name = "square",
.symbols = square_symbols,
.items = (sizeof(square_symbols) / SYMBOL_SIZE),
- .postfix = " ",
+ .suffix = " ",
.calc = calc_cyclic_system,
};
@@ -624,7 +678,7 @@ static const symbol_t cjk_decimal_symbols[] = {
static const struct list_counter_style lcs_cjk_decimal = {
.name = "cjk-decimal",
.symbols = cjk_decimal_symbols,
- .postfix = "、",
+ .suffix = "、",
.items = (sizeof(cjk_decimal_symbols) / SYMBOL_SIZE),
.calc = calc_numeric_system,
};
@@ -679,7 +733,7 @@ static const struct list_counter_style lcs_hebrew = {
.start = 1,
.end = 10999,},
.symbols = hebrew_symbols,
- .weights = hebrew_weights,
+ .weights = hebrew_weights,
.items = (sizeof(hebrew_symbols) / SYMBOL_SIZE),
.calc = calc_additive_system,
};
@@ -801,7 +855,7 @@ static struct list_counter_style lcs_cjk_earthly_branch = {
.name = "cjk-earthly-branch",
.symbols = cjk_earthly_branch_symbols,
.items = (sizeof(cjk_earthly_branch_symbols) / SYMBOL_SIZE),
- .postfix = "、",
+ .suffix = "、",
.calc = calc_alphabet_system,
};
@@ -812,7 +866,7 @@ static struct list_counter_style lcs_cjk_heavenly_stem = {
.name = "cjk-heavenly-stem",
.symbols = cjk_heavenly_stem_symbols,
.items = (sizeof(cjk_heavenly_stem_symbols) / SYMBOL_SIZE),
- .postfix = "、",
+ .suffix = "、",
.calc = calc_alphabet_system,
};
@@ -823,7 +877,7 @@ static struct list_counter_style lcs_hiragana = {
.name = "hiragana",
.symbols = hiragana_symbols,
.items = (sizeof(hiragana_symbols) / SYMBOL_SIZE),
- .postfix = "、",
+ .suffix = "、",
.calc = calc_alphabet_system,
};
@@ -834,7 +888,7 @@ static struct list_counter_style lcs_hiragana_iroha = {
.name = "hiragana-iroha",
.symbols = hiragana_iroha_symbols,
.items = (sizeof(hiragana_iroha_symbols) / SYMBOL_SIZE),
- .postfix = "、",
+ .suffix = "、",
.calc = calc_alphabet_system,
};
@@ -845,7 +899,7 @@ static struct list_counter_style lcs_katakana = {
.name = "katakana",
.symbols = katakana_symbols,
.items = (sizeof(katakana_symbols) / SYMBOL_SIZE),
- .postfix = "、",
+ .suffix = "、",
.calc = calc_alphabet_system,
};
@@ -856,203 +910,152 @@ static struct list_counter_style lcs_katakana_iroha = {
.name = "katakana-iroha",
.symbols = katakana_iroha_symbols,
.items = (sizeof(katakana_iroha_symbols) / SYMBOL_SIZE),
- .postfix = "、",
+ .suffix = "、",
.calc = calc_alphabet_system,
};
-/* exported interface defined in select.h */
-css_error css_computed_format_list_style(
- const css_computed_style *style,
- int value,
- char *buffer,
- size_t buffer_length,
- size_t *format_length)
+static const struct list_counter_style *
+counter_style_from_computed_style(const css_computed_style *style)
{
- uint8_t type = get_list_style_type(style);
-
- size_t alen;
- uint8_t aval[20];
- const struct list_counter_style *cstyle;
-
- switch (type) {
+ switch (get_list_style_type(style)) {
case CSS_LIST_STYLE_TYPE_DISC:
- cstyle = &lcs_disc;
- break;
-
+ return &lcs_disc;
case CSS_LIST_STYLE_TYPE_CIRCLE:
- cstyle = &lcs_circle;
- break;
-
+ return &lcs_circle;
case CSS_LIST_STYLE_TYPE_SQUARE:
- cstyle = &lcs_square;
- break;
-
+ return &lcs_square;
case CSS_LIST_STYLE_TYPE_DECIMAL:
- cstyle = &lcs_decimal;
- break;
-
+ return &lcs_decimal;
case CSS_LIST_STYLE_TYPE_DECIMAL_LEADING_ZERO:
- cstyle = &lcs_decimal_leading_zero;
- break;
-
+ return &lcs_decimal_leading_zero;
case CSS_LIST_STYLE_TYPE_LOWER_ROMAN:
- cstyle = &lcs_lower_roman;
- break;
-
+ return &lcs_lower_roman;
case CSS_LIST_STYLE_TYPE_UPPER_ROMAN:
- cstyle = &lcs_upper_roman;
- break;
-
+ return &lcs_upper_roman;
case CSS_LIST_STYLE_TYPE_LOWER_GREEK:
- cstyle = &lcs_lower_greek;
- break;
-
+ return &lcs_lower_greek;
case CSS_LIST_STYLE_TYPE_LOWER_ALPHA:
case CSS_LIST_STYLE_TYPE_LOWER_LATIN:
- cstyle = &lcs_lower_alpha;
- break;
-
+ return &lcs_lower_alpha;
case CSS_LIST_STYLE_TYPE_UPPER_ALPHA:
case CSS_LIST_STYLE_TYPE_UPPER_LATIN:
- cstyle = &lcs_upper_alpha;
- break;
-
+ return &lcs_upper_alpha;
case CSS_LIST_STYLE_TYPE_UPPER_ARMENIAN:
case CSS_LIST_STYLE_TYPE_ARMENIAN:
- cstyle = &lcs_upper_armenian;
- break;
-
+ return &lcs_upper_armenian;
case CSS_LIST_STYLE_TYPE_GEORGIAN:
- cstyle = &lcs_georgian;
- break;
-
+ return &lcs_georgian;
case CSS_LIST_STYLE_TYPE_NONE:
- *format_length = 0;
- return CSS_OK;
-
+ return NULL;
case CSS_LIST_STYLE_TYPE_BINARY:
- cstyle = &lcs_binary;
- break;
-
+ return &lcs_binary;
case CSS_LIST_STYLE_TYPE_OCTAL:
- cstyle = &lcs_octal;
- break;
-
+ return &lcs_octal;
case CSS_LIST_STYLE_TYPE_LOWER_HEXADECIMAL:
- cstyle = &lcs_lower_hexadecimal;
- break;
-
+ return &lcs_lower_hexadecimal;
case CSS_LIST_STYLE_TYPE_UPPER_HEXADECIMAL:
- cstyle = &lcs_upper_hexadecimal;
- break;
-
+ return &lcs_upper_hexadecimal;
case CSS_LIST_STYLE_TYPE_ARABIC_INDIC:
- cstyle = &lcs_arabic_indic;
- break;
-
+ return &lcs_arabic_indic;
case CSS_LIST_STYLE_TYPE_LOWER_ARMENIAN:
- cstyle = &lcs_lower_armenian;
- break;
-
+ return &lcs_lower_armenian;
case CSS_LIST_STYLE_TYPE_BENGALI:
- cstyle = &lcs_bengali;
- break;
-
+ return &lcs_bengali;
case CSS_LIST_STYLE_TYPE_CAMBODIAN:
case CSS_LIST_STYLE_TYPE_KHMER:
- cstyle = &lcs_cambodian;
- break;
-
+ return &lcs_cambodian;
case CSS_LIST_STYLE_TYPE_CJK_DECIMAL:
- cstyle = &lcs_cjk_decimal;
- break;
-
+ return &lcs_cjk_decimal;
case CSS_LIST_STYLE_TYPE_DEVANAGARI:
- cstyle = &lcs_devanagari;
- break;
-
+ return &lcs_devanagari;
case CSS_LIST_STYLE_TYPE_GUJARATI:
- cstyle = &lcs_gujarati;
- break;
-
+ return &lcs_gujarati;
case CSS_LIST_STYLE_TYPE_GURMUKHI:
- cstyle = &lcs_gurmukhi;
- break;
-
+ return &lcs_gurmukhi;
case CSS_LIST_STYLE_TYPE_HEBREW:
- cstyle = &lcs_hebrew;
- break;
+ return &lcs_hebrew;
case CSS_LIST_STYLE_TYPE_KANNADA:
- cstyle = &lcs_kannada;
- break;
+ return &lcs_kannada;
case CSS_LIST_STYLE_TYPE_LAO:
- cstyle = &lcs_lao;
- break;
+ return &lcs_lao;
case CSS_LIST_STYLE_TYPE_MALAYALAM:
- cstyle = &lcs_malayalam;
- break;
+ return &lcs_malayalam;
case CSS_LIST_STYLE_TYPE_MONGOLIAN:
- cstyle = &lcs_mongolian;
- break;
+ return &lcs_mongolian;
case CSS_LIST_STYLE_TYPE_MYANMAR:
- cstyle = &lcs_myanmar;
- break;
+ return &lcs_myanmar;
case CSS_LIST_STYLE_TYPE_ORIYA:
- cstyle = &lcs_oriya;
- break;
+ return &lcs_oriya;
case CSS_LIST_STYLE_TYPE_PERSIAN:
- cstyle = &lcs_persian;
- break;
+ return &lcs_persian;
case CSS_LIST_STYLE_TYPE_TAMIL:
- cstyle = &lcs_tamil;
- break;
+ return &lcs_tamil;
case CSS_LIST_STYLE_TYPE_TELUGU:
- cstyle = &lcs_telugu;
- break;
+ return &lcs_telugu;
case CSS_LIST_STYLE_TYPE_THAI:
- cstyle = &lcs_thai;
- break;
+ return &lcs_thai;
case CSS_LIST_STYLE_TYPE_TIBETAN:
- cstyle = &lcs_tibetan;
- break;
+ return &lcs_tibetan;
case CSS_LIST_STYLE_TYPE_CJK_EARTHLY_BRANCH:
- cstyle = &lcs_cjk_earthly_branch;
- break;
+ return &lcs_cjk_earthly_branch;
case CSS_LIST_STYLE_TYPE_CJK_HEAVENLY_STEM:
- cstyle = &lcs_cjk_heavenly_stem;
- break;
+ return &lcs_cjk_heavenly_stem;
case CSS_LIST_STYLE_TYPE_HIAGANA:
- cstyle = &lcs_hiragana;
- break;
+ return &lcs_hiragana;
case CSS_LIST_STYLE_TYPE_HIAGANA_IROHA:
- cstyle = &lcs_hiragana_iroha;
- break;
+ return &lcs_hiragana_iroha;
case CSS_LIST_STYLE_TYPE_KATAKANA:
- cstyle = &lcs_katakana;
- break;
+ return &lcs_katakana;
case CSS_LIST_STYLE_TYPE_KATAKANA_IROHA:
- cstyle = &lcs_katakana_iroha;
- break;
- default:
+ return &lcs_katakana_iroha;
+ }
+ return NULL;
+}
+
+
+/* exported interface defined in select.h */
+css_error css_computed_format_list_style(
+ const css_computed_style *style,
+ int value,
+ char *buffer,
+ size_t buffer_length,
+ size_t *format_length)
+{
+ uint8_t aval[20];
+ const struct list_counter_style *cstyle;
+ struct numeric nval = {
+ .val = aval,
+ .len = sizeof(aval),
+ .used = 0,
+ .negative = false
+ };
+
+ nval.negative = (value < 0)?true:false;
+
+ cstyle = counter_style_from_computed_style(style);
+ if (cstyle == NULL) {
return CSS_BADPARM;
}
- alen = cstyle->calc(aval, sizeof(aval), value, cstyle);
+ nval.used = cstyle->calc(aval, sizeof(aval), value, cstyle);
/* ensure it is possible to calculate with the selected system */
- if ((alen == 0) || (alen >= sizeof(aval))) {
+ if ((nval.used == 0) || (nval.used >= sizeof(aval))) {
/* retry in decimal */
cstyle = &lcs_decimal;
- alen = cstyle->calc(aval, sizeof(aval), value, cstyle);
- if ((alen == 0) || (alen >= sizeof(aval))) {
+ nval.used = cstyle->calc(aval, sizeof(aval), value, cstyle);
+ if ((nval.used == 0) || (nval.used >= sizeof(aval))) {
/* failed in decimal, give up */
return CSS_INVALID;
}
}
- *format_length = map_aval_to_symbols(buffer, buffer_length, aval, alen, cstyle);
+ *format_length = nval_to_symbols(&nval,
+ cstyle,
+ buffer,
+ buffer_length);
return CSS_OK;
}