Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Support for NULL-able unions

  • Loading branch information...
commit c4c164b2d6c09d93e5148cc057ca72106ded18df 1 parent b5d9721
John Jawed (JJ) authored

Showing 1 changed file with 103 additions and 64 deletions. Show diff stats Hide diff stats

  1. +103 64 xcom.c
167 xcom.c
@@ -293,7 +293,7 @@ int php_xcom_obj_from_avro_msg(zval **obj, char *msg, char *json_schema TSRMLS_D
293 293 double av_d;
294 294 float av_f;
295 295
296   - avro_reader_t reader = avro_reader_memory(msg, strlen(msg));
  296 + avro_reader_t reader = avro_reader_memory(msg, 100);
297 297
298 298 avro_schema_from_json(json_schema, strlen(json_schema), &schema, &error);
299 299
@@ -309,15 +309,16 @@ int php_xcom_obj_from_avro_msg(zval **obj, char *msg, char *json_schema TSRMLS_D
309 309
310 310 avro_generic_value_new(iface, &val);
311 311
312   - avro_value_read(reader, &val);
313   -
314 312 avro_value_get_size(&val, &sz);
315 313
  314 + avro_value_read(reader, &val);
  315 +
316 316 for(i=0; i<sz; ++i) {
317   - avro_value_t field_val;
  317 + avro_value_t field_val, branch;
318 318 char *field_name;
319 319 avro_value_get_by_index(&val, i, &field_val, (const char **)&field_name);
320 320
  321 + php_avro_read_type:
321 322 switch(avro_value_get_type(&field_val)) {
322 323 case AVRO_STRING:
323 324 if(!avro_value_get_string(&field_val, (const char **)&av_s, &vsz)) {
@@ -352,6 +353,12 @@ int php_xcom_obj_from_avro_msg(zval **obj, char *msg, char *json_schema TSRMLS_D
352 353 zend_update_property_double(zend_standard_class_def, *obj, field_name, strlen(field_name), av_d TSRMLS_CC);
353 354 }
354 355 break;
  356 + case AVRO_UNION:
  357 + avro_value_get_current_branch(&field_val, &branch);
  358 + avro_value_get_type(&branch);
  359 + field_val = branch;
  360 + goto php_avro_read_type;
  361 + break;
355 362 default:
356 363 break;
357 364 }
@@ -420,6 +427,7 @@ static void* php_xcom_send_msg_common(INTERNAL_FUNCTION_PARAMETERS, int async) {
420 427 }
421 428
422 429 snprintf(schema_ver_hdr, sizeof(schema_ver_hdr), "X-XC-SCHEMA-VERSION: %s", "1.0.0");
  430 + /* FIX ME */
423 431
424 432 req->curl_headers = curl_slist_append(req->curl_headers, "Expect:");
425 433 req->curl_headers = curl_slist_append(req->curl_headers, auth_hdr);
@@ -520,7 +528,7 @@ static void* php_xcom_send_msg_common(INTERNAL_FUNCTION_PARAMETERS, int async) {
520 528 static char* php_xcom_avro_record_from_obj(zval *obj, char *json_schema TSRMLS_DC) /* {{{ */
521 529 {
522 530 int i;
523   - HashTable *myht;
  531 + HashTable *ht;
524 532 char *msg_buf = NULL;
525 533 avro_writer_t writer = NULL;
526 534 avro_value_t val;
@@ -540,77 +548,108 @@ static char* php_xcom_avro_record_from_obj(zval *obj, char *json_schema TSRMLS_D
540 548
541 549 avro_generic_value_new(iface, &val);
542 550
543   - myht = Z_TYPE_P(obj)==IS_OBJECT ? Z_OBJPROP_P(obj) : HASH_OF(obj);
  551 + ht = Z_TYPE_P(obj)==IS_OBJECT ? Z_OBJPROP_P(obj) : HASH_OF(obj);
544 552
545   - if (myht && myht->nApplyCount > 1) {
  553 + if (ht && ht->nApplyCount > 1) {
546 554 php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
547 555 return NULL;
548 556 }
549 557
550   - i = myht ? zend_hash_num_elements(myht) : 0;
551   -
552   - if (i > 0)
553   - {
554   - char *key;
555   - zval **data;
556   - ulong index;
557   - uint key_len;
558   - HashPosition pos;
559   - HashTable *tmp_ht = NULL;
560   - avro_value_t field;
561   - avro_wrapped_buffer_t wbuf;
562   -
563   - zend_hash_internal_pointer_reset_ex(myht, &pos);
564   - for (;; zend_hash_move_forward_ex(myht, &pos)) {
565   - i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
566   - if (i == HASH_KEY_NON_EXISTANT)
567   - break;
  558 + zval **data;
  559 + avro_value_t field, branch;
  560 + avro_wrapped_buffer_t wbuf;
  561 + const char *f;
  562 + size_t record_size = 0;
  563 + int field_type, was_found = 0, branch_to_use;
568 564
569   - if (zend_hash_get_current_data_ex(myht, (void *)&data, &pos) == SUCCESS) {
570   - tmp_ht = HASH_OF(*data);
571   - if (tmp_ht) {
572   - tmp_ht->nApplyCount++;
573   - }
  565 + avro_value_get_size(&val, &record_size);
574 566
575   - avro_value_get_by_name(&val, key, &field, NULL);
576   -
577   - switch (Z_TYPE_PP(data))
578   - {
579   - case IS_NULL:
580   - avro_value_set_null(&field);
581   - writer_bytes += 64;
582   - break;
583   - case IS_BOOL:
584   - avro_value_set_boolean(&field, Z_BVAL_PP(data));
585   - writer_bytes += 64;
586   - break;
587   - case IS_LONG:
588   - avro_value_set_long(&field, Z_LVAL_PP(data));
589   - writer_bytes += 64;
590   - break;
591   - case IS_DOUBLE:
592   - avro_value_set_double(&field, Z_DVAL_PP(data));
593   - writer_bytes += 64;
594   - break;
595   - case IS_STRING:
596   - avro_wrapped_buffer_new_string(&wbuf, Z_STRVAL_PP(data));
597   - avro_value_give_string_len(&field, &wbuf);
598   - writer_bytes += Z_STRLEN_PP(data);
599   - break;
600   - case IS_ARRAY:
601   - case IS_OBJECT:
602   - /* support complex types later */
603   - break;
604   - default:
605   - break;
606   - }
  567 + for(i=0; i<record_size; ++i) {
  568 + branch_to_use = -1;
  569 + avro_value_get_by_index(&val, i, &field, &f);
  570 +
  571 + if(f==NULL) {
  572 + break;
  573 + }
  574 +
  575 + field_type = avro_value_get_type(&field);
  576 +
  577 + was_found = zend_hash_find(ht, f, strlen(f) + 1, (void *)&data);
  578 +
  579 + if(SUCCESS!=was_found) {
  580 + if(AVRO_UNION!=field_type) {
  581 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "missing data member: '%s' is in the schema but was not set!", f);
  582 + continue;
607 583 }
  584 + }
608 585
609   - if (tmp_ht) {
610   - tmp_ht->nApplyCount--;
  586 + if(AVRO_UNION==field_type) {
  587 + if(was_found==SUCCESS) {
  588 + /* member was found, select the first branch
  589 + (only two branches null-able unions are supported */
  590 + branch_to_use = 1;
  591 + } else {
  592 + /* member wasn't found, according to the avro spec the
  593 + "default" value is the first branch, so let's set that */
  594 + branch_to_use = 0;
611 595 }
  596 + avro_value_set_branch(&field, branch_to_use, &branch);
  597 + field = branch;
  598 + field_type = avro_value_get_type(&branch);
  599 + }
  600 +
  601 + switch(field_type) {
  602 + case AVRO_STRING:
  603 + case AVRO_BYTES:
  604 + convert_to_string_ex(data);
  605 + if(field_type==AVRO_BYTES) {
  606 + avro_value_set_bytes(&field, Z_STRVAL_PP(data), Z_STRLEN_PP(data));
  607 + } else {
  608 + avro_wrapped_buffer_new_string(&wbuf, Z_STRVAL_PP(data));
  609 + avro_value_give_string_len(&field, &wbuf);
  610 + }
  611 + writer_bytes += Z_STRLEN_PP(data);
  612 + break;
  613 + case AVRO_INT32:
  614 + convert_to_long_ex(data);
  615 + avro_value_set_int(&field, Z_LVAL_PP(data));
  616 + writer_bytes += 64;
  617 + break;
  618 + case AVRO_INT64:
  619 + convert_to_long_ex(data);
  620 + avro_value_set_long(&field, Z_LVAL_PP(data));
  621 + writer_bytes += 64;
  622 + break;
  623 + case AVRO_FLOAT:
  624 + convert_to_double_ex(data);
  625 + avro_value_set_float(&field, Z_DVAL_PP(data));
  626 + writer_bytes += 64;
  627 + break;
  628 + case AVRO_DOUBLE:
  629 + convert_to_double_ex(data);
  630 + avro_value_set_double(&field, Z_DVAL_PP(data));
  631 + writer_bytes += 64;
  632 + break;
  633 + case AVRO_BOOLEAN:
  634 + convert_to_boolean_ex(data);
  635 + avro_value_set_boolean(&field, Z_BVAL_PP(data));
  636 + writer_bytes += 64;
  637 + break;
  638 + case AVRO_NULL:
  639 + avro_value_set_null(&field);
  640 + writer_bytes += 64;
  641 + break;
  642 + }
  643 +
  644 + /* deal with a bug in libavro where the branch is not
  645 + finalized until the ref count on the writer is 0 or
  646 + branches are switched */
  647 + if(branch_to_use >= 0) {
  648 + avro_value_set_branch(&field, !branch_to_use, &branch);
  649 + avro_value_set_branch(&field, branch_to_use, &branch);
612 650 }
613 651 }
  652 +
614 653 writer_bytes = writer_bytes * 2;
615 654
616 655 msg_buf = emalloc(writer_bytes);

0 comments on commit c4c164b

Please sign in to comment.
Something went wrong with that request. Please try again.