-
Notifications
You must be signed in to change notification settings - Fork 23
/
expand_buf.cpp
143 lines (107 loc) · 3.11 KB
/
expand_buf.cpp
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "stdafx.h"
#include "spasm.h"
#include "expand_buf.h"
#include "utils.h"
/*
* Initializes an expandable buffer with a
* certain starting size
*/
//TODO: the size increase is exponential, I am not sure an init_size is necessary
expand_buf *eb_init (size_t init_size) {
expand_buf_t *new_buf = (expand_buf_t *) malloc (sizeof (expand_buf_t));
if (init_size == -1) init_size = 64;
new_buf->start = (unsigned char *) malloc(init_size);
new_buf->end = new_buf->start;
new_buf->size = init_size;
return new_buf;
}
int eb_append(expand_buf_t *eb, const char *text, size_t len) {
return eb_insert(eb, -1, text, len);
}
/*
* Writes text to an expandable buffer at
* offset in buffer (-1 to append), and
* expands if necessary, given length or
* -1 to find length internally, returns
* new offset
*/
int eb_insert (expand_buf *buf, int offset, const char *text, size_t length) {
unsigned char *ptr;
if (text == NULL)
return offset;
if (offset == -1)
ptr = buf->end;
else
ptr = buf->start + offset;
if (length == -1)
length = strlen (text);
if (length == 0)
return 0;
//if the string's too long for the buffer to hold, expand it
if ((size_t) (buf->end + length - buf->start) > buf->size) {
unsigned char *old_start = buf->start;
if (buf->size == 0)
buf->size = 1;
while ((size_t) (buf->end + length - buf->start) > buf->size)
buf->size *= 2;
buf->start = (unsigned char *) realloc (buf->start, buf->size);
if (buf->start == NULL) {
puts ("Expand buf out of memory.");
exit (1);
}
ptr += buf->start - old_start;
buf->end += buf->start - old_start;
}
//copy the string to the buffer and move the pointer forward
if (ptr < buf->end) {
//if necessary, move the end of the buffer forwards first
unsigned char *curr_ptr;
for (curr_ptr = buf->end - 1; curr_ptr >= ptr; curr_ptr--)
*(curr_ptr + length) = *curr_ptr;
}
strncpy ((char *) ptr, text, length);
buf->end += length;
return offset + length;
}
/*
* Overwrites text in expandable buffer
* starting at offset - DOES NOT
* do length checking!
*/
void eb_overwrite (expand_buf *buf, int offset, const char *text, size_t length) {
unsigned char *ptr = buf->start + offset;
if (length == -1)
length = strlen (text);
strncpy ((char *) ptr, text, length);
}
/*
* Erases text from buffer
*/
void eb_erase (expand_buf *buf, int offset, size_t length) {
unsigned char *ptr, *curr_ptr;
ptr = buf->start + offset;
for (curr_ptr = ptr; curr_ptr < ptr + length && curr_ptr + length < buf->end; curr_ptr++)
*curr_ptr = *(curr_ptr + length);
buf->end -= length;
}
/*
* Gets the char from the buffer
* at given offset
*/
char eb_get_char (expand_buf *buf, int offset) {
return *(buf->start + offset);
}
/*
* Extracts the contents of the buffer as
* a zero-terminated string
*/
char *eb_extract (expand_buf *buf) {
return strndup ((char *) buf->start, buf->end - buf->start);
}
/*
* Frees a buffer
*/
void eb_free (expand_buf *eb) {
free (eb->start);
free (eb);
}