Skip to content

Commit 26f5752

Browse files
committed
Added oneshot pack*() and unpack*() variants of all functions
these are useful for one-off encoding of simple stuff. While it's possible to write a utility method that accepts a first-class callable and creates a throwaway buffer internally, like function encodeOneOff(T $value, Closure $writeFunc) : string{ $writer = new ByteBufferWriter(); $writeFunc($writer, $value); return $writer->getBuffer(); } this is quite a bit slower than even unpack() for simple types, as well as being mildly inconvenient. So having dedicated one-off functions like in `Binary::` that aren't slow is a good idea.
1 parent 3c61127 commit 26f5752

File tree

8 files changed

+638
-211
lines changed

8 files changed

+638
-211
lines changed

classes/ByteBufferReader.cpp

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ static zend_object_handlers byte_buffer_reader_zend_object_handlers;
1212
zend_class_entry* byte_buffer_reader_ce;
1313

1414
static void reader_init_properties(byte_buffer_reader_zend_object* object, zend_string* buffer, size_t offset) {
15-
object->buffer = buffer;
15+
object->reader.buffer = buffer;
1616
zend_string_addref(buffer);
17-
object->offset = offset;
17+
object->reader.offset = offset;
1818
}
1919

2020
static zend_object* reader_new(zend_class_entry* ce) {
@@ -31,15 +31,15 @@ static zend_object* reader_clone(zend_object* object) {
3131

3232
zend_objects_clone_members(&new_object->std, &old_object->std);
3333

34-
reader_init_properties(new_object, old_object->buffer, old_object->offset);
34+
reader_init_properties(new_object, old_object->reader.buffer, old_object->reader.offset);
3535

3636
return &new_object->std;
3737
}
3838

3939
static void reader_free(zend_object* std) {
4040
auto object = fetch_from_zend_object<byte_buffer_reader_zend_object>(std);
4141

42-
zend_string_release_ex(object->buffer, 0);
42+
zend_string_release_ex(object->reader.buffer, 0);
4343
}
4444

4545
static int reader_compare_objects(zval* obj1, zval* obj2) {
@@ -49,8 +49,8 @@ static int reader_compare_objects(zval* obj1, zval* obj2) {
4949
auto object2 = fetch_from_zend_object<byte_buffer_reader_zend_object>(Z_OBJ_P(obj2));
5050

5151
if (
52-
object1->offset == object2->offset &&
53-
zend_string_equals(object1->buffer, object2->buffer)
52+
object1->reader.offset == object2->reader.offset &&
53+
zend_string_equals(object1->reader.buffer, object2->reader.buffer)
5454
) {
5555
return 0;
5656
}
@@ -71,8 +71,8 @@ READER_METHOD(__construct) {
7171
ZEND_PARSE_PARAMETERS_END();
7272

7373
object = READER_THIS();
74-
if (object->buffer) {
75-
zend_string_release_ex(object->buffer, 0);
74+
if (object->reader.buffer) {
75+
zend_string_release_ex(object->reader.buffer, 0);
7676
}
7777

7878
reader_init_properties(object, buffer, 0);
@@ -82,7 +82,7 @@ READER_METHOD(getData) {
8282
zend_parse_parameters_none_throw();
8383

8484
auto object = READER_THIS();
85-
RETURN_STR_COPY(object->buffer);
85+
RETURN_STR_COPY(object->reader.buffer);
8686
}
8787

8888
READER_METHOD(readByteArray) {
@@ -105,19 +105,19 @@ READER_METHOD(readByteArray) {
105105

106106
object = READER_THIS();
107107

108-
if (ZSTR_LEN(object->buffer) - object->offset < length) {
109-
zend_throw_exception_ex(data_decode_exception_ce, 0, "Need at least %zu bytes, but only have %zu bytes", length, ZSTR_LEN(object->buffer) - object->offset);
108+
if (ZSTR_LEN(object->reader.buffer) - object->reader.offset < length) {
109+
zend_throw_exception_ex(data_decode_exception_ce, 0, "Need at least %zu bytes, but only have %zu bytes", length, ZSTR_LEN(object->reader.buffer) - object->reader.offset);
110110
return;
111111
}
112112

113-
RETVAL_STRINGL(ZSTR_VAL(object->buffer) + object->offset, length);
114-
object->offset += length;
113+
RETVAL_STRINGL(ZSTR_VAL(object->reader.buffer) + object->reader.offset, length);
114+
object->reader.offset += length;
115115
}
116116

117117
READER_METHOD(getOffset) {
118118
zend_parse_parameters_none_throw();
119119
auto object = READER_THIS();
120-
RETURN_LONG(object->offset);
120+
RETURN_LONG(object->reader.offset);
121121
}
122122

123123
READER_METHOD(setOffset) {
@@ -128,29 +128,29 @@ READER_METHOD(setOffset) {
128128
ZEND_PARSE_PARAMETERS_END();
129129

130130
auto object = READER_THIS();
131-
if (offset < 0 || static_cast<size_t>(offset) > ZSTR_LEN(object->buffer)) {
131+
if (offset < 0 || static_cast<size_t>(offset) > ZSTR_LEN(object->reader.buffer)) {
132132
zend_value_error("Offset must not be less than zero or greater than the available data size");
133133
return;
134134
}
135135

136-
object->offset = static_cast<size_t>(offset);
136+
object->reader.offset = static_cast<size_t>(offset);
137137
}
138138

139139
READER_METHOD(getUnreadLength) {
140140
zend_parse_parameters_none_throw();
141141

142142
auto object = READER_THIS();
143-
RETURN_LONG(ZSTR_LEN(object->buffer) - object->offset);
143+
RETURN_LONG(ZSTR_LEN(object->reader.buffer) - object->reader.offset);
144144
}
145145

146146
READER_METHOD(__serialize) {
147147
zend_parse_parameters_none_throw();
148148

149149
auto object = READER_THIS();
150150
array_init(return_value);
151-
zend_string_addref(object->buffer);
152-
add_assoc_str(return_value, "buffer", object->buffer);
153-
add_assoc_long(return_value, "offset", object->offset);
151+
zend_string_addref(object->reader.buffer);
152+
add_assoc_str(return_value, "buffer", object->reader.buffer);
153+
add_assoc_long(return_value, "offset", object->reader.offset);
154154
}
155155

156156
static zval* fetch_serialized_property(HashTable* data, const char* name, int type) {
@@ -193,9 +193,9 @@ READER_METHOD(__debugInfo) {
193193

194194
auto object = READER_THIS();
195195
array_init(return_value);
196-
zend_string_addref(object->buffer);
197-
add_assoc_str(return_value, "buffer", object->buffer);
198-
add_assoc_long(return_value, "offset", object->offset);
196+
zend_string_addref(object->reader.buffer);
197+
add_assoc_str(return_value, "buffer", object->reader.buffer);
198+
add_assoc_long(return_value, "offset", object->reader.offset);
199199
}
200200

201201
zend_class_entry* init_class_ByteBufferReader(void) {

classes/ByteBufferReader.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ extern "C" {
66
}
77
#include "../ZendUtil.h"
88

9-
typedef struct _byte_buffer_reader_zend_object {
9+
typedef struct _byte_buffer_reader_t {
1010
zend_string* buffer;
1111
size_t offset;
12+
} byte_buffer_reader_t;
13+
14+
typedef struct _byte_buffer_reader_zend_object {
15+
byte_buffer_reader_t reader;
1216
zend_object std;
1317
} byte_buffer_reader_zend_object;
1418

classes/ByteBufferWriter.cpp

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ static zend_object_handlers byte_buffer_writer_zend_object_handlers;
1212
zend_class_entry* byte_buffer_writer_ce;
1313

1414
static void writer_init_properties(byte_buffer_writer_zend_object* object, zend_string* buffer, size_t used, size_t offset) {
15-
object->buffer = buffer;
15+
object->writer.buffer = buffer;
1616
zend_string_addref(buffer);
17-
object->offset = offset;
18-
object->used = used;
17+
object->writer.offset = offset;
18+
object->writer.used = used;
1919
}
2020

2121
static zend_object* writer_new(zend_class_entry* ce) {
@@ -32,15 +32,15 @@ static zend_object* writer_clone(zend_object* object) {
3232

3333
zend_objects_clone_members(&new_object->std, &old_object->std);
3434

35-
writer_init_properties(new_object, old_object->buffer, old_object->used, old_object->offset);
35+
writer_init_properties(new_object, old_object->writer.buffer, old_object->writer.used, old_object->writer.offset);
3636

3737
return &new_object->std;
3838
}
3939

4040
static void writer_free(zend_object* std) {
4141
auto object = fetch_from_zend_object<byte_buffer_writer_zend_object>(std);
4242

43-
zend_string_release_ex(object->buffer, 0);
43+
zend_string_release_ex(object->writer.buffer, 0);
4444
}
4545

4646
static int writer_compare_objects(zval* obj1, zval* obj2) {
@@ -50,9 +50,9 @@ static int writer_compare_objects(zval* obj1, zval* obj2) {
5050
auto object2 = fetch_from_zend_object<byte_buffer_writer_zend_object>(Z_OBJ_P(obj2));
5151

5252
if (
53-
object1->offset == object2->offset &&
54-
object1->used == object2->used &&
55-
zend_string_equals(object1->buffer, object2->buffer)
53+
object1->writer.offset == object2->writer.offset &&
54+
object1->writer.used == object2->writer.used &&
55+
zend_string_equals(object1->writer.buffer, object2->writer.buffer)
5656
) {
5757
return 0;
5858
}
@@ -74,8 +74,8 @@ WRITER_METHOD(__construct) {
7474
ZEND_PARSE_PARAMETERS_END();
7575

7676
object = WRITER_THIS();
77-
if (object->buffer) {
78-
zend_string_release_ex(object->buffer, 0);
77+
if (object->writer.buffer) {
78+
zend_string_release_ex(object->writer.buffer, 0);
7979
}
8080

8181
if (buffer == NULL) {
@@ -90,7 +90,7 @@ WRITER_METHOD(getData) {
9090
zend_parse_parameters_none_throw();
9191

9292
auto object = WRITER_THIS();
93-
RETURN_STRINGL(ZSTR_VAL(object->buffer), object->used);
93+
RETURN_STRINGL(ZSTR_VAL(object->writer.buffer), object->writer.used);
9494
}
9595

9696
WRITER_METHOD(writeByteArray) {
@@ -106,18 +106,18 @@ WRITER_METHOD(writeByteArray) {
106106

107107
auto size = ZSTR_LEN(value);
108108

109-
extendBuffer(object->buffer, object->offset, size);
110-
memcpy(ZSTR_VAL(object->buffer) + object->offset, ZSTR_VAL(value), size);
111-
object->offset += size;
112-
if (object->offset > object->used) {
113-
object->used = object->offset;
109+
extendBuffer(object->writer.buffer, object->writer.offset, size);
110+
memcpy(ZSTR_VAL(object->writer.buffer) + object->writer.offset, ZSTR_VAL(value), size);
111+
object->writer.offset += size;
112+
if (object->writer.offset > object->writer.used) {
113+
object->writer.used = object->writer.offset;
114114
}
115115
}
116116

117117
WRITER_METHOD(getOffset) {
118118
zend_parse_parameters_none_throw();
119119
auto object = WRITER_THIS();
120-
RETURN_LONG(object->offset);
120+
RETURN_LONG(object->writer.offset);
121121
}
122122

123123
WRITER_METHOD(setOffset) {
@@ -128,26 +128,26 @@ WRITER_METHOD(setOffset) {
128128
ZEND_PARSE_PARAMETERS_END();
129129

130130
auto object = WRITER_THIS();
131-
if (offset < 0 || static_cast<size_t>(offset) > object->used) {
131+
if (offset < 0 || static_cast<size_t>(offset) > object->writer.used) {
132132
zend_value_error("Offset must not be less than zero or greater than the buffer size");
133133
return;
134134
}
135135

136-
object->offset = static_cast<size_t>(offset);
136+
object->writer.offset = static_cast<size_t>(offset);
137137
}
138138

139139
WRITER_METHOD(getUsedLength) {
140140
zend_parse_parameters_none_throw();
141141

142142
auto object = WRITER_THIS();
143-
RETURN_LONG(object->used);
143+
RETURN_LONG(object->writer.used);
144144
}
145145

146146
WRITER_METHOD(getReservedLength) {
147147
zend_parse_parameters_none_throw();
148148

149149
auto object = WRITER_THIS();
150-
RETURN_LONG(ZSTR_LEN(object->buffer));
150+
RETURN_LONG(ZSTR_LEN(object->writer.buffer));
151151
}
152152

153153
WRITER_METHOD(reserve) {
@@ -162,24 +162,24 @@ WRITER_METHOD(reserve) {
162162
return;
163163
}
164164
auto object = WRITER_THIS();
165-
extendBuffer(object->buffer, static_cast<size_t>(zlength), 0);
165+
extendBuffer(object->writer.buffer, static_cast<size_t>(zlength), 0);
166166
}
167167

168168
WRITER_METHOD(trim) {
169169
zend_parse_parameters_none_throw();
170170

171171
auto object = WRITER_THIS();
172-
if (ZSTR_LEN(object->buffer) > object->used) {
173-
object->buffer = zend_string_truncate(object->buffer, object->used, 0);
172+
if (ZSTR_LEN(object->writer.buffer) > object->writer.used) {
173+
object->writer.buffer = zend_string_truncate(object->writer.buffer, object->writer.used, 0);
174174
}
175175
}
176176

177177
WRITER_METHOD(clear) {
178178
zend_parse_parameters_none_throw();
179179

180180
auto object = WRITER_THIS();
181-
object->offset = 0;
182-
object->used = 0;
181+
object->writer.offset = 0;
182+
object->writer.used = 0;
183183
}
184184

185185
WRITER_METHOD(__serialize) {
@@ -189,8 +189,8 @@ WRITER_METHOD(__serialize) {
189189
array_init(return_value);
190190

191191
//don't return the writer buffer directly - it may have uninitialized reserved memory
192-
add_assoc_stringl(return_value, "buffer", ZSTR_VAL(object->buffer), object->used);
193-
add_assoc_long(return_value, "offset", object->offset);
192+
add_assoc_stringl(return_value, "buffer", ZSTR_VAL(object->writer.buffer), object->writer.used);
193+
add_assoc_long(return_value, "offset", object->writer.offset);
194194
}
195195

196196
static zval* fetch_serialized_property(HashTable* data, const char* name, int type) {
@@ -235,8 +235,8 @@ WRITER_METHOD(__debugInfo) {
235235
array_init(return_value);
236236

237237
//don't return the writer buffer directly - it may have uninitialized reserved memory
238-
add_assoc_stringl(return_value, "buffer", ZSTR_VAL(object->buffer), object->used);
239-
add_assoc_long(return_value, "offset", object->offset);
238+
add_assoc_stringl(return_value, "buffer", ZSTR_VAL(object->writer.buffer), object->writer.used);
239+
add_assoc_long(return_value, "offset", object->writer.offset);
240240
}
241241

242242
zend_class_entry* init_class_ByteBufferWriter(void) {

classes/ByteBufferWriter.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@ extern "C" {
66
}
77
#include "../ZendUtil.h"
88

9-
typedef struct _byte_buffer_writer_zend_object {
9+
typedef struct _byte_buffer_writer_t {
1010
zend_string* buffer;
1111
size_t offset;
1212
size_t used;
13+
} byte_buffer_writer_t;
14+
15+
typedef struct _byte_buffer_writer_zend_object {
16+
byte_buffer_writer_t writer;
1317
zend_object std;
1418
} byte_buffer_writer_zend_object;
1519

0 commit comments

Comments
 (0)