-
Notifications
You must be signed in to change notification settings - Fork 0
/
StringPool.hpp
65 lines (61 loc) · 1.56 KB
/
StringPool.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#ifndef STRINGPOOL_HPP
#define STRINGPOOL_HPP
#include <vector>
#include "Common.hpp"
namespace mp
{
struct StringPool
{
const static size_type max_len = 4096;
struct Block
{
union {
char chs[sizeof(void *)];
void *next /*= nullptr*/;
} slots[1 + max_len / sizeof(void *)];
// 1 for next, not for '\0'
};
Block *pool = (Block *)calloc(1, sizeof(Block));
size_type cur = sizeof(void *);
const char *allocate(const char *src)
{
size_type size = strlen(src);
if (cur + size >= sizeof(Block))
{
Block *tmp = pool;
if (_MP_UNLIKELY(size >= max_len)) // then size + sizeof(void *) + 1 > sizeof(Block)
pool = (Block *)calloc(1, size + sizeof(void *) + 1);
else
pool = (Block *)calloc(1, sizeof(Block));
pool->slots[0].next = tmp;
cur = sizeof(void *);
}
// now cur + size + 1 <= the empty space
char *ret = (char *)pool + cur;
strcpy(ret, src);
cur += size + 1;
return ret;
}
~StringPool()
{
while (pool)
{
Block *tmp = (Block *)pool->slots[0].next;
free(pool);
pool = tmp;
}
}
};
struct StringBuilder : std::vector<char>
{
using std::vector<char>::vector;
const char *to_string(StringPool &pool)
{
push_back('\0');
const char *ret = pool.allocate(data());
pop_back();
return ret;
}
};
} // namespace mp
#endif // STRINGPOOL_HPP