// 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)
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)
{
ret = dst;
while ((*dst++ = *src++) != '\0')
- /* do nothing */;
+ ;
return ret;
}
strcpy(dst+strlen(dst),src);
return dst;
}
+*/
char *
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
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 *
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;
}
}
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++;
}
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) {
*d++ = *s++;
return dst;
+#endif
}
int
}
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
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;
+}