Usermode/libc - Implimented strtoll/strtol
authorJohn Hodge <[email protected]>
Mon, 30 Jul 2012 13:26:00 +0000 (21:26 +0800)
committerJohn Hodge <[email protected]>
Mon, 30 Jul 2012 13:26:00 +0000 (21:26 +0800)
Usermode/Libraries/libc.so_src/stdlib.c

index ddd1234..8218042 100644 (file)
@@ -2,12 +2,12 @@
  * AcessOS Basic C Library\r
  * stdlib.c\r
  */\r
-/**\r
- * \todo Move half of these to stdio\r
- */\r
 #include <acess/sys.h>\r
 #include <stdlib.h>\r
 #include <stdio.h>\r
+#include <errno.h>\r
+#include <ctype.h>\r
+#include <limits.h>\r
 #include "lib.h"\r
 \r
 #define _stdout        1\r
@@ -71,70 +71,96 @@ EXPORT void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void
        }\r
 }\r
 \r
-/**\r
- * \fn EXPORT int atoi(const char *str)\r
- * \brief Convert a string to an integer\r
- */\r
-EXPORT int atoi(const char *str)\r
+EXPORT long long strtoll(const char *str, char **end, int base)\r
 {\r
-        int    neg = 0;\r
-        int    ret = 0;\r
-       \r
-       // NULL Check\r
-       if(!str)        return 0;\r
+        int    neg;\r
+       long long       ret = 0;\r
        \r
-       while(*str == ' ' || *str == '\t')      str++;\r
+       if( !str || base < 0 || base > 36 || base == 1 ) {\r
+               if(end)\r
+                       *end = (char*)str;\r
+               errno = EINVAL;\r
+               return 0;\r
+       }\r
+\r
+       while( isspace(*str) )\r
+               str++;\r
        \r
-       // Check for negative\r
-       if(*str == '-') {\r
-               neg = 1;\r
+       // Check for negative (or positive) sign\r
+       if(*str == '-' || *str == '+') {\r
+               neg = (*str == '-');\r
                str++;\r
        }\r
        \r
-       if(*str == '0') {\r
+       if( base == 0 || base == 16 ) {\r
+               if( *str == '0' && str[1] == 'x' ) {\r
+                       str += 2;\r
+                       base = 16;\r
+               }\r
+       }\r
+       \r
+       if( base == 0 && *str == '0' ) {\r
                str ++;\r
-               if(*str == 'x') {\r
-                       str++;\r
-                       // Hex\r
-                       while( ('0' <= *str && *str <= '9')\r
-                               || ('A' <= *str && *str <= 'F' )\r
-                               || ('a' <= *str && *str <= 'f' )\r
-                               )\r
-                       {\r
-                               ret *= 16;\r
-                               if(*str <= '9') {\r
-                                       ret += *str - '0';\r
-                               } else if (*str <= 'F') {\r
-                                       ret += *str - 'A' + 10;\r
-                               } else {\r
-                                       ret += *str - 'a' + 10;\r
-                               }\r
-                               str++;\r
-                       }\r
-               } else {\r
-                       // Octal\r
-                       while( '0' <= *str && *str <= '7' )\r
-                       {\r
-                               ret *= 8;\r
-                               ret += *str - '0';\r
-                               str++;\r
-                       }\r
+               base = 8;\r
+       }\r
+\r
+       if( base == 0 )\r
+               base = 10;\r
+\r
+       while( *str )\r
+       {\r
+                int    next = -1;\r
+               if( base <= 10 ) {\r
+                       if( '0' <= *str && *str <= '0'+base-1 )\r
+                               next = *str - '0';\r
                }\r
-       } else {\r
-               // Decimal\r
-               while( '0' <= *str && *str <= '9' )\r
-               {\r
-                       ret *= 10;\r
-                       ret += *str - '0';\r
-                       str++;\r
+               else {\r
+                       if( '0' <= *str && *str <= '9' )\r
+                               next = *str - '0';\r
+                       if( 'A' <= *str && *str <= 'A'+base-10-1 )\r
+                               next = *str - 'A';\r
+                       if( 'a' <= *str && *str <= 'a'+base-10-1 )\r
+                               next = *str - 'a';\r
                }\r
+               if( next < 0 )\r
+                       break;\r
+               ret *= base;\r
+               ret += next;\r
+               str ++;\r
        }\r
-       \r
-       // Negate if needed\r
-       if(neg) ret = -ret;\r
+\r
+       if( neg )\r
+               ret = -ret;     \r
+\r
+       if(end)\r
+               *end = (char*)str;\r
        return ret;\r
 }\r
 \r
+EXPORT long strtol(const char *str, char **end, int base)\r
+{\r
+       long long tmp = strtoll(str, end, base);\r
+       if( tmp > LONG_MAX || tmp < LONG_MIN ) {\r
+               errno = ERANGE;\r
+               return (tmp > LONG_MAX) ? LONG_MAX : LONG_MIN;\r
+       }\r
+       return tmp;\r
+}\r
+\r
+/**\r
+ * \fn EXPORT int atoi(const char *str)\r
+ * \brief Convert a string to an integer\r
+ */\r
+EXPORT int atoi(const char *str)\r
+{\r
+       long long       tmp = strtoll(str, NULL, 0);\r
+       if( tmp > INT_MAX || tmp < INT_MIN ) {\r
+               errno = ERANGE;\r
+               return (tmp > INT_MAX) ? INT_MAX : INT_MIN;\r
+       }\r
+       return tmp;\r
+}\r
+\r
 int abs(int j) { return j < 0 ? -j : j; }\r
 long int labs(long int j) { return j < 0 ? -j : j; }\r
 \r

UCC git Repository :: git.ucc.asn.au