From 9fbddb2e5e7b8f92d0795a154285edc4a2aff652 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 1 Oct 2024 15:19:45 -0400 Subject: [PATCH] MT#55283 support zero-copy string references If a string is already stored within the call's memory arena, skip duplicating the string content when making a copy, and simply return the same pointer. Change-Id: I50107d87b2625234a395da21e1e4551585966a60 --- include/call.h | 30 +++++++++++++++++++++--------- lib/str.h | 24 +++++++++++++----------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/include/call.h b/include/call.h index 0e5b6e789..fdbbc12d2 100644 --- a/include/call.h +++ b/include/call.h @@ -874,39 +874,51 @@ INLINE void *call_malloc(size_t l) { ret = call_buffer_alloc(&call_memory_arena->buffer, l); return ret; } +INLINE char *call_dup(const char *b, size_t len) { + char *ret = call_malloc(len + 1); + memcpy(ret, b, len); + ret[len] = '\0'; + return ret; +} +INLINE char *call_ref(const char *b, size_t len) { + return (char *) b; +} -INLINE char *call_strdup_len(const char *s, size_t len) { +INLINE char *call_strdup_len(const char *s, size_t len, char *(*dup)(const char *, size_t)) { char *r; if (!s) return NULL; - r = call_malloc(len + 1); - memcpy(r, s, len); - r[len] = 0; + dup = dup ?: call_dup; + r = dup(s, len); return r; } INLINE char *call_strdup(const char *s) { if (!s) return NULL; - return call_strdup_len(s, strlen(s)); + return call_strdup_len(s, strlen(s), NULL); } INLINE char *call_strdup_str(const str *s) { if (!s) return NULL; - return call_strdup_len(s->s, s->len); + return call_strdup_len(s->s, s->len, s->dup); } -INLINE str call_str_cpy_len(const char *in, size_t len) { +INLINE str call_str_cpy_fn(const char *in, size_t len, char *(*dup)(const char *, size_t)) { str out; if (!in) { out = STR_NULL; return out; } - out.s = call_strdup_len(in, len); + out.s = call_strdup_len(in, len, dup); out.len = len; + out.dup = call_ref; return out; } +INLINE str call_str_cpy_len(const char *in, size_t len) { + return call_str_cpy_fn(in, len, NULL); +} INLINE str call_str_cpy(const str *in) { - return call_str_cpy_len(in ? in->s : NULL, in ? in->len : 0); + return call_str_cpy_fn(in ? in->s : NULL, in ? in->len : 0, in->dup); } INLINE str call_str_cpy_c(const char *in) { return call_str_cpy_len(in, in ? strlen(in) : 0); diff --git a/lib/str.h b/lib/str.h index 9a3de7dad..243d8af28 100644 --- a/lib/str.h +++ b/lib/str.h @@ -15,6 +15,7 @@ struct _str { char *s; size_t len; + char *(*dup)(const char *, size_t); }; typedef struct _str str; @@ -34,17 +35,17 @@ TYPED_GQUEUE(str, str) #define FMT_M(x...) rtpe_common_config_ptr->log_mark_prefix, x, \ rtpe_common_config_ptr->log_mark_suffix -#define STR_NULL ((str) { NULL, 0 }) -#define STR_EMPTY ((str) { "", 0 }) -#define STR_CONST(s) ((str) { s, sizeof(s)-1 }) -#define STR(s) ({ const char *__s = (s); (str) { (char *) (__s), (__s) ? strlen(__s) : 0 }; }) -#define STR_PTR(s) (&((str) { (char *) (s), (s) ? strlen(s) : 0 })) -#define STR_NC(s) ((str) { (char *) (s), strlen(s) }) -#define STR_GS(s) ((str) { (s)->str, (s)->len }) -#define STR_LEN(s, len) ((str) { (char *) (s), len }) -#define STR_LEN_ASSERT(s, len) ({ assert(sizeof(s) >= len); (str) { (char *) (s), len }; }) -#define STR_DUP(s) ({ const char *__s = (s); size_t __l = strlen(__s); (str) { __g_memdup(__s, __l + 1), __l }; }) -#define STR_CONST_BUF(buf) ((str) { (char *) &buf, sizeof(buf) }) +#define STR_NULL ((str) { NULL, 0, NULL }) +#define STR_EMPTY ((str) { "", 0, NULL }) +#define STR_CONST(s) ((str) { s, sizeof(s)-1, NULL }) +#define STR(s) ({ const char *__s = (s); (str) { (char *) (__s), (__s) ? strlen(__s) : 0, NULL }; }) +#define STR_PTR(s) (&((str) { (char *) (s), (s) ? strlen(s) : 0, NULL })) +#define STR_NC(s) ((str) { (char *) (s), strlen(s), NULL }) +#define STR_GS(s) ((str) { (s)->str, (s)->len, NULL }) +#define STR_LEN(s, len) ((str) { (char *) (s), len, NULL }) +#define STR_LEN_ASSERT(s, len) ({ assert(sizeof(s) >= len); (str) { (char *) (s), len, NULL }; }) +#define STR_DUP(s) ({ const char *__s = (s); size_t __l = strlen(__s); (str) { __g_memdup(__s, __l + 1), __l, NULL }; }) +#define STR_CONST_BUF(buf) ((str) { (char *) &buf, sizeof(buf), NULL }) @@ -321,6 +322,7 @@ INLINE str *str_alloc(size_t len) { r = malloc(sizeof(*r) + len + 1); r->s = ((char *) r) + sizeof(*r); r->len = 0; + r->dup = NULL; return r; } INLINE str *str_dup(const str *s) {