/* properly NULL an optional field. */ static void null_field (const ProtobufCMessage* message, const ProtobufCFieldDescriptor* field) { if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { protobuf_c_boolean* has = get_quantifier(message, field); *has = 0; } else if (field->label == PROTOBUF_C_LABEL_REPEATED) { size_t* quantifier = get_quantifier(message, field); *quantifier = 0; } if (field->type == PROTOBUF_C_TYPE_STRING) { const char** member = get_member(message, field); *member = NULL; } }
std::ostream& JSONXQType::serialize_ostream(std::ostream& os) const { os << "[JSONXQType " << theJSONKind << TypeOps::decode_quantifier(get_quantifier()); return os << "]"; }
/* Extract a single optional/required or multiple repeated sub messages from native php types into the given protobuf message. Allocates memory for the created messages */ int message_proto (const ProtobufCMessage* message, const ProtobufCFieldDescriptor* field, zval** val) { if (Z_TYPE_PP(val) != IS_ARRAY) return 1; const void* member = get_member(message, field); unsigned int* quantifier = get_quantifier(message, field); ProtobufCMessageDescriptor* descriptor = (ProtobufCMessageDescriptor*)field->descriptor; if (field->label == PROTOBUF_C_LABEL_REQUIRED) { ProtobufCMessage* base = emalloc(descriptor->sizeof_message); protobuf_c_message_init(descriptor, base); php_message(base, val[0]); memcpy((void*)member, (void*)&base, sizeof(void*)); } else if (field->label == PROTOBUF_C_LABEL_REPEATED) { HashPosition pos; HashTable* hash_table = Z_ARRVAL_PP(val); size_t* num_elements = emalloc(sizeof(size_t)); num_elements[0] = (size_t)zend_hash_num_elements(hash_table); zval** data; char* key; int i, key_len, curr = 0; long index; void** values = emalloc(sizeof(void*) * *num_elements); zend_hash_internal_pointer_reset_ex(hash_table, &pos); for (;; zend_hash_move_forward_ex(hash_table, &pos)) { zend_hash_get_current_data_ex(hash_table, (void**)&data, &pos); i = zend_hash_get_current_key_ex(hash_table, &key, &key_len, &index, 0, &pos); if (i == HASH_KEY_NON_EXISTANT) { break; } void* curr_value = emalloc(descriptor->sizeof_message); protobuf_c_message_init(descriptor, curr_value); php_message((ProtobufCMessage*)curr_value, data[0]); values[curr] = curr_value; curr++; } memcpy((void*)member, (void*)&values, sizeof(void*)); memcpy((void*)quantifier, (void*)num_elements, sizeof(void*)); } return 0; }
std::ostream& UserDefinedXQType::serialize_ostream(std::ostream& os) const { std::ostringstream info; switch (theUDTKind) { case ATOMIC_UDT: { info << "isAtomic"; break; } case COMPLEX_UDT: { info << "isComplex"; break; } case LIST_UDT: { info << " isList itemType:" << m_listItemType->toString(); break; } case UNION_UDT: { csize numMembers = m_unionItemTypes.size(); info << " Union (" ; if (numMembers > 0) { for (csize i = 0; i < numMembers-1; ++i) { info << m_unionItemTypes[i]->toString() << ", "; } info << m_unionItemTypes[numMembers-1]->toString(); } info << ")"; break; } default: ZORBA_ASSERT(false); } info << " " << contentKindStr(theContentKind); return os << "[UserDefinedXQType " << TypeOps::decode_quantifier(get_quantifier()) << " " << theQName->getLocalName() << "@" << theQName->getNamespace() << " " << info.str() << " base:" << ( theBaseType ? theBaseType->toString() : "NULL" ) << "]"; }
/* Extract uint32_t values from the given zval** and write them into the given protobuf message pointer. handle optional/required/repeated */ int uint32_proto (const ProtobufCMessage* message, const ProtobufCFieldDescriptor* field, zval** val) { uint32_t* member = (uint32_t*)get_member(message, field); unsigned int* quantifier = get_quantifier(message, field); if (field->label == PROTOBUF_C_LABEL_REQUIRED || field->label == PROTOBUF_C_LABEL_OPTIONAL) { if (Z_TYPE_PP(val) == IS_LONG) *member = (uint32_t)Z_LVAL_PP(val); else if (Z_TYPE_PP(val) == IS_DOUBLE) *member = (uint32_t)Z_DVAL_PP(val); else return 1; if (field->label == PROTOBUF_C_LABEL_OPTIONAL) *quantifier = 1; } else if (field->label == PROTOBUF_C_LABEL_REPEATED) { if (Z_TYPE_PP(val) != IS_ARRAY) return 1; HashPosition pos; HashTable* hash_table = Z_ARRVAL_PP(val); size_t num_elements = (size_t)zend_hash_num_elements(hash_table); zval** data; char* key; int i, key_len, curr = 0; long index; uint32_t* values = emalloc(sizeof(uint32_t) * num_elements); zend_hash_internal_pointer_reset_ex(hash_table, &pos); for (;; zend_hash_move_forward_ex(hash_table, &pos)) { zend_hash_get_current_data_ex(hash_table, (void**)&data, &pos); i = zend_hash_get_current_key_ex(hash_table, &key, &key_len, &index, 0, &pos); if (i == HASH_KEY_NON_EXISTANT) break; if (Z_TYPE_PP(data) == IS_LONG) values[curr++] = (uint32_t)(Z_LVAL_PP(data)); else if (Z_TYPE_PP(data) == IS_DOUBLE) values[curr++] = (uint32_t)(Z_DVAL_PP(data)); } *quantifier = num_elements; memcpy((void*)member, (void*)&values, sizeof(void*)); } return 0; }
/******************************************************************************* Return 0 if all instances of the type consist of exactly 0 items, 1 if all instances of the type consist of exactly 1 item, or -1 otherwise. ********************************************************************************/ int XQType::card() const { if (is_empty() || is_none()) return 0; SequenceType::Quantifier q = get_quantifier(); if (RootTypeManager::QUANT_MIN_CNT[q] == RootTypeManager::QUANT_MAX_CNT[q]) return RootTypeManager::QUANT_MIN_CNT[q]; return -1; }
/******************************************************************************* Returns true if the quantifier of the given sequence type is QUANT_ONE and its ItemType is an atomic type. ********************************************************************************/ bool XQType::isAtomicOne() const { if (get_quantifier() == SequenceType::QUANT_ONE) { if (type_kind() == XQType::ATOMIC_TYPE_KIND) { return true; } else if (type_kind() == XQType::USER_DEFINED_KIND) { return static_cast<const UserDefinedXQType*>(this)->theUDTKind == ATOMIC_UDT; } } return false; }
std::ostream& NodeXQType::serialize_ostream(std::ostream& os) const { store::StoreConsts::NodeKind node_kind = theNodeKind; xqtref_t content_type = get_content_type(); os << "[NodeXQType " << store::StoreConsts::toString(node_kind) << TypeOps::decode_quantifier(get_quantifier()); if (theNodeName != NULL) { os << " nametest=[uri: " << theNodeName->getNamespace() << ", local: " << theNodeName->getLocalName() << "]"; } if (content_type != NULL) { os << " content="; os << content_type->toString(); } return os << "]"; }
std::ostream& FunctionXQType::serialize_ostream(std::ostream& os) const { os << "[FunctionXQType " << TypeOps::decode_quantifier(get_quantifier()) << " "; if (m_param_types.size() != 0) { os << "params=["; size_t i = 1; for (std::vector<xqtref_t>::const_iterator lIter = m_param_types.begin(); lIter != m_param_types.end(); ++i, ++lIter) { os << (*lIter)->toString(); if (i < m_param_types.size()) os << ", "; } os << "] "; } os << "return=["; os << m_return_type->toString(); os << "]"; return os << "]"; }
/* Iterate over the given protobuf message pointer and transform values into native php types. writes an associative array into the given zval**. */ void message_php (zval* return_value, const ProtobufCMessage *message) { unsigned int i, j; for (i=0;i<message->descriptor->n_fields;i++) { const ProtobufCFieldDescriptor *field = message->descriptor->fields + i; const void* member = get_member(message, field); size_t* num_fields = get_quantifier(message, field); const ProtobufCMessage** sub_messages; const ProtobufCMessage* sub_message; zval *inner, *inner_repeated; switch (field->type) { case PROTOBUF_C_TYPE_INT32: if (field->label == PROTOBUF_C_LABEL_OPTIONAL && (protobuf_c_boolean)*num_fields) { int32_php_single(return_value, (char*)field->name, (const int32_t*)member); } else if (field->label == PROTOBUF_C_LABEL_REQUIRED) { int32_php_single(return_value, (char*)field->name, (const int32_t*)member); } else if (field->label == PROTOBUF_C_LABEL_REPEATED && *num_fields) { int32_php_repeated(return_value, (char*)field->name, (const int32_t**)member, *num_fields); } break; case PROTOBUF_C_TYPE_UINT32: if (field->label == PROTOBUF_C_LABEL_OPTIONAL && (protobuf_c_boolean)*num_fields) { uint32_php_single(return_value, (char*)field->name, (const uint32_t*)member); } else if (field->label == PROTOBUF_C_LABEL_REQUIRED) { uint32_php_single(return_value, (char*)field->name, (const uint32_t*)member); } else if (field->label == PROTOBUF_C_LABEL_REPEATED && *num_fields) { uint32_php_repeated(return_value, (char*)field->name, (const uint32_t**)member, *num_fields); } break; case PROTOBUF_C_TYPE_STRING: if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { char** pos = (char**)member; if (*pos != NULL) { string_php_single(return_value, (char*)field->name, (char* const*)member); } } else if (field->label == PROTOBUF_C_LABEL_REQUIRED) { string_php_single(return_value, (char*)field->name, (char* const*)member); } else if (field->label == PROTOBUF_C_LABEL_REPEATED && *num_fields) { string_php_repeated(return_value, (char*)field->name, (char** const*)member, *num_fields); } break; case PROTOBUF_C_TYPE_BOOL: bool_php(return_value, field->name, *(const protobuf_c_boolean *)member); break; case PROTOBUF_C_TYPE_MESSAGE: // optional or repeated field with no entries shouldn't make it to PHP if (field->label == PROTOBUF_C_LABEL_OPTIONAL || field->label == PROTOBUF_C_LABEL_REPEATED) { if (*((const ProtobufCMessage**)member) == NULL) { break; } } MAKE_STD_ZVAL(inner); array_init(inner); if (field->label == PROTOBUF_C_LABEL_OPTIONAL || field->label == PROTOBUF_C_LABEL_REQUIRED) { message_php(inner, *((const ProtobufCMessage**)member)); } else if (field->label == PROTOBUF_C_LABEL_REPEATED) { sub_messages = (const ProtobufCMessage**)*((const ProtobufCMessage**)member); for (j=0;j<*num_fields;++j) { MAKE_STD_ZVAL(inner_repeated); array_init(inner_repeated); message_php(inner_repeated, sub_messages[j]); add_next_index_zval(inner, inner_repeated); } } add_assoc_zval(return_value, (char*)field->name, inner); break; case PROTOBUF_C_TYPE_DOUBLE: // double_php(return_value, field->name, *(const uint64_t *)member); case PROTOBUF_C_TYPE_FLOAT: // float_php(return_value, field->name, *(const uint32_t *)member); case PROTOBUF_C_TYPE_SINT32: // sint32_php(return_value, field->name, *(const int32_t *)member); case PROTOBUF_C_TYPE_FIXED32: // fixed32_php(return_value, field->name, *(const uint32_t *)member); case PROTOBUF_C_TYPE_SFIXED32: // sfixed32_php(return_value, field->name, *(const uint32_t *)member); case PROTOBUF_C_TYPE_INT64: // int64_php(return_value, field->name, *(const uint64_t *)member); case PROTOBUF_C_TYPE_SINT64: // sint64_php(return_value, field->name, *(const int64_t *)member); case PROTOBUF_C_TYPE_UINT64: // uint64_php(return_value, field->name, *(const uint64_t *)member); case PROTOBUF_C_TYPE_FIXED64: // fixed64_php(return_value, field->name, *(const uint64_t *)member); case PROTOBUF_C_TYPE_SFIXED64: // sfixed64_php(return_value, field->name, *(const uint64_t *)member); // XXX unimplemented XXX case PROTOBUF_C_TYPE_ENUM: case PROTOBUF_C_TYPE_BYTES: default: break; } } }
std::ostream& AtomicXQType::serialize_ostream(std::ostream& os) const { return os << ATOMIC_TYPE_CODE_STRINGS[get_type_code()] << TypeOps::decode_quantifier(get_quantifier()); }
/******************************************************************************* Attempt to output the type as a string closer to the xs: representation ********************************************************************************/ std::string XQType::toSchemaString() const { std::string result; switch (type_kind()) { case NONE_KIND: { result = "none"; break; } case EMPTY_KIND: { result = "empty-sequence()"; break; } case ATOMIC_TYPE_KIND: { result = toString(); break; } case ITEM_KIND: { result = "item()"; result += TypeOps::decode_quantifier(get_quantifier()); break; } case STRUCTURED_ITEM_KIND: { result = "structured-item()"; result += TypeOps::decode_quantifier(get_quantifier()); break; } case JSON_TYPE_KIND: { const JSONXQType* type = static_cast<const JSONXQType*>(this); store::StoreConsts::JSONItemKind kind = type->get_json_kind(); if (kind == store::StoreConsts::jsonItem) { result = "json-item()"; } else if (kind == store::StoreConsts::jsonObject) { result = "object()"; } else if (kind == store::StoreConsts::jsonArray) { result = "array()"; } result += TypeOps::decode_quantifier(get_quantifier()); break; } case NODE_TYPE_KIND: { result = static_cast<const NodeXQType*>(this)->toSchemaStringInternal(); result += TypeOps::decode_quantifier(get_quantifier()); break; } case FUNCTION_TYPE_KIND: { result = toString(); result += TypeOps::decode_quantifier(get_quantifier()); break; } case ANY_FUNCTION_TYPE_KIND: { result = "function(*)"; result += TypeOps::decode_quantifier(get_quantifier()); break; } case ANY_TYPE_KIND: { result = "xs:anyType"; break; } case ANY_SIMPLE_TYPE_KIND: { result = "xs:anySimpleType"; break; } case UNTYPED_KIND: { result = "xs:untyped"; break; } default: { result = toString(); result += TypeOps::decode_quantifier(get_quantifier()); break; } } return result; }
std::ostream& XQType::serialize_ostream(std::ostream& os) const { return os << "[XQType " << KIND_STRINGS[type_kind()] << TypeOps::decode_quantifier(get_quantifier()) << "]"; }
/******************************************************************************* Returns true if the quantifier of the given sequence type is QUANT_ONE and its ItemType is a builtin atomic type. ********************************************************************************/ bool XQType::isBuiltinAtomicOne() const { return get_quantifier() == SequenceType::QUANT_ONE && type_kind() == XQType::ATOMIC_TYPE_KIND; }
/******************************************************************************* Return the minimum number of items that can appear in an instance of the type. Returned value may be 0 or 1. ********************************************************************************/ int XQType::min_card() const { return (is_empty() ? 0 : RootTypeManager::QUANT_MIN_CNT[get_quantifier()]); }