1
2// vim:sw=2:ai
3
4/*
5 * Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
6 * See COPYRIGHT.txt for details.
7 */
8
9#ifndef DENA_STRING_BUFFER_HPP
10#define DENA_STRING_BUFFER_HPP
11
12#include <vector>
13#include <stdlib.h>
14#include <string.h>
15
16#include "util.hpp"
17#include "allocator.hpp"
18#include "fatal.hpp"
19
20namespace dena {
21
22struct string_buffer : private noncopyable {
23 string_buffer() : buffer(0), begin_offset(0), end_offset(0), alloc_size(0) { }
24 ~string_buffer() {
25 DENA_FREE(buffer);
26 }
27 const char *begin() const {
28 return buffer + begin_offset;
29 }
30 const char *end() const {
31 return buffer + end_offset;
32 }
33 char *begin() {
34 return buffer + begin_offset;
35 }
36 char *end() {
37 return buffer + end_offset;
38 }
39 size_t size() const {
40 return end_offset - begin_offset;
41 }
42 void clear() {
43 begin_offset = end_offset = 0;
44 }
45 void resize(size_t len) {
46 if (size() < len) {
47 reserve(len);
48 memset(buffer + end_offset, 0, len - size());
49 }
50 end_offset = begin_offset + len;
51 }
52 void reserve(size_t len) {
53 if (alloc_size >= begin_offset + len) {
54 return;
55 }
56 size_t asz = alloc_size;
57 while (asz < begin_offset + len) {
58 if (asz == 0) {
59 asz = 16;
60 }
61 const size_t asz_n = asz << 1;
62 if (asz_n < asz) {
63 fatal_abort("string_buffer::resize() overflow");
64 }
65 asz = asz_n;
66 }
67 void *const p = DENA_REALLOC(buffer, asz);
68 if (p == 0) {
69 fatal_abort("string_buffer::resize() realloc");
70 }
71 buffer = static_cast<char *>(p);
72 alloc_size = asz;
73 }
74 void erase_front(size_t len) {
75 if (len >= size()) {
76 clear();
77 } else {
78 begin_offset += len;
79 }
80 }
81 char *make_space(size_t len) {
82 reserve(size() + len);
83 return buffer + end_offset;
84 }
85 void space_wrote(size_t len) {
86 len = std::min(len, alloc_size - end_offset);
87 end_offset += len;
88 }
89 template <size_t N>
90 void append_literal(const char (& str)[N]) {
91 append(str, str + N - 1);
92 }
93 void append(const char *start, const char *finish) {
94 const size_t len = finish - start;
95 reserve(size() + len);
96 memcpy(buffer + end_offset, start, len);
97 end_offset += len;
98 }
99 void append_2(const char *s1, const char *f1, const char *s2,
100 const char *f2) {
101 const size_t l1 = f1 - s1;
102 const size_t l2 = f2 - s2;
103 reserve(end_offset + l1 + l2);
104 memcpy(buffer + end_offset, s1, l1);
105 memcpy(buffer + end_offset + l1, s2, l2);
106 end_offset += l1 + l2;
107 }
108 private:
109 char *buffer;
110 size_t begin_offset;
111 size_t end_offset;
112 size_t alloc_size;
113};
114
115};
116
117#endif
118
119