aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxutil/sys_string.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/libxutil/sys_string.c')
-rw-r--r--tools/libxutil/sys_string.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/tools/libxutil/sys_string.c b/tools/libxutil/sys_string.c
new file mode 100644
index 0000000000..13a90dfd7d
--- /dev/null
+++ b/tools/libxutil/sys_string.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * 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 Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef __KERNEL__
+# include <linux/config.h>
+# include <linux/module.h>
+# include <linux/kernel.h>
+# include <linux/errno.h>
+#else
+# include <errno.h>
+#endif
+
+#include "allocate.h"
+#include "sys_string.h"
+
+/** Set the base to use for converting a string to a number. Base is
+ * hex if starts with 0x, otherwise decimal.
+ *
+ * @param s input string
+ * @param base where to put the base
+ * @return rest of s to parse as a number
+ */
+inline static const char * convert_set_base(const char *s, int *base){
+ *base = 10;
+ if(s){
+ if(*s=='0'){
+ s++;
+ if(*s=='x' || *s=='X'){
+ *base = 16;
+ s++;
+ }
+ }
+ }
+ return s;
+}
+
+/** Get the numerical value of a digit in the given base.
+ *
+ * @param c digit character
+ * @param base to use
+ * @return numerical value of digit in range 0..base-1 or
+ * -1 if not in range for the base
+ */
+inline static int convert_get_digit(char c, int base){
+ int d;
+
+ if('0'<=c && c<='9'){
+ d = c - '0';
+ } else if('a'<=c && c<='f'){
+ d = c - 'a' + 10;
+ } else if('A'<=c && c<='F'){
+ d = c - 'A' + 10;
+ } else {
+ d = -1;
+ }
+ return (d < base ? d : -1);
+}
+
+/** Convert a string to an unsigned long by parsing it as a number.
+ * Will accept hex or decimal in usual C syntax.
+ *
+ * @param str input string
+ * @param val where to put the result
+ * @return 0 if converted OK, negative otherwise
+ */
+int convert_atoul(const char *str, unsigned long *val){
+ int err = 0;
+ unsigned long v = 0;
+ int base;
+ const char *s = str;
+
+ if(!s) {
+ err = -EINVAL;
+ goto exit;
+ }
+ s = convert_set_base(s, &base);
+ for( ; !err && *s; s++){
+ int digit = convert_get_digit(*s, base);
+ if(digit<0){
+ err = -EINVAL;
+ goto exit;
+ }
+ v *= base;
+ v += digit;
+ }
+ exit:
+ *val = (err ? 0 : v);
+ return err;
+}
+
+/** Combine a directory path with a relative path to produce
+ * a new path.
+ *
+ * @param s directory path
+ * @param t relative path
+ * @return new combined path s/t
+ */
+int path_concat(char *s, char *t, char **val){
+ int err = 0;
+ int sn, tn, vn;
+ char *v;
+ sn = strlen(s);
+ if(sn > 0 && s[sn-1] == '/'){
+ sn--;
+ }
+ tn = strlen(t);
+ if(tn > 0 && t[0] == '/'){
+ tn--;
+ }
+ vn = sn+tn+1;
+ v = (char*)allocate(vn+1);
+ if(!v){
+ err = -ENOMEM;
+ goto exit;
+ }
+ strncpy(v, s, sn);
+ v[sn] = '/';
+ strncpy(v+sn+1, t, tn);
+ v[vn] = '\0';
+ exit:
+ *val = (err ? NULL : v);
+ return err;
+}