1 /* Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. */ 4 5 6 /* XRay string pool */ 7 8 /* String pool holds a large pile of strings. */ 9 /* It is up to higher level data structures to avoid duplicates. */ 10 /* It is up to higher level data structures to provide fast lookups. */ 11 12 /* _GNU_SOURCE must be defined prior to the inclusion of string.h 13 * so that strnlen is available with glibc */ 14 #define _GNU_SOURCE 15 #include <stdlib.h> 16 #include <string.h> 17 #include "xray/xray_priv.h" 18 19 #if defined(XRAY) 20 21 struct XRayStringPoolNode { 22 struct XRayStringPoolNode* next; 23 char strings[XRAY_STRING_POOL_NODE_SIZE]; 24 }; 25 26 27 struct XRayStringPool { 28 struct XRayStringPoolNode* head; 29 struct XRayStringPoolNode* current; 30 int index; 31 }; 32 33 XRayStringPoolAllocNode()34static struct XRayStringPoolNode* XRayStringPoolAllocNode() { 35 struct XRayStringPoolNode* s; 36 s = (struct XRayStringPoolNode *)XRayMalloc(sizeof(*s)); 37 s->next = NULL; 38 return s; 39 } 40 41 XRayStringPoolCurrentNodeSpaceAvail(struct XRayStringPool * pool)42static int XRayStringPoolCurrentNodeSpaceAvail(struct XRayStringPool* pool) { 43 int i = pool->index; 44 return (XRAY_STRING_POOL_NODE_SIZE - i) - 1; 45 } 46 47 48 /* Append a string to the string pool. */ XRayStringPoolAppend(struct XRayStringPool * pool,const char * src)49char* XRayStringPoolAppend(struct XRayStringPool* pool, const char* src) { 50 /* Add +1 to STRING_POOL_NODE_SIZE to detect large strings */ 51 /* Add +1 to strnlen result to account for string termination */ 52 int n = strnlen(src, XRAY_STRING_POOL_NODE_SIZE + 1) + 1; 53 int a = XRayStringPoolCurrentNodeSpaceAvail(pool); 54 char* dst; 55 /* Don't accept strings larger than the pool node. */ 56 if (n >= (XRAY_STRING_POOL_NODE_SIZE - 1)) 57 return NULL; 58 /* If string doesn't fit, alloc a new node. */ 59 if (n > a) { 60 pool->current->next = XRayStringPoolAllocNode(); 61 pool->current = pool->current->next; 62 pool->index = 0; 63 } 64 /* Copy string and return a pointer to copy. */ 65 dst = &pool->current->strings[pool->index]; 66 strcpy(dst, src); 67 pool->index += n; 68 return dst; 69 } 70 71 72 /* Create & initialize a string pool instance. */ XRayStringPoolCreate()73struct XRayStringPool* XRayStringPoolCreate() { 74 struct XRayStringPool* pool; 75 pool = (struct XRayStringPool*)XRayMalloc(sizeof(*pool)); 76 pool->head = XRayStringPoolAllocNode(); 77 pool->current = pool->head; 78 return pool; 79 } 80 81 82 /* Free a string pool. */ XRayStringPoolFree(struct XRayStringPool * pool)83void XRayStringPoolFree(struct XRayStringPool* pool) { 84 struct XRayStringPoolNode* n = pool->head; 85 while (NULL != n) { 86 struct XRayStringPoolNode* c = n; 87 n = n->next; 88 XRayFree(c); 89 } 90 XRayFree(pool); 91 } 92 93 #endif /* XRAY */ 94 95