-
Botond Baranyi authored
XML enc/dec: global namespace variants no longer overwrite inherited namespace variants (issue #545) Signed-off-by:
Botond Baranyi <botond.baranyi@ericsson.com>
Botond Baranyi authoredXML enc/dec: global namespace variants no longer overwrite inherited namespace variants (issue #545) Signed-off-by:
Botond Baranyi <botond.baranyi@ericsson.com>
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
XerAttributes.cc 13.14 KiB
/******************************************************************************
* Copyright (c) 2000-2021 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
*
* Contributors:
* Balasko, Jeno
* Baranyi, Botond
* Raduly, Csaba
* Szabados, Kristof
* Szabo, Bence Janos
*
******************************************************************************/
/*
* XerAttributes.cpp
*
* Created on: Oct 17, 2008
* Author: ecsardu
*/
#include "XerAttributes.hh"
// The above line must be the first in this file
#include "../common/memory.h"
#include "Value.hh"
static const NamespaceRestriction empty_nsr = {
0, 0, NamespaceRestriction::UNUSED
};
static const XerAttributes::NameChange nochange= { NamespaceSpecification::NO_MANGLING };
XerAttributes::XerAttributes()
: abstract_(false)
, attribute_(false)
, anyAttributes_(empty_nsr)
, anyElement_(empty_nsr)
, base64_(false)
, block_(false)
, decimal_(false)
, defaultForEmpty_(0)
, defaultForEmptyIsRef_(false)
, defaultForEmptyRef_(0)
, defaultValue_(0)
, element_(false)
, embedValues_(false)
, form_(UNSET)
, has_fractionDigits_(false)
, fractionDigits_(0)
, hex_(false)
, list_(false)
, name_(nochange)
, namespace_()
//, pi_or_comment_()
, num_text_(0)
, text_(0)
, untagged_(false)
, useNil_(false)
, useNumber_(false)
, useOrder_(false)
, useQName_(false)
, useType_(false)
, useUnion_(false)
, whitespace_(PRESERVE)
, xsd_type(XSD_NONE)
{
//__asm("int3");
//fprintf(stderr, "XER attributes(%p) new\n", (void*)this);
namespace_.global_variant = false;
}
void FreeNamespaceRestriction(NamespaceRestriction& nsr)
{
for (size_t i=0; i < nsr.nElements_; ++i) {
Free(nsr.uris_[i]);
}
Free(nsr.uris_);
}
XerAttributes::~XerAttributes()
{
FreeNamespaceRestriction(anyAttributes_);
FreeNamespaceRestriction(anyElement_);
Free(defaultForEmpty_);
delete defaultValue_;
delete defaultForEmptyRef_;
FreeNameChange(name_);
FreeNamespace(namespace_);
//if (pi_or_comment_.position_ > AFTER_VALUE) {
// Free(pi_or_comment_.value_);
//}
for (size_t i=0; i < num_text_; ++i) {
if ((unsigned long)text_[i].keyword
> (unsigned long)NamespaceSpecification::LOWERCASED) {
Free(text_[i].uri);
}
if (text_[i].prefix > (char*)NamespaceSpecification::ALL) {
Free(text_[i].prefix);
}
}
Free(text_);
}
void XerAttributes::FreeNamespace(NamespaceSpecification &ns) {
switch (ns.keyword) {
case NamespaceSpecification::NO_MANGLING:
case NamespaceSpecification::CAPITALIZED:
case NamespaceSpecification::UNCAPITALIZED:
case NamespaceSpecification::UPPERCASED:
case NamespaceSpecification::LOWERCASED:
break; // nothing to do
default: // real string, must be freed
Free(ns.uri);
break;
}
ns.uri = 0;
Free(ns.prefix);
ns.prefix = 0;
ns.global_variant = false;
}
void XerAttributes::FreeNameChange(XerAttributes::NameChange& n) {
switch (n.kw_) {
case NamespaceSpecification::NO_MANGLING:
case NamespaceSpecification::CAPITALIZED:
case NamespaceSpecification::UNCAPITALIZED:
case NamespaceSpecification::UPPERCASED:
case NamespaceSpecification::LOWERCASED:
break; // nothing to do
default: // real string, must be freed
Free(n.nn_);
break;
}
n.kw_ = NamespaceSpecification::NO_MANGLING;
}
void XerAttributes::print(const char *type_name) const {
fprintf(stderr, "XER attributes(%p) for %s:\n", (const void*)this, type_name);
if (empty()) fputs("...Empty...\n", stderr);
else {
fputs(abstract_ ? "ABSTRACT\n" : "", stderr);
fputs(attribute_ ? "ATTRIBUTE\n" : "", stderr);
if (has_aa(this)) {
if (anyAttributes_.type_ == NamespaceRestriction::NOTHING) {
fputs("ANY-ATTRIBUTES\n", stderr);
}
else for (size_t i = 0; i < anyAttributes_.nElements_; ++i) {
fprintf(stderr, "ANY-ATTRIBUTES %s %s\n",
anyAttributes_.type_ == NamespaceRestriction::FROM ? "EXCEPT" : "FROM",
(anyAttributes_.uris_[i] && *anyAttributes_.uris_[i]) ?
anyAttributes_.uris_[i] : "ABSENT");
}
}
if (has_ae(this)) {
if (anyElement_.type_ == NamespaceRestriction::NOTHING) {
fputs("ANY-ELEMENT\n", stderr);
}
else for (size_t i = 0; i < anyElement_.nElements_; ++i) {
fprintf(stderr, "ANY-ELEMENT %s %s\n",
anyElement_.type_ == NamespaceRestriction::FROM ? "EXCEPT" : "FROM",
(anyElement_.uris_[i] && *anyElement_.uris_[i]) ?
anyElement_.uris_[i] : "ABSENT");
}
}
fputs(base64_ ? "BASE64\n" : "", stderr);
fputs(block_ ? "BLOCK\n" : "", stderr);
fputs(decimal_ ? "DECIMAL\n" : "", stderr);
if (defaultForEmpty_)
fprintf(stderr, "DEFAULT-FOR-EMPTY '%s' %s\n",
defaultForEmptyIsRef_ ? defaultForEmptyRef_->get_dispname().c_str() : defaultForEmpty_,
defaultForEmptyIsRef_ ? "(reference) " : "");
if (element_) fputs("ELEMENT\n", stderr);
fputs(embedValues_ ? "EMBED-VALUES\n" : "", stderr);
fputs((form_ & QUALIFIED) ? "FORM AS QUALIFIED\n" : "", stderr);
if (has_fractionDigits_) fprintf(stderr, "FRACTIONDIGITS '%i'\n", fractionDigits_);
fputs(hex_ ? "hexBinary" : "", stderr);
fputs(list_ ? "LIST\n" : "", stderr);
static const char * xforms[] = {
"CAPITALIZED", "UNCAPITALIZED", "UPPERCASED", "LOWERCASED"
};
switch (name_.kw_) {
case NamespaceSpecification::NO_MANGLING: // nothing to do
break;
default: // a string
fprintf(stderr, "NAME AS '%s'\n", name_.nn_);
break;
case NamespaceSpecification::CAPITALIZED:
case NamespaceSpecification::UNCAPITALIZED:
case NamespaceSpecification::LOWERCASED:
case NamespaceSpecification::UPPERCASED:
fprintf(stderr, "NAME AS %s\n",
xforms[name_.kw_ - NamespaceSpecification::CAPITALIZED]);
break;
}
if (namespace_.uri) {
fprintf(stderr, "NAMESPACE '%s' %s %s\n", namespace_.uri,
(namespace_.prefix ? "PREFIX" : ""),
(namespace_.prefix ? namespace_.prefix : ""));
}
//if (pi_or_comment_.position_ != NOWHERE) {
// fputs("PI-OR-COMMENT\n", stderr);
//}
if (num_text_) {
fputs("TEXT\n", stderr);
for (size_t t=0; t < num_text_; ++t) {
const char* who = 0, *action = 0;
switch ((unsigned long)(text_[t].uri) ) {
case NamespaceSpecification::LOWERCASED:
action = "LOWERCASED"; break;
case NamespaceSpecification::UPPERCASED:
action = "UPPERCASED"; break;
case NamespaceSpecification::CAPITALIZED:
action = "CAPITALIZED"; break;
case NamespaceSpecification::UNCAPITALIZED:
action = "UNCAPITALIZED"; break;
case 0:
action = "text"; break;
default:
action = text_[t].uri; break;
}
switch ((unsigned long)text_[t].prefix) {
case 0: who = ""; break;
case NamespaceSpecification::ALL: who = "ALL"; break;
default: who = text_[t].prefix; break;
}
fprintf(stderr, " %s as %s\n", who, action);
}
}
fputs(untagged_ ? "UNTAGGED\n" : "", stderr);
fputs(useNil_ ? "USE-NIL\n" : "", stderr);
fputs(useNumber_ ? "USE-NUMBER\n" : "", stderr);
fputs(useOrder_ ? "USE-ORDER\n" : "", stderr);
fputs(useQName_ ? "USE-QNAME\n" : "", stderr);
fputs(useType_ ? "USE-TYPE\n" : "", stderr);
fputs(useUnion_ ? "USE-UNION\n" : "", stderr);
if (whitespace_ != PRESERVE) fprintf(stderr, "WHITESPACE %s\n",
whitespace_ == COLLAPSE ? "COLLAPSE" : "REPLACE");
fputs(". . . . .\n", stderr);
}
}
XerAttributes& XerAttributes::operator |= (const XerAttributes& other)
{
if (other.empty()) FATAL_ERROR("XerAttributes::operator |=");
/*
fprintf(stderr, "@@@ replacing:\n");
print("orig.");
other.print("other");
*/
abstract_ |= other.abstract_;
attribute_ |= other.attribute_;
if (has_aa(&other)) {
FreeNamespaceRestriction(anyAttributes_);
anyAttributes_.nElements_ = other.anyAttributes_.nElements_;
anyAttributes_.type_ = other.anyAttributes_.type_;
anyAttributes_.uris_ = (char**)Malloc(anyAttributes_.nElements_
* sizeof(char*));
for (size_t i=0; i < anyAttributes_.nElements_; ++i) {
anyAttributes_.uris_[i] = mcopystr(other.anyAttributes_.uris_[i]);
}
}
if (has_ae(&other)) {
FreeNamespaceRestriction(anyElement_);
anyElement_.nElements_ = other.anyElement_.nElements_;
anyElement_.type_ = other.anyElement_.type_;
anyElement_.uris_ = (char**)Malloc(anyElement_.nElements_
* sizeof(char*));
for (size_t i=0; i < anyElement_.nElements_; ++i) {
anyElement_.uris_[i] = mcopystr(other.anyElement_.uris_[i]);
}
}
base64_ |= other.base64_;
block_ |= other.block_;
decimal_ |= other.decimal_;
if (other.defaultForEmpty_ != 0) {
Free(defaultForEmpty_);
defaultForEmpty_ = mcopystr(other.defaultForEmpty_);
defaultForEmptyIsRef_ = other.defaultForEmptyIsRef_;
}
defaultForEmptyIsRef_ |= other.defaultForEmptyIsRef_;
if (other.defaultForEmptyRef_ != 0) {
Free(defaultForEmptyRef_);
defaultForEmptyRef_ = other.defaultForEmptyRef_->clone();
}
element_ |= other.element_;
embedValues_ |= other.embedValues_;
form_ = other.form_;
if (other.has_fractionDigits_) {
has_fractionDigits_ = other.has_fractionDigits_;
fractionDigits_ = other.fractionDigits_;
}
hex_ |= other.hex_;
list_ |= other.list_;
if (other.name_.kw_ != NamespaceSpecification::NO_MANGLING) {
FreeNameChange(name_);
switch (other.name_.kw_) {
case NamespaceSpecification::NO_MANGLING:
break; // not possible inside the if
case NamespaceSpecification::CAPITALIZED:
case NamespaceSpecification::UNCAPITALIZED:
case NamespaceSpecification::UPPERCASED:
case NamespaceSpecification::LOWERCASED:
name_.kw_ = other.name_.kw_;
break;
default: // a real string
name_.nn_ = mcopystr(other.name_.nn_);
break;
}
}
if (other.namespace_.uri != 0 &&
// global namespace variants should no longer overwrite inherited namespace variants (issue #545)
(namespace_.uri == 0 || !other.namespace_.global_variant)) {
switch (namespace_.keyword) {
case NamespaceSpecification::NO_MANGLING:
case NamespaceSpecification::CAPITALIZED:
case NamespaceSpecification::UNCAPITALIZED:
case NamespaceSpecification::UPPERCASED:
case NamespaceSpecification::LOWERCASED:
break; // nothing to do
default: // real string, must be freed
Free(namespace_.uri);
break;
}
switch (other.namespace_.keyword) {
case NamespaceSpecification::NO_MANGLING:
case NamespaceSpecification::CAPITALIZED:
case NamespaceSpecification::UNCAPITALIZED:
case NamespaceSpecification::UPPERCASED:
case NamespaceSpecification::LOWERCASED:
namespace_.uri = other.namespace_.uri;
break;
default: // real string
namespace_.uri = mcopystr(other.namespace_.uri);
break;
}
Free(namespace_.prefix);
namespace_.prefix = mcopystr(other.namespace_.prefix);
}
//pi_or_comment_;
if (other.num_text_) {
// Append the other TEXT. No attempt is made to eliminate duplicates.
// This will be done in Type::chk_xer_text().
size_t old_num = num_text_;
num_text_ += other.num_text_;
text_ = (NamespaceSpecification *)Realloc(
text_, num_text_ * sizeof(NamespaceSpecification));
for (size_t t = 0; t < other.num_text_; ++t) {
switch ((unsigned long)(other.text_[t].uri) ) {
case NamespaceSpecification::LOWERCASED:
case NamespaceSpecification::UPPERCASED:
case NamespaceSpecification::CAPITALIZED:
case NamespaceSpecification::UNCAPITALIZED:
case NamespaceSpecification::NO_MANGLING:
text_[old_num + t].uri = other.text_[t].uri;
break;
default:
text_[old_num + t].uri = mcopystr(other.text_[t].uri);
break;
}
switch ((unsigned long)other.text_[t].prefix) {
case 0: case NamespaceSpecification::ALL:
text_[old_num + t].prefix = other.text_[t].prefix;
break;
default:
text_[old_num + t].prefix = mcopystr(other.text_[t].prefix);
break;
}
}
}
untagged_ |= other.untagged_;
useNil_ |= other.useNil_;
useNumber_ |= other.useNumber_;
useOrder_ |= other.useOrder_;
useQName_ |= other.useQName_;
useType_ |= other.useType_;
useUnion_ |= other.useUnion_;
whitespace_ = other.whitespace_;
if (other.xsd_type != XSD_NONE) {
xsd_type = other.xsd_type;
}
return *this;
}
bool XerAttributes::empty() const
{
return !abstract_
&& !attribute_
&& !has_aa(this)
&& !has_ae(this)
&& !base64_
&& !block_
&& !decimal_
&& defaultForEmpty_ == 0
&& !defaultForEmptyIsRef_
&& !defaultForEmptyRef_
&& !element_
&& !embedValues_
&& !(form_ & LOCALLY_SET)
&& !has_fractionDigits_
&& !hex_
&& !list_
&& name_.kw_ == NamespaceSpecification::NO_MANGLING
&& namespace_.uri == 0
&& num_text_ == 0
&& !untagged_
&& !useNil_
&& !useNumber_
&& !useOrder_
&& !useQName_
&& !useType_
&& !useUnion_
&& whitespace_ == PRESERVE
&& xsd_type == XSD_NONE;
}