mirror of
https://codeberg.org/libreboot/lbmk.git
synced 2026-07-24 21:54:11 +02:00
libreboot-utils: optimised string functions
operate per word, not per byte this is also done on sdup, which uses a slightly inefficient method: the new string allocation is that of the maximum size, rather than what we need. for example, if you wanted a 20 character string (21 including null), you would still allocate 4096 bytes if that was the maximum length. it's a bit naughty, and i have half a mind to keep sdup on the old implementation, but i'll leave it be for now. Signed-off-by: Leah Rowe <leah@libreboot.org>
This commit is contained in:
@@ -372,6 +372,8 @@ void write_mac_part(size_t partnum);
|
|||||||
/* string functions
|
/* string functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
size_t page_remain(const void *p);
|
||||||
|
long pagesize(void);
|
||||||
int xunveilx(const char *path, const char *permissions);
|
int xunveilx(const char *path, const char *permissions);
|
||||||
int xpledgex(const char *promises, const char *execpromises);
|
int xpledgex(const char *promises, const char *execpromises);
|
||||||
char *smalloc(char **buf, size_t size);
|
char *smalloc(char **buf, size_t size);
|
||||||
@@ -381,6 +383,8 @@ int slen(const char *scmp, size_t maxlen,
|
|||||||
int vcmp(const void *s1, const void *s2, size_t n);
|
int vcmp(const void *s1, const void *s2, size_t n);
|
||||||
int scmp(const char *a, const char *b,
|
int scmp(const char *a, const char *b,
|
||||||
size_t maxlen, int *rval);
|
size_t maxlen, int *rval);
|
||||||
|
int ccmp(const char *a, const char *b, size_t i,
|
||||||
|
int *rval);
|
||||||
int sdup(const char *s,
|
int sdup(const char *s,
|
||||||
size_t n, char **dest);
|
size_t n, char **dest);
|
||||||
int scatn(ssize_t sc, const char **sv,
|
int scatn(ssize_t sc, const char **sv,
|
||||||
|
|||||||
@@ -19,6 +19,39 @@
|
|||||||
|
|
||||||
#include "../include/common.h"
|
#include "../include/common.h"
|
||||||
|
|
||||||
|
/* for null detection inside
|
||||||
|
* word-optimised string functions
|
||||||
|
*/
|
||||||
|
#define ff ((size_t)-1 / 0xFF)
|
||||||
|
#define high ((ff) * 0x80)
|
||||||
|
#define zeroes(x) (((x) - (ff)) & ~(x) & (high))
|
||||||
|
|
||||||
|
size_t
|
||||||
|
page_remain(const void *p)
|
||||||
|
{
|
||||||
|
static size_t pagesz = 0;
|
||||||
|
if (!pagesz)
|
||||||
|
pagesz = pagesize(),
|
||||||
|
pagesz -= ((uintptr_t)p & (pagesz - 1));
|
||||||
|
|
||||||
|
return pagesz;
|
||||||
|
}
|
||||||
|
|
||||||
|
long
|
||||||
|
pagesize(void)
|
||||||
|
{
|
||||||
|
static long rval = 0;
|
||||||
|
static int set = 0;
|
||||||
|
|
||||||
|
if (!set) {
|
||||||
|
if ((rval = sysconf(_SC_PAGESIZE)) < 0)
|
||||||
|
err_exit(errno, "could not determine page size");
|
||||||
|
set = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
free_and_set_null(char **buf)
|
free_and_set_null(char **buf)
|
||||||
{
|
{
|
||||||
@@ -78,16 +111,17 @@ vmalloc(void **buf, size_t size)
|
|||||||
return *buf = rval;
|
return *buf = rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* strict strcmp */
|
/* strict word-based strcmp */
|
||||||
int
|
int
|
||||||
scmp(const char *a,
|
scmp(const char *a,
|
||||||
const char *b,
|
const char *b,
|
||||||
size_t maxlen,
|
size_t maxlen,
|
||||||
int *rval)
|
int *rval)
|
||||||
{
|
{
|
||||||
size_t ch;
|
size_t i = 0;
|
||||||
unsigned char ac;
|
size_t j;
|
||||||
unsigned char bc;
|
size_t wa;
|
||||||
|
size_t wb;
|
||||||
|
|
||||||
if (a == NULL ||
|
if (a == NULL ||
|
||||||
b == NULL ||
|
b == NULL ||
|
||||||
@@ -96,22 +130,36 @@ scmp(const char *a,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ch = 0; ch < maxlen; ch++) {
|
for ( ; ((uintptr_t)(a + i) % sizeof(size_t)) != 0; i++) {
|
||||||
|
|
||||||
ac = (unsigned char)a[ch];
|
if (i >= maxlen)
|
||||||
bc = (unsigned char)b[ch];
|
goto err;
|
||||||
|
else if (!ccmp(a, b, i, rval))
|
||||||
if (ac != bc) {
|
|
||||||
*rval = ac - bc;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (ac == '\0') {
|
|
||||||
*rval = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ( ; i + sizeof(size_t) <= maxlen;
|
||||||
|
i += sizeof(size_t)) {
|
||||||
|
|
||||||
|
memcpy(&wa, a + i, sizeof(size_t));
|
||||||
|
memcpy(&wb, b + i, sizeof(size_t));
|
||||||
|
|
||||||
|
if (wa != wb)
|
||||||
|
for (j = 0; j < sizeof(size_t); j++)
|
||||||
|
if (!ccmp(a, b, i + j, rval))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!zeroes(wa))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*rval = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ; i < maxlen; i++)
|
||||||
|
if (!ccmp(a, b, i, rval))
|
||||||
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
errno = EFAULT;
|
errno = EFAULT;
|
||||||
if (rval != NULL)
|
if (rval != NULL)
|
||||||
@@ -119,13 +167,39 @@ err:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* strict strlen */
|
int ccmp(const char *a, const char *b,
|
||||||
|
size_t i, int *rval)
|
||||||
|
{
|
||||||
|
unsigned char ac;
|
||||||
|
unsigned char bc;
|
||||||
|
|
||||||
|
if (if_err(a == NULL || b == NULL, EFAULT) ||
|
||||||
|
rval == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ac = (unsigned char)a[i];
|
||||||
|
bc = (unsigned char)b[i];
|
||||||
|
|
||||||
|
if (ac != bc) {
|
||||||
|
*rval = ac - bc;
|
||||||
|
return 0;
|
||||||
|
} else if (ac == '\0') {
|
||||||
|
*rval = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* strict word-based strlen */
|
||||||
int
|
int
|
||||||
slen(const char *s,
|
slen(const char *s,
|
||||||
size_t maxlen,
|
size_t maxlen,
|
||||||
size_t *rval)
|
size_t *rval)
|
||||||
{
|
{
|
||||||
size_t ch;
|
size_t i = 0;
|
||||||
|
size_t w;
|
||||||
|
size_t j;
|
||||||
|
|
||||||
if (s == NULL ||
|
if (s == NULL ||
|
||||||
rval == NULL) {
|
rval == NULL) {
|
||||||
@@ -133,44 +207,109 @@ slen(const char *s,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ch = 0;
|
for ( ; ((uintptr_t)(s + i) % sizeof(size_t)) != 0; i++) {
|
||||||
ch < maxlen && s[ch] != '\0';
|
|
||||||
ch++);
|
|
||||||
|
|
||||||
if (ch == maxlen) {
|
if (i >= maxlen)
|
||||||
/* unterminated */
|
goto err;
|
||||||
errno = EFAULT;
|
if (s[i] == '\0') {
|
||||||
goto err;
|
*rval = i;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ; i + sizeof(size_t) <= maxlen;
|
||||||
|
i += sizeof(size_t)) {
|
||||||
|
|
||||||
|
memcpy(&w, s + i, sizeof(size_t));
|
||||||
|
|
||||||
|
if (!zeroes(w))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (j = 0; j < sizeof(size_t); j++) {
|
||||||
|
if (s[i + j] == '\0') {
|
||||||
|
*rval = i + j;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ; i < maxlen; i++) {
|
||||||
|
if (s[i] == '\0') {
|
||||||
|
*rval = i;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*rval = ch;
|
|
||||||
return 0;
|
|
||||||
err:
|
err:
|
||||||
|
errno = EFAULT;
|
||||||
if (rval != NULL)
|
if (rval != NULL)
|
||||||
*rval = 0;
|
*rval = 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* strict strdup */
|
/* strict word-based strdup */
|
||||||
int
|
int
|
||||||
sdup(const char *s,
|
sdup(const char *s,
|
||||||
size_t n, char **dest)
|
size_t max, char **dest)
|
||||||
{
|
{
|
||||||
size_t size;
|
size_t j;
|
||||||
char *rval = NULL;
|
size_t w;
|
||||||
|
size_t i = 0;
|
||||||
|
char *out = NULL;
|
||||||
|
|
||||||
if (dest == NULL ||
|
if (dest == NULL || *dest != NULL || s == NULL)
|
||||||
slen(s, n, &size) < 0) {
|
goto err;
|
||||||
if (dest != NULL)
|
|
||||||
*dest = NULL;
|
out = smalloc(dest, max);
|
||||||
return -1;
|
|
||||||
|
for ( ; ((uintptr_t)(s + i) % sizeof(size_t)) != 0; i++) {
|
||||||
|
|
||||||
|
if (i >= max)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
out[i] = s[i];
|
||||||
|
if (s[i] == '\0') {
|
||||||
|
*dest = out;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(smalloc(&rval, size + 1), s, size);
|
for ( ; i + sizeof(size_t) <= max; i += sizeof(size_t)) {
|
||||||
*(rval + size) = '\0';
|
|
||||||
|
|
||||||
*dest = rval;
|
if (page_remain(s + i) < sizeof(size_t))
|
||||||
return 0;
|
break;
|
||||||
|
|
||||||
|
memcpy(&w, s + i, sizeof(size_t));
|
||||||
|
if (!zeroes(w)) {
|
||||||
|
memcpy(out + i, &w, sizeof(size_t));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < sizeof(size_t); j++) {
|
||||||
|
|
||||||
|
out[i + j] = s[i + j];
|
||||||
|
if (s[i + j] == '\0') {
|
||||||
|
*dest = out;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ; i < max; i++) {
|
||||||
|
|
||||||
|
out[i] = s[i];
|
||||||
|
if (s[i] == '\0') {
|
||||||
|
*dest = out;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
free_and_set_null(&out);
|
||||||
|
if (dest != NULL)
|
||||||
|
*dest = NULL;
|
||||||
|
errno = EFAULT;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* concatenate N number of strings */
|
/* concatenate N number of strings */
|
||||||
@@ -279,15 +418,10 @@ dcat(const char *s, size_t n,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (rval1 != NULL)
|
*dest1 = *dest2 = NULL;
|
||||||
free(rval1);
|
|
||||||
if (rval2 != NULL)
|
|
||||||
free(rval2);
|
|
||||||
|
|
||||||
if (dest1 != NULL)
|
free_and_set_null(&rval1);
|
||||||
*dest1 = NULL;
|
free_and_set_null(&rval2);
|
||||||
if (dest2 != NULL)
|
|
||||||
*dest2 = NULL;
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -303,11 +437,14 @@ vcmp(const void *s1, const void *s2, size_t n)
|
|||||||
size_t a;
|
size_t a;
|
||||||
size_t b;
|
size_t b;
|
||||||
|
|
||||||
|
const unsigned char *x;
|
||||||
|
const unsigned char *y;
|
||||||
|
|
||||||
if (if_err(s1 == NULL || s2 == NULL, EFAULT))
|
if (if_err(s1 == NULL || s2 == NULL, EFAULT))
|
||||||
err_exit(EFAULT, "vcmp: null input");
|
err_exit(EFAULT, "vcmp: null input");
|
||||||
|
|
||||||
const unsigned char *x = s1;
|
x = s1;
|
||||||
const unsigned char *y = s2;
|
y = s2;
|
||||||
|
|
||||||
for ( ; i + sizeof(size_t) <= n; i += sizeof(size_t)) {
|
for ( ; i + sizeof(size_t) <= n; i += sizeof(size_t)) {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user