Implement float_precision parameter (Closes #31)
authorJose Luis Tallon <jltallon@adv-solutions.net>
Wed, 30 Dec 2015 21:25:50 +0000 (22:25 +0100)
committerJose Luis Tallon <jltallon@adv-solutions.net>
Wed, 30 Dec 2015 21:25:50 +0000 (22:25 +0100)
Added the ability to specify the amount of decimal digits (precision)
to be used when writing out (file or stream) a configuration.
Includes C & C++ versions.

As per zhaopingsun's suggestion

doc/libconfig.texi
lib/libconfig.c
lib/libconfig.h
lib/libconfig.h++
lib/libconfigcpp.c++

index 2f1938b..99d295a 100644 (file)
@@ -824,6 +824,22 @@ configuration @var{config}, or @code{NULL} if none is set.
 
 @end deftypefun
 
+@deftypefun void config_set_float_precision(@w{config_t *@var{config}}, @w{unsigned short @var{digits}})
+@deftypefunx {unsigned short} config_get_float_precision(@w{config_t *@var{config}})
+
+@b{Since @i{v1.6}}
+
+These functions set and get the number of decimal digits to output when writing
+the configuration to a file or stream.
+
+@code{config_set_float_precision(config,digits)} specifies "the number of
+digits to appear after the radix character". Please refer to printf(3) for details.
+
+Valid float precision range from 0 (no decimals) to about 15 (implementation defined).
+This parameter has no effect on parsing.
+
+@end deftypefun
+
 @deftypefun void config_set_options (@w{config_t *@var{config}}, @w{int @var{options}})
 @deftypefunx int config_get_options (@w{config_t *@var{config}})
 
@@ -1465,6 +1481,19 @@ Valid tab widths range from 0 to 15. The default tab width is 2.
 
 @end deftypemethod
 
+@deftypemethod Config void setFloatPrecision (@w{unsigned short @var{width}})
+@deftypemethodx Config {unsigned short} getFloatPrecision ()
+
+These methods set and get the float precision for the configuration. 
+This parameter influences the formatting of floating point settings in
+the configuration when it is written to a file or stream.
+Float precision has no effect on parsing.
+
+Valid precisions range from 0 to about 15 (implementation dependent),
+though the library will accept and store values up to 255.
+
+@end deftypemethod
+
 @deftypemethod Config {Setting &} getRoot ()
 
 This method returns the root setting for the configuration, which is a group.
index df66615..e62a844 100644 (file)
@@ -49,6 +49,9 @@
 #define CHUNK_SIZE 16
 #define FLOAT_PRECISION DBL_DIG
 
+#define TAB2DIGITS(x)  (((x) & 0xFF00) >> 8)
+#define DIGITS2TAB(x)  (((x) & 0xFF) << 8)
+
 #define _new(T) (T *)calloc(1, sizeof(T)) /* zeroed */
 #define _delete(P) free((void *)(P))
 
@@ -218,7 +221,10 @@ static void __config_write_value(const config_t *config,
     {
       char *q;
 
-      snprintf(fbuf, sizeof(fbuf) - 3, "%.*g", FLOAT_PRECISION, value->fval);
+      snprintf(fbuf, sizeof(fbuf) - 3, "%.*f",
+               TAB2DIGITS(config->tab_width),   /* XXX: hack; See config_set_float_precision */
+               value->fval
+      );
 
       /* check for exponent */
       q = strchr(fbuf, 'e');
@@ -752,6 +758,18 @@ void config_destroy(config_t *config)
 }
 
 /* ------------------------------------------------------------------------- */
+void config_set_float_precision(config_t *config,
+                                          unsigned short digits)
+{
+  config->tab_width |= DIGITS2TAB(digits);
+}
+
+unsigned short config_get_float_precision(config_t *config)
+{
+  return TAB2DIGITS(config->tab_width);
+}
+
+/* ------------------------------------------------------------------------- */
 
 void config_init(config_t *config)
 {
@@ -763,7 +781,13 @@ void config_init(config_t *config)
   config->options = (CONFIG_OPTION_SEMICOLON_SEPARATORS
                      | CONFIG_OPTION_COLON_ASSIGNMENT_FOR_GROUPS
                      | CONFIG_OPTION_OPEN_BRACE_ON_SEPARATE_LINE);
+
+  /* @version 1.6: piggyback float_digits on top of tab_width
+   * (ab)using the existing macros' 0x0F mask in order to preserve
+   * API & ABI compatibility ; changes are fully backwards compatible
+   */
   config->tab_width = 2;
+  config->tab_width |= DIGITS2TAB(FLOAT_PRECISION);    /* float_digits */
 }
 
 /* ------------------------------------------------------------------------- */
index e819038..89cab72 100644 (file)
@@ -142,6 +142,10 @@ extern LIBCONFIG_API void config_set_destructor(config_t *config,
 extern LIBCONFIG_API void config_set_include_dir(config_t *config,
                                                  const char *include_dir);
 
+extern LIBCONFIG_API void config_set_float_precision(config_t *config,
+                                                          unsigned short digits);
+extern LIBCONFIG_API unsigned short config_get_float_precision(config_t *config);
+
 extern LIBCONFIG_API void config_init(config_t *config);
 extern LIBCONFIG_API void config_destroy(config_t *config);
 
@@ -299,7 +303,7 @@ extern LIBCONFIG_API int config_lookup_string(const config_t *config,
   (C)->tab_width = ((W) & 0x0F)
 
 #define /* unsigned char */ config_get_tab_width(/* const config_t * */ C) \
-  ((C)->tab_width)
+  ((C)->tab_width & 0x0F)
 
 #define /* unsigned short */ config_setting_source_line(   \
   /* const config_setting_t * */ S)                        \
index 2bf418c..3c47b53 100644 (file)
@@ -466,6 +466,9 @@ class LIBCONFIGXX_API Config
   void setTabWidth(unsigned short width);
   unsigned short getTabWidth() const;
 
+  void setFloatPrecision(unsigned short digits);
+  unsigned short getFloatPrecision() const;
+
   void setIncludeDir(const char *includeDir);
   const char *getIncludeDir() const;
 
index af06fc5..7c5fd74 100644 (file)
@@ -374,6 +374,20 @@ unsigned short Config::getTabWidth() const
 
 // ---------------------------------------------------------------------------
 
+void Config::setFloatPrecision(unsigned short digits)
+{
+  return (config_set_float_precision(_config,digits));
+}
+
+// ---------------------------------------------------------------------------
+
+unsigned short Config::getFloatPrecision() const
+{
+  return (config_get_float_precision(_config));
+}
+
+// ---------------------------------------------------------------------------
+
 void Config::setIncludeDir(const char *includeDir)
 {
   config_set_include_dir(_config, includeDir);