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

MySQL数据库

开发平台:

Visual C++

  1. #include <ndb_global.h>
  2. #include <ConfigValues.hpp>
  3. #include <NdbOut.hpp>
  4. #include <NdbTCP.h>
  5. static Uint32 hash(Uint32 key, Uint32 size);
  6. static Uint32 nextHash(Uint32 key, Uint32 size, Uint32 pos, Uint32 count);
  7. static bool findKey(const Uint32 * vals, Uint32 sz, Uint32 key, Uint32 * pos);
  8. /**
  9.  * Key
  10.  *
  11.  * t = Type      -  4 bits 0-15
  12.  * s = Section   - 14 bits 0-16383
  13.  * k = Key value - 14 bits 0-16383
  14.  *
  15.  *           1111111111222222222233
  16.  * 01234567890123456789012345678901
  17.  * kkkkkkkkkkkkkkssssssssssssssoooo
  18.  */
  19. #define KP_TYPE_MASK     (15)
  20. #define KP_TYPE_SHIFT    (28)
  21. #define KP_SECTION_MASK  (0x3FFF)
  22. #define KP_SECTION_SHIFT (14)
  23. #define KP_KEYVAL_MASK   (0x3FFF)
  24. #define KP_KEYVAL_SHIFT  (0)
  25. #define KP_MASK          (0x0FFFFFFF)
  26. static const Uint32 CFV_KEY_PARENT = (KP_KEYVAL_MASK - 1);
  27. static const Uint32 CFV_KEY_FREE   = ~0;
  28. static const char Magic[] = { 'N', 'D', 'B', 'C', 'O', 'N', 'F', 'V' };
  29. //#define DEBUG_CV
  30. #ifdef DEBUG_CV
  31. #define DEBUG
  32. #else
  33. #define DEBUG if(0)
  34. #endif
  35. inline
  36. ConfigValues::ValueType
  37. getTypeOf(Uint32 k) {
  38.   return (ConfigValues::ValueType)((k >> KP_TYPE_SHIFT) & KP_TYPE_MASK);
  39. }
  40. ConfigValues::ConfigValues(Uint32 sz, Uint32 dsz){
  41.   m_size = sz;
  42.   m_dataSize = dsz;
  43.   m_stringCount = 0;
  44.   m_int64Count = 0;
  45.   for(Uint32 i = 0; i<m_size; i++){
  46.     m_values[i << 1] = CFV_KEY_FREE;
  47.   }
  48. }
  49. ConfigValues::~ConfigValues(){
  50.   for(Uint32 i = 0; i<m_stringCount; i++){
  51.     free(* getString(i));
  52.   }
  53. }
  54. bool
  55. ConfigValues::ConstIterator::get(Uint32 key, Entry * result) const {
  56.   Uint32 pos;
  57.   if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
  58.     return false;
  59.   }
  60.   
  61.   result->m_key = key;
  62.   return m_cfg.getByPos(pos, result);
  63. }
  64. bool
  65. ConfigValues::getByPos(Uint32 pos, Entry * result) const {
  66.   assert(pos < (2 * m_size));
  67.   Uint32 keypart = m_values[pos];
  68.   Uint32 val = m_values[pos+1];
  69.   switch(::getTypeOf(keypart)){
  70.   case IntType:
  71.   case SectionType:
  72.     result->m_int = val;
  73.     break;
  74.   case StringType:
  75.     result->m_string = * getString(val);
  76.     break;
  77.   case Int64Type:
  78.     result->m_int64 = * get64(val);
  79.     break;
  80.   case InvalidType: 
  81.   default:
  82.     return false;
  83.   }
  84.   result->m_type = ::getTypeOf(keypart);
  85.   
  86.   return true;
  87. }
  88. Uint64 *
  89. ConfigValues::get64(Uint32 index) const {
  90.   assert(index < m_int64Count);
  91.   const Uint32 * data = m_values + (m_size << 1);
  92.   Uint64 * ptr = (Uint64*)data;
  93.   ptr += index;
  94.   return ptr;
  95. }
  96. char **
  97. ConfigValues::getString(Uint32 index) const {
  98.   assert(index < m_stringCount); 
  99.   const Uint32 * data = m_values + (m_size << 1);
  100.   char * ptr = (char*)data;
  101.   ptr += m_dataSize; 
  102.   ptr -= (index * sizeof(char *));
  103.   return (char**)ptr;
  104. }
  105. bool
  106. ConfigValues::ConstIterator::openSection(Uint32 key, Uint32 no){
  107.   Uint32 curr = m_currentSection;
  108.   
  109.   Entry tmp;
  110.   if(get(key, &tmp) && tmp.m_type == SectionType){
  111.     m_currentSection = tmp.m_int;
  112.     if(get(no, &tmp) && tmp.m_type == IntType){
  113.       m_currentSection = tmp.m_int;
  114.       /**
  115.        * Validate
  116.        */
  117.       if(get(CFV_KEY_PARENT, &tmp)){
  118. return true;
  119.       }
  120.     }
  121.   }
  122.   
  123.   m_currentSection = curr;
  124.   return false;
  125. }
  126. bool
  127. ConfigValues::ConstIterator::closeSection() {
  128.   
  129.   Entry tmp;
  130.   if(get(CFV_KEY_PARENT, &tmp) && tmp.m_type == IntType){
  131.     m_currentSection = tmp.m_int;
  132.     return true;
  133.   }
  134.   return false;
  135. }
  136. bool
  137. ConfigValues::Iterator::set(Uint32 key, Uint32 value){
  138.   Uint32 pos;
  139.   if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
  140.     return false;
  141.   }
  142.   if(::getTypeOf(m_cfg.m_values[pos]) != IntType){
  143.     return false;
  144.   }
  145.   m_cfg.m_values[pos+1] = value;
  146.   return true;
  147. }
  148. bool
  149. ConfigValues::Iterator::set(Uint32 key, Uint64 value){
  150.   Uint32 pos;
  151.   if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
  152.     return false;
  153.   }
  154.   if(::getTypeOf(m_cfg.m_values[pos]) != Int64Type){
  155.     return false;
  156.   }
  157.   
  158.   * m_cfg.get64(m_cfg.m_values[pos+1]) = value;
  159.   return true;
  160. }
  161. bool
  162. ConfigValues::Iterator::set(Uint32 key, const char * value){
  163.   Uint32 pos;
  164.   if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
  165.     return false;
  166.   }
  167.   if(::getTypeOf(m_cfg.m_values[pos]) != StringType){
  168.     return false;
  169.   }
  170.   char **  str = m_cfg.getString(m_cfg.m_values[pos+1]);
  171.   free(* str);
  172.   * str = strdup(value ? value : "");
  173.   return true;
  174. }
  175. static
  176. bool
  177. findKey(const Uint32 * values, Uint32 sz, Uint32 key, Uint32 * _pos){
  178.   Uint32 pos = hash(key, sz);
  179.   Uint32 count = 0;
  180.   while((values[pos] & KP_MASK) != key && count < sz){
  181.     pos = nextHash(key, sz, pos, ++count);
  182.   }
  183.   if((values[pos] & KP_MASK)== key){
  184.     *_pos = pos;
  185.     return true;
  186.   }
  187.   return false;
  188. }
  189. static
  190. Uint32
  191. hash(Uint32 key, Uint32 size){
  192.   Uint32 tmp = (key >> 16) ^ (key & 0xFFFF);
  193.   return (((tmp << 16) | tmp) % size) << 1;
  194. }
  195. static
  196. Uint32
  197. nextHash(Uint32 key, Uint32 size, Uint32 pos, Uint32 count){
  198.   Uint32 p = (pos >> 1);
  199.   if((key % size) != 0)
  200.     p += key;
  201.   else
  202.     p += 1;
  203.   return (p % size) << 1;
  204. }
  205. static
  206. Uint32
  207. directory(Uint32 sz){
  208.   const Uint32 _input = sz;
  209.   if((sz & 1) == 0)
  210.     sz ++;
  211.   
  212.   bool prime = false;
  213.   while(!prime){
  214.     prime = true;
  215.     for(Uint32 n = 3; n*n <= sz; n += 2){
  216.       if((sz % n) == 0){
  217. prime = false;
  218. sz += 2;
  219. break;
  220.       }
  221.     }
  222.   }
  223.   DEBUG printf("directory %d -> %dn", _input, sz);
  224.   return sz;
  225. }
  226. ConfigValuesFactory::ConfigValuesFactory(Uint32 keys, Uint32 data){
  227.   m_sectionCounter = (1 << KP_SECTION_SHIFT);
  228.   m_freeKeys = directory(keys);
  229.   m_freeData = (data + 7) & ~7;
  230.   m_currentSection = 0;
  231.   m_cfg = create(m_freeKeys, m_freeData);
  232. }
  233. ConfigValuesFactory::ConfigValuesFactory(ConfigValues * cfg){
  234.   m_cfg = cfg;
  235.   m_freeKeys = 0;
  236.   m_freeData = m_cfg->m_dataSize;
  237.   m_sectionCounter = (1 << KP_SECTION_SHIFT);  
  238.   m_currentSection = 0;
  239.   const Uint32 sz = 2 * m_cfg->m_size;
  240.   for(Uint32 i = 0; i<sz; i += 2){
  241.     const Uint32 key = m_cfg->m_values[i];
  242.     if(key == CFV_KEY_FREE){
  243.       m_freeKeys++;
  244.     } else {
  245.       switch(::getTypeOf(key)){
  246.       case ConfigValues::IntType:
  247.       case ConfigValues::SectionType:
  248. break;
  249.       case ConfigValues::Int64Type:
  250. m_freeData -= sizeof(Uint64);
  251. break;
  252.       case ConfigValues::StringType:
  253. m_freeData -= sizeof(char *);
  254. break;
  255.       case ConfigValues::InvalidType:
  256. abort();
  257.       }
  258.       Uint32 sec = key & (KP_SECTION_MASK << KP_SECTION_SHIFT);
  259.       m_sectionCounter = (sec > m_sectionCounter ? sec : m_sectionCounter);
  260.     }
  261.   }
  262. }
  263. ConfigValues *
  264. ConfigValuesFactory::create(Uint32 keys, Uint32 data){
  265.   Uint32 sz = sizeof(ConfigValues);
  266.   sz += (2 * keys * sizeof(Uint32)); 
  267.   sz += data;
  268.   
  269.   void * tmp = malloc(sz);
  270.   return new (tmp) ConfigValues(keys, data);
  271. }
  272. void
  273. ConfigValuesFactory::expand(Uint32 fk, Uint32 fs){
  274.   if(m_freeKeys >= fk && m_freeData >= fs){
  275.     return ;
  276.   }
  277.   m_freeKeys = (m_freeKeys >= fk ? m_cfg->m_size : fk + m_cfg->m_size);
  278.   m_freeData = (m_freeData >= fs ? m_cfg->m_dataSize : fs + m_cfg->m_dataSize);
  279.   m_freeKeys = directory(m_freeKeys);
  280.   m_freeData = (m_freeData + 7) & ~7;
  281.  
  282.   ConfigValues * m_tmp = m_cfg;
  283.   m_cfg = create(m_freeKeys, m_freeData);
  284.   put(* m_tmp);
  285.   m_tmp->~ConfigValues();
  286.   free(m_tmp);
  287. }
  288. void
  289. ConfigValuesFactory::shrink(){
  290.   if(m_freeKeys == 0 && m_freeData == 0){
  291.     return ;
  292.   }
  293.   m_freeKeys = m_cfg->m_size - m_freeKeys;
  294.   m_freeData = m_cfg->m_dataSize - m_freeData;
  295.   m_freeKeys = directory(m_freeKeys);
  296.   m_freeData = (m_freeData + 7) & ~7;
  297.   ConfigValues * m_tmp = m_cfg;
  298.   m_cfg = create(m_freeKeys, m_freeData);
  299.   put(* m_tmp);
  300.   m_tmp->~ConfigValues();
  301.   free(m_tmp);
  302. }
  303. bool
  304. ConfigValuesFactory::openSection(Uint32 key, Uint32 no){
  305.   ConfigValues::Entry tmp;
  306.   const Uint32 parent = m_currentSection;
  307.   ConfigValues::ConstIterator iter(* m_cfg);
  308.   iter.m_currentSection = m_currentSection;
  309.   if(!iter.get(key, &tmp)){
  310.     tmp.m_key  = key;
  311.     tmp.m_type = ConfigValues::SectionType;
  312.     tmp.m_int  = m_sectionCounter;
  313.     m_sectionCounter += (1 << KP_SECTION_SHIFT);
  314.     if(!put(tmp)){
  315.       return false;
  316.     }
  317.   }
  318.   if(tmp.m_type != ConfigValues::SectionType){
  319.     return false;
  320.   }
  321.   m_currentSection = tmp.m_int;
  322.   tmp.m_key = no;
  323.   tmp.m_type = ConfigValues::IntType;
  324.   tmp.m_int = m_sectionCounter;
  325.   if(!put(tmp)){
  326.     m_currentSection = parent;
  327.     return false;
  328.   }
  329.   m_sectionCounter += (1 << KP_SECTION_SHIFT);
  330.   
  331.   m_currentSection = tmp.m_int;
  332.   tmp.m_type = ConfigValues::IntType;
  333.   tmp.m_key = CFV_KEY_PARENT;
  334.   tmp.m_int = parent;
  335.   if(!put(tmp)){
  336.     m_currentSection = parent;
  337.     return false;
  338.   }
  339.   return true;
  340. }
  341. bool
  342. ConfigValuesFactory::closeSection(){
  343.   ConfigValues::ConstIterator iter(* m_cfg);
  344.   iter.m_currentSection = m_currentSection;
  345.   const bool b = iter.closeSection();
  346.   m_currentSection = iter.m_currentSection;
  347.   return b;
  348. }
  349.   
  350. bool
  351. ConfigValuesFactory::put(const ConfigValues::Entry & entry){
  352.   
  353.   if(m_freeKeys == 0 ||
  354.      (entry.m_type == ConfigValues::StringType && m_freeData < sizeof(char *))
  355.      || (entry.m_type == ConfigValues::Int64Type && m_freeData < 8 )){ 
  356.     
  357.     DEBUG ndbout_c("m_freeKeys = %d, m_freeData = %d -> expand",
  358.    m_freeKeys, m_freeData);
  359.     
  360.     expand(31, 20);
  361.   }
  362.   
  363.   const Uint32 tmp = entry.m_key | m_currentSection;
  364.   const Uint32 sz = m_cfg->m_size;
  365.   Uint32 pos = hash(tmp, sz);
  366.   Uint32 count = 0;
  367.   Uint32 val = m_cfg->m_values[pos];
  368.   while((val & KP_MASK) != tmp && val != CFV_KEY_FREE && count < sz){
  369.     pos = nextHash(tmp, sz, pos, ++count);
  370.     val = m_cfg->m_values[pos];
  371.   }
  372.   if((val & KP_MASK) == tmp){
  373.     DEBUG ndbout_c("key %x already found at pos: %d", tmp, pos);
  374.     return false;
  375.   }
  376.   if(count >= sz){
  377.     pos = hash(tmp, sz);    
  378.     count = 0;
  379.     Uint32 val = m_cfg->m_values[pos];
  380.    
  381.     printf("key: %d, (key %% size): %dn", entry.m_key, (entry.m_key % sz));
  382.     printf("pos: %d", pos);
  383.     while((val & KP_MASK) != tmp && val != CFV_KEY_FREE && count < sz){
  384.       pos = nextHash(tmp, sz, pos, ++count);
  385.       val = m_cfg->m_values[pos];
  386.       printf(" %d", pos);
  387.     }
  388.     printf("n");
  389.     abort();
  390.     printf("Fulln");
  391.     return false;
  392.   }
  393.   assert(pos < (sz << 1));
  394.   Uint32 key = tmp;
  395.   key |= (entry.m_type << KP_TYPE_SHIFT);
  396.   m_cfg->m_values[pos] = key;
  397.   switch(entry.m_type){
  398.   case ConfigValues::IntType:
  399.   case ConfigValues::SectionType:
  400.     m_cfg->m_values[pos+1] = entry.m_int;    
  401.     m_freeKeys--;
  402.     DEBUG printf("Putting at: %d(%d) (loop = %d) key: %d value: %dn", 
  403.    pos, sz, count, 
  404.    (key >> KP_KEYVAL_SHIFT) & KP_KEYVAL_MASK,
  405.    entry.m_int);
  406.     return true;
  407.   case ConfigValues::StringType:{
  408.     Uint32 index = m_cfg->m_stringCount++;
  409.     m_cfg->m_values[pos+1] = index;
  410.     char **  ref = m_cfg->getString(index);
  411.     * ref = strdup(entry.m_string ? entry.m_string : "");
  412.     m_freeKeys--;
  413.     m_freeData -= sizeof(char *);
  414.     DEBUG printf("Putting at: %d(%d) (loop = %d) key: %d value(%d): %sn", 
  415.    pos, sz, count, 
  416.    (key >> KP_KEYVAL_SHIFT) & KP_KEYVAL_MASK,
  417.    index,
  418.    entry.m_string);
  419.     return true;
  420.   }
  421.   case ConfigValues::Int64Type:{
  422.     Uint32 index = m_cfg->m_int64Count++;
  423.     m_cfg->m_values[pos+1] = index;
  424.     * m_cfg->get64(index) = entry.m_int64;
  425.     m_freeKeys--;
  426.     m_freeData -= 8;
  427.     DEBUG printf("Putting at: %d(%d) (loop = %d) key: %d value64(%d): %lldn", 
  428.    pos, sz, count, 
  429.    (key >> KP_KEYVAL_SHIFT) & KP_KEYVAL_MASK,
  430.    index,
  431.    entry.m_int64);
  432.     return true;
  433.   }
  434.   case ConfigValues::InvalidType:
  435.   default:
  436.     return false;
  437.   }
  438.   return false;
  439. }
  440. void
  441. ConfigValuesFactory::put(const ConfigValues & cfg){
  442.   
  443.   Uint32 curr = m_currentSection;
  444.   m_currentSection = 0;
  445.   ConfigValues::Entry tmp;
  446.   for(Uint32 i = 0; i < 2 * cfg.m_size; i += 2){
  447.     if(cfg.m_values[i] != CFV_KEY_FREE){
  448.       tmp.m_key = cfg.m_values[i];
  449.       cfg.getByPos(i, &tmp);
  450.       put(tmp);
  451.     }
  452.   }
  453.   m_currentSection = curr;
  454. }
  455. ConfigValues *
  456. ConfigValuesFactory::extractCurrentSection(const ConfigValues::ConstIterator & cfg){
  457.   ConfigValuesFactory * fac = new ConfigValuesFactory(20, 20);
  458.   Uint32 curr = cfg.m_currentSection;
  459.  
  460.   ConfigValues::Entry tmp;
  461.   for(Uint32 i = 0; i < 2 * cfg.m_cfg.m_size; i += 2){
  462.     Uint32 keypart = cfg.m_cfg.m_values[i];
  463.     const Uint32 sec = keypart & (KP_SECTION_MASK << KP_SECTION_SHIFT);
  464.     const Uint32 key = keypart & KP_KEYVAL_MASK;
  465.     if(sec == curr && key != CFV_KEY_PARENT){
  466.       tmp.m_key = cfg.m_cfg.m_values[i];
  467.       cfg.m_cfg.getByPos(i, &tmp);
  468.       tmp.m_key = key;
  469.       fac->put(tmp);
  470.     }
  471.   }
  472.   
  473.   ConfigValues * ret = fac->m_cfg;
  474.   delete fac;
  475.   return ret;
  476. }
  477. ConfigValues *
  478. ConfigValuesFactory::getConfigValues(){
  479.   ConfigValues * ret = m_cfg;
  480.   m_cfg = create(10, 10);
  481.   return ret;
  482. }
  483. static int
  484. mod4(unsigned int i){
  485.   int res = i + (4 - (i % 4));
  486.   return res;
  487. }
  488. Uint32
  489. ConfigValues::getPackedSize() const {
  490.   Uint32 size = 0;
  491.   for(Uint32 i = 0; i < 2 * m_size; i += 2){
  492.     Uint32 key = m_values[i];
  493.     if(key != CFV_KEY_FREE){
  494.       switch(::getTypeOf(key)){
  495.       case IntType:
  496.       case SectionType:
  497. size += 8;
  498. break;
  499.       case Int64Type:
  500. size += 12;
  501. break;
  502.       case StringType:
  503. size += 8; // key + len
  504. size += mod4(strlen(* getString(m_values[i+1])) + 1);
  505. break;
  506.       case InvalidType:
  507.       default:
  508. abort();
  509.       }
  510.     }
  511.   }
  512.   return size + sizeof(Magic) + 4; // checksum also
  513. }
  514. Uint32
  515. ConfigValues::pack(void * _dst, Uint32 _len) const {
  516.   Uint32 i;
  517.   char * dst = (char*)_dst;
  518.   memcpy(dst, Magic, sizeof(Magic)); dst += sizeof(Magic);
  519.   for(i = 0; i < 2 * m_size; i += 2){
  520.     Uint32 key = m_values[i];
  521.     Uint32 val = m_values[i+1];
  522.     if(key != CFV_KEY_FREE){
  523.       switch(::getTypeOf(key)){
  524.       case IntType:
  525.       case SectionType:
  526. * (Uint32*)dst = htonl(key); dst += 4;
  527. * (Uint32*)dst = htonl(val); dst += 4;
  528. break;
  529.       case Int64Type:{
  530. Uint64 i64 = * get64(val); 
  531. Uint32 hi = (i64 >> 32);
  532. Uint32 lo = (i64 & 0xFFFFFFFF);
  533. * (Uint32*)dst = htonl(key); dst += 4;
  534. * (Uint32*)dst = htonl(hi); dst += 4;
  535. * (Uint32*)dst = htonl(lo); dst += 4;
  536.       }
  537. break;
  538.       case StringType:{
  539. const char * str = * getString(val);
  540. Uint32 len = strlen(str) + 1;
  541. * (Uint32*)dst = htonl(key); dst += 4;
  542. * (Uint32*)dst = htonl(len); dst += 4;
  543. memcpy(dst, str, len); 
  544. memset(dst+len, 0, mod4(len) - len);
  545. dst += mod4(len);
  546.       }
  547. break;
  548.       case InvalidType:
  549.       default:
  550. abort();
  551.       }
  552.     }
  553.   }
  554.   const Uint32 * sum = (Uint32*)_dst;
  555.   const Uint32 len = ((Uint32*)dst) - sum;
  556.   Uint32 chk = 0;
  557.   for(i = 0; i<len; i++){
  558.     chk ^= htonl(sum[i]);
  559.   }
  560.   * (Uint32*)dst = htonl(chk); dst += 4;
  561.   return 4 * (len + 1);
  562. }
  563. bool
  564. ConfigValuesFactory::unpack(const void * _src, Uint32 len){
  565.   if(len < sizeof(Magic) + 4){
  566.     DEBUG abort();
  567.     return false;
  568.   }
  569.   if(memcmp(_src, Magic, sizeof(Magic)) != 0){
  570.     DEBUG abort();
  571.     return false;
  572.   }
  573.   const char * src = (const char *)_src;
  574.   {
  575.     Uint32 len32 = (len >> 2);
  576.     const Uint32 * tmp = (const Uint32*)_src;
  577.     Uint32 chk = 0;
  578.     for(Uint32 i = 0; (i+1)<len32; i++){
  579.       chk ^= ntohl(tmp[i]);
  580.     }
  581.     if(chk != ntohl(tmp[len32-1])){
  582.       DEBUG abort();
  583.       return false;
  584.     }
  585.   }
  586.   const char * end = src + len - 4;
  587.   src += sizeof(Magic);
  588.  
  589.   ConfigValues::Entry entry;
  590.   while(end - src > 4){
  591.     Uint32 tmp = ntohl(* (const Uint32 *)src); src += 4;
  592.     entry.m_key = tmp  & KP_MASK;
  593.     entry.m_type = ::getTypeOf(tmp);
  594.     switch(entry.m_type){
  595.     case ConfigValues::IntType:
  596.     case ConfigValues::SectionType:
  597.       entry.m_int = ntohl(* (const Uint32 *)src); src += 4;
  598.       break;
  599.     case ConfigValues::Int64Type:{
  600.       Uint64 hi = ntohl(* (const Uint32 *)src); src += 4;
  601.       Uint64 lo = ntohl(* (const Uint32 *)src); src += 4;
  602.       entry.m_int64 = (hi <<32) | lo;
  603.     }
  604.       break;
  605.     case ConfigValues::StringType:{
  606.       Uint32 s_len = ntohl(* (const Uint32 *)src); src += 4;
  607.       size_t s_len2 = strlen((const char*)src);
  608.       if(s_len2 + 1 != s_len){
  609. DEBUG abort();
  610. return false;
  611.       }
  612.       entry.m_string = (const char*)src; src+= mod4(s_len);
  613.     }
  614.       break;
  615.     case ConfigValues::InvalidType:
  616.     default:
  617.       DEBUG abort();
  618.       return false;
  619.     }
  620.     if(!put(entry)){
  621.       DEBUG abort();
  622.       return false;
  623.     }
  624.   }
  625.   if(src != end){
  626.     DEBUG abort();
  627.     return false;
  628.   }
  629.   return true;
  630. }
  631. #ifdef __TEST_CV_HASH_HPP
  632. int
  633. main(void){
  634.   srand(time(0));
  635.   for(int t = 0; t<100; t++){
  636.     const size_t len = directory(rand() % 1000);
  637.     printf("size = %dn", len);
  638.     unsigned * buf = new unsigned[len];
  639.     for(size_t key = 0; key<len; key++){
  640.       Uint32 p = hash(key, len);
  641.       for(size_t j = 0; j<len; j++){
  642. buf[j] = p;
  643. p = nextHash(key, len, p, j+1);
  644.       }
  645.     
  646.       for(size_t j = 0; j<len; j++){
  647. Uint32 pos = buf[j];
  648. int unique = 0;
  649. for(size_t k = j + 1; k<len; k++){
  650.   if(pos == buf[k]){
  651.     if(unique > 0)
  652.       printf("size=%d key=%d pos(%d)=%d buf[%d]=%dn", len, key, j, pos, k, buf[k]);
  653.     unique ++;
  654.   }
  655. }
  656. if(unique > 1){
  657.   printf("key = %d size = %d not uniqe!!n", key, len);
  658.   for(size_t k = 0; k<len; k++){
  659.     printf("%d ", buf[k]);
  660.   }
  661.   printf("n");
  662. }
  663.       }
  664.     }
  665.     delete[] buf;
  666.   }
  667.   return 0;
  668. }
  669. #endif