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 21struct XRayStringPoolNode { 22 struct XRayStringPoolNode* next; 23 char strings[XRAY_STRING_POOL_NODE_SIZE]; 24}; 25 26 27struct XRayStringPool { 28 struct XRayStringPoolNode* head; 29 struct XRayStringPoolNode* current; 30 int index; 31}; 32 33 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 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. */ 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. */ 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. */ 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