aboutsummaryrefslogtreecommitdiff
path: root/lib/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/util.c')
-rw-r--r--lib/util.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/lib/util.c b/lib/util.c
new file mode 100644
index 0000000..b4b00b8
--- /dev/null
+++ b/lib/util.c
@@ -0,0 +1,122 @@
+/* ----------------------------------------------------------------------------
+ libconfig - A library for processing structured configuration files
+ Copyright (C) 2005-2018 Mark A Lindner
+
+ This file is part of libconfig.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, see
+ <http://www.gnu.org/licenses/>.
+ ----------------------------------------------------------------------------
+*/
+
+#include "util.h"
+#include "wincompat.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* ------------------------------------------------------------------------- */
+
+long long libconfig_parse_integer(const char *s, int *ok)
+{
+ long long llval;
+ char *endptr;
+ int errsave = errno;
+ errno = 0;
+ llval = strtoll(s, &endptr, 0); /* base 10 or base 8 */
+ if(*endptr || errno)
+ {
+ errno = 0;
+ *ok = 0;
+ return(0); /* parse error */
+ }
+ errno = errsave;
+
+ *ok = 1;
+ return(llval);
+}
+
+/* ------------------------------------------------------------------------- */
+
+unsigned long long libconfig_parse_hex64(const char *s)
+{
+#ifdef __MINGW32__
+
+ /* MinGW's strtoull() seems to be broken; it only returns the lower
+ * 32 bits...
+ */
+
+ const char *p = s;
+ unsigned long long val = 0;
+
+ if(*p != '0')
+ return(0);
+
+ ++p;
+
+ if(*p != 'x' && *p != 'X')
+ return(0);
+
+ for(++p; isxdigit(*p); ++p)
+ {
+ val <<= 4;
+ val |= ((*p < 'A') ? (*p & 0xF) : (9 + (*p & 0x7)));
+ }
+
+ return(val);
+
+#else /* ! __MINGW32__ */
+
+ return(strtoull(s, NULL, 16));
+
+#endif /* __MINGW32__ */
+}
+
+/* ------------------------------------------------------------------------- */
+
+void libconfig_format_double(double val, int precision, int sci_ok, char *buf,
+ size_t buflen)
+{
+ const char *fmt = sci_ok ? "%.*g" : "%.*f";
+ char *p, *q;
+
+ snprintf(buf, buflen - 3, fmt, precision, val);
+
+ /* Check for exponent. */
+ p = strchr(buf, 'e');
+ if(p) return;
+
+ /* Check for decimal point. */
+ p = strchr(buf, '.');
+ if(!p)
+ {
+ /* No decimal point. Add trailing ".0". */
+ strcat(buf, ".0");
+ }
+ else
+ {
+ /* Remove any excess trailing 0's after decimal point. */
+ for(q = buf + strlen(buf) - 1; q > p + 1; --q)
+ {
+ if(*q == '0')
+ *q = '\0';
+ else
+ break;
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */