81 lines
1.9 KiB
C
81 lines
1.9 KiB
C
#include <libowfat/uint32.h>
|
|
#include <sys/types.h>
|
|
#include <string.h>
|
|
#include "mstorage.h"
|
|
|
|
/* this is tinyldap specific. If the data contains at least one 0-byte,
|
|
* it is stored in a tinyldap specific encoding:
|
|
* char 0;
|
|
* uint32 len;
|
|
* char data[len] */
|
|
ssize_t mstorage_add_bin(mstorage_t* p,const char* s,size_t n) {
|
|
ssize_t x;
|
|
if (n >> 31) // limit length to 32-bit SSIZE_MAX
|
|
return -1; // #range
|
|
#if 1
|
|
// unsigned int i;
|
|
// static char zero;
|
|
// char intbuf[4];
|
|
if (n==0 || memchr(s,0,n)) {
|
|
// n+5 can't overflow because we limited to SSIZE_MAX on a size_t
|
|
x=mstorage_reserve(p,n+5);
|
|
if (x!=-1) {
|
|
char* t=p->root+x;
|
|
*t=0;
|
|
uint32_pack(t+1,n);
|
|
memcpy(t+5,s,n);
|
|
}
|
|
return x;
|
|
} else {
|
|
// regular string; make sure there's a 0-terminator
|
|
// n-1 doesn't underflow because for n==0 we took the other branch
|
|
size_t needzero=(s[n-1] != 0);
|
|
x=mstorage_reserve(p,n+needzero);
|
|
if (x!=-1) {
|
|
char* t=p->root+x;
|
|
memcpy(t,s,n);
|
|
if (needzero)
|
|
t[n]=0;
|
|
}
|
|
return x;
|
|
}
|
|
#else
|
|
if (n==0 || (n==1 && s[0]==0)) goto encodebinary;
|
|
for (i=0; i<n-1; ++i)
|
|
if (!s[i]) {
|
|
encodebinary:
|
|
x=mstorage_add(p,&zero,1);
|
|
uint32_pack(intbuf,n);
|
|
mstorage_add(p,intbuf,4);
|
|
mstorage_add(p,s,n);
|
|
return x;
|
|
}
|
|
x=mstorage_add(p,s,n);
|
|
if (s[n-1])
|
|
mstorage_add(p,&zero,1);
|
|
return x;
|
|
#endif
|
|
}
|
|
|
|
#ifdef UNITTEST
|
|
#undef UNITTEST
|
|
#include <assert.h>
|
|
#include "mstorage_add.c"
|
|
#include "mstorage_init.c"
|
|
#include "mstorage_unmap.c"
|
|
int main() {
|
|
mstorage_t m;
|
|
mstorage_init(&m);
|
|
assert(mstorage_add_bin(&m,"foo",(size_t)-1) == -1); // #range
|
|
assert(mstorage_add_bin(&m,"foo",3) == 0);
|
|
// make sure 0 byte is added
|
|
assert(mstorage_add_bin(&m,"bar",3) == 4);
|
|
// trigger binary header
|
|
m.used=0;
|
|
assert(mstorage_add_bin(&m,"f\x00o",3) == 0);
|
|
assert(m.used == 8); // 0, len, f\0o
|
|
mstorage_unmap(&m);
|
|
return 0;
|
|
}
|
|
#endif
|