Remove the frontend appserver code
[akaros.git] / kern / src / string.c
index bb72872..30a6986 100644 (file)
@@ -1,10 +1,9 @@
 // Basic string routines.  Not hardware optimized, but not shabby.
 
-#ifdef __DEPUTY__
-#pragma nodeputy
-#endif
-
+#include <stdio.h>
 #include <string.h>
+#include <ros/memlayout.h>
+#include <assert.h>
 
 int
 strlen(const char *s)
@@ -26,6 +25,7 @@ strnlen(const char *s, size_t size)
        return n;
 }
 
+/* zra: These aren't being used, and they are dangerous, so I'm rm'ing them
 char *
 strcpy(char *dst, const char *src)
 {
@@ -33,7 +33,7 @@ strcpy(char *dst, const char *src)
 
        ret = dst;
        while ((*dst++ = *src++) != '\0')
-               /* do nothing */;
+               ;
        return ret;
 }
 
@@ -43,6 +43,7 @@ strcat(char *dst, const char *src)
        strcpy(dst+strlen(dst),src);
        return dst;
 }
+*/
 
 char *
 strncpy(char *dst, const char *src, size_t size) {
@@ -62,15 +63,39 @@ strncpy(char *dst, const char *src, size_t size) {
 size_t
 strlcpy(char *dst, const char *src, size_t size)
 {
-       char *dst_in;
-
-       dst_in = dst;
        if (size > 0) {
                while (--size > 0 && *src != '\0')
                        *dst++ = *src++;
                *dst = '\0';
        }
-       return dst - dst_in;
+
+       return strlen(src);
+}
+
+size_t
+strlcat(char *dst, const char *src, size_t size)
+{
+       size_t rem;     /* Buffer space remaining after null in dst. */
+
+       /* We must find the terminating NUL byte in dst, but abort the
+        * search if we go past 'size' bytes.  At the end of this loop,
+        * 'dst' will point to either the NUL byte in the original
+        * destination or to one byte beyond the end of the buffer.
+        *
+        * 'rem' will be the amount of 'size' remaining beyond the NUL byte;
+        * potentially zero. This implies that 'size - rem' is equal to the
+        * distance from the beginning of the destination buffer to 'dst'.
+        *
+        * The return value of strlcat is the sum of the length of the
+        * original destination buffer (size - rem) plus the size of the
+        * src string (the return value of strlcpy). */
+       rem = size;
+       while ((rem > 0) && (*dst != '\0')) {
+               rem--;
+               dst++;
+       }
+
+       return (size - rem) + strlcpy(dst, src, rem);
 }
 
 int
@@ -103,6 +128,29 @@ strchr(const char *s, char c)
        return 0;
 }
 
+// Return a pointer to the last occurrence of 'c' in 's',
+// or a null pointer if the string has no 'c'.
+char *
+strrchr(const char *s, char c)
+{
+       char *lastc = NULL;
+       for (; *s; s++)
+               if (*s == c){
+                       lastc = (char*)s;
+               }
+       return lastc;
+}
+
+void *memchr(const void *mem, int chr, int len)
+{
+       char *s = (char*) mem;
+
+       for (int i = 0; i < len; i++)
+               if (s[i] == (char) chr)
+                       return s + i;
+       return NULL;
+}
+
 // Return a pointer to the first occurrence of 'c' in 's',
 // or a pointer to the string-ending null character if the string has no 'c'.
 char *
@@ -114,61 +162,84 @@ strfind(const char *s, char c)
        return (char *) s;
 }
 
-// n must be a multiple of 16 and v must be uint32_t-aligned
+// memset aligned words.
 static inline void *
-memset16(uint32_t *v, uint32_t c, size_t n)
+memsetw(long* _v, long c, size_t n)
 {
-       uint32_t *start, *end;
-
-       start = v;
-       end = v + n/sizeof(uint32_t);
-       c = c | c<<8 | c<<16 | c<<24;
-
-       while(v < end)
+       long *start, *end, *v;
+
+       start = _v;
+       end = _v + n/sizeof(long);
+       v = _v;
+       c = c & 0xff;
+       c = c | c<<8;
+       c = c | c<<16;
+       #if NUM_ADDR_BITS == 64
+       c = c | c<<32;
+       #elif NUM_ADDR_BITS != 32
+       # error
+       #endif
+
+       while(v < end - (8-1))
        {
                v[3] = v[2] = v[1] = v[0] = c;
                v += 4;
+               v[3] = v[2] = v[1] = v[0] = c;
+               v += 4;
        }
 
+       while(v < end)
+         *v++ = c;
+
        return start;
 }
 
-// n must be a multiple of 16 and v must be 4-byte aligned.
-// as allowed by ISO, behavior undefined if dst/src overlap
-static inline void *
-memcpy16(uint32_t* dst, const uint32_t* src, size_t n)
-{
-       uint32_t *dststart, *dstend;
-
-       dststart = dst;
-       dstend = dst + n/sizeof(uint32_t);
-
-       while(dst < dstend)
-       {
-               dst[0] = src[0];
-               dst[1] = src[1];
-               dst[2] = src[2];
-               dst[3] = src[3];
-
-               src += 4;
-               dst += 4;
-       }
-
-       return dststart;
-}
+// copy aligned words.
+// unroll 9 ways to get multiple misses in flight
+#define memcpyw(type, _dst, _src, n) \
+  do { \
+       type* restrict src = (type*)(_src); \
+       type* restrict dst = (type*)(_dst); \
+       type* srcend = src + (n)/sizeof(type); \
+       type* dstend = dst + (n)/sizeof(type); \
+       while (dst < dstend - (9-1)) { \
+               dst[0] = src[0]; \
+               dst[1] = src[1]; \
+               dst[2] = src[2]; \
+               dst[3] = src[3]; \
+               dst[4] = src[4]; \
+               dst[5] = src[5]; \
+               dst[6] = src[6]; \
+               dst[7] = src[7]; \
+               dst[8] = src[8]; \
+               src += 9; \
+               dst += 9; \
+       } \
+       while(dst < dstend) \
+         *dst++ = *src++; \
+  } while(0)
 
 void *
-memset(void *v, int c, size_t n)
+memset(void *v, int c, size_t _n)
 {
        char *p;
        size_t n0;
+       size_t n = _n;
+
+       if (n == 0) return NULL; // zra: complain here?
 
        p = v;
 
-       if(n >= 16 && ((uintptr_t)v & 3) == 0)
+    while (n > 0 && ((uintptr_t)p & (sizeof(long)-1)))
+       {
+               *p++ = c;
+               n--;
+       }
+
+       if (n >= sizeof(long))
        {
-               n0 = (n/16)*16;
-               memset16((uint32_t*)v,c,n0);
+               n0 = n / sizeof(long) * sizeof(long);
+               memsetw((long*)p, c, n0);
                n -= n0;
                p += n0;
        }
@@ -183,24 +254,37 @@ memset(void *v, int c, size_t n)
 }
 
 void *
-memcpy(void *dst, const void *src, size_t n)
+memcpy(void* dst, const void* src, size_t _n)
 {
-       const char *s;
-       char *d;
-       size_t n0;
+       const char* s;
+       char* d;
+       size_t n0 = 0;
+       size_t n = _n;
+       int align = sizeof(long)-1;
 
        s = src;
        d = dst;
 
-       if(n >= 16 && ((uintptr_t)src  & 3) == 0 && ((uintptr_t)dst & 3) == 0)
+       if ((((uintptr_t)s | (uintptr_t)d) & (sizeof(long)-1)) == 0)
        {
-               n0 = (n/16)*16;
-               memcpy16((uint32_t*)dst,(const uint32_t*)src,n0);
-               n -= n0;
-               s += n0;
-               d += n0;
+               n0 = n / sizeof(long) * sizeof(long);
+               memcpyw(long, d, s, n0);
+       }
+       else if ((((uintptr_t)s | (uintptr_t)d) & (sizeof(int)-1)) == 0)
+       {
+               n0 = n / sizeof(int) * sizeof(int);
+               memcpyw(int, d, s, n0);
+       }
+       else if ((((uintptr_t)s | (uintptr_t)d) & (sizeof(short)-1)) == 0)
+       {
+               n0 = n / sizeof(short) * sizeof(short);
+               memcpyw(short, d, s, n0);
        }
 
+       n -= n0;
+       s += n0;
+       d += n0;
+
        while (n-- > 0)
                *d++ = *s++;
 
@@ -208,11 +292,16 @@ memcpy(void *dst, const void *src, size_t n)
 }
 
 void *
-memmove(void *dst, const void *src, size_t n)
+memmove(void *dst, const void *src, size_t _n)
 {
+#ifdef CONFIG_X86
+       bcopy(src, dst, _n);
+       return dst;
+#else
        const char *s;
        char *d;
-       
+       size_t n = _n;
+
        s = src;
        d = dst;
        if (s < d && s + n > d) {
@@ -225,6 +314,7 @@ memmove(void *dst, const void *src, size_t n)
                        *d++ = *s++;
 
        return dst;
+#endif
 }
 
 int
@@ -243,13 +333,14 @@ memcmp(const void *v1, const void *v2, size_t n)
 }
 
 void *
-memfind(const void *s, int c, size_t n)
+memfind(const void *_s, int c, size_t n)
 {
-       const void *ends = (const char *) s + n;
+       const void *ends = (const char *) _s + n;
+       const void *s = _s;
        for (; s < ends; s++)
                if (*(const unsigned char *) s == (unsigned char) c)
                        break;
-       return (void *) s;
+       return (void *)s;
 }
 
 long
@@ -299,3 +390,86 @@ strtol(const char *s, char **endptr, int base)
        return (neg ? -val : val);
 }
 
+unsigned long
+strtoul(const char *s, char **endptr, int base)
+{
+       int neg = 0;
+       unsigned long val = 0;
+
+       // gobble initial whitespace
+       while (*s == ' ' || *s == '\t')
+               s++;
+
+       // plus/minus sign
+       if (*s == '+')
+               s++;
+       else if (*s == '-')
+               s++, neg = 1;
+
+       // hex or octal base prefix
+       if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x'))
+               s += 2, base = 16;
+       else if (base == 0 && s[0] == '0')
+               s++, base = 8;
+       else if (base == 0)
+               base = 10;
+
+       // digits
+       while (1) {
+               int dig;
+
+               if (*s >= '0' && *s <= '9')
+                       dig = *s - '0';
+               else if (*s >= 'a' && *s <= 'z')
+                       dig = *s - 'a' + 10;
+               else if (*s >= 'A' && *s <= 'Z')
+                       dig = *s - 'A' + 10;
+               else
+                       break;
+               if (dig >= base)
+                       break;
+               s++, val = (val * base) + dig;
+               // we don't properly detect overflow!
+       }
+
+       if (endptr)
+               *endptr = (char *) s;
+       return (neg ? -val : val);
+}
+
+int atoi(const char *s)
+{
+       if (!s)
+               return 0;
+       if (s[0] == '0' && s[1] == 'x')
+               warn("atoi() used on a hex string!");
+       // no overflow detection
+       return (int)strtol(s,NULL,10);
+}
+
+int sigchecksum(void *address, int length)
+{
+       uint8_t *p, sum;
+
+       sum = 0;
+       for (p = address; length-- > 0; p++)
+               sum += *p;
+
+       return sum;
+}
+
+void *sigscan(uint8_t *address, int length, char *signature)
+{
+       uint8_t *e, *p;
+       int siglength;
+
+       e = address + length;
+       siglength = strlen(signature);
+       for (p = address; p + siglength < e; p += 16) {
+               if (memcmp(p, signature, siglength))
+                       continue;
+               return p;
+       }
+
+       return NULL;
+}