| /* Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. */ |
| |
| |
| /* XRay string pool */ |
| |
| /* String pool holds a large pile of strings. */ |
| /* It is up to higher level data structures to avoid duplicates. */ |
| /* It is up to higher level data structures to provide fast lookups. */ |
| |
| #include <stdlib.h> |
| #include <string.h> |
| #include "xray/xray_priv.h" |
| |
| #if defined(XRAY) |
| |
| struct XRayStringPoolNode { |
| struct XRayStringPoolNode* next; |
| char strings[XRAY_STRING_POOL_NODE_SIZE]; |
| }; |
| |
| |
| struct XRayStringPool { |
| struct XRayStringPoolNode* head; |
| struct XRayStringPoolNode* current; |
| int index; |
| }; |
| |
| |
| static struct XRayStringPoolNode* XRayStringPoolAllocNode() { |
| struct XRayStringPoolNode* s; |
| s = (struct XRayStringPoolNode *)XRayMalloc(sizeof(*s)); |
| s->next = NULL; |
| return s; |
| } |
| |
| |
| static int XRayStringPoolCurrentNodeSpaceAvail(struct XRayStringPool* pool) { |
| int i = pool->index; |
| return (XRAY_STRING_POOL_NODE_SIZE - i) - 1; |
| } |
| |
| |
| /* Append a string to the string pool. */ |
| char* XRayStringPoolAppend(struct XRayStringPool* pool, const char* src) { |
| /* Add +1 to STRING_POOL_NODE_SIZE to detect large strings */ |
| /* Add +1 to strnlen result to account for string termination */ |
| int n = strnlen(src, XRAY_STRING_POOL_NODE_SIZE + 1) + 1; |
| int a = XRayStringPoolCurrentNodeSpaceAvail(pool); |
| char* dst; |
| /* Don't accept strings larger than the pool node. */ |
| if (n >= (XRAY_STRING_POOL_NODE_SIZE - 1)) |
| return NULL; |
| /* If string doesn't fit, alloc a new node. */ |
| if (n > a) { |
| pool->current->next = XRayStringPoolAllocNode(); |
| pool->current = pool->current->next; |
| pool->index = 0; |
| } |
| /* Copy string and return a pointer to copy. */ |
| dst = &pool->current->strings[pool->index]; |
| strcpy(dst, src); |
| pool->index += n; |
| return dst; |
| } |
| |
| |
| /* Create & initialize a string pool instance. */ |
| struct XRayStringPool* XRayStringPoolCreate() { |
| struct XRayStringPool* pool; |
| pool = (struct XRayStringPool*)XRayMalloc(sizeof(*pool)); |
| pool->head = XRayStringPoolAllocNode(); |
| pool->current = pool->head; |
| return pool; |
| } |
| |
| |
| /* Free a string pool. */ |
| void XRayStringPoolFree(struct XRayStringPool* pool) { |
| struct XRayStringPoolNode* n = pool->head; |
| while (NULL != n) { |
| struct XRayStringPoolNode* c = n; |
| n = n->next; |
| XRayFree(c); |
| } |
| XRayFree(pool); |
| } |
| |
| #endif /* XRAY */ |
| |