summaryrefslogtreecommitdiff
path: root/ndb/src/common/util/Properties.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ndb/src/common/util/Properties.cpp')
-rw-r--r--ndb/src/common/util/Properties.cpp1019
1 files changed, 1019 insertions, 0 deletions
diff --git a/ndb/src/common/util/Properties.cpp b/ndb/src/common/util/Properties.cpp
new file mode 100644
index 00000000000..4841d6e5e9e
--- /dev/null
+++ b/ndb/src/common/util/Properties.cpp
@@ -0,0 +1,1019 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <Properties.hpp>
+
+#include <NdbTCP.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <NdbString.h>
+
+#include <NdbOut.hpp>
+
+/**
+ * Note has to be a multiple of 4 bytes
+ */
+const char Properties::version[] = { 2, 0, 0, 1, 1, 1, 1, 4 };
+
+/**
+ * PropertyImpl
+ */
+struct PropertyImpl{
+ PropertiesType valueType;
+ const char * name;
+ void * value;
+
+ ~PropertyImpl();
+ PropertyImpl(const char * name, Uint32 value);
+ PropertyImpl(const char * name, const char * value);
+ PropertyImpl(const char * name, const Properties * value);
+
+ static PropertyImpl * copyPropertyImpl(const PropertyImpl &);
+};
+
+/**
+ * PropertiesImpl
+ */
+class PropertiesImpl {
+ PropertiesImpl(const PropertiesImpl &); // Not implemented
+ PropertiesImpl& operator=(const PropertiesImpl&); // Not implemented
+public:
+ PropertiesImpl(Properties *);
+ PropertiesImpl(Properties *, const PropertiesImpl &);
+ ~PropertiesImpl();
+
+ Properties * properties;
+
+ Uint32 size;
+ Uint32 items;
+ PropertyImpl **content;
+
+ bool m_insensitive;
+ int (* compare)(const char *s1, const char *s2);
+
+ void grow(int sizeToAdd);
+
+ PropertyImpl * get(const char * name) const;
+ PropertyImpl * put(PropertyImpl *);
+ void remove(const char * name);
+
+ Uint32 getPackedSize(Uint32 pLen) const;
+ bool pack(Uint32 *& buf, const char * prefix, Uint32 prefixLen) const;
+ bool unpack(const Uint32 * buf, Uint32 &bufLen, Properties * top, int items);
+
+ Uint32 getTotalItems() const;
+
+ void setErrno(Uint32 pErr, Uint32 osErr = 0){
+ properties->setErrno(pErr, osErr);
+ }
+
+ const char * getProps(const char * name, const PropertiesImpl ** impl) const;
+ const char * getPropsPut(const char * name, PropertiesImpl ** impl);
+};
+
+/**
+ * Methods for Property
+ */
+Property::Property(const char * name, Uint32 value){
+ impl = new PropertyImpl(name, value);
+}
+
+Property::Property(const char * name, const char * value){
+ impl = new PropertyImpl(name, value);
+}
+
+Property::Property(const char * name, const class Properties * value){
+ impl = new PropertyImpl(name, value);
+
+ ((Properties*)impl->value)->setCaseInsensitiveNames(value->getCaseInsensitiveNames());
+}
+
+Property::~Property(){
+ delete impl;
+}
+
+/**
+ * Methods for Properties
+ */
+Properties::Properties(){
+ parent = 0;
+ impl = new PropertiesImpl(this);
+}
+
+Properties::Properties(const Properties & org){
+ parent = 0;
+ impl = new PropertiesImpl(this, * org.impl);
+}
+
+Properties::Properties(const Property * anArray, int arrayLen){
+ impl = new PropertiesImpl(this);
+
+ put(anArray, arrayLen);
+}
+
+Properties::~Properties(){
+ clear();
+ delete impl;
+}
+
+void
+Properties::put(const Property * anArray, int arrayLen){
+ if(anArray == 0)
+ return;
+ for(int i = 0; i<arrayLen; i++)
+ impl->put(anArray[i].impl);
+}
+
+template <class T>
+bool
+put(PropertiesImpl * impl, const char * name, T value, bool replace){
+ if(name == 0){
+ impl->setErrno(E_PROPERTIES_INVALID_NAME);
+ return false;
+ }
+
+ PropertiesImpl * tmp = 0;
+ const char * short_name = impl->getPropsPut(name, &tmp);
+
+ if(tmp == 0){
+ impl->setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
+ return false;
+ }
+
+ if(tmp->get(short_name) != 0){
+ if(replace){
+ tmp->remove(short_name);
+ } else {
+ impl->setErrno(E_PROPERTIES_ELEMENT_ALREADY_EXISTS);
+ return false;
+ }
+ }
+ return tmp->put(new PropertyImpl(short_name, value));
+}
+
+bool
+Properties::put(const char * name, Uint32 value, bool replace){
+ return ::put(impl, name, value, replace);
+}
+
+bool
+Properties::put(const char * name, const char * value, bool replace){
+ return ::put(impl, name, value, replace);
+}
+
+bool
+Properties::put(const char * name, const Properties * value, bool replace){
+ return ::put(impl, name, value, replace);
+}
+
+bool
+Properties::getTypeOf(const char * name, PropertiesType * type) const {
+ PropertyImpl * nvp = impl->get(name);
+ if(nvp == 0){
+ setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
+ return false;
+ }
+ setErrno(E_PROPERTIES_OK);
+ * type = nvp->valueType;
+ return true;
+}
+
+bool
+Properties::contains(const char * name) const {
+ PropertyImpl * nvp = impl->get(name);
+ return nvp != 0;
+}
+
+bool
+Properties::get(const char * name, Uint32 * value) const {
+ PropertyImpl * nvp = impl->get(name);
+ if(nvp == 0){
+ setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
+ return false;
+ }
+
+ if(nvp->valueType == PropertiesType_Uint32){
+ * value = * (Uint32 *)nvp->value;
+ setErrno(E_PROPERTIES_OK);
+ return true;
+ }
+ setErrno(E_PROPERTIES_INVALID_TYPE);
+ return false;
+}
+
+bool
+Properties::get(const char * name, const char ** value) const {
+ PropertyImpl * nvp = impl->get(name);
+ if(nvp == 0){
+ setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
+ return false;
+ }
+
+ if(nvp->valueType == PropertiesType_char){
+ * value = (const char *)nvp->value;
+ setErrno(E_PROPERTIES_OK);
+ return true;
+ }
+ setErrno(E_PROPERTIES_INVALID_TYPE);
+ return false;
+}
+
+bool
+Properties::get(const char * name, BaseString& value) const {
+ const char *tmp = "";
+ bool ret;
+ ret = get(name, &tmp);
+ value.assign(tmp);
+ return ret;
+}
+
+bool
+Properties::get(const char * name, const Properties ** value) const {
+ PropertyImpl * nvp = impl->get(name);
+ if(nvp == 0){
+ setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
+ return false;
+ }
+ if(nvp->valueType == PropertiesType_Properties){
+ * value = (const Properties *)nvp->value;
+ setErrno(E_PROPERTIES_OK);
+ return true;
+ }
+ setErrno(E_PROPERTIES_INVALID_TYPE);
+ return false;
+}
+
+bool
+Properties::getCopy(const char * name, char ** value) const {
+ PropertyImpl * nvp = impl->get(name);
+ if(nvp == 0){
+ setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
+ return false;
+ }
+
+ if(nvp->valueType == PropertiesType_char){
+ * value = strdup((const char *)nvp->value);
+ setErrno(E_PROPERTIES_OK);
+ return true;
+ }
+ setErrno(E_PROPERTIES_INVALID_TYPE);
+ return false;
+}
+
+bool
+Properties::getCopy(const char * name, Properties ** value) const {
+ PropertyImpl * nvp = impl->get(name);
+ if(nvp == 0){
+ setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
+ return false;
+ }
+
+ if(nvp->valueType == PropertiesType_Properties){
+ * value = new Properties(* (const Properties *)nvp->value);
+ setErrno(E_PROPERTIES_OK);
+ return true;
+ }
+ setErrno(E_PROPERTIES_INVALID_TYPE);
+ return false;
+}
+
+void
+Properties::clear(){
+ while(impl->items > 0)
+ impl->remove(impl->content[0]->name);
+}
+
+void
+Properties::remove(const char * name) {
+ impl->remove(name);
+}
+
+void
+Properties::print(FILE * out, const char * prefix) const{
+ char buf[1024];
+ if(prefix == 0)
+ buf[0] = 0;
+ else
+ strncpy(buf, prefix, 1024);
+
+ for(unsigned int i = 0; i<impl->items; i++){
+ switch(impl->content[i]->valueType){
+ case PropertiesType_Uint32:
+ fprintf(out, "%s%s = (Uint32) %d\n", buf, impl->content[i]->name,
+ *(Uint32 *)impl->content[i]->value);
+ break;
+ case PropertiesType_char:
+ fprintf(out, "%s%s = (char*) \"%s\"\n", buf, impl->content[i]->name,
+ (char *)impl->content[i]->value);
+ break;
+ case PropertiesType_Properties:
+ char buf2 [1024];
+ snprintf(buf2, sizeof(buf2), "%s%s%c",buf, impl->content[i]->name,
+ Properties::delimiter);
+ ((Properties *)impl->content[i]->value)->print(out, buf2);
+ break;
+ }
+ }
+}
+
+Properties::Iterator::Iterator(const Properties* prop) :
+ m_prop(prop),
+ m_iterator(0) {
+}
+
+const char*
+Properties::Iterator::first() {
+ m_iterator = 0;
+ return next();
+}
+
+const char*
+Properties::Iterator::next() {
+ if (m_iterator < m_prop->impl->items)
+ return m_prop->impl->content[m_iterator++]->name;
+ else
+ return NULL;
+}
+
+Uint32
+Properties::getPackedSize() const {
+ Uint32 sz = 0;
+
+ sz += sizeof(version); // Version id of properties object
+ sz += 4; // No Of Items
+ sz += 4; // Checksum
+
+ return sz + impl->getPackedSize(0);
+}
+
+static
+Uint32
+computeChecksum(const Uint32 * buf, Uint32 words){
+ Uint32 sum = 0;
+ for(unsigned int i = 0; i<words; i++)
+ sum ^= htonl(buf[i]);
+
+ return sum;
+}
+
+bool
+Properties::pack(Uint32 * buf) const {
+ Uint32 * bufStart = buf;
+
+ memcpy(buf, version, sizeof(version));
+
+ // Note that version must be a multiple of 4
+ buf += (sizeof(version) / 4);
+
+ * buf = htonl(impl->getTotalItems());
+ buf++;
+ bool res = impl->pack(buf, "", 0);
+ if(!res)
+ return res;
+
+ * buf = htonl(computeChecksum(bufStart, (buf - bufStart)));
+
+ return true;
+}
+
+bool
+Properties::unpack(const Uint32 * buf, Uint32 bufLen){
+ const Uint32 * bufStart = buf;
+ Uint32 bufLenOrg = bufLen;
+
+ if(bufLen < sizeof(version)){
+ setErrno(E_PROPERTIES_INVALID_BUFFER_TO_SHORT);
+ return false;
+ }
+
+ if(memcmp(buf, version, sizeof(version)) != 0){
+ setErrno(E_PROPERTIES_INVALID_VERSION_WHILE_UNPACKING);
+ return false;
+ }
+ bufLen -= sizeof(version);
+
+ // Note that version must be a multiple of 4
+ buf += (sizeof(version) / 4);
+
+ if(bufLen < 4){
+ setErrno(E_PROPERTIES_INVALID_BUFFER_TO_SHORT);
+ return false;
+ }
+
+ Uint32 totalItems = ntohl(* buf);
+ buf++; bufLen -= 4;
+ bool res = impl->unpack(buf, bufLen, this, totalItems);
+ if(!res)
+ return res;
+
+ Uint32 sum = computeChecksum(bufStart, (bufLenOrg-bufLen)/4);
+ if(sum != ntohl(bufStart[(bufLenOrg-bufLen)/4])){
+ setErrno(E_PROPERTIES_INVALID_CHECKSUM);
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Methods for PropertiesImpl
+ */
+PropertiesImpl::PropertiesImpl(Properties * p){
+ this->properties = p;
+ items = 0;
+ size = 25;
+ content = new PropertyImpl * [size];
+ this->m_insensitive = false;
+ this->compare = strcmp;
+}
+
+PropertiesImpl::PropertiesImpl(Properties * p, const PropertiesImpl & org){
+ this->properties = p;
+ this->size = org.size;
+ this->items = org.items;
+ this->m_insensitive = org.m_insensitive;
+ this->compare = org.compare;
+ content = new PropertyImpl * [size];
+ for(unsigned int i = 0; i<items; i++){
+ content[i] = PropertyImpl::copyPropertyImpl(* org.content[i]);
+ }
+}
+
+PropertiesImpl::~PropertiesImpl(){
+ for(unsigned int i = 0; i<items; i++)
+ delete content[i];
+ delete [] content;
+}
+
+void
+PropertiesImpl::grow(int sizeToAdd){
+ PropertyImpl ** newContent = new PropertyImpl * [size + sizeToAdd];
+ memcpy(newContent, content, items * sizeof(PropertyImpl *));
+ delete [] content;
+ content = newContent;
+ size += sizeToAdd;
+}
+
+PropertyImpl *
+PropertiesImpl::get(const char * name) const {
+ const PropertiesImpl * tmp = 0;
+ const char * short_name = getProps(name, &tmp);
+ if(tmp == 0){
+ return 0;
+ }
+
+ for(unsigned int i = 0; i<tmp->items; i++)
+ if((* compare)(tmp->content[i]->name, short_name) == 0)
+ return tmp->content[i];
+ return 0;
+}
+
+PropertyImpl *
+PropertiesImpl::put(PropertyImpl * nvp){
+ if(items == size)
+ grow(size);
+ content[items] = nvp;
+
+ items ++;
+
+ if(nvp->valueType == PropertiesType_Properties){
+ ((Properties*)nvp->value)->parent = properties;
+ }
+ return nvp;
+}
+
+void
+PropertiesImpl::remove(const char * name){
+ for(unsigned int i = 0; i<items; i++){
+ if((* compare)(content[i]->name, name) == 0){
+ delete content[i];
+ memmove(&content[i], &content[i+1], (items-i-1)*sizeof(PropertyImpl *));
+ items --;
+ return;
+ }
+ }
+}
+
+Uint32
+PropertiesImpl::getTotalItems() const {
+ int ret = 0;
+ for(unsigned int i = 0; i<items; i++)
+ if(content[i]->valueType == PropertiesType_Properties){
+ ret += ((Properties*)content[i]->value)->impl->getTotalItems();
+ } else {
+ ret ++;
+ }
+ return ret;
+}
+
+const char *
+PropertiesImpl::getProps(const char * name,
+ const PropertiesImpl ** impl) const {
+ const char * ret = name;
+ const char * tmp = strchr(name, Properties::delimiter);
+ if(tmp == 0){
+ * impl = this;
+ return ret;
+ } else {
+ Uint32 sz = tmp - name;
+ char * tmp2 = (char*)malloc(sz + 1);
+ memcpy(tmp2, name, sz);
+ tmp2[sz] = 0;
+
+ PropertyImpl * nvp = get(tmp2);
+
+ free(tmp2);
+
+ if(nvp == 0){
+ * impl = 0;
+ return 0;
+ }
+ if(nvp->valueType != PropertiesType_Properties){
+ * impl = 0;
+ return name;
+ }
+ return ((Properties*)nvp->value)->impl->getProps(tmp+1, impl);
+ }
+}
+
+const char *
+PropertiesImpl::getPropsPut(const char * name,
+ PropertiesImpl ** impl) {
+ const char * ret = name;
+ const char * tmp = strchr(name, Properties::delimiter);
+ if(tmp == 0){
+ * impl = this;
+ return ret;
+ } else {
+ Uint32 sz = tmp - name;
+ char * tmp2 = (char*)malloc(sz + 1);
+ memcpy(tmp2, name, sz);
+ tmp2[sz] = 0;
+
+ PropertyImpl * nvp = get(tmp2);
+
+ if(nvp == 0){
+ Properties * tmpP = new Properties();
+ PropertyImpl * tmpPI = new PropertyImpl(tmp2, tmpP);
+ PropertyImpl * nvp = put(tmpPI);
+
+ delete tmpP;
+ free(tmp2);
+ return ((Properties*)nvp->value)->impl->getPropsPut(tmp+1, impl);
+ }
+ free(tmp2);
+ if(nvp->valueType != PropertiesType_Properties){
+ * impl = 0;
+ return name;
+ }
+ return ((Properties*)nvp->value)->impl->getPropsPut(tmp+1, impl);
+ }
+}
+
+int
+mod4(unsigned int i){
+ int res = i + (4 - (i % 4));
+ return res;
+}
+
+Uint32
+PropertiesImpl::getPackedSize(Uint32 pLen) const {
+ Uint32 sz = 0;
+ for(unsigned int i = 0; i<items; i++){
+ if(content[i]->valueType == PropertiesType_Properties){
+ Properties * p = (Properties*)content[i]->value;
+ sz += p->impl->getPackedSize(pLen+strlen(content[i]->name)+1);
+ } else {
+ sz += 4; // Type
+ sz += 4; // Name Len
+ sz += 4; // Value Len
+ sz += mod4(pLen + strlen(content[i]->name)); // Name
+ if(content[i]->valueType == PropertiesType_char){
+ sz += mod4(strlen((char *)content[i]->value));
+ } else if(content[i]->valueType == PropertiesType_Uint32){
+ sz += mod4(4);
+ } else {
+ assert(0);
+ }
+ }
+ }
+ return sz;
+}
+
+struct CharBuf {
+ char * buffer;
+ Uint32 bufLen;
+ Uint32 contentLen;
+
+ CharBuf(){
+ buffer = 0;
+ bufLen = 0;
+ contentLen = 0;
+ }
+
+ ~CharBuf(){
+ free(buffer);
+ }
+
+ void clear() { contentLen = 0;}
+ bool add(const char * str, Uint32 strLen){
+ if(!expand(contentLen + strLen + 1))
+ return false;
+ memcpy(&buffer[contentLen], str, strLen);
+ contentLen += strLen;
+ buffer[contentLen] = 0;
+ return true;
+ }
+
+ bool add(char c){
+ return add(&c, 1);
+ }
+
+ bool expand(Uint32 newSize){
+ if(newSize >= bufLen){
+
+ char * tmp = (char*)malloc(newSize + 1024);
+ memset(tmp, 0, newSize + 1024);
+ if(tmp == 0)
+ return false;
+ if(contentLen > 0)
+ memcpy(tmp, buffer, contentLen);
+ if(buffer != 0)
+ free(buffer);
+ buffer = tmp;
+ bufLen = newSize + 1024;
+ }
+ return true;
+ }
+};
+
+bool
+PropertiesImpl::pack(Uint32 *& buf, const char * prefix, Uint32 pLen) const {
+ CharBuf charBuf;
+
+ for(unsigned int i = 0; i<items; i++){
+ const int strLenName = strlen(content[i]->name);
+
+ if(content[i]->valueType == PropertiesType_Properties){
+ charBuf.clear();
+ if(!charBuf.add(prefix, pLen)){
+ properties->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING,
+ errno);
+ return false;
+ }
+
+ if(!charBuf.add(content[i]->name, strLenName)){
+ properties->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING,
+ errno);
+ return false;
+ }
+
+ if(!charBuf.add(Properties::delimiter)){
+ properties->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING,
+ errno);
+ return false;
+ }
+
+ if(!((Properties*)(content[i]->value))->impl->pack(buf,
+ charBuf.buffer,
+ charBuf.contentLen)){
+
+ return false;
+ }
+ continue;
+ }
+
+ Uint32 valLenData = 0;
+ Uint32 valLenWrite = 0;
+ Uint32 sz = 4 + 4 + 4 + mod4(pLen + strLenName);
+ switch(content[i]->valueType){
+ case PropertiesType_Uint32:
+ valLenData = 4;
+ break;
+ case PropertiesType_char:
+ valLenData = strlen((char *)content[i]->value);
+ break;
+ case PropertiesType_Properties:
+ assert(0);
+ }
+ valLenWrite = mod4(valLenData);
+ sz += valLenWrite;
+
+ * (buf + 0) = htonl(content[i]->valueType);
+ * (buf + 1) = htonl(pLen + strLenName);
+ * (buf + 2) = htonl(valLenData);
+
+ char * valBuf = (char*)(buf + 3);
+ char * nameBuf = (char*)(buf + 3 + (valLenWrite / 4));
+
+ memset(valBuf, 0, sz-12);
+
+ switch(content[i]->valueType){
+ case PropertiesType_Uint32:
+ * (Uint32 *)valBuf = htonl(* (Uint32 *)content[i]->value);
+ break;
+ case PropertiesType_char:
+ memcpy(valBuf, content[i]->value, strlen((char*)content[i]->value));
+ break;
+ case PropertiesType_Properties:
+ assert(0);
+ }
+ if(pLen > 0)
+ memcpy(nameBuf, prefix, pLen);
+ memcpy(nameBuf + pLen, content[i]->name, strLenName);
+
+ buf += (sz / 4);
+ }
+
+ return true;
+}
+
+bool
+PropertiesImpl::unpack(const Uint32 * buf, Uint32 &bufLen, Properties * top,
+ int _items){
+ CharBuf charBuf;
+ while(_items > 0){
+ Uint32 tmp[3];
+
+ if(bufLen <= 12){
+ top->setErrno(E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING);
+ return false;
+ }
+
+ tmp[0] = ntohl(buf[0]);
+ tmp[1] = ntohl(buf[1]);
+ tmp[2] = ntohl(buf[2]);
+ buf += 3;
+ bufLen -= 12;
+
+ PropertiesType pt = (PropertiesType)tmp[0];
+ Uint32 nameLen = tmp[1];
+ Uint32 valueLen = tmp[2];
+ Uint32 nameLenRead = mod4(nameLen);
+ Uint32 valueLenRead = mod4(valueLen);
+
+ Uint32 sz = nameLenRead + valueLenRead;
+ if(bufLen < sz){
+ top->setErrno(E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING);
+ return false;
+ }
+
+ if(!charBuf.expand(sz)){
+ top->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_UNPACKING, errno);
+ return false;
+ }
+
+ memcpy(charBuf.buffer, buf, sz);
+ buf += (sz / 4);
+ bufLen -= sz ;
+
+ char * valBuf = charBuf.buffer;
+ char * nameBuf = charBuf.buffer + valueLenRead;
+
+ nameBuf[nameLen] = 0;
+ valBuf[valueLen] = 0;
+
+ bool res3 = false;
+ switch(pt){
+ case PropertiesType_Uint32:
+ res3 = top->put(nameBuf, ntohl(* (Uint32 *)valBuf), true);
+ break;
+ case PropertiesType_char:
+ res3 = top->put(nameBuf, valBuf, true);
+ break;
+ case PropertiesType_Properties:
+ assert(0);
+ }
+ if(res3 != true){
+ return false;
+ }
+ _items--;
+ }
+ return true;
+}
+
+PropertyImpl::~PropertyImpl(){
+ free((char*)name);
+ switch(valueType){
+ case PropertiesType_Uint32:
+ delete (Uint32 *)value;
+ break;
+ case PropertiesType_char:
+ free((char *)value);
+ break;
+ case PropertiesType_Properties:
+ delete (Properties *)value;
+ break;
+ }
+}
+
+PropertyImpl *
+PropertyImpl::copyPropertyImpl(const PropertyImpl & org){
+ switch(org.valueType){
+ case PropertiesType_Uint32:
+ return new PropertyImpl(org.name, * (Uint32 *)org.value);
+ break;
+ case PropertiesType_char:
+ return new PropertyImpl(org.name, (char *)org.value);
+ break;
+ case PropertiesType_Properties:
+ return new PropertyImpl(org.name, (Properties *)org.value);
+ break;
+ default:
+ assert(0);
+ }
+ return 0;
+}
+
+PropertyImpl::PropertyImpl(const char * _name, Uint32 _value){
+ this->name = strdup(_name);
+ this->value = new Uint32;
+ * ((Uint32 *)this->value) = _value;
+ this->valueType = PropertiesType_Uint32;
+}
+
+PropertyImpl::PropertyImpl(const char * _name, const char * _value){
+ this->name = strdup(_name);
+ this->value = strdup(_value);
+ this->valueType = PropertiesType_char;
+
+}
+
+PropertyImpl::PropertyImpl(const char * _name, const Properties * _value){
+ this->name = strdup(_name);
+ this->value = new Properties(* _value);
+ this->valueType = PropertiesType_Properties;
+}
+
+const Uint32 E_PROPERTIES_OK = 0;
+const Uint32 E_PROPERTIES_INVALID_NAME = 1;
+const Uint32 E_PROPERTIES_NO_SUCH_ELEMENT = 2;
+const Uint32 E_PROPERTIES_INVALID_TYPE = 3;
+const Uint32 E_PROPERTIES_ELEMENT_ALREADY_EXISTS = 4;
+
+const Uint32 E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING = 5;
+const Uint32 E_PROPERTIES_INVALID_VERSION_WHILE_UNPACKING = 6;
+const Uint32 E_PROPERTIES_INVALID_BUFFER_TO_SHORT = 7;
+const Uint32 E_PROPERTIES_ERROR_MALLOC_WHILE_UNPACKING = 8;
+const Uint32 E_PROPERTIES_INVALID_CHECKSUM = 9;
+const Uint32 E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING = 10;
+
+/**
+ * These are methods that used to be inline
+ *
+ * But Diab 4.1f could not compile -release with to many inlines
+ */
+void
+Properties::setErrno(Uint32 pErr, Uint32 osErr) const {
+ if(parent != 0){
+ parent->setErrno(pErr, osErr);
+ return ;
+ }
+
+ /**
+ * propErrno & osErrno used to be mutable,
+ * but diab didn't know what mutable meant.
+ */
+ *((Uint32*)&propErrno) = pErr;
+ *((Uint32*)&osErrno) = osErr;
+}
+
+/**
+ * Inlined get/put(name, no, ...) - methods
+ */
+
+bool
+Properties::put(const char * name, Uint32 no, Uint32 val, bool replace){
+ size_t tmp_len = strlen(name)+20;
+ char * tmp = (char*)malloc(tmp_len);
+ snprintf(tmp, tmp_len, "%s_%d", name, no);
+ bool res = put(tmp, val, replace);
+ free(tmp);
+ return res;
+}
+
+
+bool
+Properties::put(const char * name, Uint32 no, const char * val, bool replace){
+ size_t tmp_len = strlen(name)+20;
+ char * tmp = (char*)malloc(tmp_len);
+ snprintf(tmp, tmp_len, "%s_%d", name, no);
+ bool res = put(tmp, val, replace);
+ free(tmp);
+ return res;
+}
+
+
+bool
+Properties::put(const char * name, Uint32 no, const Properties * val,
+ bool replace){
+ size_t tmp_len = strlen(name)+20;
+ char * tmp = (char*)malloc(tmp_len);
+ snprintf(tmp, tmp_len, "%s_%d", name, no);
+ bool res = put(tmp, val, replace);
+ free(tmp);
+ return res;
+}
+
+
+bool
+Properties::getTypeOf(const char * name, Uint32 no,
+ PropertiesType * type) const {
+ size_t tmp_len = strlen(name)+20;
+ char * tmp = (char*)malloc(tmp_len);
+ snprintf(tmp, tmp_len, "%s_%d", name, no);
+ bool res = getTypeOf(tmp, type);
+ free(tmp);
+ return res;
+}
+
+bool
+Properties::contains(const char * name, Uint32 no) const {
+ size_t tmp_len = strlen(name)+20;
+ char * tmp = (char*)malloc(tmp_len);
+ snprintf(tmp, tmp_len, "%s_%d", name, no);
+ bool res = contains(tmp);
+ free(tmp);
+ return res;
+}
+
+bool
+Properties::get(const char * name, Uint32 no, Uint32 * value) const{
+ size_t tmp_len = strlen(name)+20;
+ char * tmp = (char*)malloc(tmp_len);
+ snprintf(tmp, tmp_len, "%s_%d", name, no);
+ bool res = get(tmp, value);
+ free(tmp);
+ return res;
+}
+
+
+bool
+Properties::get(const char * name, Uint32 no, const char ** value) const {
+ size_t tmp_len = strlen(name)+20;
+ char * tmp = (char*)malloc(tmp_len);
+ snprintf(tmp, tmp_len, "%s_%d", name, no);
+ bool res = get(tmp, value);
+ free(tmp);
+ return res;
+}
+
+
+bool
+Properties::get(const char * name, Uint32 no, const Properties ** value) const{
+ size_t tmp_len = strlen(name)+20;
+ char * tmp = (char*)malloc(tmp_len);
+ snprintf(tmp, tmp_len, "%s_%d", name, no);
+ bool res = get(tmp, value);
+ free(tmp);
+ return res;
+}
+
+
+bool
+Properties::getCopy(const char * name, Uint32 no, char ** value) const {
+ size_t tmp_len = strlen(name)+20;
+ char * tmp = (char*)malloc(tmp_len);
+ snprintf(tmp, tmp_len, "%s_%d", name, no);
+ bool res = getCopy(tmp, value);
+ free(tmp);
+ return res;
+}
+
+
+bool
+Properties::getCopy(const char * name, Uint32 no, Properties ** value) const {
+ size_t tmp_len = strlen(name)+20;
+ char * tmp = (char*)malloc(tmp_len);
+ snprintf(tmp, tmp_len, "%s_%d", name, no);
+ bool res = getCopy(tmp, value);
+ free(tmp);
+ return res;
+}
+
+void
+Properties::setCaseInsensitiveNames(bool value){
+ impl->m_insensitive = value;
+ if(value)
+ impl->compare = strcasecmp;
+ else
+ impl->compare = strcmp;
+}
+
+bool
+Properties::getCaseInsensitiveNames() const {
+ return impl->m_insensitive;
+}