From: Ben Pfaff Date: Sun, 29 Aug 2010 21:53:01 +0000 (-0700) Subject: format: Introduce a new type, struct fmt_settings. X-Git-Tag: sav-api~59 X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp;a=commitdiff_plain;h=377d05c1eb7b390e2cdb049469fe6b0cfcf52615 format: Introduce a new type, struct fmt_settings. Until now the collection of formatting styles have been poorly abstracted, as an array. This commit introduces a new type, struct fmt_settings, that represents all of the formatting styles currently in use. --- diff --git a/src/data/format.c b/src/data/format.c index 5fe620b8b0..a78ea91c57 100644 --- a/src/data/format.c +++ b/src/data/format.c @@ -37,7 +37,10 @@ #include "gettext.h" #define _(msgid) gettext (msgid) - +struct fmt_settings + { + struct fmt_number_style styles[FMT_NUMBER_OF_FORMATS]; + }; bool is_fmt_type (enum fmt_type); @@ -46,35 +49,110 @@ static bool valid_width (enum fmt_type, int width, bool for_input); static int max_digits_for_bytes (int bytes); static void fmt_number_style_init (struct fmt_number_style *); +static void fmt_number_style_clone (struct fmt_number_style *, + const struct fmt_number_style *); static void fmt_number_style_destroy (struct fmt_number_style *); +/* Creates and returns a new struct fmt_settings with default format styles. */ +struct fmt_settings * +fmt_settings_create (void) +{ + struct fmt_settings *settings; + int t; + + settings = xzalloc (sizeof *settings); + for (t = 0 ; t < FMT_NUMBER_OF_FORMATS ; ++t ) + fmt_number_style_init (&settings->styles[t]); + fmt_settings_set_decimal (settings, '.'); + + return settings; +} -/* Initialize the format module. */ -struct fmt_number_style * -fmt_create (void) +/* Destroys SETTINGS. */ +void +fmt_settings_destroy (struct fmt_settings *settings) { - struct fmt_number_style *styles = - xcalloc (FMT_NUMBER_OF_FORMATS, sizeof (*styles)); + if (settings != NULL) + { + int t; + + for (t = 0 ; t < FMT_NUMBER_OF_FORMATS ; ++t ) + fmt_number_style_destroy (&settings->styles[t]); + free (settings->styles); + } +} + +/* Returns a copy of SETTINGS. */ +struct fmt_settings * +fmt_settings_clone (const struct fmt_settings *old) +{ + struct fmt_settings *new; int t; + + new = xmalloc (sizeof *new); for (t = 0 ; t < FMT_NUMBER_OF_FORMATS ; ++t ) - fmt_number_style_init (&styles[t]); + fmt_number_style_clone (&new->styles[t], &old->styles[t]); - fmt_set_decimal (styles, '.'); + return new; +} - return styles; +/* Returns the number formatting style associated with the given + format TYPE. */ +const struct fmt_number_style * +fmt_settings_get_style (const struct fmt_settings *settings, + enum fmt_type type) +{ + assert (is_fmt_type (type)); + return &settings->styles[type]; } +void +fmt_settings_set_style (struct fmt_settings *settings, enum fmt_type type, + const struct fmt_number_style *style) +{ + fmt_check_style (style); + fmt_number_style_destroy (&settings->styles[type]); + fmt_number_style_clone (&settings->styles[type], style); +} + +/* Sets the number style for TYPE to have the given standard + PREFIX and SUFFIX, "-" as prefix suffix, an empty negative + suffix, DECIMAL as the decimal point character, and GROUPING + as the grouping character. */ +static void +set_style (struct fmt_settings *settings, enum fmt_type type, + const char *prefix, const char *suffix, + char decimal, char grouping) +{ + struct fmt_number_style *style; -/* Deinitialize the format module. */ + assert (is_fmt_type (type)); + + style = &settings->styles[type]; + + fmt_number_style_destroy (style); + + ss_alloc_substring (&style->neg_prefix, ss_cstr ("-")); + ss_alloc_substring (&style->prefix, ss_cstr (prefix)); + ss_alloc_substring (&style->suffix, ss_cstr (suffix)); + style->decimal = decimal; + style->grouping = grouping; +} + +/* Sets the decimal point character for SETTINGS to DECIMAL. */ void -fmt_done (struct fmt_number_style *styles) +fmt_settings_set_decimal (struct fmt_settings *settings, char decimal) { - int t; - for (t = 0 ; t < FMT_NUMBER_OF_FORMATS ; ++t ) - fmt_number_style_destroy (&styles[t]); + int grouping = decimal == '.' ? ',' : '.'; + assert (decimal == '.' || decimal == ','); - free (styles); + set_style (settings, FMT_F, "", "", decimal, 0); + set_style (settings, FMT_E, "", "", decimal, 0); + set_style (settings, FMT_COMMA, "", "", decimal, grouping); + set_style (settings, FMT_DOT, "", "", grouping, decimal); + set_style (settings, FMT_DOLLAR, "$", "", decimal, grouping); + set_style (settings, FMT_PCT, "", "%", decimal, 0); } /* Returns an input format specification with type TYPE, width W, @@ -869,6 +947,17 @@ fmt_number_style_init (struct fmt_number_style *style) style->grouping = 0; } +static void +fmt_number_style_clone (struct fmt_number_style *new, + const struct fmt_number_style *old) +{ + ss_alloc_substring (&new->neg_prefix, old->neg_prefix); + ss_alloc_substring (&new->prefix, old->prefix); + ss_alloc_substring (&new->suffix, old->suffix); + ss_alloc_substring (&new->neg_suffix, old->neg_suffix); + new->decimal = old->decimal; + new->grouping = old->grouping; +} /* Destroys a struct fmt_number_style. */ static void @@ -883,16 +972,6 @@ fmt_number_style_destroy (struct fmt_number_style *style) } } -/* Returns the number formatting style associated with the given - format TYPE. */ -const struct fmt_number_style * -fmt_get_style (const struct fmt_number_style *styles, enum fmt_type type) -{ - assert (is_fmt_type (type)); - return &styles[type]; -} - - /* Checks that style is STYLE sane */ void fmt_check_style (const struct fmt_number_style *style) @@ -924,46 +1003,6 @@ fmt_neg_affix_width (const struct fmt_number_style *style) return ss_length (style->neg_prefix) + ss_length (style->neg_suffix); } - -/* Sets the number style for TYPE to have the given standard - PREFIX and SUFFIX, "-" as prefix suffix, an empty negative - suffix, DECIMAL as the decimal point character, and GROUPING - as the grouping character. */ -static void -set_style (struct fmt_number_style *styles, enum fmt_type type, - const char *prefix, const char *suffix, - char decimal, char grouping) -{ - struct fmt_number_style *style; - - assert (is_fmt_type (type)); - - style = &styles[type] ; - - fmt_number_style_destroy (style); - - ss_alloc_substring (&style->neg_prefix, ss_cstr ("-")); - ss_alloc_substring (&style->prefix, ss_cstr (prefix)); - ss_alloc_substring (&style->suffix, ss_cstr (suffix)); - style->decimal = decimal; - style->grouping = grouping; -} - -/* Sets the decimal point character to DECIMAL. */ -void -fmt_set_decimal (struct fmt_number_style *styles, char decimal) -{ - int grouping = decimal == '.' ? ',' : '.'; - assert (decimal == '.' || decimal == ','); - - set_style (styles, FMT_F, "", "", decimal, 0); - set_style (styles, FMT_E, "", "", decimal, 0); - set_style (styles, FMT_COMMA, "", "", decimal, grouping); - set_style (styles, FMT_DOT, "", "", grouping, decimal); - set_style (styles, FMT_DOLLAR, "$", "", decimal, grouping); - set_style (styles, FMT_PCT, "", "%", decimal, 0); -} - /* Returns the struct fmt_desc for the given format TYPE. */ static const struct fmt_desc * get_fmt_desc (enum fmt_type type) diff --git a/src/data/format.h b/src/data/format.h index c97f46c5f7..36726542de 100644 --- a/src/data/format.h +++ b/src/data/format.h @@ -72,22 +72,6 @@ struct fmt_spec /* Maximum width of any numeric format. */ #define FMT_MAX_NUMERIC_WIDTH 40 -/* A numeric output style. */ -struct fmt_number_style - { - struct substring neg_prefix; /* Negative prefix. */ - struct substring prefix; /* Prefix. */ - struct substring suffix; /* Suffix. */ - struct substring neg_suffix; /* Negative suffix. */ - char decimal; /* Decimal point: '.' or ','. */ - char grouping; /* Grouping character: ',', '.', or 0. */ - }; - - -/* Initialization. */ -struct fmt_number_style * fmt_create (void); -void fmt_done (struct fmt_number_style *); - /* Constructing formats. */ struct fmt_spec fmt_for_input (enum fmt_type, int w, int d) PURE_FUNCTION; struct fmt_spec fmt_for_output (enum fmt_type, int w, int d) PURE_FUNCTION; @@ -142,6 +126,32 @@ bool fmt_from_io (int io, enum fmt_type *); const char *fmt_date_template (enum fmt_type) PURE_FUNCTION; +/* Format settings. + + A fmt_settings is really just a collection of one "struct fmt_number_style" + for each format type. */ +struct fmt_settings *fmt_settings_create (void); +void fmt_settings_destroy (struct fmt_settings *); +struct fmt_settings *fmt_settings_clone (const struct fmt_settings *); + +void fmt_settings_set_decimal (struct fmt_settings *, char); + +const struct fmt_number_style *fmt_settings_get_style ( + const struct fmt_settings *, enum fmt_type); +void fmt_settings_set_style (struct fmt_settings *, enum fmt_type, + const struct fmt_number_style *); + +/* A numeric output style. */ +struct fmt_number_style + { + struct substring neg_prefix; /* Negative prefix. */ + struct substring prefix; /* Prefix. */ + struct substring suffix; /* Suffix. */ + struct substring neg_suffix; /* Negative suffix. */ + char decimal; /* Decimal point: '.' or ','. */ + char grouping; /* Grouping character: ',', '.', or 0. */ + }; + /* Maximum length of prefix or suffix string in struct fmt_number_style. */ #define FMT_STYLE_AFFIX_MAX 16 @@ -149,11 +159,8 @@ const char *fmt_date_template (enum fmt_type) PURE_FUNCTION; int fmt_affix_width (const struct fmt_number_style *); int fmt_neg_affix_width (const struct fmt_number_style *); -const struct fmt_number_style *fmt_get_style (const struct fmt_number_style *, enum fmt_type); - void fmt_check_style (const struct fmt_number_style *style); -void fmt_set_decimal (struct fmt_number_style *, char); extern const struct fmt_spec F_8_0 ; diff --git a/src/data/settings.c b/src/data/settings.c index 10b20f8a35..3e637a31b3 100644 --- a/src/data/settings.c +++ b/src/data/settings.c @@ -73,7 +73,7 @@ struct settings int *algorithm; int syntax; - struct fmt_number_style *styles; + struct fmt_settings *styles; enum settings_output_devices output_routing[SETTINGS_N_OUTPUT_TYPES]; }; @@ -151,7 +151,7 @@ settings_init (int *width, int *length) { init_viewport (width, length); settings_set_epoch (-1); - the_settings.styles = fmt_create (); + the_settings.styles = fmt_settings_create (); settings_set_decimal_char (get_system_decimal ()); } @@ -159,7 +159,7 @@ settings_init (int *width, int *length) void settings_done (void) { - fmt_done (the_settings.styles); + fmt_settings_destroy (the_settings.styles); } /* Returns the floating-point format used for RB and RBHEX @@ -589,41 +589,46 @@ find_cc_separators (const char *cc_string, struct fmt_number_style *cc) return true; } -/* Extracts a token from IN into a newly allocated AFFIX. Tokens - are delimited by GROUPING. The token is truncated to at most - FMT_STYLE_AFFIX_MAX characters. Returns the first character - following the token. */ +/* Extracts a token from IN into AFFIX, using BUFFER for storage. BUFFER must + have at least FMT_STYLE_AFFIX_MAX + 1 bytes of space. Tokens are delimited + by GROUPING. The token is truncated to at most FMT_STYLE_AFFIX_MAX bytes, + followed by a null terminator. Returns the first character following the + token. */ static const char * -extract_cc_token (const char *in, int grouping, struct substring *affix) +extract_cc_token (const char *in, int grouping, struct substring *affix, + char buffer[FMT_STYLE_AFFIX_MAX + 1]) { size_t ofs = 0; - ss_alloc_uninit (affix, FMT_STYLE_AFFIX_MAX); + for (; *in != '\0' && *in != grouping; in++) { if (*in == '\'' && in[1] == grouping) in++; if (ofs < FMT_STYLE_AFFIX_MAX) - ss_data (*affix)[ofs++] = *in; + buffer[ofs++] = *in; } - affix->length = ofs; + *affix = ss_buffer (buffer, ofs); if (*in == grouping) in++; return in; } - /* Sets custom currency specifier CC having name CC_NAME ('A' through 'E') to correspond to the settings in CC_STRING. */ bool settings_set_cc (const char *cc_string, enum fmt_type type) { - struct fmt_number_style *cc = &the_settings.styles[type]; + char a[FMT_STYLE_AFFIX_MAX + 1]; + char b[FMT_STYLE_AFFIX_MAX + 1]; + char c[FMT_STYLE_AFFIX_MAX + 1]; + char d[FMT_STYLE_AFFIX_MAX + 1]; + struct fmt_number_style cc; assert (fmt_get_category (type) == FMT_CAT_CUSTOM); /* Determine separators. */ - if (!find_cc_separators (cc_string, cc)) + if (!find_cc_separators (cc_string, &cc)) { msg (SE, _("%s: Custom currency string `%s' does not contain " "exactly three periods or commas (or it contains both)."), @@ -631,12 +636,12 @@ settings_set_cc (const char *cc_string, enum fmt_type type) return false; } - cc_string = extract_cc_token (cc_string, cc->grouping, &cc->neg_prefix); - cc_string = extract_cc_token (cc_string, cc->grouping, &cc->prefix); - cc_string = extract_cc_token (cc_string, cc->grouping, &cc->suffix); - cc_string = extract_cc_token (cc_string, cc->grouping, &cc->neg_suffix); + cc_string = extract_cc_token (cc_string, cc.grouping, &cc.neg_prefix, a); + cc_string = extract_cc_token (cc_string, cc.grouping, &cc.prefix, b); + cc_string = extract_cc_token (cc_string, cc.grouping, &cc.suffix, c); + cc_string = extract_cc_token (cc_string, cc.grouping, &cc.neg_suffix, d); - fmt_check_style (cc); + fmt_settings_set_style (the_settings.styles, type, &cc); return true; } @@ -645,41 +650,37 @@ settings_set_cc (const char *cc_string, enum fmt_type type) int settings_get_decimal_char (enum fmt_type type) { - return fmt_get_style (the_settings.styles, type)->decimal; + return fmt_settings_get_style (the_settings.styles, type)->decimal; } void settings_set_decimal_char (char decimal) { - fmt_set_decimal (the_settings.styles, decimal); + fmt_settings_set_decimal (the_settings.styles, decimal); } - - /* Returns the number formatting style associated with the given format TYPE. */ const struct fmt_number_style * settings_get_style (enum fmt_type type) { assert (is_fmt_type (type)); - return &the_settings.styles[type]; + return fmt_settings_get_style (the_settings.styles, type); } - /* Returns a string of the form "$#,###.##" according to FMT, which must be of type FMT_DOLLAR. The caller must free the string. */ char * settings_dollar_template (const struct fmt_spec *fmt) { - const struct fmt_number_style *styles = the_settings.styles; struct string str = DS_EMPTY_INITIALIZER; int c; const struct fmt_number_style *fns ; assert (fmt->type == FMT_DOLLAR); - fns = fmt_get_style (styles, fmt->type); + fns = fmt_settings_get_style (the_settings.styles, fmt->type); ds_put_char (&str, '$'); for (c = MAX (fmt->w - fmt->d - 1, 0); c > 0; )