diff options
author | Nicholas Noll <nbnoll@eml.cc> | 2021-12-05 09:47:21 -0800 |
---|---|---|
committer | Nicholas Noll <nbnoll@eml.cc> | 2021-12-05 10:54:20 -0800 |
commit | 521d01e8ad87e931af3e9a763cc84a6cf7fe5ee3 (patch) | |
tree | f544119060c3eefc7b0fec6cff1740a362541213 /src/base/string/raw/find.c | |
parent | 158d9b84f14457136379f42e7c071eb79d87ee6b (diff) |
Feat: basic string and memory functions
Continue filling out the basic standard lib functions.
Included prototypes of the str* and mem* families.
Plan to add e(str|mem) and n(str|mem) variants as well.
Diffstat (limited to 'src/base/string/raw/find.c')
-rw-r--r-- | src/base/string/raw/find.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/src/base/string/raw/find.c b/src/base/string/raw/find.c new file mode 100644 index 0000000..3faf040 --- /dev/null +++ b/src/base/string/raw/find.c @@ -0,0 +1,48 @@ +#include <u.h> +#include <base/memory.h> +#include <base/string.h> + +char * +str·find(char *h, char *n) +{ + char *s, *ih, *in; + intptr i, sum, len; + + if(!n || !n[0]) + return h; + + if(!h || !h[0]) + return nil; + + /* two way string matching */ + + /* align first characters */ + if(!(s = str·findc(h, n[0]))) + return nil; + + ih = s+1; + in = n+1; + i = 1, sum = 0; + while(*ih && *in){ + sum += *ih; + sum -= *in; + i &= (*ih++ == *in++); + } + + if(*in) /* needle is larger than haystack! */ + return nil; + else if(i) /* found match */ + return s; + + /* no hit: loop for remainder of haystack + * if prefix sum ever falls to zero, we have equal hashes + * compare! */ + len = in - n - 1; + for(; *ih; ih++){ + sum -= *s++; /* sub the last character, advance the location on haystack */ + sum += *ih; /* add the next character */ + if(sum == 0 && mem·compare(s, len, n)==0) + return s; + } + return nil; +} |