diff --git a/docs/API/Buffer/HFloatBuffer.md b/docs/API/Buffer/HFloatBuffer.md index f2846bfe..0f310414 100644 --- a/docs/API/Buffer/HFloatBuffer.md +++ b/docs/API/Buffer/HFloatBuffer.md @@ -1,6 +1,6 @@ # HFloatBuffer The class `GL\Buffer\HFloatBuffer` comes with the PHP-GLFW extension to more efficiently -handle large arrays of `GLhalf` values (`float` in php). +handle large arrays of `GLhalf` values (`int` in php). **Don't confuse these objects with actual GPU buffers.** @@ -27,16 +27,16 @@ use GL\Buffer\HFloatBuffer; $buffer = new HFloatBuffer; // values can be pushed into the array using subscript -$buffer[] = 42.69; -$buffer[] = 3.14; +$buffer[] = 42; +$buffer[] = 123; // values can be accessed like an array -echo $buffer[0]; // 42.69 +echo $buffer[0]; // 42 // values can be modifed like an array // just make sure the used index actually exists, // it will NOT be created implicitly! -$buffer[0] = 1.23; +$buffer[0] = 8; // dumping the buffer will display the first 127 value var_dump($buffer); @@ -57,7 +57,7 @@ your array contains invalid values. ```php $buffer = new HFloatBuffer([ - 42.69, 3.14, 1.23 + 42, 123, 8 ]); ``` @@ -67,15 +67,15 @@ The `HFloatBuffer` class exposes the following methods to userland. ### `push` -pushes a value into the buffer, this is exactly the same as when you would write `$buffer[] = 3.14`. +pushes a value into the buffer, this is exactly the same as when you would write `$buffer[] = 123`. ```php -function push(float $value) : void +function push(int $value) : void ``` arguments -: 1. `float` `$value` The value to be pushed into the buffer. +: 1. `int` `$value` The value to be pushed into the buffer. returns @@ -94,7 +94,7 @@ function pushArray(array $values) : void arguments -: 1. `float[]` `$values` The values to be pushed into the buffer. +: 1. `int[]` `$values` The values to be pushed into the buffer. returns @@ -108,13 +108,13 @@ returns Fills the buffer with `$count` amount of values. The second argument is the value that is filled in. ```php -function fill(int $count, float $value) : void +function fill(int $count, int $value) : void ``` arguments : 1. `int $count` The number of elements to fill. - 2. `float $value` That value that will be filled in. + 2. `int $value` That value that will be filled in. returns diff --git a/generator/build b/generator/build index 923deff7..562f39b6 100755 --- a/generator/build +++ b/generator/build @@ -47,7 +47,7 @@ $nanovg->process(GEN_PATH_EXT . '/vendor/nanovg/src/nanovg.h', $gen); // 'GLhalf' => 'HALF_FLOAT', // 'GLdouble' => 'DOUBLE', $gen->phpglfwBuffers[] = new PHPGLFWBuffer('FloatBuffer', 'GLfloat', ExtType::T_DOUBLE); -$gen->phpglfwBuffers[] = new PHPGLFWBuffer('HFloatBuffer', 'GLhalf', ExtType::T_DOUBLE); +$gen->phpglfwBuffers[] = new PHPGLFWBuffer('HFloatBuffer', 'GLhalf', ExtType::T_LONG); // we currenly have no way to handle 16bit floats, so we consider them like the "GLhalf" as a unsigned short $gen->phpglfwBuffers[] = new PHPGLFWBuffer('DoubleBuffer', 'GLdouble', ExtType::T_DOUBLE); $gen->phpglfwBuffers[] = new PHPGLFWBuffer('IntBuffer', 'GLint', ExtType::T_LONG); $gen->phpglfwBuffers[] = new PHPGLFWBuffer('UIntBuffer', 'GLuint', ExtType::T_LONG); diff --git a/generator/templates/phpglfw_buffer.c.php b/generator/templates/phpglfw_buffer.c.php index c56dd38e..ebb5da41 100644 --- a/generator/templates/phpglfw_buffer.c.php +++ b/generator/templates/phpglfw_buffer.c.php @@ -339,7 +339,7 @@ getObjectName(); ?> *obj; size_t exp_item_count, item_count; - char *endptr, *token; + char *endptr, *token, *tmp_copy; // prints the buffer for debugging // for (size_t i = 0; i < buf_len; i++) { @@ -358,6 +358,12 @@ // skip the ':' endptr++; + // create a copy of the buffer, we are going to modify it + // @TODO: when using `strtok` we are modifying the entire buffer, + // which will cause an issue when we are using the same buffer for multiple elements + // This copy for sure can be avoided, but im going to tackle that in the future + tmp_copy = estrndup(endptr, buf_len - (endptr - (char *)buf)); + // make the object object_init_ex(object, getClassEntryName(); ?>); obj = objectFromZObjFunctionName(); ?>(Z_OBJ_P(object)); @@ -365,15 +371,17 @@ cvector_reserve(obj->vec, exp_item_count); // read the elements, check if our endptr is still valid and we have not reached the end of the buffer - while ((token = strtok(endptr, " ")) && item_count > 0 && endptr < (char *)buf + buf_len) { - type == "GLfloat" || $buffer->type == "GLhalf" || $buffer->type == "GLdouble"): ?> + token = strtok(tmp_copy, " "); + while (token != NULL && item_count > 0) { + type == "GLfloat" || $buffer->type == "GLdouble"): ?> cvector_push_back(obj->vec, atof(token)); - type == "GLint" || $buffer->type == "GLuint" || $buffer->type == "GLshort" || $buffer->type == "GLushort" || $buffer->type == "GLbyte" || $buffer->type == "GLubyte"): ?> + type == "GLint" || $buffer->type == "GLuint" || $buffer->type == "GLshort" || $buffer->type == "GLushort" || $buffer->type == "GLhalf" || $buffer->type == "GLbyte" || $buffer->type == "GLubyte"): ?> cvector_push_back(obj->vec, strtol(token, NULL, 10)); zend_throw_error(NULL, "Unknown buffer type for deserialization."); return FAILURE; + token = strtok(NULL, " "); item_count--; } diff --git a/phpglfw.stub.php b/phpglfw.stub.php index 0ff54cdd..e56d9688 100644 --- a/phpglfw.stub.php +++ b/phpglfw.stub.php @@ -217,9 +217,9 @@ public function reserve(int $size) : void {} class HFloatBuffer implements BufferInterface { public function __construct(?array $initalData = null) {} public function __toString() : string {} - public function push(float $value) : void {} + public function push(int $value) : void {} public function pushArray(array $values) : void {} - public function fill(int $count, float $value) : void {} + public function fill(int $count, int $value) : void {} public function clear() : void {} public function size() : int {} public function capacity() : int {} diff --git a/phpglfw_arginfo.h b/phpglfw_arginfo.h index b97f8b45..5b3f0566 100644 --- a/phpglfw_arginfo.h +++ b/phpglfw_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 5534d8a667da4be66ea9c03ef9a48c4f6eacc0b4 */ + * Stub hash: 6d737f2c1a2752aa1b7120b6e4585c4de706881a */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_glCullFace, 0, 1, IS_VOID, 0) ZEND_ARG_TYPE_INFO(0, mode, IS_LONG, 0) @@ -2643,11 +2643,16 @@ ZEND_END_ARG_INFO() #define arginfo_class_GL_Buffer_HFloatBuffer___toString arginfo_glfwGetVersionString -#define arginfo_class_GL_Buffer_HFloatBuffer_push arginfo_glMinSampleShading +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_GL_Buffer_HFloatBuffer_push, 0, 1, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, value, IS_LONG, 0) +ZEND_END_ARG_INFO() #define arginfo_class_GL_Buffer_HFloatBuffer_pushArray arginfo_class_GL_Buffer_FloatBuffer_pushArray -#define arginfo_class_GL_Buffer_HFloatBuffer_fill arginfo_class_GL_Buffer_FloatBuffer_fill +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_GL_Buffer_HFloatBuffer_fill, 0, 2, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, count, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, value, IS_LONG, 0) +ZEND_END_ARG_INFO() #define arginfo_class_GL_Buffer_HFloatBuffer_clear arginfo_glFinish @@ -2679,16 +2684,11 @@ ZEND_END_ARG_INFO() #define arginfo_class_GL_Buffer_IntBuffer___toString arginfo_glfwGetVersionString -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_GL_Buffer_IntBuffer_push, 0, 1, IS_VOID, 0) - ZEND_ARG_TYPE_INFO(0, value, IS_LONG, 0) -ZEND_END_ARG_INFO() +#define arginfo_class_GL_Buffer_IntBuffer_push arginfo_class_GL_Buffer_HFloatBuffer_push #define arginfo_class_GL_Buffer_IntBuffer_pushArray arginfo_class_GL_Buffer_FloatBuffer_pushArray -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_GL_Buffer_IntBuffer_fill, 0, 2, IS_VOID, 0) - ZEND_ARG_TYPE_INFO(0, count, IS_LONG, 0) - ZEND_ARG_TYPE_INFO(0, value, IS_LONG, 0) -ZEND_END_ARG_INFO() +#define arginfo_class_GL_Buffer_IntBuffer_fill arginfo_class_GL_Buffer_HFloatBuffer_fill #define arginfo_class_GL_Buffer_IntBuffer_clear arginfo_glFinish @@ -2702,11 +2702,11 @@ ZEND_END_ARG_INFO() #define arginfo_class_GL_Buffer_UIntBuffer___toString arginfo_glfwGetVersionString -#define arginfo_class_GL_Buffer_UIntBuffer_push arginfo_class_GL_Buffer_IntBuffer_push +#define arginfo_class_GL_Buffer_UIntBuffer_push arginfo_class_GL_Buffer_HFloatBuffer_push #define arginfo_class_GL_Buffer_UIntBuffer_pushArray arginfo_class_GL_Buffer_FloatBuffer_pushArray -#define arginfo_class_GL_Buffer_UIntBuffer_fill arginfo_class_GL_Buffer_IntBuffer_fill +#define arginfo_class_GL_Buffer_UIntBuffer_fill arginfo_class_GL_Buffer_HFloatBuffer_fill #define arginfo_class_GL_Buffer_UIntBuffer_clear arginfo_glFinish @@ -2720,11 +2720,11 @@ ZEND_END_ARG_INFO() #define arginfo_class_GL_Buffer_ShortBuffer___toString arginfo_glfwGetVersionString -#define arginfo_class_GL_Buffer_ShortBuffer_push arginfo_class_GL_Buffer_IntBuffer_push +#define arginfo_class_GL_Buffer_ShortBuffer_push arginfo_class_GL_Buffer_HFloatBuffer_push #define arginfo_class_GL_Buffer_ShortBuffer_pushArray arginfo_class_GL_Buffer_FloatBuffer_pushArray -#define arginfo_class_GL_Buffer_ShortBuffer_fill arginfo_class_GL_Buffer_IntBuffer_fill +#define arginfo_class_GL_Buffer_ShortBuffer_fill arginfo_class_GL_Buffer_HFloatBuffer_fill #define arginfo_class_GL_Buffer_ShortBuffer_clear arginfo_glFinish @@ -2738,11 +2738,11 @@ ZEND_END_ARG_INFO() #define arginfo_class_GL_Buffer_UShortBuffer___toString arginfo_glfwGetVersionString -#define arginfo_class_GL_Buffer_UShortBuffer_push arginfo_class_GL_Buffer_IntBuffer_push +#define arginfo_class_GL_Buffer_UShortBuffer_push arginfo_class_GL_Buffer_HFloatBuffer_push #define arginfo_class_GL_Buffer_UShortBuffer_pushArray arginfo_class_GL_Buffer_FloatBuffer_pushArray -#define arginfo_class_GL_Buffer_UShortBuffer_fill arginfo_class_GL_Buffer_IntBuffer_fill +#define arginfo_class_GL_Buffer_UShortBuffer_fill arginfo_class_GL_Buffer_HFloatBuffer_fill #define arginfo_class_GL_Buffer_UShortBuffer_clear arginfo_glFinish @@ -2756,11 +2756,11 @@ ZEND_END_ARG_INFO() #define arginfo_class_GL_Buffer_ByteBuffer___toString arginfo_glfwGetVersionString -#define arginfo_class_GL_Buffer_ByteBuffer_push arginfo_class_GL_Buffer_IntBuffer_push +#define arginfo_class_GL_Buffer_ByteBuffer_push arginfo_class_GL_Buffer_HFloatBuffer_push #define arginfo_class_GL_Buffer_ByteBuffer_pushArray arginfo_class_GL_Buffer_FloatBuffer_pushArray -#define arginfo_class_GL_Buffer_ByteBuffer_fill arginfo_class_GL_Buffer_IntBuffer_fill +#define arginfo_class_GL_Buffer_ByteBuffer_fill arginfo_class_GL_Buffer_HFloatBuffer_fill #define arginfo_class_GL_Buffer_ByteBuffer_clear arginfo_glFinish @@ -2774,11 +2774,11 @@ ZEND_END_ARG_INFO() #define arginfo_class_GL_Buffer_UByteBuffer___toString arginfo_glfwGetVersionString -#define arginfo_class_GL_Buffer_UByteBuffer_push arginfo_class_GL_Buffer_IntBuffer_push +#define arginfo_class_GL_Buffer_UByteBuffer_push arginfo_class_GL_Buffer_HFloatBuffer_push #define arginfo_class_GL_Buffer_UByteBuffer_pushArray arginfo_class_GL_Buffer_FloatBuffer_pushArray -#define arginfo_class_GL_Buffer_UByteBuffer_fill arginfo_class_GL_Buffer_IntBuffer_fill +#define arginfo_class_GL_Buffer_UByteBuffer_fill arginfo_class_GL_Buffer_HFloatBuffer_fill #define arginfo_class_GL_Buffer_UByteBuffer_clear arginfo_glFinish diff --git a/phpglfw_buffer.c b/phpglfw_buffer.c index 7f7800bb..964168d5 100644 --- a/phpglfw_buffer.c +++ b/phpglfw_buffer.c @@ -390,7 +390,7 @@ static int phpglfw_buffer_glfloat_unserialize_handler(zval *object, zend_class_e phpglfw_buffer_glfloat_object *obj; size_t exp_item_count, item_count; - char *endptr, *token; + char *endptr, *token, *tmp_copy; // prints the buffer for debugging // for (size_t i = 0; i < buf_len; i++) { @@ -409,6 +409,12 @@ static int phpglfw_buffer_glfloat_unserialize_handler(zval *object, zend_class_e // skip the ':' endptr++; + // create a copy of the buffer, we are going to modify it + // @TODO: when using `strtok` we are modifying the entire buffer, + // which will cause an issue when we are using the same buffer for multiple elements + // This copy for sure can be avoided, but im going to tackle that in the future + tmp_copy = estrndup(endptr, buf_len - (endptr - (char *)buf)); + // make the object object_init_ex(object, phpglfw_buffer_glfloat_ce); obj = phpglfw_buffer_glfloat_objectptr_from_zobj_p(Z_OBJ_P(object)); @@ -416,9 +422,11 @@ static int phpglfw_buffer_glfloat_unserialize_handler(zval *object, zend_class_e cvector_reserve(obj->vec, exp_item_count); // read the elements, check if our endptr is still valid and we have not reached the end of the buffer - while ((token = strtok(endptr, " ")) && item_count > 0 && endptr < (char *)buf + buf_len) { + token = strtok(tmp_copy, " "); + while (token != NULL && item_count > 0) { cvector_push_back(obj->vec, atof(token)); - item_count--; + token = strtok(NULL, " "); + item_count--; } if (cvector_size(obj->vec) != exp_item_count) { @@ -738,7 +746,7 @@ static zval *phpglfw_buffer_glhalf_it_current_data_handler(zend_object_iterator phpglfw_buffer_glhalf_iterator *iterator = (phpglfw_buffer_glhalf_iterator*)iter; phpglfw_buffer_glhalf_object *obj_ptr = phpglfw_buffer_glhalf_objectptr_from_zobj_p(Z_OBJ_P(&iter->data)); - ZVAL_DOUBLE(&iterator->current, obj_ptr->vec[iterator->index]); + ZVAL_LONG(&iterator->current, obj_ptr->vec[iterator->index]); return &iterator->current; } @@ -812,7 +820,7 @@ zval *phpglfw_buffer_glhalf_array_get_handler(zend_object *object, zval *offset, size_t index = (size_t)Z_LVAL_P(offset); if (index < cvector_size(obj_ptr->vec)) { - ZVAL_DOUBLE(rv, obj_ptr->vec[index]); + ZVAL_LONG(rv, obj_ptr->vec[index]); } else { ZVAL_NULL(rv); } @@ -826,8 +834,8 @@ zval *phpglfw_buffer_glhalf_array_get_handler(zend_object *object, zval *offset, void phpglfw_buffer_glhalf_array_set_handler(zend_object *object, zval *offset, zval *value) { - if (Z_TYPE_P(value) != IS_DOUBLE) { - zend_throw_error(NULL, "Trying to store non float value in a float type buffer."); + if (Z_TYPE_P(value) != IS_LONG) { + zend_throw_error(NULL, "Trying to store non int value in a int type buffer."); return; } @@ -835,7 +843,7 @@ void phpglfw_buffer_glhalf_array_set_handler(zend_object *object, zval *offset, // if offset is not given ($buff[] = 3.14) if (offset == NULL) { - cvector_push_back(obj_ptr->vec, Z_DVAL_P(value)); + cvector_push_back(obj_ptr->vec, Z_LVAL_P(value)); } else { if (Z_TYPE_P(offset) == IS_LONG) { @@ -845,7 +853,7 @@ void phpglfw_buffer_glhalf_array_set_handler(zend_object *object, zval *offset, zend_throw_error(NULL, "Cannot modify unallocated buffer space, the element at index [%d] does not exist. Use `push` or `fill` to allocate the requested spaces.", (int) index); } - obj_ptr->vec[index] = Z_DVAL_P(value); + obj_ptr->vec[index] = Z_LVAL_P(value); } else { zend_throw_error(NULL, "Only a int offset '$buffer[int]' can be used with the GL\\Buffer\\BufferInterface object"); } @@ -944,7 +952,7 @@ static int phpglfw_buffer_glhalf_unserialize_handler(zval *object, zend_class_en phpglfw_buffer_glhalf_object *obj; size_t exp_item_count, item_count; - char *endptr, *token; + char *endptr, *token, *tmp_copy; // prints the buffer for debugging // for (size_t i = 0; i < buf_len; i++) { @@ -963,6 +971,12 @@ static int phpglfw_buffer_glhalf_unserialize_handler(zval *object, zend_class_en // skip the ':' endptr++; + // create a copy of the buffer, we are going to modify it + // @TODO: when using `strtok` we are modifying the entire buffer, + // which will cause an issue when we are using the same buffer for multiple elements + // This copy for sure can be avoided, but im going to tackle that in the future + tmp_copy = estrndup(endptr, buf_len - (endptr - (char *)buf)); + // make the object object_init_ex(object, phpglfw_buffer_glhalf_ce); obj = phpglfw_buffer_glhalf_objectptr_from_zobj_p(Z_OBJ_P(object)); @@ -970,9 +984,11 @@ static int phpglfw_buffer_glhalf_unserialize_handler(zval *object, zend_class_en cvector_reserve(obj->vec, exp_item_count); // read the elements, check if our endptr is still valid and we have not reached the end of the buffer - while ((token = strtok(endptr, " ")) && item_count > 0 && endptr < (char *)buf + buf_len) { - cvector_push_back(obj->vec, atof(token)); - item_count--; + token = strtok(tmp_copy, " "); + while (token != NULL && item_count > 0) { + cvector_push_back(obj->vec, strtol(token, NULL, 10)); + token = strtok(NULL, " "); + item_count--; } if (cvector_size(obj->vec) != exp_item_count) { @@ -999,7 +1015,7 @@ static HashTable *phpglfw_buffer_glhalf_debug_info_handler(zend_object *object, zend_hash_str_update(ht, "size", sizeof("size") - 1, &zv); for(size_t i = 0; i < pglmin(127, cvector_size(obj_ptr->vec)); i++) { - ZVAL_DOUBLE(&zv, obj_ptr->vec[i]); + ZVAL_LONG(&zv, obj_ptr->vec[i]); zend_hash_index_update(dataht, i, &zv); } @@ -1037,8 +1053,8 @@ PHP_METHOD(GL_Buffer_HFloatBuffer, __toString) PHP_METHOD(GL_Buffer_HFloatBuffer, push) { - double value; - if (zend_parse_parameters(ZEND_NUM_ARGS() , "d", &value) == FAILURE) { + zend_long value; + if (zend_parse_parameters(ZEND_NUM_ARGS() , "l", &value) == FAILURE) { return; } @@ -1061,12 +1077,12 @@ PHP_METHOD(GL_Buffer_HFloatBuffer, pushArray) phpglfw_buffer_glhalf_object *obj_ptr = phpglfw_buffer_glhalf_objectptr_from_zobj_p(Z_OBJ_P(obj)); ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(array), array) { - if (Z_TYPE_P(array) != IS_DOUBLE) { - zend_throw_error(NULL, "Trying to store non float value in a float type buffer."); + if (Z_TYPE_P(array) != IS_LONG) { + zend_throw_error(NULL, "Trying to store non int value in a int type buffer."); return; } - cvector_push_back(obj_ptr->vec, Z_DVAL_P(array)); + cvector_push_back(obj_ptr->vec, Z_LVAL_P(array)); } ZEND_HASH_FOREACH_END(); } @@ -1098,9 +1114,9 @@ PHP_METHOD(GL_Buffer_HFloatBuffer, clear) PHP_METHOD(GL_Buffer_HFloatBuffer, fill) { - double value; + zend_long value; zend_long fill_size; - if (zend_parse_parameters(ZEND_NUM_ARGS() , "ld", &fill_size, &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() , "ll", &fill_size, &value) == FAILURE) { return; } @@ -1152,10 +1168,10 @@ PHP_METHOD(GL_Buffer_HFloatBuffer, __construct) cvector_reserve(obj_ptr->vec, zend_hash_num_elements(initaldata)); ZEND_HASH_FOREACH_VAL(initaldata, data) - if (Z_TYPE_P(data) == IS_DOUBLE) { - cvector_push_back(obj_ptr->vec, Z_DVAL_P(data)); + if (Z_TYPE_P(data) == IS_LONG) { + cvector_push_back(obj_ptr->vec, Z_LVAL_P(data)); } else { - zend_throw_error(NULL, "All elements of the inital data array has to be of type: float"); + zend_throw_error(NULL, "All elements of the inital data array has to be of type: int"); } ZEND_HASH_FOREACH_END(); } @@ -1432,7 +1448,7 @@ static int phpglfw_buffer_gldouble_unserialize_handler(zval *object, zend_class_ phpglfw_buffer_gldouble_object *obj; size_t exp_item_count, item_count; - char *endptr, *token; + char *endptr, *token, *tmp_copy; // prints the buffer for debugging // for (size_t i = 0; i < buf_len; i++) { @@ -1451,6 +1467,12 @@ static int phpglfw_buffer_gldouble_unserialize_handler(zval *object, zend_class_ // skip the ':' endptr++; + // create a copy of the buffer, we are going to modify it + // @TODO: when using `strtok` we are modifying the entire buffer, + // which will cause an issue when we are using the same buffer for multiple elements + // This copy for sure can be avoided, but im going to tackle that in the future + tmp_copy = estrndup(endptr, buf_len - (endptr - (char *)buf)); + // make the object object_init_ex(object, phpglfw_buffer_gldouble_ce); obj = phpglfw_buffer_gldouble_objectptr_from_zobj_p(Z_OBJ_P(object)); @@ -1458,9 +1480,11 @@ static int phpglfw_buffer_gldouble_unserialize_handler(zval *object, zend_class_ cvector_reserve(obj->vec, exp_item_count); // read the elements, check if our endptr is still valid and we have not reached the end of the buffer - while ((token = strtok(endptr, " ")) && item_count > 0 && endptr < (char *)buf + buf_len) { + token = strtok(tmp_copy, " "); + while (token != NULL && item_count > 0) { cvector_push_back(obj->vec, atof(token)); - item_count--; + token = strtok(NULL, " "); + item_count--; } if (cvector_size(obj->vec) != exp_item_count) { @@ -1912,7 +1936,7 @@ static int phpglfw_buffer_glint_unserialize_handler(zval *object, zend_class_ent phpglfw_buffer_glint_object *obj; size_t exp_item_count, item_count; - char *endptr, *token; + char *endptr, *token, *tmp_copy; // prints the buffer for debugging // for (size_t i = 0; i < buf_len; i++) { @@ -1931,6 +1955,12 @@ static int phpglfw_buffer_glint_unserialize_handler(zval *object, zend_class_ent // skip the ':' endptr++; + // create a copy of the buffer, we are going to modify it + // @TODO: when using `strtok` we are modifying the entire buffer, + // which will cause an issue when we are using the same buffer for multiple elements + // This copy for sure can be avoided, but im going to tackle that in the future + tmp_copy = estrndup(endptr, buf_len - (endptr - (char *)buf)); + // make the object object_init_ex(object, phpglfw_buffer_glint_ce); obj = phpglfw_buffer_glint_objectptr_from_zobj_p(Z_OBJ_P(object)); @@ -1938,9 +1968,11 @@ static int phpglfw_buffer_glint_unserialize_handler(zval *object, zend_class_ent cvector_reserve(obj->vec, exp_item_count); // read the elements, check if our endptr is still valid and we have not reached the end of the buffer - while ((token = strtok(endptr, " ")) && item_count > 0 && endptr < (char *)buf + buf_len) { + token = strtok(tmp_copy, " "); + while (token != NULL && item_count > 0) { cvector_push_back(obj->vec, strtol(token, NULL, 10)); - item_count--; + token = strtok(NULL, " "); + item_count--; } if (cvector_size(obj->vec) != exp_item_count) { @@ -2392,7 +2424,7 @@ static int phpglfw_buffer_gluint_unserialize_handler(zval *object, zend_class_en phpglfw_buffer_gluint_object *obj; size_t exp_item_count, item_count; - char *endptr, *token; + char *endptr, *token, *tmp_copy; // prints the buffer for debugging // for (size_t i = 0; i < buf_len; i++) { @@ -2411,6 +2443,12 @@ static int phpglfw_buffer_gluint_unserialize_handler(zval *object, zend_class_en // skip the ':' endptr++; + // create a copy of the buffer, we are going to modify it + // @TODO: when using `strtok` we are modifying the entire buffer, + // which will cause an issue when we are using the same buffer for multiple elements + // This copy for sure can be avoided, but im going to tackle that in the future + tmp_copy = estrndup(endptr, buf_len - (endptr - (char *)buf)); + // make the object object_init_ex(object, phpglfw_buffer_gluint_ce); obj = phpglfw_buffer_gluint_objectptr_from_zobj_p(Z_OBJ_P(object)); @@ -2418,9 +2456,11 @@ static int phpglfw_buffer_gluint_unserialize_handler(zval *object, zend_class_en cvector_reserve(obj->vec, exp_item_count); // read the elements, check if our endptr is still valid and we have not reached the end of the buffer - while ((token = strtok(endptr, " ")) && item_count > 0 && endptr < (char *)buf + buf_len) { + token = strtok(tmp_copy, " "); + while (token != NULL && item_count > 0) { cvector_push_back(obj->vec, strtol(token, NULL, 10)); - item_count--; + token = strtok(NULL, " "); + item_count--; } if (cvector_size(obj->vec) != exp_item_count) { @@ -2872,7 +2912,7 @@ static int phpglfw_buffer_glshort_unserialize_handler(zval *object, zend_class_e phpglfw_buffer_glshort_object *obj; size_t exp_item_count, item_count; - char *endptr, *token; + char *endptr, *token, *tmp_copy; // prints the buffer for debugging // for (size_t i = 0; i < buf_len; i++) { @@ -2891,6 +2931,12 @@ static int phpglfw_buffer_glshort_unserialize_handler(zval *object, zend_class_e // skip the ':' endptr++; + // create a copy of the buffer, we are going to modify it + // @TODO: when using `strtok` we are modifying the entire buffer, + // which will cause an issue when we are using the same buffer for multiple elements + // This copy for sure can be avoided, but im going to tackle that in the future + tmp_copy = estrndup(endptr, buf_len - (endptr - (char *)buf)); + // make the object object_init_ex(object, phpglfw_buffer_glshort_ce); obj = phpglfw_buffer_glshort_objectptr_from_zobj_p(Z_OBJ_P(object)); @@ -2898,9 +2944,11 @@ static int phpglfw_buffer_glshort_unserialize_handler(zval *object, zend_class_e cvector_reserve(obj->vec, exp_item_count); // read the elements, check if our endptr is still valid and we have not reached the end of the buffer - while ((token = strtok(endptr, " ")) && item_count > 0 && endptr < (char *)buf + buf_len) { + token = strtok(tmp_copy, " "); + while (token != NULL && item_count > 0) { cvector_push_back(obj->vec, strtol(token, NULL, 10)); - item_count--; + token = strtok(NULL, " "); + item_count--; } if (cvector_size(obj->vec) != exp_item_count) { @@ -3352,7 +3400,7 @@ static int phpglfw_buffer_glushort_unserialize_handler(zval *object, zend_class_ phpglfw_buffer_glushort_object *obj; size_t exp_item_count, item_count; - char *endptr, *token; + char *endptr, *token, *tmp_copy; // prints the buffer for debugging // for (size_t i = 0; i < buf_len; i++) { @@ -3371,6 +3419,12 @@ static int phpglfw_buffer_glushort_unserialize_handler(zval *object, zend_class_ // skip the ':' endptr++; + // create a copy of the buffer, we are going to modify it + // @TODO: when using `strtok` we are modifying the entire buffer, + // which will cause an issue when we are using the same buffer for multiple elements + // This copy for sure can be avoided, but im going to tackle that in the future + tmp_copy = estrndup(endptr, buf_len - (endptr - (char *)buf)); + // make the object object_init_ex(object, phpglfw_buffer_glushort_ce); obj = phpglfw_buffer_glushort_objectptr_from_zobj_p(Z_OBJ_P(object)); @@ -3378,9 +3432,11 @@ static int phpglfw_buffer_glushort_unserialize_handler(zval *object, zend_class_ cvector_reserve(obj->vec, exp_item_count); // read the elements, check if our endptr is still valid and we have not reached the end of the buffer - while ((token = strtok(endptr, " ")) && item_count > 0 && endptr < (char *)buf + buf_len) { + token = strtok(tmp_copy, " "); + while (token != NULL && item_count > 0) { cvector_push_back(obj->vec, strtol(token, NULL, 10)); - item_count--; + token = strtok(NULL, " "); + item_count--; } if (cvector_size(obj->vec) != exp_item_count) { @@ -3832,7 +3888,7 @@ static int phpglfw_buffer_glbyte_unserialize_handler(zval *object, zend_class_en phpglfw_buffer_glbyte_object *obj; size_t exp_item_count, item_count; - char *endptr, *token; + char *endptr, *token, *tmp_copy; // prints the buffer for debugging // for (size_t i = 0; i < buf_len; i++) { @@ -3851,6 +3907,12 @@ static int phpglfw_buffer_glbyte_unserialize_handler(zval *object, zend_class_en // skip the ':' endptr++; + // create a copy of the buffer, we are going to modify it + // @TODO: when using `strtok` we are modifying the entire buffer, + // which will cause an issue when we are using the same buffer for multiple elements + // This copy for sure can be avoided, but im going to tackle that in the future + tmp_copy = estrndup(endptr, buf_len - (endptr - (char *)buf)); + // make the object object_init_ex(object, phpglfw_buffer_glbyte_ce); obj = phpglfw_buffer_glbyte_objectptr_from_zobj_p(Z_OBJ_P(object)); @@ -3858,9 +3920,11 @@ static int phpglfw_buffer_glbyte_unserialize_handler(zval *object, zend_class_en cvector_reserve(obj->vec, exp_item_count); // read the elements, check if our endptr is still valid and we have not reached the end of the buffer - while ((token = strtok(endptr, " ")) && item_count > 0 && endptr < (char *)buf + buf_len) { + token = strtok(tmp_copy, " "); + while (token != NULL && item_count > 0) { cvector_push_back(obj->vec, strtol(token, NULL, 10)); - item_count--; + token = strtok(NULL, " "); + item_count--; } if (cvector_size(obj->vec) != exp_item_count) { @@ -4312,7 +4376,7 @@ static int phpglfw_buffer_glubyte_unserialize_handler(zval *object, zend_class_e phpglfw_buffer_glubyte_object *obj; size_t exp_item_count, item_count; - char *endptr, *token; + char *endptr, *token, *tmp_copy; // prints the buffer for debugging // for (size_t i = 0; i < buf_len; i++) { @@ -4331,6 +4395,12 @@ static int phpglfw_buffer_glubyte_unserialize_handler(zval *object, zend_class_e // skip the ':' endptr++; + // create a copy of the buffer, we are going to modify it + // @TODO: when using `strtok` we are modifying the entire buffer, + // which will cause an issue when we are using the same buffer for multiple elements + // This copy for sure can be avoided, but im going to tackle that in the future + tmp_copy = estrndup(endptr, buf_len - (endptr - (char *)buf)); + // make the object object_init_ex(object, phpglfw_buffer_glubyte_ce); obj = phpglfw_buffer_glubyte_objectptr_from_zobj_p(Z_OBJ_P(object)); @@ -4338,9 +4408,11 @@ static int phpglfw_buffer_glubyte_unserialize_handler(zval *object, zend_class_e cvector_reserve(obj->vec, exp_item_count); // read the elements, check if our endptr is still valid and we have not reached the end of the buffer - while ((token = strtok(endptr, " ")) && item_count > 0 && endptr < (char *)buf + buf_len) { + token = strtok(tmp_copy, " "); + while (token != NULL && item_count > 0) { cvector_push_back(obj->vec, strtol(token, NULL, 10)); - item_count--; + token = strtok(NULL, " "); + item_count--; } if (cvector_size(obj->vec) != exp_item_count) { diff --git a/stubs/phpglfw.php b/stubs/phpglfw.php index 341b51c6..f0b41c0d 100644 --- a/stubs/phpglfw.php +++ b/stubs/phpglfw.php @@ -1234,24 +1234,24 @@ class HFloatBuffer implements BufferInterface { /** * Constructs a new HFloatBuffer, internally (GLhalf) * - * @param null|array $intialData Inital data to be pushed into the buffer. + * @param null|array $intialData Inital data to be pushed into the buffer. */ public function __construct(?array $initalData = null) {} public function __toString() : string {} /** - * pushes a value into the buffer, this is exactly the same as when you would write `$buffer[] = 3.14`. + * pushes a value into the buffer, this is exactly the same as when you would write `$buffer[] = 123`. * - * @param float $value The value to be pushed into the buffer. + * @param int $value The value to be pushed into the buffer. * * @return void */ - public function push(float $value) : void {} + public function push(int $value) : void {} /** * pushes an array of values into the buffer. This works the same as when you pass inital data to the constructor. * - * @param array $values The values to be pushed into the buffer. + * @param array $values The values to be pushed into the buffer. * * @return void */ @@ -1262,11 +1262,11 @@ public function pushArray(array $values) : void {} * Fills the buffer with $count amount of values. The second argument is the value that is filled in. * * @param int $count The number of elements to fill. - * @param float $value The value that will be filled in. + * @param int $value The value that will be filled in. * * @return void */ - public function fill(int $count, float $value) : void {} + public function fill(int $count, int $value) : void {} /** * Reserves the $size amount of space. Values are still undefined. diff --git a/tests/Buffer/BufferTestCase.php b/tests/Buffer/BufferTestCase.php index ed5e06db..92a1396a 100644 --- a/tests/Buffer/BufferTestCase.php +++ b/tests/Buffer/BufferTestCase.php @@ -206,6 +206,36 @@ public function testIterator() } } + public function testSerialisation() + { + $className = $this->getBufferClass(); + $data = $this->getTestData(); + $buffer = new $className($data); + + ini_set('glfw.buffer_serialize_hex_float', false); + + $serialized = serialize($buffer); + $unserialized = unserialize($serialized); + + $this->assertEquals($buffer->size(), $unserialized->size()); + + for($i=0; $iassertEqualBufferValue($data[$i], $unserialized[$i]); + } + + // test with hex serialization + ini_set('glfw.buffer_serialize_hex_float', true); + + $serialized = serialize($buffer); + $unserialized = unserialize($serialized); + + $this->assertEquals($buffer->size(), $unserialized->size()); + + for($i=0; $iassertEqualBufferValue($data[$i], $unserialized[$i]); + } + } + public function testToString() { $className = $this->getBufferClass(); diff --git a/tests/Buffer/ByteBufferTest.php b/tests/Buffer/ByteBufferTest.php index ad169511..ac75d04c 100644 --- a/tests/Buffer/ByteBufferTest.php +++ b/tests/Buffer/ByteBufferTest.php @@ -19,9 +19,7 @@ protected function getBufferClass() : string */ protected function getTestData() : array { - return [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 - ]; + return range(-128, 127); } /** diff --git a/tests/Buffer/DoubleBufferTest.php b/tests/Buffer/DoubleBufferTest.php index b3d01b86..7986fe02 100644 --- a/tests/Buffer/DoubleBufferTest.php +++ b/tests/Buffer/DoubleBufferTest.php @@ -21,7 +21,7 @@ protected function getTestData() : array { return [ 0.0, 1.1, 2.2, 3.3, 4.4, 5.5, - 6.6, 7.7, 8.8, 9.9, 10.0, + 6.6, 7.7, 8.8, 9.9, 10.0, M_PI ]; } diff --git a/tests/Buffer/HFloatBufferTest.php b/tests/Buffer/HFloatBufferTest.php new file mode 100644 index 00000000..5d548e82 --- /dev/null +++ b/tests/Buffer/HFloatBufferTest.php @@ -0,0 +1,16 @@ +assertEquals($expected, $actual); + } + + public function testOverflow() + { + $buffer = new ShortBuffer(); + $buffer->push(42); + $buffer->push(32767); + $buffer->push(32767 + 1); + $buffer->push(32768 * 2 + 1); + + $this->assertEquals(42, $buffer[0]); + $this->assertEquals(32767, $buffer[1]); + $this->assertEquals(-32768, $buffer[2]); + $this->assertEquals(1, $buffer[3]); + } +} \ No newline at end of file diff --git a/tests/Buffer/UByteBufferTest.php b/tests/Buffer/UByteBufferTest.php index a45836ee..c1656045 100644 --- a/tests/Buffer/UByteBufferTest.php +++ b/tests/Buffer/UByteBufferTest.php @@ -19,9 +19,7 @@ protected function getBufferClass() : string */ protected function getTestData() : array { - return [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 - ]; + return range(0, 255); } /** diff --git a/tests/Buffer/UIntBufferTest.php b/tests/Buffer/UIntBufferTest.php new file mode 100644 index 00000000..8bccb09f --- /dev/null +++ b/tests/Buffer/UIntBufferTest.php @@ -0,0 +1,47 @@ +assertEquals($expected, $actual); + } + + public function testOverflow() + { + $buffer = new UIntBuffer(); + $buffer->push(42); + $buffer->push(4294967295); + $buffer->push(4294967295 + 1); + $buffer->push(-1); + + $this->assertEquals(42, $buffer[0]); + $this->assertEquals(4294967295, $buffer[1]); + $this->assertEquals(0, $buffer[2]); + $this->assertEquals(4294967295, $buffer[3]); + } +} diff --git a/tests/Buffer/UShortBufferTest.php b/tests/Buffer/UShortBufferTest.php new file mode 100644 index 00000000..a64752df --- /dev/null +++ b/tests/Buffer/UShortBufferTest.php @@ -0,0 +1,48 @@ +assertEquals($expected, $actual); + } + + /** + * Test to ensure that values above the ushort max wrap around + */ + public function testUpperBoundOverflow() + { + $buffer = new UShortBuffer(); + $buffer->push(65535); + $buffer->push(65536); + $buffer->push(-1); + + $this->assertEquals(65535, $buffer[0]); + $this->assertEquals(0, $buffer[1]); + $this->assertEquals(65535, $buffer[2]); + } +}