include/cc_bstring.h (76 lines of code) (raw):
/*
* ccommon - a cache common library.
* Copyright (C) 2013 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <cc_define.h>
#include <cc_util.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
/* TODO(yao): separate byte string related functionalities into cc_bstring */
struct bstring {
uint32_t len; /* string length */
char *data; /* string data */
};
#define str2bstr(_str) (struct bstring){ sizeof(_str) - 1, (_str) }
#define null_bstring (struct bstring){ 0, NULL }
#define bstring_set_literal(_str, _literal) do { \
(_str)->len = (uint32_t)(sizeof(_literal) - 1); \
(_str)->data = (_literal); \
} while (0);
#define bstring_set_cstr(_str, _cstr) do { \
(_str)->len = (uint32_t)(cc_strlen(_cstr)); \
(_str)->data = (char *)(_cstr); \
} while (0);
void bstring_init(struct bstring *str);
void bstring_deinit(struct bstring *str);
bool bstring_empty(const struct bstring *str);
rstatus_i bstring_duplicate(struct bstring *dst, const struct bstring *src);
rstatus_i bstring_copy(struct bstring *dst, const char *src, uint32_t srclen);
int bstring_compare(const struct bstring *s1, const struct bstring *s2);
struct bstring *bstring_alloc(uint32_t size);
void bstring_free(struct bstring **bstring);
/* efficient implementation of string comparion of short strings */
#define str2cmp(m, c0, c1) \
(m[0] == c0 && m[1] == c1)
#define str3cmp(m, c0, c1, c2) \
(m[0] == c0 && m[1] == c1 && m[2] == c2)
#define str4cmp(m, c0, c1, c2, c3) \
((m[0] << 24 | m[1] << 16 | m[2] << 8 | m[3]) == \
((c0 << 24) | (c1 << 16) | (c2 << 8) | c3))
#define str5cmp(m, c0, c1, c2, c3, c4) \
(str4cmp(m, c0, c1, c2, c3) && (m[4] == c4))
#define str6cmp(m, c0, c1, c2, c3, c4, c5) \
(str5cmp(m, c0, c1, c2, c3, c4) && m[5] == c5)
#define str7cmp(m, c0, c1, c2, c3, c4, c5, c6) \
(str6cmp(m, c0, c1, c2, c3, c4, c5) && m[6] == c6)
#define str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \
(str4cmp(m, c0, c1, c2, c3) && \
(m[4] << 24 | m[5] << 16 | m[6] << 8 | m[7]) == \
((c4 << 24) | (c5 << 16) | (c6 << 8) | c7))
#define str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8) \
(str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) && m[8] == c8)
#define str10cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9) \
(str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8) && m[9] == c9)
#define str11cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10) \
(str10cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9) && m[10] == c10)
#define str12cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11) \
(str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) && \
(m[8] << 24 | m[9] << 16 | m[10] << 8 | m[11]) == \
((c8 << 24) | (c9 << 16) | (c10 << 8) | c11))
/* below is a more efficient implementation for little-endian only, it takes
* about 50% the cycles compared to the generic implementation above in the
* extreme cases (e.g. string length being multiples of 4), however, our
* profiling showed that string comparison does not contribute meaningfully to
* overall processing cost, both events and hashes are far more notable, and
* therefore we can choose the generic implementation until profiling results
* indicate otherwise.
*/
/*
#define str4cmp(m, c0, c1, c2, c3) \
(*(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0))
#define str5cmp(m, c0, c1, c2, c3, c4) \
(str4cmp(m, c0, c1, c2, c3) && (m[4] == c4))
#define str6cmp(m, c0, c1, c2, c3, c4, c5) \
(str4cmp(m, c0, c1, c2, c3) && \
(((uint32_t *) m)[1] & 0xffff) == ((c5 << 8) | c4))
#define str7cmp(m, c0, c1, c2, c3, c4, c5, c6) \
(str6cmp(m, c0, c1, c2, c3, c4, c5) && (m[6] == c6))
#define str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \
(str4cmp(m, c0, c1, c2, c3) && \
(((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4)))
#define str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8) \
(str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) && m[8] == c8)
#define str10cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9) \
(str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) && \
(((uint32_t *) m)[2] & 0xffff) == ((c9 << 8) | c8))
#define str11cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10) \
(str10cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9) && (m[10] == c10))
#define str12cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11) \
(str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) && \
(((uint32_t *) m)[2] == ((c11 << 24) | (c10 << 16) | (c9 << 8) | c8)))
*/
/*
* Wrapper around common routines for manipulating C character strings
*
* cc_memcmp
* cc_memcpy
* cc_memmove
* cc_memchr
* cc_memset
* cc_bcmp
*/
#define cc_memcmp(_p1, _p2, _n) \
memcmp(_p1, _p2, (size_t)(_n))
#define cc_memcpy(_d, _c, _n) \
memcpy(_d, _c, (size_t)(_n))
#define cc_memmove(_d, _c, _n) \
memmove(_d, _c, (size_t)(_n))
#define cc_memchr(_d, _c, _n) \
memchr(_d, _c, (size_t)(_n))
#define cc_memset(_p, _v, _n) \
memset(_p, _v, (size_t)(_n))
#define cc_bcmp(_s1, _s2, _n) \
bcmp((char *)(_s1), (char *)(_s2), (size_t)(_n))
/* bstring to uint conversion */
rstatus_i bstring_atou64(uint64_t *u64, struct bstring *str);
rstatus_i bstring_atoi64(int64_t *i64, struct bstring *str);
#ifdef __cplusplus
}
#endif