Home | History | Annotate | Download | only in xray
      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 
     34 static struct XRayStringPoolNode* XRayStringPoolAllocNode() {
     35   struct XRayStringPoolNode* s;
     36   s = (struct XRayStringPoolNode *)XRayMalloc(sizeof(*s));
     37   s->next = NULL;
     38   return s;
     39 }
     40 
     41 
     42 static 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. */
     49 char* 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. */
     73 struct 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. */
     83 void 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