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