-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuffer.c
More file actions
194 lines (163 loc) · 5.59 KB
/
buffer.c
File metadata and controls
194 lines (163 loc) · 5.59 KB
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stddef.h>
#include <limits.h>
#include "buffer.h"
////////////////////////////////////////////////////////////////////////////////
//
// Function buffer_init
//
// Purpose:
//
// This function will return a struct with the values it needs before it
// can be used with buffer_append. The default "expand_length" is
//
// Parameters:
//
// initial_size (IN) This parameter will preallocate the buffer with this
// size in bytes.
//
// Returns:
//
// returns a struct, or NULL on error
//
// Error Definitions:
//
// NULL = Couldn't create the structure
//
////////////////////////////////////////////////////////////////////////////////
buffer_data * buffer_init(unsigned int initial_size) {
buffer_data * buffer = NULL;
// only allow max initial size of SIZE_MAX
if (initial_size > 65535) {
return NULL;
}
// malloc the space for a pointer to a buffer_data
buffer = malloc(sizeof(buffer_data));
if (buffer == NULL) {
return NULL;
}
// fill the struct up
buffer->expand_length = initial_size;
buffer->capacity = initial_size;
buffer->length = 0;
// allocate the buffer space
buffer->content = malloc(sizeof(char) * initial_size);
if (buffer->content == NULL) {
// can't allocate the buffer, therefore we need to clean everything up
free(buffer);
return NULL;
}
// return a pointer to our buffer_data structure
return buffer;
}
////////////////////////////////////////////////////////////////////////////////
//
// Function buffer_append
//
// Purpose:
//
// This function will take data and append it into a buffer in the struct
// given. It will growing as required (or as allowed by realloc) by the
// length desired in the structure element "expand_length" plus the length
// of the data being appended. If additional expansion is not desired, you
// can set the struct element "expand_length" to zero.
//
// Parameters:
//
// buffer_data (IN/OUT) This parameter is a struct (mapped below) to
// keep track of the internal buffer and its working parameters.
//
// typedef struct {
// unsigned int length; // the current length of the content in bytes
// unsigned int capacity; // the total capacity of "content" in bytes
// unsigned int expand_length; // the amount to expand the buffer on resize
// char * content; // the target for appending data
// } buffer_data;
//
//
// append_data (IN) This parameter is a const char * that is the data
// to be appended.
//
// Returns:
//
// This function will return the amount of bytes appended. If the
// return value is <= 0 there was an error.
//
// Error Definitions:
//
// -1 = No data was given to append
// -2 = Additional space could not be allocated for the buffer.
//
////////////////////////////////////////////////////////////////////////////////
int buffer_append(buffer_data * buffer, const char * append_data) {
// ensure there IS something to append..
const unsigned int append_len = strlen(append_data);
if (append_len < 1) {
return -1;
}
// is there enough space, or should we reallocate memory?
if (buffer->length + append_len > buffer->capacity) {
const unsigned int realloc_size =
buffer->capacity + append_len + buffer->expand_length;
// allocate the new buffer
char *new_buffer = realloc(buffer->content, realloc_size);
// resize success..
if (new_buffer == NULL) {
return -2;
}
// copy the data to append into the new content buffer
strcat(new_buffer, append_data);
// update the struct with the new values
buffer->content = new_buffer; // new buffer content
buffer->capacity = realloc_size; // add the amount to expand beyond our initial needs
buffer->length = buffer->length + append_len;
} else {
// append the string
strcat(buffer->content, append_data);
}
// update the buffer length
buffer->length += append_len;
// return the amount appended
return append_len;
}
////////////////////////////////////////////////////////////////////////////////
//
// Function buffer_destroy
//
// Purpose:
//
// This function will destroy the inner buffer and reset all of the data
// if the struct was dynamically allocated, it is expected that you will
// take care of freeing the data.
//
// Parameters:
//
// buffer_data (IN) This parameter is a struct (mapped below) to
// keep track of the internal buffer and its working parameters.
//
// typedef struct {
// unsigned int length; // the current length of the content in bytes
// unsigned int capacity; // the total capacity of "content" in bytes
// unsigned int expand_length; // the amount to expand the buffer on resize
// char * content; // the target for appending data
// } buffer_data;
//
// Returns:
//
// returns nothing
//
////////////////////////////////////////////////////////////////////////////////
void buffer_destroy(buffer_data * buffer) {
// only work with valid data..
if (buffer != NULL) {
// if the content is not null, free it.
if (buffer->content != NULL) {
free(buffer->content);
}
// free the buffer
free(buffer);
}
}