nostrdb

an unfairly fast embedded nostr database backed by lmdb
git clone git://jb55.com/nostrdb
Log | Files | Refs | Submodules | README | LICENSE

mem.h (7836B)


      1 /* CC0 (Public domain) - see LICENSE file for details */
      2 #ifndef CCAN_MEM_H
      3 #define CCAN_MEM_H
      4 
      5 #include "../config.h"
      6 #include "../compiler.h"
      7 
      8 #include <string.h>
      9 #include <stdbool.h>
     10 
     11 #if !HAVE_MEMMEM
     12 PURE_FUNCTION
     13 void *memmem(const void *haystack, size_t haystacklen,
     14          const void *needle, size_t needlelen);
     15 #endif
     16 
     17 #if !HAVE_MEMRCHR
     18 PURE_FUNCTION
     19 void *memrchr(const void *s, int c, size_t n);
     20 #endif
     21 
     22 /**
     23  * mempbrkm - locates the first occurrence in @data of any bytes in @accept
     24  * @data: where we search
     25  * @len: length of data in bytes
     26  * @accept: array of bytes we search for
     27  * @accept_len: # of bytes in accept
     28  *
     29  * Returns a pointer to the byte in @data that matches one of the bytes in
     30  * @accept, or NULL if no such byte is found.
     31  *
     32  * Example:
     33  *    char otherbytes[] = "Hello \0world";
     34  *    size_t otherbytes_len = sizeof(otherbytes) - 1;
     35  *    char *r = mempbrkm(otherbytes, otherbytes_len, "\0b", 2);
     36  *    if (r) {
     37  *        printf("Found %c\n", *r);
     38  *    } else {
     39  *        printf("Nada\n");
     40  *    }
     41  *
     42  */
     43 PURE_FUNCTION
     44 void *mempbrkm(const void *data, size_t len, const void *accept, size_t accept_len);
     45 
     46 /**
     47  * mempbrk - locates the first occurrence in @data of any bytes in @accept
     48  * @data: where we search
     49  * @len: length of data in bytes
     50  * @accept: NUL terminated string containing the bytes we search for
     51  *
     52  * Returns a pointer to the byte in @data that matches one of the bytes in
     53  * @accept, or NULL if no such byte is found.
     54  *
     55  * Example:
     56  *
     57  *    r = mempbrk(otherbytes, otherbytes_len, "abcde");
     58  *    if (r) {
     59  *        printf("Found %c\n", *r);
     60  *    } else {
     61  *        printf("Nada\n");
     62  *    }
     63  */
     64 PURE_FUNCTION
     65 static inline char *mempbrk(const void *data, size_t len, const char *accept)
     66 {
     67     return mempbrkm(data, len, accept, strlen(accept));
     68 }
     69 
     70 /**
     71  * memcchr - scan memory until a character does _not_ match
     72  * @data: pointer to memory to scan
     73  * @data_len: length of data
     74  * @c: character to scan for
     75  *
     76  * The complement of memchr().
     77  *
     78  * Returns a pointer to the first character which is _not_ @c. If all memory in
     79  * @data is @c, returns NULL.
     80  *
     81  * Example:
     82  *    char somebytes[] = "HI By\0e";
     83  *    size_t bytes_len = sizeof(somebytes) - 1;
     84  *    r = memcchr(somebytes, ' ', bytes_len);
     85  *    if (r) {
     86  *        printf("Found %c after trimming spaces\n", *r);
     87  *    }
     88  */
     89 PURE_FUNCTION
     90 void *memcchr(void const *data, int c, size_t data_len);
     91 
     92 /**
     93  * memeq - Are two byte arrays equal?
     94  * @a: first array
     95  * @al: bytes in first array
     96  * @b: second array
     97  * @bl: bytes in second array
     98  *
     99  * Example:
    100  *    if (memeq(somebytes, bytes_len, otherbytes, otherbytes_len)) {
    101  *        printf("memory blocks are the same!\n");
    102  *    }
    103  */
    104 PURE_FUNCTION
    105 static inline bool memeq(const void *a, size_t al, const void *b, size_t bl)
    106 {
    107     return al == bl && !memcmp(a, b, bl);
    108 }
    109 
    110 /**
    111  * memstarts - determine if @data starts with @prefix
    112  * @data: does this begin with @prefix?
    113  * @data_len: bytes in @data
    114  * @prefix: does @data begin with these bytes?
    115  * @prefix_len: bytes in @prefix
    116  *
    117  * Returns true if @data starts with @prefix, otherwise return false.
    118  *
    119  * Example:
    120  *    if (memstarts(somebytes, bytes_len, otherbytes, otherbytes_len)) {
    121  *        printf("somebytes starts with otherbytes!\n");
    122  *    }
    123  */
    124 PURE_FUNCTION
    125 static inline bool memstarts(void const *data, size_t data_len,
    126         void const *prefix, size_t prefix_len)
    127 {
    128     if (prefix_len > data_len)
    129         return false;
    130     return memeq(data, prefix_len, prefix, prefix_len);
    131 }
    132 
    133 /**
    134  * memeqstr - Is a byte array equal to a NUL terminated string?
    135  * @data: byte array
    136  * @length: length of @data in bytes
    137  * @string: NUL terminated string
    138  *
    139  * The '\0' byte is ignored when checking if @bytes == @string.
    140  *
    141  * Example:
    142  *    if (memeqstr(somebytes, bytes_len, "foo")) {
    143  *        printf("somebytes == 'foo'!\n");
    144  *    }
    145  */
    146 PURE_FUNCTION
    147 static inline bool memeqstr(const void *data, size_t length, const char *string)
    148 {
    149     return memeq(data, length, string, strlen(string));
    150 }
    151 
    152 /**
    153  * memeqzero - Is a byte array all zeroes?
    154  * @data: byte array
    155  * @length: length of @data in bytes
    156  *
    157  * Example:
    158  *    if (memeqzero(somebytes, bytes_len)) {
    159  *        printf("somebytes == 0!\n");
    160  *    }
    161  */
    162 PURE_FUNCTION
    163 bool memeqzero(const void *data, size_t length);
    164 
    165 /**
    166  * memstarts_str - Does this byte array start with a string prefix?
    167  * @a: byte array
    168  * @al: length in bytes
    169  * @s: string prefix
    170  *
    171  * Example:
    172  *    if (memstarts_str(somebytes, bytes_len, "It")) {
    173  *        printf("somebytes starts with 'It'\n");
    174  *    }
    175  */
    176 PURE_FUNCTION
    177 static inline bool memstarts_str(const void *a, size_t al, const char *s)
    178 {
    179     return memstarts(a, al, s, strlen(s));
    180 }
    181 
    182 /**
    183  * memends - Does this byte array end with a given byte-array suffix?
    184  * @s: byte array
    185  * @s_len: length in bytes
    186  * @suffix: byte array suffix
    187  * @suffix_len: length of suffix in bytes
    188  *
    189  * Returns true if @suffix appears as a substring at the end of @s,
    190  * false otherwise.
    191  */
    192 PURE_FUNCTION
    193 static inline bool memends(const void *s, size_t s_len, const void *suffix, size_t suffix_len)
    194 {
    195     return (s_len >= suffix_len) && (memcmp((const char *)s + s_len - suffix_len,
    196                         suffix, suffix_len) == 0);
    197 }
    198 
    199 /**
    200  * memends_str - Does this byte array end with a string suffix?
    201  * @a: byte array
    202  * @al: length in bytes
    203  * @s: string suffix
    204  *
    205  * Example:
    206  *    if (memends_str(somebytes, bytes_len, "It")) {
    207  *        printf("somebytes ends with with 'It'\n");
    208  *    }
    209  */
    210 PURE_FUNCTION
    211 static inline bool memends_str(const void *a, size_t al, const char *s)
    212 {
    213     return memends(a, al, s, strlen(s));
    214 }
    215 
    216 /**
    217  * memoverlaps - Do two memory ranges overlap?
    218  * @a: pointer to first memory range
    219  * @al: length of first memory range
    220  * @b: pointer to second memory range
    221  * @al: length of second memory range
    222  */
    223 CONST_FUNCTION
    224 static inline bool memoverlaps(const void *a_, size_t al,
    225                    const void *b_, size_t bl)
    226 {
    227     const char *a = a_;
    228     const char *b = b_;
    229 
    230     return (a < (b + bl)) && (b < (a + al));
    231 }
    232 
    233 /*
    234  * memswap - Exchange two memory regions
    235  * @a: first region
    236  * @b: second region
    237  * @n: length of the regions
    238  *
    239  * Undefined results if the two memory regions overlap.
    240  */
    241 void memswap(void *a, void *b, size_t n);
    242 
    243 #if HAVE_VALGRIND_MEMCHECK_H
    244 #include <valgrind/memcheck.h>
    245 static inline void *memcheck_(const void *data, size_t len)
    246 {
    247     VALGRIND_CHECK_MEM_IS_DEFINED(data, len);
    248     return (void *)data;
    249 }
    250 #else
    251 static inline void *memcheck_(const void *data, size_t len)
    252 {
    253     (void)len;
    254     return (void *)data;
    255 }
    256 #endif
    257 
    258 #if HAVE_TYPEOF
    259 /**
    260  * memcheck - check that a memory region is initialized
    261  * @data: start of region
    262  * @len: length in bytes
    263  *
    264  * When running under valgrind, this causes an error to be printed
    265  * if the entire region is not defined.  Otherwise valgrind only
    266  * reports an error when an undefined value is used for a branch, or
    267  * written out.
    268  *
    269  * Example:
    270  *    // Search for space, but make sure it's all initialized.
    271  *    if (memchr(memcheck(somebytes, bytes_len), ' ', bytes_len)) {
    272  *        printf("space was found!\n");
    273  *    }
    274  */
    275 #define memcheck(data, len) ((__typeof__((data)+0))memcheck_((data), (len)))
    276 #else
    277 #define memcheck(data, len) memcheck_((data), (len))
    278 #endif
    279 
    280 /**
    281  * memtaint - mark a memory region unused
    282  * @data: start of region
    283  * @len: length in bytes
    284  *
    285  * This writes an "0xdeadbeef" eyecatcher repeatedly to the memory.
    286  * When running under valgrind, it also tells valgrind that the memory is
    287  * uninitialized, triggering valgrind errors if it is used for branches
    288  * or written out (or passed to memcheck!) in future.
    289  *
    290  * Example:
    291  *    // We'll reuse this buffer later, but be sure we don't access it.
    292  *    memtaint(somebytes, bytes_len);
    293  */
    294 void memtaint(void *data, size_t len);
    295 #endif /* CCAN_MEM_H */