00001
00002
00003
00004
00005
00006
00007
00008 #ifdef CHASH_C
00009 #define IO_IN_C_FILE
00010 #endif
00011 #include "Common_inline.h"
00012 #ifdef IO_DECLARE_INLINES
00013
00014 #define CRecords_recordAt_(records, pos) (CHashRecord *)(records + (pos * sizeof(CHashRecord)))
00015
00016 IOINLINE CHashRecord *CHash_record1_(CHash *self, void *k)
00017 {
00018
00019 size_t pos = self->hash1(k) & self->mask;
00020
00021 return CRecords_recordAt_(self->records, pos);
00022 }
00023
00024 IOINLINE CHashRecord *CHash_record2_(CHash *self, void *k)
00025 {
00026
00027 size_t pos = self->hash2(k) & self->mask;
00028
00029 return CRecords_recordAt_(self->records, pos);
00030 }
00031
00032 IOINLINE void *CHash_at_(CHash *self, void *k)
00033 {
00034 CHashRecord *r;
00035
00036 r = CHash_record1_(self, k);
00037
00038 if(r->k && self->equals(k, r->k))
00039 {
00040 return r->v;
00041 }
00042
00043 r = CHash_record2_(self, k);
00044
00045 if(r->k && self->equals(k, r->k))
00046 {
00047 return r->v;
00048 }
00049
00050 return 0x0;
00051 }
00052
00053 IOINLINE size_t CHash_count(CHash *self)
00054 {
00055 return self->keyCount;
00056 }
00057
00058 IOINLINE int CHashKey_hasKey_(CHash *self, void *key)
00059 {
00060 return CHash_at_(self, key) != NULL;
00061 }
00062
00063 IOINLINE int CHash_at_put_(CHash *self, void *k, void *v)
00064 {
00065 CHashRecord *r;
00066
00067 r = CHash_record1_(self, k);
00068
00069 if(!r->k)
00070 {
00071 r->k = k;
00072 r->v = v;
00073 self->keyCount ++;
00074 return 0;
00075 }
00076
00077 if(k == r->k || self->equals(k, r->k))
00078 {
00079 r->v = v;
00080 return 0;
00081 }
00082
00083 r = CHash_record2_(self, k);
00084
00085 if(!r->k)
00086 {
00087 r->k = k;
00088 r->v = v;
00089 self->keyCount ++;
00090 return 0;
00091 }
00092
00093 if(k == r->k || self->equals(k, r->k))
00094 {
00095 r->v = v;
00096 return 0;
00097 }
00098
00099
00100 {
00101 CHashRecord x;
00102 x.k = k;
00103 x.v = v;
00104 return CHash_insert_(self, &x);
00105 }
00106 }
00107
00108 IOINLINE void CHash_shrinkIfNeeded(CHash *self)
00109 {
00110 if(self->keyCount < self->size/5)
00111 {
00112 CHash_shrink(self);
00113 }
00114 }
00115
00116 IOINLINE void CHashRecord_swapWith_(CHashRecord *self, CHashRecord *other)
00117 {
00118 CHashRecord tmp = *self;
00119 *self = *other;
00120 *other = tmp;
00121 }
00122
00123 IOINLINE void CHash_clean(CHash *self)
00124 {
00125 memset(self->records, 0, sizeof(CHashRecord) * self->size);
00126 self->keyCount = 0;
00127 }
00128
00129
00130
00131 #define CHASH_FOREACH(self, pkey, pvalue, code) \
00132 {\
00133 CHash *_self = (self);\
00134 unsigned char *_records = _self->records;\
00135 unsigned int _i, _size = _self->size;\
00136 void *pkey;\
00137 void *pvalue;\
00138 \
00139 for (_i = 0; _i < _size; _i ++)\
00140 {\
00141 CHashRecord *_record = CRecords_recordAt_(_records, _i);\
00142 if (_record->k)\
00143 {\
00144 pkey = _record->k;\
00145 pvalue = _record->v;\
00146 code;\
00147 }\
00148 }\
00149 }
00150
00151 #undef IO_IN_C_FILE
00152 #endif