added config_set_options(), config_get_options(), setOptions(), getOptions().
authorMark Lindner <mark.a.lindner@gmail.com>
Sat, 20 Sep 2014 06:44:33 +0000 (23:44 -0700)
committerMark Lindner <mark.a.lindner@gmail.com>
Sat, 20 Sep 2014 06:44:33 +0000 (23:44 -0700)
ChangeLog
doc/libconfig.texi
examples/c/example2.c
lib/libconfig.c
lib/libconfig.h
lib/libconfig.h++
lib/libconfigcpp.c++

index 1d84b48..7537230 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,13 @@
-
        ----- version 1.5 ------
 
+2014-09-19  Mark Lindner  <markl@neuromancer>
+
+       * lib/libconfig.c, lib/wincompat.h - check if file being opened is a
+         directory
+       * lib/libconfig.c, lib/libconfig.h, lib/libconfig.h++,
+         doc/libconfig.texi - added config_set_options(),
+         config_get_options(), setOptions(), getOptions().
+
 2014-05-25  Mark Lindner  <markl@neuromancer>
 
        * lib/libconfig.c++, lib/libconfig.h++ - added patches from Matt
index 1098b0b..f6f89eb 100644 (file)
@@ -7,7 +7,7 @@
 @settitle libconfig
 
 @set edition 1.5
-@set update-date 26 May 2014
+@set update-date 21 Sep 2014
 @set subtitle-text A Library For Processing Structured Configuration Files
 @set author-text Mark A.@: Lindner
 
@@ -36,7 +36,7 @@
 
 @page
 @vskip 0pt plus 1filll
-Copyright @copyright{} 2005-2012  Mark A Lindner
+Copyright @copyright{} 2005-2014  Mark A Lindner
 
 Permission is granted to make and distribute verbatim copies of
 this manual provided the copyright notice and this permission notice
@@ -766,21 +766,60 @@ configuration @var{config}, or @code{NULL} if none is set.
 
 @end deftypefun
 
-@deftypefun void config_set_auto_convert (@w{config_t *@var{config}}, @w{int @var{flag}})
-@deftypefunx int config_get_auto_convert (@w{const config_t *@var{config}})
+@deftypefun void config_set_options (@w{config_t *@var{config}}, @w{int @var{options}})
+@deftypefunx int config_get_options (@w{config_t *@var{config}})
+
+These functions set and get the options for the configuration
+@var{config}. The options affect how configurations are read and
+written. The following options are defined:
+
+@table @code
 
-@code{config_set_auto_convert()} enables number auto-conversion for
-the configuration @var{config} if @var{flag} is non-zero, and disables
-it otherwise. When this feature is enabled, an attempt to retrieve a
+@item CONFIG_OPTION_AUTOCONVERT
+Turning this option on enables number auto-conversion for
+the configuration. When this feature is enabled, an attempt to retrieve a
 floating point setting's value into an integer (or vice versa), or
 store an integer to a floating point setting's value (or vice versa)
 will cause the library to silently perform the necessary conversion
 (possibly leading to loss of data), rather than reporting failure. By
-default this feature is disabled.
+default this option is turned off.
+
+@item CONFIG_OPTION_SEMICOLON_SEPARATORS
+This option controls whether a semicolon (`;') is output after each setting
+when the configuration is written to a file or stream. (The semicolon
+separators are optional in the configuration syntax.) By default this
+option is turned on.
+
+@item CONFIG_OPTION_COLON_ASSIGNMENT_FOR_GROUPS
+This option controls whether a colon (`:') is output between each
+group setting's name and its value when the configuration is written to
+a file or stream. If the option is turned off, an equals sign (`=') is
+output instead. (These tokens are interchangeable in the configuration
+syntax.) By default this option is turned on.
+
+@item CONFIG_OPTION_COLON_ASSIGNMENT_FOR_NON_GROUPS
+This option controls whether a colon (`:') is output between each
+non-group setting's name and its value when the configuration is written
+to a file or stream. If the option is turned off, an equals sign (`=')
+is output instead. (These tokens are interchangeable in the configuration
+syntax.) By default this option is turned off.
+
+@item CONFIG_OPTION_OPEN_BRACE_ON_SEPARATE_LINE
+This option controls whether an open brace (`@{') will be written on its own
+line when the configuration is written to a file or stream. If the option is
+turned off, the brace will be written at the end of the previous line.
+By default this option is turned on.
 
-@code{config_get_auto_convert()} returns @code{CONFIG_TRUE} if number
-auto-conversion is currently enabled for @var{config}; otherwise it
-returns @code{CONFIG_FALSE}.
+@end table
+
+@end deftypefun
+
+@deftypefun void config_set_auto_convert (@w{config_t *@var{config}}, @w{int @var{flag}})
+@deftypefunx int config_get_auto_convert (@w{const config_t *@var{config}})
+
+These functions get and set the @code{CONFIG_OPTION_AUTO_CONVERT}
+option. They are obsoleted by the @code{config_set_options()} and
+@code{config_get_options()} functions described above.
 
 @end deftypefun
 
@@ -1284,21 +1323,60 @@ configuration, or @code{NULL} if none is set.
 
 @end deftypemethod
 
+@deftypemethod Config void setOptions (int @var{options})
+@deftypemethodx Config int getOptions ()
+
+These methods set and get the options for the configuration. The
+options affect how configurations are read and written. The following
+options are defined:
+
+@table @code
+
+@item OptionAutoConvert
+Turning this option on enables number auto-conversion for
+the configuration. When this feature is enabled, an attempt to retrieve a
+floating point setting's value into an integer (or vice versa), or
+store an integer to a floating point setting's value (or vice versa)
+will cause the library to silently perform the necessary conversion
+(possibly leading to loss of data), rather than reporting failure. By
+default this option is turned off.
+
+@item OptionSemicolonSeparators
+This option controls whether a semicolon (`;') is output after each setting
+when the configuration is written to a file or stream. (The semicolon
+separators are optional in the configuration syntax.) By default this
+option is turned on.
+
+@item OptionColonAssignmentForGroups
+This option controls whether a colon (`:') is output between each
+group setting's name and its value when the configuration is written to
+a file or stream. If the option is turned off, an equals sign (`=') is
+output instead. (These tokens are interchangeable in the configuration
+syntax.) By default this option is turned on.
+
+@item OptionColonAssignmentForNonGroups
+This option controls whether a colon (`:') is output between each
+non-group setting's name and its value when the configuration is written
+to a file or stream. If the option is turned off, an equals sign (`=')
+is output instead. (These tokens are interchangeable in the configuration
+syntax.) By default this option is turned off.
+
+@item OptionOpenBraceOnSeparateLine
+This option controls whether an open brace (`@{') will be written on its own
+line when the configuration is written to a file or stream. If the option is
+turned off, the brace will be written at the end of the previous line.
+By default this option is turned on.
+
+@end table
+
+@end deftypemethod
+
 @deftypemethod Config void setAutoConvert (bool @var{flag})
 @deftypemethodx Config bool getAutoConvert ()
 
-@code{setAutoConvert()} enables number auto-conversion for the
-configuration if @var{flag} is @code{true}, and disables it
-otherwise. When this feature is enabled, an attempt to assign a
-floating point setting to an integer (or vice versa), or
-assign an integer to a floating point setting (or vice versa) will
-cause the library to silently perform the necessary conversion
-(possibly leading to loss of data), rather than throwing a
-@code{SettingTypeException}. By default this feature is disabled.
-
-@code{getAutoConvert()} returns @code{true} if number auto-conversion
-is currently enabled for the configuration; otherwise it returns
-@code{false}.
+These methods get and set the @code{OptionAutoConvert} option. They
+are obsoleted by the @code{setOptions()} and @code{getOptions()}
+methods described above.
 
 @end deftypemethod
 
@@ -1790,7 +1868,7 @@ These methods test if the setting has a child setting with the given
 @code{false} otherwise. These methods do not throw exceptions.
 
 @end deftypemethod
-
+@page
 @deftypemethod Setting iterator begin ()
 @deftypemethodx Setting iterator end ()
 @deftypemethodx Setting const_iterator begin ()
index f1886b9..076a8fa 100644 (file)
@@ -74,6 +74,8 @@ int main(int argc, char **argv)
   setting = config_setting_add(movie, "qty", CONFIG_TYPE_INT);
   config_setting_set_float(setting, 20);
 
+  config_set_options(&cfg, 0);
+
   /* Write out the updated configuration. */
   if(! config_write_file(&cfg, output_file))
   {
index 6889883..1ea0643 100644 (file)
@@ -71,9 +71,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
 static const char *__io_error = "file I/O error";
 
 static void __config_list_destroy(config_list_t *list);
-static void __config_write_setting(const config_setting_t *setting,
-                                   FILE *stream, int depth,
-                                   unsigned short tab_width);
+static void __config_write_setting(const config_t *config,
+                                   const config_setting_t *setting,
+                                   FILE *stream, int depth);
 
 /* ------------------------------------------------------------------------- */
 
@@ -104,6 +104,11 @@ static void __config_locale_override(void)
 
 /* ------------------------------------------------------------------------- */
 
+#define __config_has_option(C, O)               \
+  (((C)->options & (O)) != 0)
+
+/* ------------------------------------------------------------------------- */
+
 static void __config_locale_restore(void)
 {
 #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
@@ -165,9 +170,9 @@ static void __config_indent(FILE *stream, int depth, unsigned short w)
 
 /* ------------------------------------------------------------------------- */
 
-static void __config_write_value(const config_value_t *value, int type,
-                                 int format, int depth,
-                                 unsigned short tab_width, FILE *stream)
+static void __config_write_value(const config_t *config,
+                                 const config_value_t *value, int type,
+                                 int format, int depth, FILE *stream)
 {
   char fbuf[64];
 
@@ -304,9 +309,9 @@ static void __config_write_value(const config_value_t *value, int type,
 
         for(s = list->elements; len--; s++)
         {
-          __config_write_value(&((*s)->value), (*s)->type,
-                               config_setting_get_format(*s),
-                               depth + 1, tab_width, stream);
+          __config_write_value(config, &((*s)->value), (*s)->type,
+                               config_setting_get_format(*s), depth + 1,
+                               stream);
 
           if(len)
             fputc(',', stream);
@@ -333,9 +338,9 @@ static void __config_write_value(const config_value_t *value, int type,
 
         for(s = list->elements; len--; s++)
         {
-          __config_write_value(&((*s)->value), (*s)->type,
-                               config_setting_get_format(*s),
-                               depth + 1, tab_width, stream);
+          __config_write_value(config, &((*s)->value), (*s)->type,
+                               config_setting_get_format(*s), depth + 1,
+                               stream);
 
           if(len)
             fputc(',', stream);
@@ -355,14 +360,14 @@ static void __config_write_value(const config_value_t *value, int type,
 
       if(depth > 0)
       {
-#ifdef K_AND_R_STYLE /* Horrendous, but many people like it. */
-        fputc(' ', stream);
-#else
-        fputc('\n', stream);
+        if((config->options & CONFIG_OPTION_OPEN_BRACE_ON_SEPARATE_LINE) != 0)
+        {
+          fputc('\n', stream);
+
+          if(depth > 1)
+            __config_indent(stream, depth, config->tab_width);
+        }
 
-        if(depth > 1)
-          __config_indent(stream, depth, tab_width);
-#endif
         fprintf(stream, "{\n");
       }
 
@@ -372,11 +377,11 @@ static void __config_write_value(const config_value_t *value, int type,
         config_setting_t **s;
 
         for(s = list->elements; len--; s++)
-          __config_write_setting(*s, stream, depth + 1, tab_width);
+          __config_write_setting(config, *s, stream, depth + 1);
       }
 
       if(depth > 1)
-        __config_indent(stream, depth, tab_width);
+        __config_indent(stream, depth, config->tab_width);
 
       if(depth > 0)
         fputc('}', stream);
@@ -560,7 +565,7 @@ static int __config_read(config_t *config, FILE *stream, const char *filename,
   void (*destructor)(void *) = config->destructor;
   const char *include_dir = config->include_dir;
   unsigned short tab_width = config->tab_width;
-  unsigned short flags = config->flags;
+  int options = config->options;
 
   config->include_dir = NULL;
   config_destroy(config);
@@ -569,7 +574,7 @@ static int __config_read(config_t *config, FILE *stream, const char *filename,
   config->destructor = destructor;
   config->include_dir = include_dir;
   config->tab_width = tab_width;
-  config->flags = flags;
+  config->options = options;
 
   parsectx_init(&parse_ctx);
   parse_ctx.config = config;
@@ -628,26 +633,38 @@ int config_read_string(config_t *config, const char *str)
 
 /* ------------------------------------------------------------------------- */
 
-static void __config_write_setting(const config_setting_t *setting,
-                                   FILE *stream, int depth,
-                                   unsigned short tab_width)
+static void __config_write_setting(const config_t *config,
+                                   const config_setting_t *setting,
+                                   FILE *stream, int depth)
 {
+  char group_assign_char = ((config->options
+                             & CONFIG_OPTION_COLON_ASSIGNMENT_FOR_GROUPS) != 0)
+    ? ':' : '=';
+
+  char nongroup_assign_char
+    = ((config->options & CONFIG_OPTION_COLON_ASSIGNMENT_FOR_NON_GROUPS) != 0)
+    ? ':' : '=';
+
   if(depth > 1)
-    __config_indent(stream, depth, tab_width);
+    __config_indent(stream, depth, config->tab_width);
+
 
   if(setting->name)
   {
     fputs(setting->name, stream);
-    fprintf(stream, " %c ", (setting->type == CONFIG_TYPE_GROUP ? ':' : '='));
+    fprintf(stream, " %c ", ((setting->type == CONFIG_TYPE_GROUP)
+                             ? group_assign_char
+                             : nongroup_assign_char));
   }
 
-  __config_write_value(&(setting->value), setting->type,
-                       config_setting_get_format(setting),
-                       depth, tab_width, stream);
+  __config_write_value(config, &(setting->value), setting->type,
+                       config_setting_get_format(setting), depth, stream);
 
   if(depth > 0)
   {
-    fputc(';', stream);
+    if((config->options & CONFIG_OPTION_SEMICOLON_SEPARATORS) != 0)
+      fputc(';', stream);
+
     fputc('\n', stream);
   }
 }
@@ -658,7 +675,7 @@ void config_write(const config_t *config, FILE *stream)
 {
   __config_locale_override();
 
-  __config_write_setting(config->root, stream, 0, config->tab_width);
+  __config_write_setting(config, config->root, stream, 0);
 
   __config_locale_restore();
 }
@@ -743,6 +760,9 @@ void config_init(config_t *config)
   config->root = _new(config_setting_t);
   config->root->type = CONFIG_TYPE_GROUP;
   config->root->config = config;
+  config->options = (CONFIG_OPTION_SEMICOLON_SEPARATORS
+                     | CONFIG_OPTION_COLON_ASSIGNMENT_FOR_GROUPS
+                     | CONFIG_OPTION_OPEN_BRACE_ON_SEPARATE_LINE);
   config->tab_width = 2;
 }
 
@@ -751,16 +771,30 @@ void config_init(config_t *config)
 void config_set_auto_convert(config_t *config, int flag)
 {
   if(flag)
-    config->flags |= CONFIG_OPTION_AUTOCONVERT;
+    config->options |= CONFIG_OPTION_AUTOCONVERT;
   else
-    config->flags &= ~CONFIG_OPTION_AUTOCONVERT;
+    config->options &= ~CONFIG_OPTION_AUTOCONVERT;
 }
 
 /* ------------------------------------------------------------------------- */
 
 int config_get_auto_convert(const config_t *config)
 {
-  return((config->flags & CONFIG_OPTION_AUTOCONVERT) != 0);
+  return((config->options & CONFIG_OPTION_AUTOCONVERT) != 0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+void config_set_options(config_t *config, int options)
+{
+  config->options = options;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_get_options(const config_t *config)
+{
+  return(config->options);
 }
 
 /* ------------------------------------------------------------------------- */
@@ -814,7 +848,7 @@ static int __config_setting_get_int(const config_setting_t *setting,
       return(CONFIG_TRUE);
 
     case CONFIG_TYPE_FLOAT:
-      if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
+      if((setting->config->options & CONFIG_OPTION_AUTOCONVERT) != 0)
       {
         *value = (int)(setting->value.fval);
         return(CONFIG_TRUE);
@@ -852,7 +886,7 @@ static int __config_setting_get_int64(const config_setting_t *setting,
       return(CONFIG_TRUE);
 
     case CONFIG_TYPE_FLOAT:
-      if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
+      if((setting->config->options & CONFIG_OPTION_AUTOCONVERT) != 0)
       {
         *value = (long long)(setting->value.fval);
         return(CONFIG_TRUE);
@@ -1063,7 +1097,7 @@ int config_setting_set_float(config_setting_t *setting, double value)
       return(CONFIG_TRUE);
 
     case CONFIG_TYPE_INT:
-      if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
+      if((setting->config->options & CONFIG_OPTION_AUTOCONVERT) != 0)
       {
         setting->value.ival = (int)value;
         return(CONFIG_TRUE);
@@ -1072,7 +1106,7 @@ int config_setting_set_float(config_setting_t *setting, double value)
         return(CONFIG_FALSE);
 
     case CONFIG_TYPE_INT64:
-      if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
+      if((setting->config->options & CONFIG_OPTION_AUTOCONVERT) != 0)
       {
         setting->value.llval = (long long)value;
         return(CONFIG_TRUE);
index 10eb7b5..e819038 100644 (file)
@@ -58,7 +58,11 @@ extern "C" {
 #define CONFIG_FORMAT_DEFAULT  0
 #define CONFIG_FORMAT_HEX      1
 
-#define CONFIG_OPTION_AUTOCONVERT 0x01
+#define CONFIG_OPTION_AUTOCONVERT                     0x01
+#define CONFIG_OPTION_SEMICOLON_SEPARATORS            0x02
+#define CONFIG_OPTION_COLON_ASSIGNMENT_FOR_GROUPS     0x04
+#define CONFIG_OPTION_COLON_ASSIGNMENT_FOR_NON_GROUPS 0x08
+#define CONFIG_OPTION_OPEN_BRACE_ON_SEPARATE_LINE     0x10
 
 #define CONFIG_TRUE  (1)
 #define CONFIG_FALSE (0)
@@ -102,7 +106,7 @@ typedef struct config_t
 {
   config_setting_t *root;
   void (*destructor)(void *);
-  unsigned short flags;
+  int options;
   unsigned short tab_width;
   short default_format;
   const char *include_dir;
@@ -120,6 +124,9 @@ extern LIBCONFIG_API void config_write(const config_t *config, FILE *stream);
 extern LIBCONFIG_API void config_set_default_format(config_t *config,
                                                     short format);
 
+extern LIBCONFIG_API void config_set_options(config_t *config, int options);
+extern LIBCONFIG_API int config_get_options(const config_t *config);
+
 extern LIBCONFIG_API void config_set_auto_convert(config_t *config, int flag);
 extern LIBCONFIG_API int config_get_auto_convert(const config_t *config);
 
index e7dd8b9..a43672c 100644 (file)
@@ -170,6 +170,16 @@ class LIBCONFIGXX_API Setting
     FormatHex = 1
   };
 
+  enum Option
+  {
+    OptionNone = 0,
+    OptionAutoConvert = 0x01,
+    OptionSemicolonSeparators = 0x02,
+    OptionColonAssignmentForGroups = 0x04,
+    OptionColonAssignmentForNonGroups = 0x08,
+    OptionOpenBraceOnSeparateLine = 0x10
+  };
+
   typedef SettingIterator iterator;
   typedef SettingConstIterator const_iterator;
 
@@ -439,6 +449,9 @@ class LIBCONFIGXX_API Config
   Config();
   virtual ~Config();
 
+  void setOptions(int options);
+  int getOptions() const;
+
   void setAutoConvert(bool flag);
   bool getAutoConvert() const;
 
index 24897a2..af06fc5 100644 (file)
@@ -327,6 +327,20 @@ void Config::setAutoConvert(bool flag)
 
 // ---------------------------------------------------------------------------
 
+void Config::setOptions(int options)
+{
+  config_set_options(_config, options);
+}
+
+// ---------------------------------------------------------------------------
+
+int Config::getOptions() const
+{
+  return(config_get_options(_config));
+}
+
+// ---------------------------------------------------------------------------
+
 bool Config::getAutoConvert() const
 {
   return(config_get_auto_convert(_config) != CONFIG_FALSE);