00001 /* Copyright (C) 2003 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 #include <ndb_global.h> 00018 00019 #include <Properties.hpp> 00020 00021 #include <NdbTCP.h> 00022 #include <NdbOut.hpp> 00023 00024 static 00025 char * f_strdup(const char * s){ 00026 if(!s) return 0; 00027 return strdup(s); 00028 } 00029 00033 const char Properties::version[] = { 2, 0, 0, 1, 1, 1, 1, 4 }; 00034 const char Properties::delimiter = ':'; 00035 00039 struct PropertyImpl{ 00040 PropertiesType valueType; 00041 const char * name; 00042 void * value; 00043 00044 ~PropertyImpl(); 00045 PropertyImpl(const char * name, Uint32 value); 00046 PropertyImpl(const char * name, Uint64 value); 00047 PropertyImpl(const char * name, const char * value); 00048 PropertyImpl(const char * name, const Properties * value); 00049 00050 static PropertyImpl * copyPropertyImpl(const PropertyImpl &); 00051 }; 00052 00056 class PropertiesImpl { 00057 PropertiesImpl(const PropertiesImpl &); // Not implemented 00058 PropertiesImpl& operator=(const PropertiesImpl&); // Not implemented 00059 public: 00060 PropertiesImpl(Properties *, bool case_insensitive); 00061 PropertiesImpl(Properties *, const PropertiesImpl &); 00062 ~PropertiesImpl(); 00063 00064 Properties * properties; 00065 00066 Uint32 size; 00067 Uint32 items; 00068 PropertyImpl **content; 00069 00070 bool m_insensitive; 00071 int (* compare)(const char *s1, const char *s2); 00072 00073 void setCaseInsensitiveNames(bool value); 00074 void grow(int sizeToAdd); 00075 00076 PropertyImpl * get(const char * name) const; 00077 PropertyImpl * put(PropertyImpl *); 00078 void remove(const char * name); 00079 00080 Uint32 getPackedSize(Uint32 pLen) const; 00081 bool pack(Uint32 *& buf, const char * prefix, Uint32 prefixLen) const; 00082 bool unpack(const Uint32 * buf, Uint32 &bufLen, Properties * top, int items); 00083 00084 Uint32 getTotalItems() const; 00085 00086 void setErrno(Uint32 pErr, Uint32 osErr = 0){ 00087 properties->setErrno(pErr, osErr); 00088 } 00089 00090 const char * getProps(const char * name, const PropertiesImpl ** impl) const; 00091 const char * getPropsPut(const char * name, PropertiesImpl ** impl); 00092 }; 00093 00097 Property::Property(const char * name, Uint32 value){ 00098 impl = new PropertyImpl(name, value); 00099 } 00100 00101 Property::Property(const char * name, const char * value){ 00102 impl = new PropertyImpl(name, value); 00103 } 00104 00105 Property::Property(const char * name, const class Properties * value){ 00106 impl = new PropertyImpl(name, value); 00107 00108 ((Properties*)impl->value)->setCaseInsensitiveNames(value->getCaseInsensitiveNames()); 00109 } 00110 00111 Property::~Property(){ 00112 delete impl; 00113 } 00114 00118 Properties::Properties(bool case_insensitive){ 00119 parent = 0; 00120 impl = new PropertiesImpl(this, case_insensitive); 00121 } 00122 00123 Properties::Properties(const Properties & org){ 00124 parent = 0; 00125 impl = new PropertiesImpl(this, * org.impl); 00126 } 00127 00128 Properties::Properties(const Property * anArray, int arrayLen){ 00129 impl = new PropertiesImpl(this, false); 00130 00131 put(anArray, arrayLen); 00132 } 00133 00134 Properties::~Properties(){ 00135 clear(); 00136 delete impl; 00137 } 00138 00139 void 00140 Properties::put(const Property * anArray, int arrayLen){ 00141 if(anArray == 0) 00142 return; 00143 for(int i = 0; i<arrayLen; i++) 00144 impl->put(anArray[i].impl); 00145 } 00146 00147 template <class T> 00148 bool 00149 put(PropertiesImpl * impl, const char * name, T value, bool replace){ 00150 if(name == 0){ 00151 impl->setErrno(E_PROPERTIES_INVALID_NAME); 00152 return false; 00153 } 00154 00155 PropertiesImpl * tmp = 0; 00156 const char * short_name = impl->getPropsPut(name, &tmp); 00157 00158 if(tmp == 0){ 00159 impl->setErrno(E_PROPERTIES_NO_SUCH_ELEMENT); 00160 return false; 00161 } 00162 00163 if(tmp->get(short_name) != 0){ 00164 if(replace){ 00165 tmp->remove(short_name); 00166 } else { 00167 impl->setErrno(E_PROPERTIES_ELEMENT_ALREADY_EXISTS); 00168 return false; 00169 } 00170 } 00171 return tmp->put(new PropertyImpl(short_name, value)); 00172 } 00173 00174 00175 bool 00176 Properties::put(const char * name, Uint32 value, bool replace){ 00177 return ::put(impl, name, value, replace); 00178 } 00179 00180 bool 00181 Properties::put64(const char * name, Uint64 value, bool replace){ 00182 return ::put(impl, name, value, replace); 00183 } 00184 00185 bool 00186 Properties::put(const char * name, const char * value, bool replace){ 00187 return ::put(impl, name, value, replace); 00188 } 00189 00190 bool 00191 Properties::put(const char * name, const Properties * value, bool replace){ 00192 return ::put(impl, name, value, replace); 00193 } 00194 00195 bool 00196 Properties::getTypeOf(const char * name, PropertiesType * type) const { 00197 PropertyImpl * nvp = impl->get(name); 00198 if(nvp == 0){ 00199 setErrno(E_PROPERTIES_NO_SUCH_ELEMENT); 00200 return false; 00201 } 00202 setErrno(E_PROPERTIES_OK); 00203 * type = nvp->valueType; 00204 return true; 00205 } 00206 00207 bool 00208 Properties::contains(const char * name) const { 00209 PropertyImpl * nvp = impl->get(name); 00210 return nvp != 0; 00211 } 00212 00213 bool 00214 Properties::get(const char * name, Uint32 * value) const { 00215 PropertyImpl * nvp = impl->get(name); 00216 if(nvp == 0){ 00217 setErrno(E_PROPERTIES_NO_SUCH_ELEMENT); 00218 return false; 00219 } 00220 00221 if(nvp->valueType == PropertiesType_Uint32){ 00222 * value = * (Uint32 *)nvp->value; 00223 setErrno(E_PROPERTIES_OK); 00224 return true; 00225 } 00226 00227 if(nvp->valueType == PropertiesType_Uint64){ 00228 Uint64 tmp = * (Uint64 *)nvp->value; 00229 Uint64 max = 1; max <<= 32; 00230 if(tmp < max){ 00231 * value = (Uint32)tmp; 00232 setErrno(E_PROPERTIES_OK); 00233 return true; 00234 } 00235 } 00236 setErrno(E_PROPERTIES_INVALID_TYPE); 00237 return false; 00238 } 00239 00240 bool 00241 Properties::get(const char * name, Uint64 * value) const { 00242 PropertyImpl * nvp = impl->get(name); 00243 if(nvp == 0){ 00244 setErrno(E_PROPERTIES_NO_SUCH_ELEMENT); 00245 return false; 00246 } 00247 00248 if(nvp->valueType == PropertiesType_Uint32){ 00249 Uint32 tmp = * (Uint32 *)nvp->value; 00250 * value = (Uint64)tmp; 00251 setErrno(E_PROPERTIES_OK); 00252 return true; 00253 } 00254 00255 if(nvp->valueType == PropertiesType_Uint64){ 00256 * value = * (Uint64 *)nvp->value; 00257 setErrno(E_PROPERTIES_OK); 00258 return true; 00259 } 00260 setErrno(E_PROPERTIES_INVALID_TYPE); 00261 return false; 00262 } 00263 00264 bool 00265 Properties::get(const char * name, const char ** value) const { 00266 PropertyImpl * nvp = impl->get(name); 00267 if(nvp == 0){ 00268 setErrno(E_PROPERTIES_NO_SUCH_ELEMENT); 00269 return false; 00270 } 00271 00272 if(nvp->valueType == PropertiesType_char){ 00273 * value = (const char *)nvp->value; 00274 setErrno(E_PROPERTIES_OK); 00275 return true; 00276 } 00277 setErrno(E_PROPERTIES_INVALID_TYPE); 00278 return false; 00279 } 00280 00281 bool 00282 Properties::get(const char * name, BaseString& value) const { 00283 const char *tmp = ""; 00284 bool ret; 00285 ret = get(name, &tmp); 00286 value.assign(tmp); 00287 return ret; 00288 } 00289 00290 bool 00291 Properties::get(const char * name, const Properties ** value) const { 00292 PropertyImpl * nvp = impl->get(name); 00293 if(nvp == 0){ 00294 setErrno(E_PROPERTIES_NO_SUCH_ELEMENT); 00295 return false; 00296 } 00297 if(nvp->valueType == PropertiesType_Properties){ 00298 * value = (const Properties *)nvp->value; 00299 setErrno(E_PROPERTIES_OK); 00300 return true; 00301 } 00302 setErrno(E_PROPERTIES_INVALID_TYPE); 00303 return false; 00304 } 00305 00306 bool 00307 Properties::getCopy(const char * name, char ** value) const { 00308 PropertyImpl * nvp = impl->get(name); 00309 if(nvp == 0){ 00310 setErrno(E_PROPERTIES_NO_SUCH_ELEMENT); 00311 return false; 00312 } 00313 00314 if(nvp->valueType == PropertiesType_char){ 00315 * value = f_strdup((const char *)nvp->value); 00316 setErrno(E_PROPERTIES_OK); 00317 return true; 00318 } 00319 setErrno(E_PROPERTIES_INVALID_TYPE); 00320 return false; 00321 } 00322 00323 bool 00324 Properties::getCopy(const char * name, Properties ** value) const { 00325 PropertyImpl * nvp = impl->get(name); 00326 if(nvp == 0){ 00327 setErrno(E_PROPERTIES_NO_SUCH_ELEMENT); 00328 return false; 00329 } 00330 00331 if(nvp->valueType == PropertiesType_Properties){ 00332 * value = new Properties(* (const Properties *)nvp->value); 00333 setErrno(E_PROPERTIES_OK); 00334 return true; 00335 } 00336 setErrno(E_PROPERTIES_INVALID_TYPE); 00337 return false; 00338 } 00339 00340 void 00341 Properties::clear(){ 00342 while(impl->items > 0) 00343 impl->remove(impl->content[0]->name); 00344 } 00345 00346 void 00347 Properties::remove(const char * name) { 00348 impl->remove(name); 00349 } 00350 00351 void 00352 Properties::print(FILE * out, const char * prefix) const{ 00353 char buf[1024]; 00354 if(prefix == 0) 00355 buf[0] = 0; 00356 else 00357 strncpy(buf, prefix, 1024); 00358 00359 for(unsigned int i = 0; i<impl->items; i++){ 00360 switch(impl->content[i]->valueType){ 00361 case PropertiesType_Uint32: 00362 fprintf(out, "%s%s = (Uint32) %d\n", buf, impl->content[i]->name, 00363 *(Uint32 *)impl->content[i]->value); 00364 break; 00365 case PropertiesType_Uint64: 00366 fprintf(out, "%s%s = (Uint64) %lld\n", buf, impl->content[i]->name, 00367 *(Uint64 *)impl->content[i]->value); 00368 break; 00369 case PropertiesType_char: 00370 fprintf(out, "%s%s = (char*) \"%s\"\n", buf, impl->content[i]->name, 00371 (char *)impl->content[i]->value); 00372 break; 00373 case PropertiesType_Properties: 00374 char buf2 [1024]; 00375 BaseString::snprintf(buf2, sizeof(buf2), "%s%s%c",buf, impl->content[i]->name, 00376 Properties::delimiter); 00377 ((Properties *)impl->content[i]->value)->print(out, buf2); 00378 break; 00379 } 00380 } 00381 } 00382 00383 Properties::Iterator::Iterator(const Properties* prop) : 00384 m_prop(prop), 00385 m_iterator(0) { 00386 } 00387 00388 const char* 00389 Properties::Iterator::first() { 00390 m_iterator = 0; 00391 return next(); 00392 } 00393 00394 const char* 00395 Properties::Iterator::next() { 00396 if (m_iterator < m_prop->impl->items) 00397 return m_prop->impl->content[m_iterator++]->name; 00398 else 00399 return NULL; 00400 } 00401 00402 Uint32 00403 Properties::getPackedSize() const { 00404 Uint32 sz = 0; 00405 00406 sz += sizeof(version); // Version id of properties object 00407 sz += 4; // No Of Items 00408 sz += 4; // Checksum 00409 00410 return sz + impl->getPackedSize(0); 00411 } 00412 00413 static 00414 Uint32 00415 computeChecksum(const Uint32 * buf, Uint32 words){ 00416 Uint32 sum = 0; 00417 for(unsigned int i = 0; i<words; i++) 00418 sum ^= htonl(buf[i]); 00419 00420 return sum; 00421 } 00422 00423 bool 00424 Properties::pack(Uint32 * buf) const { 00425 Uint32 * bufStart = buf; 00426 00427 memcpy(buf, version, sizeof(version)); 00428 00429 // Note that version must be a multiple of 4 00430 buf += (sizeof(version) / 4); 00431 00432 * buf = htonl(impl->getTotalItems()); 00433 buf++; 00434 bool res = impl->pack(buf, "", 0); 00435 if(!res) 00436 return res; 00437 00438 * buf = htonl(computeChecksum(bufStart, (buf - bufStart))); 00439 00440 return true; 00441 } 00442 00443 bool 00444 Properties::unpack(const Uint32 * buf, Uint32 bufLen){ 00445 const Uint32 * bufStart = buf; 00446 Uint32 bufLenOrg = bufLen; 00447 00448 if(bufLen < sizeof(version)){ 00449 setErrno(E_PROPERTIES_INVALID_BUFFER_TO_SHORT); 00450 return false; 00451 } 00452 00453 if(memcmp(buf, version, sizeof(version)) != 0){ 00454 setErrno(E_PROPERTIES_INVALID_VERSION_WHILE_UNPACKING); 00455 return false; 00456 } 00457 bufLen -= sizeof(version); 00458 00459 // Note that version must be a multiple of 4 00460 buf += (sizeof(version) / 4); 00461 00462 if(bufLen < 4){ 00463 setErrno(E_PROPERTIES_INVALID_BUFFER_TO_SHORT); 00464 return false; 00465 } 00466 00467 Uint32 totalItems = ntohl(* buf); 00468 buf++; bufLen -= 4; 00469 bool res = impl->unpack(buf, bufLen, this, totalItems); 00470 if(!res) 00471 return res; 00472 00473 Uint32 sum = computeChecksum(bufStart, (bufLenOrg-bufLen)/4); 00474 if(sum != ntohl(bufStart[(bufLenOrg-bufLen)/4])){ 00475 setErrno(E_PROPERTIES_INVALID_CHECKSUM); 00476 return false; 00477 } 00478 return true; 00479 } 00480 00484 PropertiesImpl::PropertiesImpl(Properties * p, bool case_insensitive){ 00485 this->properties = p; 00486 items = 0; 00487 size = 25; 00488 content = new PropertyImpl * [size]; 00489 setCaseInsensitiveNames(case_insensitive); 00490 } 00491 00492 PropertiesImpl::PropertiesImpl(Properties * p, const PropertiesImpl & org){ 00493 this->properties = p; 00494 this->size = org.size; 00495 this->items = org.items; 00496 this->m_insensitive = org.m_insensitive; 00497 this->compare = org.compare; 00498 content = new PropertyImpl * [size]; 00499 for(unsigned int i = 0; i<items; i++){ 00500 content[i] = PropertyImpl::copyPropertyImpl(* org.content[i]); 00501 } 00502 } 00503 00504 PropertiesImpl::~PropertiesImpl(){ 00505 for(unsigned int i = 0; i<items; i++) 00506 delete content[i]; 00507 delete [] content; 00508 } 00509 00510 void 00511 PropertiesImpl::setCaseInsensitiveNames(bool value){ 00512 m_insensitive = value; 00513 if(value) 00514 compare = strcasecmp; 00515 else 00516 compare = strcmp; 00517 } 00518 00519 void 00520 PropertiesImpl::grow(int sizeToAdd){ 00521 PropertyImpl ** newContent = new PropertyImpl * [size + sizeToAdd]; 00522 memcpy(newContent, content, items * sizeof(PropertyImpl *)); 00523 delete [] content; 00524 content = newContent; 00525 size += sizeToAdd; 00526 } 00527 00528 PropertyImpl * 00529 PropertiesImpl::get(const char * name) const { 00530 const PropertiesImpl * tmp = 0; 00531 const char * short_name = getProps(name, &tmp); 00532 if(tmp == 0){ 00533 return 0; 00534 } 00535 00536 for(unsigned int i = 0; i<tmp->items; i++) { 00537 if((* compare)(tmp->content[i]->name, short_name) == 0) 00538 return tmp->content[i]; 00539 } 00540 00541 return 0; 00542 } 00543 00544 PropertyImpl * 00545 PropertiesImpl::put(PropertyImpl * nvp){ 00546 if(items == size) 00547 grow(size); 00548 content[items] = nvp; 00549 00550 items ++; 00551 00552 if(nvp->valueType == PropertiesType_Properties){ 00553 ((Properties*)nvp->value)->parent = properties; 00554 } 00555 return nvp; 00556 } 00557 00558 void 00559 PropertiesImpl::remove(const char * name){ 00560 for(unsigned int i = 0; i<items; i++){ 00561 if((* compare)(content[i]->name, name) == 0){ 00562 delete content[i]; 00563 memmove(&content[i], &content[i+1], (items-i-1)*sizeof(PropertyImpl *)); 00564 items --; 00565 return; 00566 } 00567 } 00568 } 00569 00570 Uint32 00571 PropertiesImpl::getTotalItems() const { 00572 int ret = 0; 00573 for(unsigned int i = 0; i<items; i++) 00574 if(content[i]->valueType == PropertiesType_Properties){ 00575 ret += ((Properties*)content[i]->value)->impl->getTotalItems(); 00576 } else { 00577 ret ++; 00578 } 00579 return ret; 00580 } 00581 00582 const char * 00583 PropertiesImpl::getProps(const char * name, 00584 const PropertiesImpl ** impl) const { 00585 const char * ret = name; 00586 const char * tmp = strchr(name, Properties::delimiter); 00587 if(tmp == 0){ 00588 * impl = this; 00589 return ret; 00590 } else { 00591 Uint32 sz = tmp - name; 00592 char * tmp2 = (char*)malloc(sz + 1); 00593 memcpy(tmp2, name, sz); 00594 tmp2[sz] = 0; 00595 00596 PropertyImpl * nvp = get(tmp2); 00597 00598 free(tmp2); 00599 00600 if(nvp == 0){ 00601 * impl = 0; 00602 return 0; 00603 } 00604 if(nvp->valueType != PropertiesType_Properties){ 00605 * impl = 0; 00606 return name; 00607 } 00608 return ((Properties*)nvp->value)->impl->getProps(tmp+1, impl); 00609 } 00610 } 00611 00612 const char * 00613 PropertiesImpl::getPropsPut(const char * name, 00614 PropertiesImpl ** impl) { 00615 const char * ret = name; 00616 const char * tmp = strchr(name, Properties::delimiter); 00617 if(tmp == 0){ 00618 * impl = this; 00619 return ret; 00620 } else { 00621 Uint32 sz = tmp - name; 00622 char * tmp2 = (char*)malloc(sz + 1); 00623 memcpy(tmp2, name, sz); 00624 tmp2[sz] = 0; 00625 00626 PropertyImpl * nvp = get(tmp2); 00627 00628 if(nvp == 0){ 00629 Properties * tmpP = new Properties(); 00630 PropertyImpl * tmpPI = new PropertyImpl(tmp2, tmpP); 00631 PropertyImpl * nvp = put(tmpPI); 00632 00633 delete tmpP; 00634 free(tmp2); 00635 return ((Properties*)nvp->value)->impl->getPropsPut(tmp+1, impl); 00636 } 00637 free(tmp2); 00638 if(nvp->valueType != PropertiesType_Properties){ 00639 * impl = 0; 00640 return name; 00641 } 00642 return ((Properties*)nvp->value)->impl->getPropsPut(tmp+1, impl); 00643 } 00644 } 00645 00646 int 00647 mod4(unsigned int i){ 00648 int res = i + (4 - (i % 4)); 00649 return res; 00650 } 00651 00652 Uint32 00653 PropertiesImpl::getPackedSize(Uint32 pLen) const { 00654 Uint32 sz = 0; 00655 for(unsigned int i = 0; i<items; i++){ 00656 if(content[i]->valueType == PropertiesType_Properties){ 00657 Properties * p = (Properties*)content[i]->value; 00658 sz += p->impl->getPackedSize(pLen+strlen(content[i]->name)+1); 00659 } else { 00660 sz += 4; // Type 00661 sz += 4; // Name Len 00662 sz += 4; // Value Len 00663 sz += mod4(pLen + strlen(content[i]->name)); // Name 00664 switch(content[i]->valueType){ 00665 case PropertiesType_char: 00666 sz += mod4(strlen((char *)content[i]->value)); 00667 break; 00668 case PropertiesType_Uint32: 00669 sz += mod4(4); 00670 break; 00671 case PropertiesType_Uint64: 00672 sz += mod4(8); 00673 break; 00674 case PropertiesType_Properties: 00675 default: 00676 assert(0); 00677 } 00678 } 00679 } 00680 return sz; 00681 } 00682 00683 struct CharBuf { 00684 char * buffer; 00685 Uint32 bufLen; 00686 Uint32 contentLen; 00687 00688 CharBuf(){ 00689 buffer = 0; 00690 bufLen = 0; 00691 contentLen = 0; 00692 } 00693 00694 ~CharBuf(){ 00695 free(buffer); 00696 } 00697 00698 void clear() { contentLen = 0;} 00699 bool add(const char * str, Uint32 strLen){ 00700 if(!expand(contentLen + strLen + 1)) 00701 return false; 00702 memcpy(&buffer[contentLen], str, strLen); 00703 contentLen += strLen; 00704 buffer[contentLen] = 0; 00705 return true; 00706 } 00707 00708 bool add(char c){ 00709 return add(&c, 1); 00710 } 00711 00712 bool expand(Uint32 newSize){ 00713 if(newSize >= bufLen){ 00714 00715 char * tmp = (char*)malloc(newSize + 1024); 00716 memset(tmp, 0, newSize + 1024); 00717 if(tmp == 0) 00718 return false; 00719 if(contentLen > 0) 00720 memcpy(tmp, buffer, contentLen); 00721 if(buffer != 0) 00722 free(buffer); 00723 buffer = tmp; 00724 bufLen = newSize + 1024; 00725 } 00726 return true; 00727 } 00728 }; 00729 00730 bool 00731 PropertiesImpl::pack(Uint32 *& buf, const char * prefix, Uint32 pLen) const { 00732 CharBuf charBuf; 00733 00734 for(unsigned int i = 0; i<items; i++){ 00735 const int strLenName = strlen(content[i]->name); 00736 00737 if(content[i]->valueType == PropertiesType_Properties){ 00738 charBuf.clear(); 00739 if(!charBuf.add(prefix, pLen)){ 00740 properties->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING, 00741 errno); 00742 return false; 00743 } 00744 00745 if(!charBuf.add(content[i]->name, strLenName)){ 00746 properties->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING, 00747 errno); 00748 return false; 00749 } 00750 00751 if(!charBuf.add(Properties::delimiter)){ 00752 properties->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING, 00753 errno); 00754 return false; 00755 } 00756 00757 if(!((Properties*)(content[i]->value))->impl->pack(buf, 00758 charBuf.buffer, 00759 charBuf.contentLen)){ 00760 00761 return false; 00762 } 00763 continue; 00764 } 00765 00766 Uint32 valLenData = 0; 00767 Uint32 valLenWrite = 0; 00768 Uint32 sz = 4 + 4 + 4 + mod4(pLen + strLenName); 00769 switch(content[i]->valueType){ 00770 case PropertiesType_Uint32: 00771 valLenData = 4; 00772 break; 00773 case PropertiesType_Uint64: 00774 valLenData = 8; 00775 break; 00776 case PropertiesType_char: 00777 valLenData = strlen((char *)content[i]->value); 00778 break; 00779 case PropertiesType_Properties: 00780 assert(0); 00781 } 00782 valLenWrite = mod4(valLenData); 00783 sz += valLenWrite; 00784 00785 * (buf + 0) = htonl(content[i]->valueType); 00786 * (buf + 1) = htonl(pLen + strLenName); 00787 * (buf + 2) = htonl(valLenData); 00788 00789 char * valBuf = (char*)(buf + 3); 00790 char * nameBuf = (char*)(buf + 3 + (valLenWrite / 4)); 00791 00792 memset(valBuf, 0, sz-12); 00793 00794 switch(content[i]->valueType){ 00795 case PropertiesType_Uint32: 00796 * (Uint32 *)valBuf = htonl(* (Uint32 *)content[i]->value); 00797 break; 00798 case PropertiesType_Uint64:{ 00799 Uint64 val = * (Uint64 *)content[i]->value; 00800 Uint32 hi = (val >> 32); 00801 Uint32 lo = (val & 0xFFFFFFFF); 00802 * (Uint32 *)valBuf = htonl(hi); 00803 * (Uint32 *)(valBuf + 4) = htonl(lo); 00804 } 00805 break; 00806 case PropertiesType_char: 00807 memcpy(valBuf, content[i]->value, strlen((char*)content[i]->value)); 00808 break; 00809 case PropertiesType_Properties: 00810 assert(0); 00811 } 00812 if(pLen > 0) 00813 memcpy(nameBuf, prefix, pLen); 00814 memcpy(nameBuf + pLen, content[i]->name, strLenName); 00815 00816 buf += (sz / 4); 00817 } 00818 00819 return true; 00820 } 00821 00822 bool 00823 PropertiesImpl::unpack(const Uint32 * buf, Uint32 &bufLen, Properties * top, 00824 int _items){ 00825 CharBuf charBuf; 00826 while(_items > 0){ 00827 Uint32 tmp[3]; 00828 00829 if(bufLen <= 12){ 00830 top->setErrno(E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING); 00831 return false; 00832 } 00833 00834 tmp[0] = ntohl(buf[0]); 00835 tmp[1] = ntohl(buf[1]); 00836 tmp[2] = ntohl(buf[2]); 00837 buf += 3; 00838 bufLen -= 12; 00839 00840 PropertiesType pt = (PropertiesType)tmp[0]; 00841 Uint32 nameLen = tmp[1]; 00842 Uint32 valueLen = tmp[2]; 00843 Uint32 nameLenRead = mod4(nameLen); 00844 Uint32 valueLenRead = mod4(valueLen); 00845 00846 Uint32 sz = nameLenRead + valueLenRead; 00847 if(bufLen < sz){ 00848 top->setErrno(E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING); 00849 return false; 00850 } 00851 00852 if(!charBuf.expand(sz)){ 00853 top->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_UNPACKING, errno); 00854 return false; 00855 } 00856 00857 memcpy(charBuf.buffer, buf, sz); 00858 buf += (sz / 4); 00859 bufLen -= sz ; 00860 00861 char * valBuf = charBuf.buffer; 00862 char * nameBuf = charBuf.buffer + valueLenRead; 00863 00864 nameBuf[nameLen] = 0; 00865 valBuf[valueLen] = 0; 00866 00867 bool res3 = false; 00868 switch(pt){ 00869 case PropertiesType_Uint32: 00870 res3 = top->put(nameBuf, ntohl(* (Uint32 *)valBuf), true); 00871 break; 00872 case PropertiesType_Uint64:{ 00873 Uint64 hi = ntohl(* (Uint32 *)valBuf); 00874 Uint64 lo = ntohl(* (Uint32 *)(valBuf + 4)); 00875 res3 = top->put64(nameBuf, (hi << 32) + lo, true); 00876 } 00877 break; 00878 case PropertiesType_char: 00879 res3 = top->put(nameBuf, valBuf, true); 00880 break; 00881 case PropertiesType_Properties: 00882 assert(0); 00883 } 00884 if(!res3){ 00885 return false; 00886 } 00887 _items--; 00888 } 00889 return true; 00890 } 00891 00892 PropertyImpl::~PropertyImpl(){ 00893 free((char*)name); 00894 switch(valueType){ 00895 case PropertiesType_Uint32: 00896 delete (Uint32 *)value; 00897 break; 00898 case PropertiesType_Uint64: 00899 delete (Uint64 *)value; 00900 break; 00901 case PropertiesType_char: 00902 free((char *)value); 00903 break; 00904 case PropertiesType_Properties: 00905 delete (Properties *)value; 00906 break; 00907 } 00908 } 00909 00910 PropertyImpl * 00911 PropertyImpl::copyPropertyImpl(const PropertyImpl & org){ 00912 switch(org.valueType){ 00913 case PropertiesType_Uint32: 00914 return new PropertyImpl(org.name, * (Uint32 *)org.value); 00915 case PropertiesType_Uint64: 00916 return new PropertyImpl(org.name, * (Uint64 *)org.value); 00917 break; 00918 case PropertiesType_char: 00919 return new PropertyImpl(org.name, (char *)org.value); 00920 break; 00921 case PropertiesType_Properties: 00922 return new PropertyImpl(org.name, (Properties *)org.value); 00923 break; 00924 default: 00925 assert(0); 00926 } 00927 return 0; 00928 } 00929 00930 PropertyImpl::PropertyImpl(const char * _name, Uint32 _value){ 00931 this->name = f_strdup(_name); 00932 this->value = new Uint32; 00933 * ((Uint32 *)this->value) = _value; 00934 this->valueType = PropertiesType_Uint32; 00935 } 00936 00937 PropertyImpl::PropertyImpl(const char * _name, Uint64 _value){ 00938 this->name = f_strdup(_name); 00939 this->value = new Uint64; 00940 * ((Uint64 *)this->value) = _value; 00941 this->valueType = PropertiesType_Uint64; 00942 } 00943 00944 PropertyImpl::PropertyImpl(const char * _name, const char * _value){ 00945 this->name = f_strdup(_name); 00946 this->value = f_strdup(_value); 00947 this->valueType = PropertiesType_char; 00948 00949 } 00950 00951 PropertyImpl::PropertyImpl(const char * _name, const Properties * _value){ 00952 this->name = f_strdup(_name); 00953 this->value = new Properties(* _value); 00954 this->valueType = PropertiesType_Properties; 00955 } 00956 00957 const Uint32 E_PROPERTIES_OK = 0; 00958 const Uint32 E_PROPERTIES_INVALID_NAME = 1; 00959 const Uint32 E_PROPERTIES_NO_SUCH_ELEMENT = 2; 00960 const Uint32 E_PROPERTIES_INVALID_TYPE = 3; 00961 const Uint32 E_PROPERTIES_ELEMENT_ALREADY_EXISTS = 4; 00962 00963 const Uint32 E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING = 5; 00964 const Uint32 E_PROPERTIES_INVALID_VERSION_WHILE_UNPACKING = 6; 00965 const Uint32 E_PROPERTIES_INVALID_BUFFER_TO_SHORT = 7; 00966 const Uint32 E_PROPERTIES_ERROR_MALLOC_WHILE_UNPACKING = 8; 00967 const Uint32 E_PROPERTIES_INVALID_CHECKSUM = 9; 00968 const Uint32 E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING = 10; 00969 00975 void 00976 Properties::setErrno(Uint32 pErr, Uint32 osErr) const { 00977 if(parent != 0){ 00978 parent->setErrno(pErr, osErr); 00979 return ; 00980 } 00981 00986 *((Uint32*)&propErrno) = pErr; 00987 *((Uint32*)&osErrno) = osErr; 00988 } 00989 00994 bool 00995 Properties::put(const char * name, Uint32 no, Uint32 val, bool replace){ 00996 size_t tmp_len = strlen(name)+20; 00997 char * tmp = (char*)malloc(tmp_len); 00998 BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no); 00999 bool res = put(tmp, val, replace); 01000 free(tmp); 01001 return res; 01002 } 01003 01004 bool 01005 Properties::put64(const char * name, Uint32 no, Uint64 val, bool replace){ 01006 size_t tmp_len = strlen(name)+20; 01007 char * tmp = (char*)malloc(tmp_len); 01008 BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no); 01009 bool res = put(tmp, val, replace); 01010 free(tmp); 01011 return res; 01012 } 01013 01014 01015 bool 01016 Properties::put(const char * name, Uint32 no, const char * val, bool replace){ 01017 size_t tmp_len = strlen(name)+20; 01018 char * tmp = (char*)malloc(tmp_len); 01019 BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no); 01020 bool res = put(tmp, val, replace); 01021 free(tmp); 01022 return res; 01023 } 01024 01025 01026 bool 01027 Properties::put(const char * name, Uint32 no, const Properties * val, 01028 bool replace){ 01029 size_t tmp_len = strlen(name)+20; 01030 char * tmp = (char*)malloc(tmp_len); 01031 BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no); 01032 bool res = put(tmp, val, replace); 01033 free(tmp); 01034 return res; 01035 } 01036 01037 01038 bool 01039 Properties::getTypeOf(const char * name, Uint32 no, 01040 PropertiesType * type) const { 01041 size_t tmp_len = strlen(name)+20; 01042 char * tmp = (char*)malloc(tmp_len); 01043 BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no); 01044 bool res = getTypeOf(tmp, type); 01045 free(tmp); 01046 return res; 01047 } 01048 01049 bool 01050 Properties::contains(const char * name, Uint32 no) const { 01051 size_t tmp_len = strlen(name)+20; 01052 char * tmp = (char*)malloc(tmp_len); 01053 BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no); 01054 bool res = contains(tmp); 01055 free(tmp); 01056 return res; 01057 } 01058 01059 bool 01060 Properties::get(const char * name, Uint32 no, Uint32 * value) const{ 01061 size_t tmp_len = strlen(name)+20; 01062 char * tmp = (char*)malloc(tmp_len); 01063 BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no); 01064 bool res = get(tmp, value); 01065 free(tmp); 01066 return res; 01067 } 01068 01069 bool 01070 Properties::get(const char * name, Uint32 no, Uint64 * value) const{ 01071 size_t tmp_len = strlen(name)+20; 01072 char * tmp = (char*)malloc(tmp_len); 01073 BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no); 01074 bool res = get(tmp, value); 01075 free(tmp); 01076 return res; 01077 } 01078 01079 01080 bool 01081 Properties::get(const char * name, Uint32 no, const char ** value) const { 01082 size_t tmp_len = strlen(name)+20; 01083 char * tmp = (char*)malloc(tmp_len); 01084 BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no); 01085 bool res = get(tmp, value); 01086 free(tmp); 01087 return res; 01088 } 01089 01090 01091 bool 01092 Properties::get(const char * name, Uint32 no, const Properties ** value) const{ 01093 size_t tmp_len = strlen(name)+20; 01094 char * tmp = (char*)malloc(tmp_len); 01095 BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no); 01096 bool res = get(tmp, value); 01097 free(tmp); 01098 return res; 01099 } 01100 01101 01102 bool 01103 Properties::getCopy(const char * name, Uint32 no, char ** value) const { 01104 size_t tmp_len = strlen(name)+20; 01105 char * tmp = (char*)malloc(tmp_len); 01106 BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no); 01107 bool res = getCopy(tmp, value); 01108 free(tmp); 01109 return res; 01110 } 01111 01112 01113 bool 01114 Properties::getCopy(const char * name, Uint32 no, Properties ** value) const { 01115 size_t tmp_len = strlen(name)+20; 01116 char * tmp = (char*)malloc(tmp_len); 01117 BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no); 01118 bool res = getCopy(tmp, value); 01119 free(tmp); 01120 return res; 01121 } 01122 01123 void 01124 Properties::setCaseInsensitiveNames(bool value){ 01125 impl->setCaseInsensitiveNames(value); 01126 } 01127 01128 bool 01129 Properties::getCaseInsensitiveNames() const { 01130 return impl->m_insensitive; 01131 } 01132 01133 template bool put(PropertiesImpl *, const char *, Uint32, bool); 01134 template bool put(PropertiesImpl *, const char *, Uint64, bool); 01135 template bool put(PropertiesImpl *, const char *, const char *, bool); 01136 template bool put(PropertiesImpl *, const char *, const Properties*, bool);
1.4.7

