19 #include <ndb_global.h>
21 #include <Properties.hpp>
27 char * f_strdup(
const char * s){
36 const char Properties::delimiter =
':';
42 PropertiesType valueType;
73 int (* compare)(
const char *s1,
const char *s2);
75 void setCaseInsensitiveNames(
bool value);
76 void grow(
int sizeToAdd);
80 void remove(
const char *
name);
82 Uint32 getPackedSize(Uint32 pLen)
const;
83 bool pack(Uint32 *&
buf,
const char * prefix, Uint32 prefixLen)
const;
84 bool unpack(
const Uint32 * buf, Uint32 &bufLen,
Properties * top,
int items);
86 Uint32 getTotalItems()
const;
88 void setErrno(Uint32 pErr, Uint32 osErr = 0){
89 properties->setErrno(pErr, osErr);
93 const char * getPropsPut(
const char * name,
PropertiesImpl ** impl);
110 ((
Properties*)impl->value)->setCaseInsensitiveNames(value->getCaseInsensitiveNames());
113 Property::~Property(){
133 put(anArray, arrayLen);
136 Properties::~Properties(){
145 for(
int i = 0;
i<arrayLen;
i++)
146 impl->put(anArray[
i].impl);
153 impl->setErrno(E_PROPERTIES_INVALID_NAME);
158 const char * short_name = impl->getPropsPut(name, &tmp);
161 impl->setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
165 if(tmp->get(short_name) != 0){
167 tmp->remove(short_name);
169 impl->setErrno(E_PROPERTIES_ELEMENT_ALREADY_EXISTS);
173 return (tmp->put(
new PropertyImpl(short_name, value)) != 0);
183 Properties::put64(
const char * name, Uint64 value,
bool replace){
198 Properties::getTypeOf(
const char * name, PropertiesType *
type)
const {
201 setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
204 setErrno(E_PROPERTIES_OK);
205 * type = nvp->valueType;
216 Properties::get(
const char * name, Uint32 * value)
const {
219 setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
223 if(nvp->valueType == PropertiesType_Uint32){
224 * value = * (Uint32 *)nvp->value;
225 setErrno(E_PROPERTIES_OK);
229 if(nvp->valueType == PropertiesType_Uint64){
230 Uint64 tmp = * (Uint64 *)nvp->value;
231 Uint64 max = 1; max <<= 32;
233 * value = (Uint32)tmp;
234 setErrno(E_PROPERTIES_OK);
238 setErrno(E_PROPERTIES_INVALID_TYPE);
243 Properties::get(
const char * name, Uint64 * value)
const {
246 setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
250 if(nvp->valueType == PropertiesType_Uint32){
251 Uint32 tmp = * (Uint32 *)nvp->value;
252 * value = (Uint64)tmp;
253 setErrno(E_PROPERTIES_OK);
257 if(nvp->valueType == PropertiesType_Uint64){
258 * value = * (Uint64 *)nvp->value;
259 setErrno(E_PROPERTIES_OK);
262 setErrno(E_PROPERTIES_INVALID_TYPE);
267 Properties::get(
const char * name,
const char ** value)
const {
270 setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
274 if(nvp->valueType == PropertiesType_char){
275 * value = (
const char *)nvp->value;
276 setErrno(E_PROPERTIES_OK);
279 setErrno(E_PROPERTIES_INVALID_TYPE);
284 Properties::get(
const char * name,
BaseString& value)
const {
285 const char *tmp =
"";
287 ret =
get(
name, &tmp);
293 Properties::get(
const char * name,
const Properties ** value)
const {
296 setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
299 if(nvp->valueType == PropertiesType_Properties){
301 setErrno(E_PROPERTIES_OK);
304 setErrno(E_PROPERTIES_INVALID_TYPE);
309 Properties::getCopy(
const char * name,
char ** value)
const {
312 setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
316 if(nvp->valueType == PropertiesType_char){
317 * value = f_strdup((
const char *)nvp->value);
318 setErrno(E_PROPERTIES_OK);
321 setErrno(E_PROPERTIES_INVALID_TYPE);
326 Properties::getCopy(
const char * name,
Properties ** value)
const {
329 setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
333 if(nvp->valueType == PropertiesType_Properties){
335 setErrno(E_PROPERTIES_OK);
338 setErrno(E_PROPERTIES_INVALID_TYPE);
344 while(impl->items > 0)
345 impl->remove(impl->content[0]->name);
349 Properties::remove(
const char * name) {
354 Properties::print(FILE * out,
const char * prefix)
const{
359 strncpy(buf, prefix, 1024);
361 for(
unsigned int i = 0;
i<impl->items;
i++){
362 switch(impl->content[
i]->valueType){
363 case PropertiesType_Uint32:
364 fprintf(out,
"%s%s = (Uint32) %d\n", buf, impl->content[
i]->name,
365 *(Uint32 *)impl->content[
i]->value);
367 case PropertiesType_Uint64:
368 fprintf(out,
"%s%s = (Uint64) %lld\n", buf, impl->content[
i]->name,
369 *(Uint64 *)impl->content[
i]->value);
371 case PropertiesType_char:
372 fprintf(out,
"%s%s = (char*) \"%s\"\n", buf, impl->content[
i]->name,
373 (
char *)impl->content[
i]->value);
375 case PropertiesType_Properties:
378 Properties::delimiter);
379 ((
Properties *)impl->content[
i]->value)->print(out, buf2);
385 Properties::Iterator::Iterator(
const Properties* prop) :
391 Properties::Iterator::first() {
397 Properties::Iterator::next() {
398 if (m_iterator < m_prop->impl->items)
399 return m_prop->impl->content[m_iterator++]->name;
405 Properties::getPackedSize()
const {
412 return sz + impl->getPackedSize(0);
417 computeChecksum(
const Uint32 * buf, Uint32 words){
419 for(
unsigned int i = 0;
i<words;
i++)
420 sum ^= htonl(buf[
i]);
426 Properties::pack(Uint32 * buf)
const {
427 Uint32 * bufStart =
buf;
434 * buf = htonl(impl->getTotalItems());
436 bool res = impl->pack(buf,
"", 0);
440 * buf = htonl(computeChecksum(bufStart, Uint32(buf - bufStart)));
446 Properties::unpack(
const Uint32 * buf, Uint32 bufLen){
447 const Uint32 * bufStart =
buf;
448 Uint32 bufLenOrg = bufLen;
451 setErrno(E_PROPERTIES_INVALID_BUFFER_TO_SHORT);
456 setErrno(E_PROPERTIES_INVALID_VERSION_WHILE_UNPACKING);
465 setErrno(E_PROPERTIES_INVALID_BUFFER_TO_SHORT);
469 Uint32 totalItems = ntohl(* buf);
471 bool res = impl->unpack(buf, bufLen,
this, totalItems);
475 Uint32 sum = computeChecksum(bufStart, (bufLenOrg-bufLen)/4);
476 if(sum != ntohl(bufStart[(bufLenOrg-bufLen)/4])){
477 setErrno(E_PROPERTIES_INVALID_CHECKSUM);
486 PropertiesImpl::PropertiesImpl(
Properties * p,
bool case_insensitive){
487 this->properties = p;
495 this->properties = p;
496 this->
size = org.size;
497 this->
items = org.items;
498 this->m_insensitive = org.m_insensitive;
501 for(
unsigned int i = 0;
i<
items;
i++){
502 content[
i] = PropertyImpl::copyPropertyImpl(* org.content[
i]);
506 PropertiesImpl::~PropertiesImpl(){
507 for(
unsigned int i = 0;
i<
items;
i++)
514 m_insensitive = value;
522 PropertiesImpl::grow(
int sizeToAdd){
526 content = newContent;
531 PropertiesImpl::get(
const char * name)
const {
533 const char * short_name = getProps(name, &tmp);
538 for(
unsigned int i = 0;
i<tmp->items;
i++) {
539 if((*
compare)(tmp->content[
i]->name, short_name) == 0)
540 return tmp->content[
i];
550 content[
items] = nvp;
554 if(nvp->valueType == PropertiesType_Properties){
555 ((
Properties*)nvp->value)->parent = properties;
561 PropertiesImpl::remove(
const char * name){
562 for(
unsigned int i = 0;
i<
items;
i++){
563 if((*
compare)(content[
i]->name, name) == 0){
565 memmove(&content[
i], &content[i+1], (items-i-1)*
sizeof(
PropertyImpl *));
573 PropertiesImpl::getTotalItems()
const {
575 for(
unsigned int i = 0;
i<items;
i++)
576 if(content[
i]->valueType == PropertiesType_Properties){
577 ret += ((
Properties*)content[
i]->value)->impl->getTotalItems();
585 PropertiesImpl::getProps(
const char * name,
587 const char * ret =
name;
588 const char * tmp = strchr(name, Properties::delimiter);
593 Uint32 sz = Uint32(tmp - name);
594 char * tmp2 = (
char*)malloc(sz + 1);
595 memcpy(tmp2, name, sz);
606 if(nvp->valueType != PropertiesType_Properties){
610 return ((
Properties*)nvp->value)->impl->getProps(tmp+1, impl);
615 PropertiesImpl::getPropsPut(
const char * name,
617 const char * ret =
name;
618 const char * tmp = strchr(name, Properties::delimiter);
623 Uint32 sz = Uint32(tmp - name);
624 char * tmp2 = (
char*)malloc(sz + 1);
625 memcpy(tmp2, name, sz);
637 return ((
Properties*)nvp2->value)->impl->getPropsPut(tmp+1, impl);
640 if(nvp->valueType != PropertiesType_Properties){
644 return ((
Properties*)nvp->value)->impl->getPropsPut(tmp+1, impl);
649 mod4(
unsigned int i){
650 int res = i + (4 - (i % 4));
655 PropertiesImpl::getPackedSize(Uint32 pLen)
const {
657 for(
unsigned int i = 0;
i<items;
i++){
658 if(content[
i]->valueType == PropertiesType_Properties){
660 sz += p->impl->getPackedSize(pLen+(Uint32)strlen(content[
i]->name)+1);
665 sz += mod4(pLen + strlen(content[
i]->name));
666 switch(content[
i]->valueType){
667 case PropertiesType_char:
668 sz += mod4(strlen((
char *)content[
i]->value));
670 case PropertiesType_Uint32:
673 case PropertiesType_Uint64:
676 case PropertiesType_Properties:
700 void clear() { contentLen = 0;}
701 bool add(
const char * str, Uint32 strLen){
702 if(!expand(contentLen + strLen + 1))
704 memcpy(&buffer[contentLen], str, strLen);
705 contentLen += strLen;
706 buffer[contentLen] = 0;
714 bool expand(Uint32 newSize){
715 if(newSize >= bufLen){
717 char * tmp = (
char*)malloc(newSize + 1024);
718 memset(tmp, 0, newSize + 1024);
722 memcpy(tmp, buffer, contentLen);
726 bufLen = newSize + 1024;
733 PropertiesImpl::pack(Uint32 *& buf,
const char * prefix, Uint32 pLen)
const {
736 for(
unsigned int i = 0;
i<items;
i++){
737 const int strLenName = strlen(content[
i]->name);
739 if(content[
i]->valueType == PropertiesType_Properties){
741 if(!charBuf.add(prefix, pLen)){
742 properties->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING,
747 if(!charBuf.add(content[
i]->name, strLenName)){
748 properties->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING,
753 if(!charBuf.add(Properties::delimiter)){
754 properties->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING,
759 if(!((
Properties*)(content[i]->value))->impl->pack(buf,
761 charBuf.contentLen)){
768 Uint32 valLenData = 0;
769 Uint32 valLenWrite = 0;
770 Uint32 sz = 4 + 4 + 4 + mod4(pLen + strLenName);
771 switch(content[i]->valueType){
772 case PropertiesType_Uint32:
775 case PropertiesType_Uint64:
778 case PropertiesType_char:
779 valLenData = Uint32(strlen((
char *)content[i]->value));
781 case PropertiesType_Properties:
784 valLenWrite = mod4(valLenData);
787 * (buf + 0) = htonl(content[i]->valueType);
788 * (buf + 1) = htonl(pLen + strLenName);
789 * (buf + 2) = htonl(valLenData);
791 char * valBuf = (
char*)(buf + 3);
792 char * nameBuf = (
char*)(buf + 3 + (valLenWrite / 4));
794 memset(valBuf, 0, sz-12);
796 switch(content[i]->valueType){
797 case PropertiesType_Uint32:
798 * (Uint32 *)valBuf = htonl(* (Uint32 *)content[
i]->value);
800 case PropertiesType_Uint64:{
801 Uint64 val = * (Uint64 *)content[i]->value;
802 Uint32 hi = (Uint32)(val >> 32);
803 Uint32 lo = (Uint32)(val & 0xFFFFFFFF);
804 * (Uint32 *)valBuf = htonl(hi);
805 * (Uint32 *)(valBuf + 4) = htonl(lo);
808 case PropertiesType_char:
809 memcpy(valBuf, content[i]->value, strlen((
char*)content[i]->value));
811 case PropertiesType_Properties:
815 memcpy(nameBuf, prefix, pLen);
816 memcpy(nameBuf + pLen, content[i]->name, strLenName);
825 PropertiesImpl::unpack(
const Uint32 * buf, Uint32 &bufLen,
Properties * top,
832 top->setErrno(E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING);
836 tmp[0] = ntohl(buf[0]);
837 tmp[1] = ntohl(buf[1]);
838 tmp[2] = ntohl(buf[2]);
842 PropertiesType pt = (PropertiesType)tmp[0];
843 Uint32 nameLen = tmp[1];
844 Uint32 valueLen = tmp[2];
845 Uint32 nameLenRead = mod4(nameLen);
846 Uint32 valueLenRead = mod4(valueLen);
848 Uint32 sz = nameLenRead + valueLenRead;
850 top->setErrno(E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING);
854 if(!charBuf.expand(sz)){
855 top->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_UNPACKING, errno);
859 memcpy(charBuf.buffer, buf, sz);
863 char * valBuf = charBuf.buffer;
864 char * nameBuf = charBuf.buffer + valueLenRead;
866 nameBuf[nameLen] = 0;
867 valBuf[valueLen] = 0;
871 case PropertiesType_Uint32:
872 res3 = top->
put(nameBuf, ntohl(* (Uint32 *)valBuf),
true);
874 case PropertiesType_Uint64:{
875 Uint64 hi = ntohl(* (Uint32 *)valBuf);
876 Uint64 lo = ntohl(* (Uint32 *)(valBuf + 4));
877 res3 = top->put64(nameBuf, (hi << 32) + lo,
true);
880 case PropertiesType_char:
881 res3 = top->
put(nameBuf, valBuf,
true);
883 case PropertiesType_Properties:
894 PropertyImpl::~PropertyImpl(){
897 case PropertiesType_Uint32:
898 delete (Uint32 *)value;
900 case PropertiesType_Uint64:
901 delete (Uint64 *)value;
903 case PropertiesType_char:
906 case PropertiesType_Properties:
913 PropertyImpl::copyPropertyImpl(
const PropertyImpl & org){
914 switch(org.valueType){
915 case PropertiesType_Uint32:
916 return new PropertyImpl(org.name, * (Uint32 *)org.value);
917 case PropertiesType_Uint64:
918 return new PropertyImpl(org.name, * (Uint64 *)org.value);
920 case PropertiesType_char:
923 case PropertiesType_Properties:
932 PropertyImpl::PropertyImpl(
const char * _name, Uint32 _value){
933 this->name = f_strdup(_name);
934 this->value =
new Uint32;
935 * ((Uint32 *)this->value) = _value;
936 this->valueType = PropertiesType_Uint32;
939 PropertyImpl::PropertyImpl(
const char * _name, Uint64 _value){
940 this->name = f_strdup(_name);
941 this->value =
new Uint64;
942 * ((Uint64 *)this->value) = _value;
943 this->valueType = PropertiesType_Uint64;
946 PropertyImpl::PropertyImpl(
const char * _name,
const char * _value){
947 this->name = f_strdup(_name);
948 this->value = f_strdup(_value);
949 this->valueType = PropertiesType_char;
953 PropertyImpl::PropertyImpl(
const char * _name,
const Properties * _value){
954 this->name = f_strdup(_name);
956 this->valueType = PropertiesType_Properties;
959 const Uint32 E_PROPERTIES_OK = 0;
960 const Uint32 E_PROPERTIES_INVALID_NAME = 1;
961 const Uint32 E_PROPERTIES_NO_SUCH_ELEMENT = 2;
962 const Uint32 E_PROPERTIES_INVALID_TYPE = 3;
963 const Uint32 E_PROPERTIES_ELEMENT_ALREADY_EXISTS = 4;
965 const Uint32 E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING = 5;
966 const Uint32 E_PROPERTIES_INVALID_VERSION_WHILE_UNPACKING = 6;
967 const Uint32 E_PROPERTIES_INVALID_BUFFER_TO_SHORT = 7;
968 const Uint32 E_PROPERTIES_ERROR_MALLOC_WHILE_UNPACKING = 8;
969 const Uint32 E_PROPERTIES_INVALID_CHECKSUM = 9;
970 const Uint32 E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING = 10;
978 Properties::setErrno(Uint32 pErr, Uint32 osErr)
const {
980 parent->setErrno(pErr, osErr);
988 *((Uint32*)&propErrno) = pErr;
989 *((Uint32*)&osErrno) = osErr;
998 size_t tmp_len = strlen(name)+20;
999 char * tmp = (
char*)malloc(tmp_len);
1001 bool res =
put(tmp, val, replace);
1007 Properties::put64(
const char * name, Uint32 no, Uint64 val,
bool replace){
1008 size_t tmp_len = strlen(name)+20;
1009 char * tmp = (
char*)malloc(tmp_len);
1011 bool res = put64(tmp, val, replace);
1018 Properties::put(
const char * name, Uint32 no,
const char * val,
bool replace){
1019 size_t tmp_len = strlen(name)+20;
1020 char * tmp = (
char*)malloc(tmp_len);
1022 bool res =
put(tmp, val, replace);
1031 size_t tmp_len = strlen(name)+20;
1032 char * tmp = (
char*)malloc(tmp_len);
1034 bool res =
put(tmp, val, replace);
1041 Properties::getTypeOf(
const char * name, Uint32 no,
1042 PropertiesType * type)
const {
1043 size_t tmp_len = strlen(name)+20;
1044 char * tmp = (
char*)malloc(tmp_len);
1046 bool res = getTypeOf(tmp, type);
1053 size_t tmp_len = strlen(name)+20;
1054 char * tmp = (
char*)malloc(tmp_len);
1062 Properties::get(
const char * name, Uint32 no, Uint32 * value)
const{
1063 size_t tmp_len = strlen(name)+20;
1064 char * tmp = (
char*)malloc(tmp_len);
1066 bool res =
get(tmp, value);
1072 Properties::get(
const char * name, Uint32 no, Uint64 * value)
const{
1073 size_t tmp_len = strlen(name)+20;
1074 char * tmp = (
char*)malloc(tmp_len);
1076 bool res =
get(tmp, value);
1083 Properties::get(
const char * name, Uint32 no,
const char ** value)
const {
1084 size_t tmp_len = strlen(name)+20;
1085 char * tmp = (
char*)malloc(tmp_len);
1087 bool res =
get(tmp, value);
1094 Properties::get(
const char * name, Uint32 no,
const Properties ** value)
const{
1095 size_t tmp_len = strlen(name)+20;
1096 char * tmp = (
char*)malloc(tmp_len);
1098 bool res =
get(tmp, value);
1105 Properties::getCopy(
const char * name, Uint32 no,
char ** value)
const {
1106 size_t tmp_len = strlen(name)+20;
1107 char * tmp = (
char*)malloc(tmp_len);
1109 bool res = getCopy(tmp, value);
1116 Properties::getCopy(
const char * name, Uint32 no,
Properties ** value)
const {
1117 size_t tmp_len = strlen(name)+20;
1118 char * tmp = (
char*)malloc(tmp_len);
1120 bool res = getCopy(tmp, value);
1127 impl->setCaseInsensitiveNames(value);
1131 Properties::getCaseInsensitiveNames()
const {
1132 return impl->m_insensitive;