Objectively 1.0.0
Ultra-lightweight object oriented framework for GNU C.
MutableData.c
Go to the documentation of this file.
1/*
2 * Objectively: Ultra-lightweight object oriented framework for GNU C.
3 * Copyright (C) 2014 Jay Dolan <jay@jaydolan.com>
4 *
5 * This software is provided 'as-is', without any express or implied
6 * warranty. In no event will the authors be held liable for any damages
7 * arising from the use of this software.
8 *
9 * Permission is granted to anyone to use this software for any purpose,
10 * including commercial applications, and to alter it and redistribute it
11 * freely, subject to the following restrictions:
12 *
13 * 1. The origin of this software must not be misrepresented; you must not
14 * claim that you wrote the original software. If you use this software
15 * in a product, an acknowledgment in the product documentation would be
16 * appreciated but is not required.
17 *
18 * 2. Altered source versions must be plainly marked as such, and must not be
19 * misrepresented as being the original software.
20 *
21 * 3. This notice may not be removed or altered from any source distribution.
22 */
23
24#include <assert.h>
25#include <stdlib.h>
26#include <string.h>
27
28#include "MutableData.h"
29
30#define _Class _MutableData
31
32#pragma mark - Object
33
37static Object *copy(const Object *self) {
38
39 Data *this = (Data *) self;
40
41 MutableData *that = $(alloc(MutableData), init);
42 $(that, appendBytes, this->bytes, this->length);
43
44 return (Object *) that;
45}
46
47#pragma mark - MutableData
48
53static void appendBytes(MutableData *self, const uint8_t *bytes, size_t length) {
54
55 const size_t oldLength = self->data.length;
56
57 $(self, setLength, self->data.length + length);
58
59 memcpy(self->data.bytes + oldLength, bytes, length);
60}
61
66static void appendData(MutableData *self, const Data *data) {
67
68 $(self, appendBytes, data->bytes, data->length);
69}
70
75static MutableData *data(void) {
76
77 return $(alloc(MutableData), init);
78}
79
84static MutableData *dataWithCapacity(size_t capacity) {
85
86 return $(alloc(MutableData), initWithCapacity, capacity);
87}
88
94
95 return $(self, initWithCapacity, 0);
96}
97
102static MutableData *initWithCapacity(MutableData *self, size_t capacity) {
103
104 self = (MutableData *) super(Object, self, init);
105 if (self) {
106
107 self->capacity = capacity;
108 if (self->capacity) {
109
110 self->data.bytes = calloc(capacity, sizeof(uint8_t));
111 assert(self->data.bytes);
112 }
113
114 self->data.destroy = free;
115 }
116
117 return self;
118}
119
125
126 self = $(self, initWithCapacity, data->length);
127 if (self) {
128 $(self, appendData, data);
129 }
130
131 return self;
132}
133
138static void setLength(MutableData *self, size_t length) {
139
140 const size_t newCapacity = (length / _pageSize + 1) * _pageSize;
141 if (newCapacity > self->capacity) {
142
143 if (self->data.bytes == NULL) {
144 self->data.bytes = calloc(newCapacity, sizeof(uint8_t));
145 assert(self->data.bytes);
146 } else {
147 self->data.bytes = realloc(self->data.bytes, newCapacity);
148 assert(self->data.bytes);
149
150 memset(self->data.bytes + self->data.length, 0, length - self->data.length);
151 }
152
153 self->capacity = newCapacity;
154 }
155
156 self->data.length = length;
157}
158
159#pragma mark - Class lifecycle
160
164static void initialize(Class *clazz) {
165
166 ((ObjectInterface *) clazz->interface)->copy = copy;
167
168 ((MutableDataInterface *) clazz->interface)->appendBytes = appendBytes;
169 ((MutableDataInterface *) clazz->interface)->appendData = appendData;
170 ((MutableDataInterface *) clazz->interface)->data = data;
171 ((MutableDataInterface *) clazz->interface)->dataWithCapacity = dataWithCapacity;
172 ((MutableDataInterface *) clazz->interface)->init = init;
173 ((MutableDataInterface *) clazz->interface)->initWithCapacity = initWithCapacity;
174 ((MutableDataInterface *) clazz->interface)->initWithData = initWithData;
175 ((MutableDataInterface *) clazz->interface)->setLength = setLength;
176}
177
183 static Class *clazz;
184 static Once once;
185
186 do_once(&once, {
187 clazz = _initialize(&(const ClassDef) {
188 .name = "MutableData",
189 .superclass = _Data(),
190 .instanceSize = sizeof(MutableData),
191 .interfaceOffset = offsetof(MutableData, interface),
192 .interfaceSize = sizeof(MutableDataInterface),
194 });
195 });
196
197 return clazz;
198}
199
200#undef _Class
size_t _pageSize
Definition: Class.c:39
Class * _initialize(const ClassDef *def)
Initializes the given Class.
Definition: Class.c:91
#define alloc(type)
Allocate and initialize and instance of type.
Definition: Class.h:159
#define super(type, obj, method,...)
static void initialize(Class *clazz)
Definition: MutableData.c:164
Mutable data buffers.
Immutable UTF-8 strings.
long Once
The Once type.
Definition: Once.h:37
#define do_once(once, block)
Executes the given block at most one time.
Definition: Once.h:43
ClassDefs are passed to _initialize via an archetype to initialize a Class.
Definition: Class.h:41
The runtime representation of a Class.
Definition: Class.h:95
ident interface
The interface of the Class.
Definition: Class.h:105
Condition * init(Condition *self)
Initializes this Condition.
Definition: Condition.c:67
Immutable data buffers.
Definition: Data.h:50
Class * _Data(void)
The Data archetype.
Definition: Data.c:283
DataDestructor destroy
An optional destructor that, if set, is called on dealloc.
Definition: Data.h:71
size_t length
The length of bytes.
Definition: Data.h:76
uint8_t * bytes
The bytes.
Definition: Data.h:66
MutableArray * initWithCapacity(MutableArray *self, size_t capacity)
Initializes this MutableArray with the specified capacity.
Definition: MutableArray.c:195
Mutable data buffers.
Definition: MutableData.h:40
Class * _MutableData(void)
The MutableData archetype.
Definition: MutableData.c:182
void setLength(MutableData *self, size_t length)
Sets the length of this Data, truncating or expanding it.
Definition: MutableData.c:138
MutableData * dataWithCapacity(size_t capacity)
Returns a new MutableData with the given capacity.
Definition: MutableData.c:84
MutableData * initWithData(MutableData *self, const Data *data)
Initializes this Data with the contents of data.
Definition: MutableData.c:124
Data data
The superclass.
Definition: MutableData.h:45
MutableData * init(MutableData *self)
Initializes this Data with length 0.
Definition: MutableData.c:93
MutableData * data(void)
Returns a new MutableData.
Definition: MutableData.c:75
void appendBytes(MutableData *self, const uint8_t *bytes, size_t length)
Appends the given bytes to this Data.
Definition: MutableData.c:53
void appendData(MutableData *self, const Data *data)
Appends the given data to this Data.
Definition: MutableData.c:66
Object is the root Class of The Objectively Class hierarchy.
Definition: Object.h:46
Object * copy(const Object *self)
Creates a shallow copy of this Object.
Definition: Array.c:40