Properties.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:27k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include <ndb_global.h>
  14. #include <Properties.hpp>
  15. #include <NdbTCP.h>
  16. #include <NdbOut.hpp>
  17. static
  18. char * f_strdup(const char * s){
  19.   if(!s) return 0;
  20.   return strdup(s);
  21. }
  22. /**
  23.  * Note has to be a multiple of 4 bytes
  24.  */
  25. const char Properties::version[] = { 2, 0, 0, 1, 1, 1, 1, 4 };
  26. const char Properties::delimiter = ':';
  27. /**
  28.  * PropertyImpl
  29.  */
  30. struct PropertyImpl{
  31.   PropertiesType valueType;
  32.   const char * name;
  33.   void * value;
  34.   ~PropertyImpl();
  35.   PropertyImpl(const char * name, Uint32 value);
  36.   PropertyImpl(const char * name, Uint64 value);
  37.   PropertyImpl(const char * name, const char * value);
  38.   PropertyImpl(const char * name, const Properties * value);
  39.   
  40.   static PropertyImpl * copyPropertyImpl(const PropertyImpl &);
  41. };
  42. /**
  43.  * PropertiesImpl
  44.  */
  45. class PropertiesImpl {
  46.   PropertiesImpl(const PropertiesImpl &);           // Not implemented
  47.   PropertiesImpl& operator=(const PropertiesImpl&); // Not implemented
  48. public:
  49.   PropertiesImpl(Properties *, bool case_insensitive);
  50.   PropertiesImpl(Properties *, const PropertiesImpl &);
  51.   ~PropertiesImpl();
  52.   Properties * properties;
  53.   
  54.   Uint32 size;
  55.   Uint32 items;
  56.   PropertyImpl **content;
  57.   bool m_insensitive;
  58.   int (* compare)(const char *s1, const char *s2);
  59.   
  60.   void setCaseInsensitiveNames(bool value);
  61.   void grow(int sizeToAdd);
  62.   
  63.   PropertyImpl * get(const char * name) const;
  64.   PropertyImpl * put(PropertyImpl *);
  65.   void remove(const char * name);
  66.   
  67.   Uint32 getPackedSize(Uint32 pLen) const;
  68.   bool pack(Uint32 *& buf, const char * prefix, Uint32 prefixLen) const;
  69.   bool unpack(const Uint32 * buf, Uint32 &bufLen, Properties * top, int items);
  70.   
  71.   Uint32 getTotalItems() const;
  72.   void setErrno(Uint32 pErr, Uint32 osErr = 0){
  73.     properties->setErrno(pErr, osErr);
  74.   }
  75.   const char * getProps(const char * name, const PropertiesImpl ** impl) const;
  76.   const char * getPropsPut(const char * name, PropertiesImpl ** impl);
  77. };
  78. /**
  79.  * Methods for Property
  80.  */
  81. Property::Property(const char * name, Uint32 value){
  82.   impl = new PropertyImpl(name, value);
  83. }
  84. Property::Property(const char * name, const char * value){
  85.   impl = new PropertyImpl(name, value);
  86. }
  87. Property::Property(const char * name, const class Properties * value){
  88.   impl = new PropertyImpl(name, value);
  89.   ((Properties*)impl->value)->setCaseInsensitiveNames(value->getCaseInsensitiveNames());
  90. }
  91. Property::~Property(){
  92.   delete impl;
  93. }
  94. /**
  95.  * Methods for Properties
  96.  */
  97. Properties::Properties(bool case_insensitive){
  98.   parent = 0;
  99.   impl = new PropertiesImpl(this, case_insensitive);
  100. }
  101. Properties::Properties(const Properties & org){
  102.   parent = 0;
  103.   impl = new PropertiesImpl(this, * org.impl);
  104. }
  105. Properties::Properties(const Property * anArray, int arrayLen){
  106.   impl = new PropertiesImpl(this, false);
  107.   put(anArray, arrayLen);
  108. }
  109. Properties::~Properties(){
  110.   clear();
  111.   delete impl;
  112. }
  113. void
  114. Properties::put(const Property * anArray, int arrayLen){
  115.   if(anArray == 0)
  116.     return;
  117.   for(int i = 0; i<arrayLen; i++)
  118.     impl->put(anArray[i].impl);
  119. }
  120. template <class T>
  121. bool
  122. put(PropertiesImpl * impl, const char * name, T value, bool replace){
  123.   if(name == 0){
  124.     impl->setErrno(E_PROPERTIES_INVALID_NAME);
  125.     return false;
  126.   }
  127.   PropertiesImpl * tmp = 0;
  128.   const char * short_name = impl->getPropsPut(name, &tmp);
  129.   if(tmp == 0){
  130.     impl->setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
  131.     return false;
  132.   }
  133.   
  134.   if(tmp->get(short_name) != 0){
  135.     if(replace){
  136.       tmp->remove(short_name);
  137.     } else {
  138.       impl->setErrno(E_PROPERTIES_ELEMENT_ALREADY_EXISTS);
  139.       return false;
  140.     }
  141.   }
  142.   return tmp->put(new PropertyImpl(short_name, value));  
  143. }
  144. bool
  145. Properties::put(const char * name, Uint32 value, bool replace){
  146.   return ::put(impl, name, value, replace);
  147. }
  148. bool
  149. Properties::put64(const char * name, Uint64 value, bool replace){
  150.   return ::put(impl, name, value, replace);
  151. }
  152. bool 
  153. Properties::put(const char * name, const char * value, bool replace){
  154.   return ::put(impl, name, value, replace);
  155. }
  156. bool 
  157. Properties::put(const char * name, const Properties * value, bool replace){
  158.   return ::put(impl, name, value, replace);
  159. }
  160. bool
  161. Properties::getTypeOf(const char * name, PropertiesType * type) const {
  162.   PropertyImpl * nvp = impl->get(name);
  163.   if(nvp == 0){
  164.     setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
  165.     return false;
  166.   }
  167.   setErrno(E_PROPERTIES_OK);
  168.   * type = nvp->valueType;
  169.   return true;
  170. }
  171. bool
  172. Properties::contains(const char * name) const {
  173.   PropertyImpl * nvp = impl->get(name);
  174.   return nvp != 0;
  175. }
  176. bool
  177. Properties::get(const char * name, Uint32 * value) const {
  178.   PropertyImpl * nvp = impl->get(name);
  179.   if(nvp == 0){
  180.     setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
  181.     return false;
  182.   }
  183.   
  184.   if(nvp->valueType == PropertiesType_Uint32){
  185.     * value = * (Uint32 *)nvp->value;
  186.     setErrno(E_PROPERTIES_OK);
  187.     return true;
  188.   }
  189.   if(nvp->valueType == PropertiesType_Uint64){
  190.     Uint64 tmp = * (Uint64 *)nvp->value;
  191.     Uint64 max = 1; max <<= 32;
  192.     if(tmp < max){
  193.       * value = (Uint32)tmp;
  194.       setErrno(E_PROPERTIES_OK);
  195.       return true;
  196.     }
  197.   }
  198.   setErrno(E_PROPERTIES_INVALID_TYPE);
  199.   return false;
  200. }
  201. bool
  202. Properties::get(const char * name, Uint64 * value) const {
  203.   PropertyImpl * nvp = impl->get(name);
  204.   if(nvp == 0){
  205.     setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
  206.     return false;
  207.   }
  208.   
  209.   if(nvp->valueType == PropertiesType_Uint32){
  210.     Uint32 tmp = * (Uint32 *)nvp->value;
  211.     * value = (Uint64)tmp;
  212.     setErrno(E_PROPERTIES_OK);
  213.     return true;
  214.   }
  215.   if(nvp->valueType == PropertiesType_Uint64){
  216.     * value = * (Uint64 *)nvp->value;
  217.     setErrno(E_PROPERTIES_OK);
  218.     return true;
  219.   }
  220.   setErrno(E_PROPERTIES_INVALID_TYPE);
  221.   return false;
  222. }
  223. bool
  224. Properties::get(const char * name, const char ** value) const {
  225.   PropertyImpl * nvp = impl->get(name);
  226.   if(nvp == 0){
  227.     setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
  228.     return false;
  229.   }
  230.   if(nvp->valueType == PropertiesType_char){
  231.     * value = (const char *)nvp->value;
  232.     setErrno(E_PROPERTIES_OK);
  233.     return true;
  234.   }
  235.   setErrno(E_PROPERTIES_INVALID_TYPE);
  236.   return false;
  237. }
  238. bool
  239. Properties::get(const char * name, BaseString& value) const {
  240.   const char *tmp = "";
  241.   bool ret;
  242.   ret = get(name, &tmp);
  243.   value.assign(tmp);
  244.   return ret;
  245. }
  246. bool
  247. Properties::get(const char * name, const Properties ** value) const {
  248.   PropertyImpl * nvp = impl->get(name);
  249.   if(nvp == 0){
  250.     setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
  251.     return false;
  252.   }
  253.   if(nvp->valueType == PropertiesType_Properties){
  254.     * value = (const Properties *)nvp->value;
  255.     setErrno(E_PROPERTIES_OK);
  256.     return true;
  257.   }
  258.   setErrno(E_PROPERTIES_INVALID_TYPE);
  259.   return false;
  260. }
  261. bool
  262. Properties::getCopy(const char * name, char ** value) const {
  263.   PropertyImpl * nvp = impl->get(name);
  264.   if(nvp == 0){
  265.     setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
  266.     return false;
  267.   }
  268.   if(nvp->valueType == PropertiesType_char){
  269.     * value = f_strdup((const char *)nvp->value);
  270.     setErrno(E_PROPERTIES_OK);
  271.     return true;
  272.   }
  273.   setErrno(E_PROPERTIES_INVALID_TYPE);
  274.   return false;
  275. }
  276. bool
  277. Properties::getCopy(const char * name, Properties ** value) const {
  278.   PropertyImpl * nvp = impl->get(name);
  279.   if(nvp == 0){
  280.     setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
  281.     return false;
  282.   }
  283.   
  284.   if(nvp->valueType == PropertiesType_Properties){
  285.     * value = new Properties(* (const Properties *)nvp->value);
  286.     setErrno(E_PROPERTIES_OK);
  287.     return true;
  288.   }
  289.   setErrno(E_PROPERTIES_INVALID_TYPE);
  290.   return false;
  291. }
  292. void 
  293. Properties::clear(){
  294.   while(impl->items > 0)
  295.     impl->remove(impl->content[0]->name);
  296. }
  297. void
  298. Properties::remove(const char * name) {
  299.   impl->remove(name);
  300. }
  301. void
  302. Properties::print(FILE * out, const char * prefix) const{
  303.   char buf[1024];
  304.   if(prefix == 0)
  305.     buf[0] = 0;
  306.   else
  307.     strncpy(buf, prefix, 1024);
  308.   
  309.   for(unsigned int i = 0; i<impl->items; i++){
  310.     switch(impl->content[i]->valueType){
  311.     case PropertiesType_Uint32:
  312.       fprintf(out, "%s%s = (Uint32) %dn", buf, impl->content[i]->name,
  313.       *(Uint32 *)impl->content[i]->value);
  314.       break;
  315.     case PropertiesType_Uint64:
  316.       fprintf(out, "%s%s = (Uint64) %lldn", buf, impl->content[i]->name,
  317.       *(Uint64 *)impl->content[i]->value);
  318.       break;
  319.     case PropertiesType_char:
  320.       fprintf(out, "%s%s = (char*) "%s"n", buf, impl->content[i]->name,
  321.       (char *)impl->content[i]->value);
  322.       break;
  323.     case PropertiesType_Properties:
  324.       char buf2 [1024];
  325.       BaseString::snprintf(buf2, sizeof(buf2), "%s%s%c",buf, impl->content[i]->name, 
  326.       Properties::delimiter);
  327.       ((Properties *)impl->content[i]->value)->print(out, buf2);
  328.       break;
  329.     }
  330.   }
  331. }
  332. Properties::Iterator::Iterator(const Properties* prop) :
  333.   m_prop(prop),
  334.   m_iterator(0) {
  335. }
  336. const char*
  337. Properties::Iterator::first() {
  338.   m_iterator = 0;
  339.   return next();
  340. }
  341. const char*
  342. Properties::Iterator::next() {
  343.   if (m_iterator < m_prop->impl->items) 
  344.     return m_prop->impl->content[m_iterator++]->name;
  345.   else
  346.     return NULL;
  347. }
  348. Uint32
  349. Properties::getPackedSize() const {
  350.   Uint32 sz = 0;
  351.   
  352.   sz += sizeof(version); // Version id of properties object
  353.   sz += 4;               // No Of Items
  354.   sz += 4;               // Checksum
  355.   return sz + impl->getPackedSize(0);
  356. }
  357. static
  358. Uint32
  359. computeChecksum(const Uint32 * buf, Uint32 words){
  360.   Uint32 sum = 0;
  361.   for(unsigned int i = 0; i<words; i++)
  362.     sum ^= htonl(buf[i]);
  363.   
  364.   return sum;
  365. }
  366. bool
  367. Properties::pack(Uint32 * buf) const {
  368.   Uint32 * bufStart = buf;
  369.   
  370.   memcpy(buf, version, sizeof(version));
  371.   
  372.   // Note that version must be a multiple of 4
  373.   buf += (sizeof(version) / 4); 
  374.   
  375.   * buf = htonl(impl->getTotalItems());
  376.   buf++;
  377.   bool res = impl->pack(buf, "", 0);
  378.   if(!res)
  379.     return res;
  380.   * buf = htonl(computeChecksum(bufStart, (buf - bufStart)));
  381.   return true;
  382. }
  383. bool
  384. Properties::unpack(const Uint32 * buf, Uint32 bufLen){
  385.   const Uint32 * bufStart = buf;
  386.   Uint32 bufLenOrg = bufLen;
  387.   
  388.   if(bufLen < sizeof(version)){
  389.     setErrno(E_PROPERTIES_INVALID_BUFFER_TO_SHORT);
  390.     return false;
  391.   }
  392.   
  393.   if(memcmp(buf, version, sizeof(version)) != 0){
  394.     setErrno(E_PROPERTIES_INVALID_VERSION_WHILE_UNPACKING);
  395.     return false;
  396.   }
  397.   bufLen -= sizeof(version);
  398.   
  399.   // Note that version must be a multiple of 4
  400.   buf += (sizeof(version) / 4); 
  401.   
  402.   if(bufLen < 4){
  403.     setErrno(E_PROPERTIES_INVALID_BUFFER_TO_SHORT);
  404.     return false;
  405.   }
  406.   Uint32 totalItems = ntohl(* buf);
  407.   buf++; bufLen -= 4;
  408.   bool res = impl->unpack(buf, bufLen, this, totalItems);
  409.   if(!res)
  410.     return res;
  411.   Uint32 sum = computeChecksum(bufStart, (bufLenOrg-bufLen)/4);
  412.   if(sum != ntohl(bufStart[(bufLenOrg-bufLen)/4])){
  413.     setErrno(E_PROPERTIES_INVALID_CHECKSUM);
  414.     return false;
  415.   }
  416.   return true;
  417. }
  418. /**
  419.  * Methods for PropertiesImpl
  420.  */
  421. PropertiesImpl::PropertiesImpl(Properties * p, bool case_insensitive){
  422.   this->properties = p;
  423.   items = 0;
  424.   size  = 25;
  425.   content = new PropertyImpl * [size];
  426.   setCaseInsensitiveNames(case_insensitive);
  427. }
  428. PropertiesImpl::PropertiesImpl(Properties * p, const PropertiesImpl & org){
  429.   this->properties = p;
  430.   this->size  = org.size;
  431.   this->items = org.items;
  432.   this->m_insensitive = org.m_insensitive;
  433.   this->compare = org.compare;
  434.   content = new PropertyImpl * [size];
  435.   for(unsigned int i = 0; i<items; i++){
  436.     content[i] = PropertyImpl::copyPropertyImpl(* org.content[i]);
  437.   }
  438. }
  439. PropertiesImpl::~PropertiesImpl(){
  440.   for(unsigned int i = 0; i<items; i++)
  441.     delete content[i];
  442.   delete [] content;
  443. }
  444. void
  445. PropertiesImpl::setCaseInsensitiveNames(bool value){
  446.   m_insensitive = value;
  447.   if(value)
  448.     compare = strcasecmp;
  449.   else
  450.     compare = strcmp;
  451. }
  452. void 
  453. PropertiesImpl::grow(int sizeToAdd){
  454.   PropertyImpl ** newContent = new PropertyImpl * [size + sizeToAdd];
  455.   memcpy(newContent, content, items * sizeof(PropertyImpl *));
  456.   delete [] content;
  457.   content = newContent;
  458.   size   += sizeToAdd;
  459. }
  460. PropertyImpl *
  461. PropertiesImpl::get(const char * name) const {
  462.   const PropertiesImpl * tmp = 0;
  463.   const char * short_name = getProps(name, &tmp);
  464.   if(tmp == 0){
  465.     return 0;
  466.   }
  467.   for(unsigned int i = 0; i<tmp->items; i++) {
  468.     if((* compare)(tmp->content[i]->name, short_name) == 0)
  469.       return tmp->content[i];
  470.   }
  471.   return 0;
  472. }
  473. PropertyImpl *
  474. PropertiesImpl::put(PropertyImpl * nvp){
  475.   if(items == size)
  476.     grow(size);
  477.   content[items] = nvp;
  478.   items ++;
  479.   if(nvp->valueType == PropertiesType_Properties){
  480.     ((Properties*)nvp->value)->parent = properties;
  481.   }
  482.   return nvp;
  483. }
  484. void
  485. PropertiesImpl::remove(const char * name){
  486.   for(unsigned int i = 0; i<items; i++){
  487.     if((* compare)(content[i]->name, name) == 0){
  488.       delete content[i];
  489.       memmove(&content[i], &content[i+1], (items-i-1)*sizeof(PropertyImpl *));
  490.       items --;
  491.       return;
  492.     }
  493.   }
  494. }
  495. Uint32 
  496. PropertiesImpl::getTotalItems() const {
  497.   int ret = 0;
  498.   for(unsigned int i = 0; i<items; i++)
  499.     if(content[i]->valueType == PropertiesType_Properties){
  500.       ret += ((Properties*)content[i]->value)->impl->getTotalItems();
  501.     } else {
  502.       ret ++;
  503.     }
  504.   return ret;
  505. }
  506. const char * 
  507. PropertiesImpl::getProps(const char * name, 
  508.  const PropertiesImpl ** impl) const {
  509.   const char * ret = name;
  510.   const char * tmp = strchr(name, Properties::delimiter);
  511.   if(tmp == 0){
  512.     * impl = this;
  513.     return ret;
  514.   } else {
  515.     Uint32 sz = tmp - name;
  516.     char * tmp2 = (char*)malloc(sz + 1);
  517.     memcpy(tmp2, name, sz);
  518.     tmp2[sz] = 0;
  519.     PropertyImpl * nvp = get(tmp2);
  520.     free(tmp2);
  521.     if(nvp == 0){
  522.       * impl = 0;
  523.       return 0;
  524.     }
  525.     if(nvp->valueType != PropertiesType_Properties){
  526.       * impl = 0;
  527.       return name;
  528.     }
  529.     return ((Properties*)nvp->value)->impl->getProps(tmp+1, impl);
  530.   }
  531. }
  532. const char * 
  533. PropertiesImpl::getPropsPut(const char * name, 
  534.     PropertiesImpl ** impl) {
  535.   const char * ret = name;
  536.   const char * tmp = strchr(name, Properties::delimiter);
  537.   if(tmp == 0){
  538.     * impl = this;
  539.     return ret;
  540.   } else {
  541.     Uint32 sz = tmp - name;
  542.     char * tmp2 = (char*)malloc(sz + 1);
  543.     memcpy(tmp2, name, sz);
  544.     tmp2[sz] = 0;
  545.     
  546.     PropertyImpl * nvp = get(tmp2);
  547.     if(nvp == 0){
  548.       Properties   * tmpP  = new Properties();
  549.       PropertyImpl * tmpPI = new PropertyImpl(tmp2, tmpP);
  550.       PropertyImpl * nvp = put(tmpPI);
  551.       delete tmpP;
  552.       free(tmp2);
  553.       return ((Properties*)nvp->value)->impl->getPropsPut(tmp+1, impl);
  554.     }
  555.     free(tmp2);
  556.     if(nvp->valueType != PropertiesType_Properties){
  557.       * impl = 0;
  558.       return name;
  559.     }
  560.     return ((Properties*)nvp->value)->impl->getPropsPut(tmp+1, impl);
  561.   }
  562. }
  563. int
  564. mod4(unsigned int i){
  565.   int res = i + (4 - (i % 4));
  566.   return res;
  567. }
  568. Uint32
  569. PropertiesImpl::getPackedSize(Uint32 pLen) const {
  570.   Uint32 sz = 0;
  571.   for(unsigned int i = 0; i<items; i++){
  572.     if(content[i]->valueType == PropertiesType_Properties){
  573.       Properties * p = (Properties*)content[i]->value;
  574.       sz += p->impl->getPackedSize(pLen+strlen(content[i]->name)+1);
  575.     } else { 
  576.       sz += 4; // Type
  577.       sz += 4; // Name Len
  578.       sz += 4; // Value Len
  579.       sz += mod4(pLen + strlen(content[i]->name)); // Name
  580.       switch(content[i]->valueType){
  581.       case PropertiesType_char:
  582. sz += mod4(strlen((char *)content[i]->value));
  583. break;
  584.       case PropertiesType_Uint32:
  585. sz += mod4(4);
  586. break;
  587.       case PropertiesType_Uint64:
  588. sz += mod4(8);
  589. break;
  590.       case PropertiesType_Properties:
  591.       default:
  592. assert(0);
  593.       }
  594.     }
  595.   }
  596.   return sz;
  597. }
  598. struct CharBuf {
  599.   char * buffer;
  600.   Uint32 bufLen;
  601.   Uint32 contentLen;
  602.   CharBuf(){
  603.     buffer     = 0;
  604.     bufLen     = 0;
  605.     contentLen = 0;
  606.   }
  607.   ~CharBuf(){
  608.     free(buffer);
  609.   }
  610.   
  611.   void clear() { contentLen = 0;}
  612.   bool add(const char * str, Uint32 strLen){
  613.     if(!expand(contentLen + strLen + 1))
  614.       return false;
  615.     memcpy(&buffer[contentLen], str, strLen);
  616.     contentLen += strLen;
  617.     buffer[contentLen] = 0;
  618.     return true;
  619.   }
  620.   
  621.   bool add(char c){
  622.     return add(&c, 1);
  623.   }
  624.   bool expand(Uint32 newSize){
  625.     if(newSize >= bufLen){
  626.       
  627.       char * tmp = (char*)malloc(newSize + 1024);
  628.       memset(tmp, 0, newSize + 1024);
  629.       if(tmp == 0)
  630. return false;
  631.       if(contentLen > 0)
  632. memcpy(tmp, buffer, contentLen);
  633.       if(buffer != 0)
  634. free(buffer);
  635.       buffer = tmp;
  636.       bufLen = newSize + 1024;
  637.     }
  638.     return true;
  639.   }
  640. };
  641. bool
  642. PropertiesImpl::pack(Uint32 *& buf, const char * prefix, Uint32 pLen) const {
  643.   CharBuf charBuf;
  644.   
  645.   for(unsigned int i = 0; i<items; i++){
  646.     const int strLenName      = strlen(content[i]->name);
  647.     
  648.     if(content[i]->valueType == PropertiesType_Properties){
  649.       charBuf.clear();
  650.       if(!charBuf.add(prefix, pLen)){
  651. properties->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING,
  652.      errno);
  653. return false;
  654.       }
  655.       
  656.       if(!charBuf.add(content[i]->name, strLenName)){
  657. properties->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING,
  658.      errno);
  659. return false;
  660.       }
  661.       if(!charBuf.add(Properties::delimiter)){
  662. properties->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING,
  663.      errno);
  664. return false;
  665.       }
  666.       
  667.       if(!((Properties*)(content[i]->value))->impl->pack(buf, 
  668.  charBuf.buffer,
  669.  charBuf.contentLen)){
  670. return false;
  671.       }
  672.       continue;
  673.     }
  674.     
  675.     Uint32 valLenData  = 0;
  676.     Uint32 valLenWrite = 0;
  677.     Uint32 sz = 4 + 4 + 4 + mod4(pLen + strLenName);
  678.     switch(content[i]->valueType){
  679.     case PropertiesType_Uint32:
  680.       valLenData  = 4;
  681.       break;
  682.     case PropertiesType_Uint64:
  683.       valLenData  = 8;
  684.       break;
  685.     case PropertiesType_char:
  686.       valLenData  = strlen((char *)content[i]->value);
  687.       break;
  688.     case PropertiesType_Properties:
  689.       assert(0);
  690.     }
  691.     valLenWrite = mod4(valLenData);
  692.     sz += valLenWrite;
  693.     
  694.     * (buf + 0) = htonl(content[i]->valueType);
  695.     * (buf + 1) = htonl(pLen + strLenName);
  696.     * (buf + 2) = htonl(valLenData);
  697.     char * valBuf  = (char*)(buf + 3);
  698.     char * nameBuf = (char*)(buf + 3 + (valLenWrite / 4));
  699.     
  700.     memset(valBuf, 0, sz-12);
  701.     switch(content[i]->valueType){
  702.     case PropertiesType_Uint32:
  703.       * (Uint32 *)valBuf = htonl(* (Uint32 *)content[i]->value);
  704.       break;
  705.     case PropertiesType_Uint64:{
  706.       Uint64 val =  * (Uint64 *)content[i]->value;
  707.       Uint32 hi = (val >> 32);
  708.       Uint32 lo = (val & 0xFFFFFFFF);
  709.       * (Uint32 *)valBuf = htonl(hi);
  710.       * (Uint32 *)(valBuf + 4) = htonl(lo);
  711.     }
  712.       break;
  713.     case PropertiesType_char:
  714.       memcpy(valBuf, content[i]->value, strlen((char*)content[i]->value));
  715.       break;
  716.     case PropertiesType_Properties:
  717.       assert(0);
  718.     }
  719.     if(pLen > 0)
  720.       memcpy(nameBuf, prefix, pLen);
  721.     memcpy(nameBuf + pLen, content[i]->name, strLenName);
  722.     
  723.     buf += (sz / 4);
  724.   }
  725.   return true;
  726. }
  727. bool
  728. PropertiesImpl::unpack(const Uint32 * buf, Uint32 &bufLen, Properties * top,
  729.        int _items){
  730.   CharBuf charBuf;
  731.   while(_items > 0){
  732.     Uint32 tmp[3]; 
  733.     
  734.     if(bufLen <= 12){
  735.       top->setErrno(E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING);
  736.       return false;
  737.     }
  738.     tmp[0] = ntohl(buf[0]);
  739.     tmp[1] = ntohl(buf[1]);
  740.     tmp[2] = ntohl(buf[2]);
  741.     buf    += 3;
  742.     bufLen -= 12;
  743.     PropertiesType pt   = (PropertiesType)tmp[0];
  744.     Uint32 nameLen      = tmp[1];
  745.     Uint32 valueLen     = tmp[2];
  746.     Uint32 nameLenRead  = mod4(nameLen);
  747.     Uint32 valueLenRead = mod4(valueLen);
  748.     Uint32 sz = nameLenRead + valueLenRead;
  749.     if(bufLen < sz){
  750.       top->setErrno(E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING);
  751.       return false;
  752.     }
  753.     if(!charBuf.expand(sz)){
  754.       top->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_UNPACKING, errno);
  755.       return false;
  756.     }
  757.     memcpy(charBuf.buffer, buf, sz);
  758.     buf    += (sz / 4);
  759.     bufLen -= sz ;
  760.     char * valBuf  = charBuf.buffer;
  761.     char * nameBuf = charBuf.buffer + valueLenRead;
  762.     
  763.     nameBuf[nameLen] = 0;
  764.     valBuf[valueLen] = 0;
  765.     
  766.     bool res3 = false;
  767.     switch(pt){
  768.     case PropertiesType_Uint32:
  769.       res3 = top->put(nameBuf, ntohl(* (Uint32 *)valBuf), true);
  770.       break;
  771.     case PropertiesType_Uint64:{
  772.       Uint64 hi = ntohl(* (Uint32 *)valBuf);
  773.       Uint64 lo = ntohl(* (Uint32 *)(valBuf + 4));
  774.       res3 = top->put64(nameBuf, (hi << 32) + lo, true);
  775.     }
  776.       break;
  777.     case PropertiesType_char:
  778.       res3 = top->put(nameBuf, valBuf, true);
  779.       break;
  780.     case PropertiesType_Properties:
  781.       assert(0);
  782.     }
  783.     if(!res3){
  784.       return false;
  785.     }
  786.     _items--;
  787.   }
  788.   return true;
  789. }
  790. PropertyImpl::~PropertyImpl(){
  791.   free((char*)name);
  792.   switch(valueType){
  793.   case PropertiesType_Uint32:
  794.     delete (Uint32 *)value;
  795.     break;
  796.   case PropertiesType_Uint64:
  797.     delete (Uint64 *)value;
  798.     break;
  799.   case PropertiesType_char:
  800.     free((char *)value);
  801.     break;
  802.   case PropertiesType_Properties:
  803.     delete (Properties *)value;
  804.     break;
  805.   }
  806. }
  807. PropertyImpl *
  808. PropertyImpl::copyPropertyImpl(const PropertyImpl & org){
  809.   switch(org.valueType){
  810.   case PropertiesType_Uint32:
  811.     return new PropertyImpl(org.name, * (Uint32 *)org.value);
  812.   case PropertiesType_Uint64:
  813.     return new PropertyImpl(org.name, * (Uint64 *)org.value);
  814.     break;
  815.   case PropertiesType_char:
  816.     return new PropertyImpl(org.name, (char *)org.value);
  817.     break;
  818.   case PropertiesType_Properties:
  819.     return new PropertyImpl(org.name, (Properties *)org.value);
  820.     break;
  821.   default:
  822.     assert(0);
  823.   }
  824.   return 0;
  825. }
  826. PropertyImpl::PropertyImpl(const char * _name, Uint32 _value){
  827.   this->name = f_strdup(_name);
  828.   this->value = new Uint32;
  829.   * ((Uint32 *)this->value) = _value;
  830.   this->valueType = PropertiesType_Uint32;
  831. }
  832. PropertyImpl::PropertyImpl(const char * _name, Uint64 _value){
  833.   this->name = f_strdup(_name);
  834.   this->value = new Uint64;
  835.   * ((Uint64 *)this->value) = _value;
  836.   this->valueType = PropertiesType_Uint64;
  837. }
  838. PropertyImpl::PropertyImpl(const char * _name, const char * _value){
  839.   this->name = f_strdup(_name);
  840.   this->value = f_strdup(_value);
  841.   this->valueType = PropertiesType_char;
  842. }
  843. PropertyImpl::PropertyImpl(const char * _name, const Properties * _value){
  844.   this->name = f_strdup(_name);
  845.   this->value = new Properties(* _value);
  846.   this->valueType = PropertiesType_Properties;
  847. }
  848. const Uint32 E_PROPERTIES_OK                                      = 0;
  849. const Uint32 E_PROPERTIES_INVALID_NAME                            = 1;
  850. const Uint32 E_PROPERTIES_NO_SUCH_ELEMENT                         = 2;
  851. const Uint32 E_PROPERTIES_INVALID_TYPE                            = 3;
  852. const Uint32 E_PROPERTIES_ELEMENT_ALREADY_EXISTS                  = 4;
  853. const Uint32 E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING              = 5;
  854. const Uint32 E_PROPERTIES_INVALID_VERSION_WHILE_UNPACKING         = 6;
  855. const Uint32 E_PROPERTIES_INVALID_BUFFER_TO_SHORT                 = 7;
  856. const Uint32 E_PROPERTIES_ERROR_MALLOC_WHILE_UNPACKING            = 8;
  857. const Uint32 E_PROPERTIES_INVALID_CHECKSUM                        = 9;
  858. const Uint32 E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING         = 10;
  859. /**
  860.  * These are methods that used to be inline
  861.  *
  862.  * But Diab 4.1f could not compile -release with to many inlines
  863.  */
  864. void
  865. Properties::setErrno(Uint32 pErr, Uint32 osErr) const {
  866.   if(parent != 0){
  867.     parent->setErrno(pErr, osErr);
  868.     return ;
  869.   }
  870.   
  871.   /**
  872.    * propErrno & osErrno used to be mutable,
  873.    * but diab didn't know what mutable meant.
  874.    */
  875.   *((Uint32*)&propErrno) = pErr;
  876.   *((Uint32*)&osErrno)   = osErr;
  877. }
  878. /**
  879.  * Inlined get/put(name, no, ...) - methods
  880.  */
  881.  
  882. bool
  883. Properties::put(const char * name, Uint32 no, Uint32 val, bool replace){
  884.   size_t tmp_len = strlen(name)+20;
  885.   char * tmp = (char*)malloc(tmp_len);
  886.   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
  887.   bool res = put(tmp, val, replace);
  888.   free(tmp);
  889.   return res;
  890. }
  891. bool
  892. Properties::put64(const char * name, Uint32 no, Uint64 val, bool replace){
  893.   size_t tmp_len = strlen(name)+20;
  894.   char * tmp = (char*)malloc(tmp_len);
  895.   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
  896.   bool res = put(tmp, val, replace);
  897.   free(tmp);
  898.   return res;
  899. }
  900. bool 
  901. Properties::put(const char * name, Uint32 no, const char * val, bool replace){
  902.   size_t tmp_len = strlen(name)+20;
  903.   char * tmp = (char*)malloc(tmp_len);
  904.   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
  905.   bool res = put(tmp, val, replace);
  906.   free(tmp);
  907.   return res;
  908. }
  909. bool 
  910. Properties::put(const char * name, Uint32 no, const Properties * val, 
  911. bool replace){
  912.   size_t tmp_len = strlen(name)+20;
  913.   char * tmp = (char*)malloc(tmp_len);
  914.   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
  915.   bool res = put(tmp, val, replace);
  916.   free(tmp);
  917.   return res;
  918. }
  919. bool 
  920. Properties::getTypeOf(const char * name, Uint32 no, 
  921.       PropertiesType * type) const {
  922.   size_t tmp_len = strlen(name)+20;
  923.   char * tmp = (char*)malloc(tmp_len);
  924.   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
  925.   bool res = getTypeOf(tmp, type);
  926.   free(tmp);
  927.   return res;
  928. }
  929. bool 
  930. Properties::contains(const char * name, Uint32 no) const {
  931.   size_t tmp_len = strlen(name)+20;
  932.   char * tmp = (char*)malloc(tmp_len);
  933.   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
  934.   bool res = contains(tmp);
  935.   free(tmp);
  936.   return res;
  937. }
  938. bool 
  939. Properties::get(const char * name, Uint32 no, Uint32 * value) const{
  940.   size_t tmp_len = strlen(name)+20;
  941.   char * tmp = (char*)malloc(tmp_len);
  942.   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
  943.   bool res = get(tmp, value);
  944.   free(tmp);
  945.   return res;
  946. }
  947. bool 
  948. Properties::get(const char * name, Uint32 no, Uint64 * value) const{
  949.   size_t tmp_len = strlen(name)+20;
  950.   char * tmp = (char*)malloc(tmp_len);
  951.   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
  952.   bool res = get(tmp, value);
  953.   free(tmp);
  954.   return res;
  955. }
  956. bool 
  957. Properties::get(const char * name, Uint32 no, const char ** value) const {
  958.   size_t tmp_len = strlen(name)+20;
  959.   char * tmp = (char*)malloc(tmp_len);
  960.   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
  961.   bool res = get(tmp, value);
  962.   free(tmp);
  963.   return res;
  964. }
  965. bool 
  966. Properties::get(const char * name, Uint32 no, const Properties ** value) const{
  967.   size_t tmp_len = strlen(name)+20;
  968.   char * tmp = (char*)malloc(tmp_len);
  969.   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
  970.   bool res = get(tmp, value);
  971.   free(tmp);
  972.   return res;
  973. }
  974. bool 
  975. Properties::getCopy(const char * name, Uint32 no, char ** value) const {
  976.   size_t tmp_len = strlen(name)+20;
  977.   char * tmp = (char*)malloc(tmp_len);
  978.   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
  979.   bool res = getCopy(tmp, value);
  980.   free(tmp);
  981.   return res;
  982. }
  983. bool 
  984. Properties::getCopy(const char * name, Uint32 no, Properties ** value) const {
  985.   size_t tmp_len = strlen(name)+20;
  986.   char * tmp = (char*)malloc(tmp_len);
  987.   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
  988.   bool res = getCopy(tmp, value);
  989.   free(tmp);
  990.   return res;
  991. }
  992. void
  993. Properties::setCaseInsensitiveNames(bool value){
  994.   impl->setCaseInsensitiveNames(value);
  995. }
  996. bool
  997. Properties::getCaseInsensitiveNames() const {
  998.   return impl->m_insensitive;
  999. }
  1000. template bool put(PropertiesImpl *, const char *, Uint32, bool);
  1001. template bool put(PropertiesImpl *, const char *, Uint64, bool);
  1002. template bool put(PropertiesImpl *, const char *, const char *, bool);
  1003. template bool put(PropertiesImpl *, const char *, const Properties*, bool);