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