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