20
20
21
21
#include "php_phongo.h"
22
22
#include "phongo_error.h"
23
+ #include "Binary.h"
23
24
#include "Binary_arginfo.h"
24
-
25
- #define PHONGO_BINARY_UUID_SIZE 16
25
+ #include "BinaryVector_arginfo.h"
26
26
27
27
zend_class_entry * php_phongo_binary_ce ;
28
28
29
+ static phongo_bson_vector_type_t phongo_binary_get_vector_type_from_data (const uint8_t * data , uint32_t data_len );
30
+
29
31
/* Initialize the object and return whether it was successful. An exception will
30
32
* be thrown on error. */
31
33
static bool php_phongo_binary_init (php_phongo_binary_t * intern , const char * data , size_t data_len , zend_long type )
@@ -40,6 +42,11 @@ static bool php_phongo_binary_init(php_phongo_binary_t* intern, const char* data
40
42
return false;
41
43
}
42
44
45
+ if ((type == BSON_SUBTYPE_VECTOR ) && phongo_binary_get_vector_type_from_data ((const uint8_t * ) data , data_len ) == PHONGO_BSON_VECTOR_TYPE_INVALID ) {
46
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT , "Binary vector data is invalid" );
47
+ return false;
48
+ }
49
+
43
50
intern -> data = estrndup (data , data_len );
44
51
intern -> data_len = data_len ;
45
52
intern -> type = (uint8_t ) type ;
@@ -299,6 +306,7 @@ bool phongo_binary_new(zval* object, const char* data, size_t data_len, bson_sub
299
306
{
300
307
php_phongo_binary_t * intern ;
301
308
309
+ // TODO: Support BinaryVector
302
310
object_init_ex (object , php_phongo_binary_ce );
303
311
304
312
intern = Z_BINARY_OBJ_P (object );
@@ -308,3 +316,250 @@ bool phongo_binary_new(zval* object, const char* data, size_t data_len, bson_sub
308
316
309
317
return true;
310
318
}
319
+
320
+ /* MongoDB\BSON\BinaryVector implementation */
321
+
322
+ zend_class_entry * php_phongo_binaryvector_ce ;
323
+
324
+ static PHP_METHOD (MongoDB_BSON_BinaryVector , __construct )
325
+ {
326
+ php_phongo_binary_t * intern ;
327
+ zval * vector ;
328
+ zend_long vector_type ;
329
+
330
+ intern = Z_BINARY_OBJ_P (getThis ());
331
+
332
+ PHONGO_PARSE_PARAMETERS_START (2 , 2 )
333
+ Z_PARAM_ARRAY (vector )
334
+ Z_PARAM_LONG (vector_type )
335
+ PHONGO_PARSE_PARAMETERS_END ();
336
+
337
+ if (!zend_array_is_list (Z_ARRVAL_P (vector ))) {
338
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT , "Expected vector to be a list" );
339
+ return ;
340
+ }
341
+
342
+ const size_t vector_len = zend_array_count (Z_ARRVAL_P (vector ));
343
+
344
+ /*
345
+ bson_t doc = BSON_INITIALIZER;
346
+
347
+ php_phongo_zval_to_bson(vector, PHONGO_BSON_NONE, &doc, NULL);
348
+
349
+ if (EG(exception)) {
350
+ return;
351
+ }
352
+
353
+ bson_iter_t iter;
354
+ bson_error_t error;
355
+
356
+ bson_iter_init(&iter, &doc);
357
+
358
+ if (!BSON_APPEND_VECTOR_INT8_FROM_ARRAY(&bson, "vector", &iter, &err)) {
359
+ phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "%s", error.message);
360
+ return;
361
+ }
362
+ */
363
+
364
+ bson_t doc = BSON_INITIALIZER ;
365
+
366
+ if (vector_type == PHONGO_BSON_VECTOR_TYPE_INT8 ) {
367
+ bson_vector_int8_view_t view ;
368
+
369
+ if (!BSON_APPEND_VECTOR_INT8_UNINIT (& doc , "vector" , vector_len , & view )) {
370
+ phongo_throw_exception (PHONGO_ERROR_UNEXPECTED_VALUE , "BSON_APPEND_VECTOR_INT8_UNINIT failed for vector of size %zu" , vector_len );
371
+ RETURN_THROWS ();
372
+ }
373
+
374
+ zval * val ;
375
+ size_t i = 0 ;
376
+
377
+ ZEND_HASH_FOREACH_VAL_IND (Z_ARRVAL_P (vector ), val )
378
+ {
379
+ if (Z_TYPE_P (val ) != IS_LONG ) {
380
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT , "Expected vector[%zu] to be an integer, %s given" , i , zend_zval_type_name (val ));
381
+ RETURN_THROWS ();
382
+ }
383
+
384
+ if (Z_LVAL_P (val ) < INT8_MIN || Z_LVAL_P (val ) > INT8_MAX ) {
385
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT , "Expected vector[%zu] to be a signed 8-bit integer, %" PHONGO_LONG_FORMAT " given" , i , Z_LVAL_P (val ));
386
+ RETURN_THROWS ();
387
+ }
388
+
389
+ int8_t v = (int8_t ) Z_LVAL_P (val );
390
+
391
+ if (!bson_vector_int8_view_write (view , & v , 1 , i )) {
392
+ phongo_throw_exception (PHONGO_ERROR_UNEXPECTED_VALUE , "bson_vector_int8_view_write failed to write vector[%zu]" , i );
393
+ RETURN_THROWS ();
394
+ }
395
+
396
+ i += 1 ;
397
+ }
398
+ ZEND_HASH_FOREACH_END ();
399
+ } else {
400
+ // TODO: Support PHONGO_BSON_VECTOR_TYPE_FLOAT32 and PHONGO_BSON_VECTOR_TYPE_PACKED_BIT
401
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT , "Unsupported vector type: %" PHONGO_LONG_FORMAT , vector_type );
402
+ RETURN_THROWS ();
403
+ }
404
+
405
+ bson_iter_t iter ;
406
+
407
+ if (bson_iter_init_find (& iter , & doc , "vector" ) && BSON_ITER_HOLDS_BINARY (& iter )) {
408
+ uint32_t data_len ;
409
+ const uint8_t * data ;
410
+
411
+ bson_iter_binary (& iter , NULL , & data_len , & data );
412
+ php_phongo_binary_init (intern , (const char * ) data , data_len , BSON_SUBTYPE_VECTOR );
413
+ }
414
+ }
415
+
416
+ static phongo_bson_vector_type_t phongo_binary_get_vector_type_from_data (const uint8_t * data , uint32_t data_len )
417
+ {
418
+ if (bson_vector_int8_const_view_init (NULL , data , data_len )) {
419
+ return PHONGO_BSON_VECTOR_TYPE_INT8 ;
420
+ }
421
+
422
+ if (bson_vector_float32_const_view_init (NULL , data , data_len )) {
423
+ return PHONGO_BSON_VECTOR_TYPE_FLOAT32 ;
424
+ }
425
+
426
+ if (bson_vector_packed_bit_const_view_init (NULL , data , data_len )) {
427
+ return PHONGO_BSON_VECTOR_TYPE_PACKED_BIT ;
428
+ }
429
+
430
+ return PHONGO_BSON_VECTOR_TYPE_INVALID ;
431
+ }
432
+
433
+ static phongo_bson_vector_type_t phongo_binary_get_vector_type (const php_phongo_binary_t * intern )
434
+ {
435
+ return phongo_binary_get_vector_type_from_data ((const uint8_t * ) intern -> data , intern -> data_len );
436
+ }
437
+
438
+ static PHP_METHOD (MongoDB_BSON_BinaryVector , getVectorType )
439
+ {
440
+ PHONGO_PARSE_PARAMETERS_NONE ();
441
+
442
+ php_phongo_binary_t * intern = Z_BINARY_OBJ_P (getThis ());
443
+ phongo_bson_vector_type_t type = phongo_binary_get_vector_type (intern );
444
+
445
+ // The vector should always be valid by this point, but check for an error
446
+ if (type == PHONGO_BSON_VECTOR_TYPE_INVALID ) {
447
+ phongo_throw_exception (PHONGO_ERROR_UNEXPECTED_VALUE , "Binary vector data is invalid" );
448
+ RETURN_THROWS ();
449
+ }
450
+
451
+ RETURN_LONG (type );
452
+ }
453
+
454
+ static PHP_METHOD (MongoDB_BSON_BinaryVector , toArray )
455
+ {
456
+ PHONGO_PARSE_PARAMETERS_NONE ();
457
+
458
+ php_phongo_binary_t * intern = Z_BINARY_OBJ_P (getThis ());
459
+ phongo_bson_vector_type_t type = phongo_binary_get_vector_type (intern );
460
+
461
+ // The vector should always be valid by this point, but check for an error
462
+ if (type == PHONGO_BSON_VECTOR_TYPE_INVALID ) {
463
+ phongo_throw_exception (PHONGO_ERROR_UNEXPECTED_VALUE , "Binary vector data is invalid" );
464
+ RETURN_THROWS ();
465
+ }
466
+
467
+ bson_t doc = BSON_INITIALIZER ;
468
+
469
+ if (type == PHONGO_BSON_VECTOR_TYPE_INT8 ) {
470
+ bson_vector_int8_const_view_t view ;
471
+
472
+ if (!bson_vector_int8_const_view_init (& view , (const uint8_t * ) intern -> data , intern -> data_len ) ||
473
+ !BSON_APPEND_ARRAY_FROM_VECTOR_INT8 (& doc , "vector" , view )) {
474
+ phongo_throw_exception (PHONGO_ERROR_UNEXPECTED_VALUE , "Failed to convert binary vector data to an array" );
475
+ bson_destroy (& doc );
476
+ RETURN_THROWS ();
477
+ }
478
+ } else if (type == PHONGO_BSON_VECTOR_TYPE_FLOAT32 ) {
479
+ bson_vector_float32_const_view_t view ;
480
+
481
+ if (!bson_vector_float32_const_view_init (& view , (const uint8_t * ) intern -> data , intern -> data_len ) ||
482
+ !BSON_APPEND_ARRAY_FROM_VECTOR_FLOAT32 (& doc , "vector" , view )) {
483
+ phongo_throw_exception (PHONGO_ERROR_UNEXPECTED_VALUE , "Failed to convert binary vector data to an array" );
484
+ bson_destroy (& doc );
485
+ RETURN_THROWS ();
486
+ }
487
+ } else if (type == PHONGO_BSON_VECTOR_TYPE_PACKED_BIT ) {
488
+ bson_vector_packed_bit_const_view_t view ;
489
+
490
+ if (!bson_vector_packed_bit_const_view_init (& view , (const uint8_t * ) intern -> data , intern -> data_len ) ||
491
+ !BSON_APPEND_ARRAY_FROM_VECTOR_PACKED_BIT (& doc , "vector" , view )) {
492
+ phongo_throw_exception (PHONGO_ERROR_UNEXPECTED_VALUE , "Failed to convert binary vector data to an array" );
493
+ bson_destroy (& doc );
494
+ RETURN_THROWS ();
495
+ }
496
+ }
497
+
498
+ php_phongo_bson_state state ;
499
+ PHONGO_BSON_INIT_STATE (state );
500
+ state .is_visiting_array = true;
501
+
502
+ if (!php_phongo_bson_to_zval_ex (& doc , & state )) {
503
+ // Exception already thrown
504
+ bson_destroy (& doc );
505
+ zval_ptr_dtor (& state .zchild );
506
+ php_phongo_bson_typemap_dtor (& state .map );
507
+ RETURN_THROWS ();
508
+ }
509
+
510
+ bson_destroy (& doc );
511
+ php_phongo_bson_typemap_dtor (& state .map );
512
+
513
+ RETURN_ZVAL (& state .zchild , 0 , 1 );
514
+ }
515
+
516
+ static PHP_METHOD (MongoDB_BSON_BinaryVector , __set_state )
517
+ {
518
+ php_phongo_binary_t * intern ;
519
+ HashTable * props ;
520
+ zval * array ;
521
+
522
+ PHONGO_PARSE_PARAMETERS_START (1 , 1 )
523
+ Z_PARAM_ARRAY (array )
524
+ PHONGO_PARSE_PARAMETERS_END ();
525
+
526
+ /* This implementation is similar to Binary::__set_state(), except that we
527
+ * initialize a BinaryVector object and also validate its data. */
528
+ object_init_ex (return_value , php_phongo_binaryvector_ce );
529
+
530
+ intern = Z_BINARY_OBJ_P (return_value );
531
+ props = Z_ARRVAL_P (array );
532
+
533
+ php_phongo_binary_init_from_hash (intern , props );
534
+
535
+ if (intern -> type != BSON_SUBTYPE_VECTOR || phongo_binary_get_vector_type (intern ) == PHONGO_BSON_VECTOR_TYPE_INVALID ) {
536
+ phongo_throw_exception (PHONGO_ERROR_INVALID_ARGUMENT , "Binary vector data is invalid" );
537
+ RETURN_THROWS ();
538
+ }
539
+ }
540
+
541
+ /* MongoDB\BSON\BinaryVector object handlers */
542
+ static zend_object_handlers php_phongo_handler_binaryvector ;
543
+
544
+ static zend_object * php_phongo_binaryvector_create_object (zend_class_entry * class_type )
545
+ {
546
+ php_phongo_binary_t * intern = zend_object_alloc (sizeof (php_phongo_binary_t ), class_type );
547
+
548
+ zend_object_std_init (& intern -> std , class_type );
549
+ object_properties_init (& intern -> std , class_type );
550
+
551
+ intern -> std .handlers = & php_phongo_handler_binaryvector ;
552
+
553
+ return & intern -> std ;
554
+ }
555
+
556
+ void php_phongo_binaryvector_init_ce (INIT_FUNC_ARGS )
557
+ {
558
+ php_phongo_binaryvector_ce = register_class_MongoDB_BSON_BinaryVector (php_phongo_binary_ce );
559
+ php_phongo_binaryvector_ce -> create_object = php_phongo_binaryvector_create_object ;
560
+
561
+ memcpy (& php_phongo_handler_binaryvector , & php_phongo_handler_binary , sizeof (zend_object_handlers ));
562
+ // TODO: Override debug and prop handlers to include vector
563
+ //php_phongo_handler_binaryvector.get_debug_info = php_phongo_binaryvector_get_debug_info;
564
+ //php_phongo_handler_binaryvector.get_properties = php_phongo_binaryvector_get_properties;
565
+ }
0 commit comments