coding啊coding,有帮忙测试代码的没

lbaby 2007-08-04 01:10:56
平时的工作里需要对很多数据进行查找,数据的格式不定,每新加一个数据
都要写对应的查找接口(程序的构架不好),真累人。

数据大致看起来这样:
f1|f2|f3
fn|fn1|fn2
就是列数固定的 用同样分隔符 分隔的数据

这次要新加很多数据,别说作了,就连事先想一想就够累人的了,于是俺怒了--虽然俺是从乡下来的,但是---俺怒了,新写了一个查找类,可以查找任意列数任意长度(当然了,不能太离谱,因为我们的数据基本上格式是一致的)的数据,可以对第N(非第一列)列定义不同的查找规则(比如说,指定第二比参数大)

其中一部分代码是抄的sgi的stl,水平所限,没法将代码写得更通用:
//hash 查找
//htable.h

#ifndef HASH_TABLE_H
#define HASH_TABLE_H

#include <vector>
#include <stdexcept>


#ifdef _USING_NAMESPACE_STD
using namespace std;
#endif

#ifdef _NEED_STDINT
#include <stdint.h>
#endif

#include <stdio.h>




//To find a data member with your need
template <class T>
class hashvisitor
{
public:
virtual bool done(void)
{
return false;
}

virtual void visit(T *t) =0;

};



//hash function for a string
//
inline size_t hashstr(const char* s)
{
unsigned long h = 0;
for ( ; *s; ++s) {
h = 5*h + *s;
}

return size_t(h);
}

template <class _Key>
struct hash
{ }
;


template<>
struct hash<const char *>
{
size_t operator ()(const char *s)const
{
return (hashstr(s));
}
};

template<>
struct hash<char *>
{
size_t operator ()(char *s)const
{
return (hashstr(s));
}
};



//prime list , for hash table's size
//
enum { num_primes = 28 };

static const unsigned long prime_list[num_primes] =
{
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul
};


//layout for data
//data member's are organized with a chunk of data,
//every data member's size can change with need
//
enum {num_layout = 13};
static const size_t layout_list [ num_layout] =
{
1, 2, 3, 5,
8, 13, 21, 34,
55,89,144,233,377
};



size_t proper_layout(const size_t n);

//note:hash node does not manage data memory itself
//he just point an exist memory region
//obversely , the node is a link list node
template <class T, class HF=hash<T* > >
class hnode
{

public :
hnode( T* v=NULL):m_value(v),m_next(NULL)
{}

virtual void accept(hashvisitor<T> &v)
{

hnode<T> *p = this;

while (!v.done() && p) {
if(!p->m_value) {
break;
}
v.visit(p->m_value);
p = p->m_next;
}
}

size_t hashvalue(void) const
{
return hf(m_value);
}

T * value(void) const
{
return m_value;
}


hnode<T>* back(void)
{
hnode<T>* p = this;
while(p->m_next) {
p= p->m_next;
}
return p;
}

const hnode<T> &
set_next(hnode<T > * h)
{
m_next = h;
return *h;
}

T * set_value(T* v)
{
return m_value = v;

}

private:
HF hf;
T *m_value;
hnode<T> *m_next;
};


//layout infomation for data chunk:
//
typedef struct layout
{
int pos;
size_t len;
bool operator == (const layout &arg) const
{
return (pos == arg.pos) && (len == arg.len);
}

bool operator > (const layout &arg) const
{
return (pos > arg.pos) ||(len > arg.len);
}

bool operator < (const layout &arg) const
{
return (pos < arg.pos) ||(len <arg.len);
}

layout():pos(0),len(0)
{}

}
layout_t;

typedef vector<layout> lo_t;




//this htable can only used to search for data
//never delete any data!

template <class T>
class htable
{
public:

htable(size_t n):size(n),base(NULL),data()
{
size_t i;
for(i = 0 ; i < num_primes; i++) {
if(n <= prime_list[i]) {
break;
}
}
size = (i == num_primes) ? prime_list[i-1]:prime_list[i];
base = new hnode<T> [size];
extra_size = size/4;
}


~htable()
{
purge();
}

void purge(void);

const hnode<T> &insert(const hnode<T> &h);
const hnode<T> & insert(T *h, const vector<layout_t> &l);
hnode<T> &find(const hnode<T> &h);



void set_layout(const vector <layout_t> &l)
{
/*
size_t addn = 0;
for(size_t i = 0 ; i < l.size(); i++){
layout_t nl;
nl.pos += addn;
nl.len = proper_layout(l[i].len);

addn += nl.len -l[i].len;
nl.pos += l[i].pos;
data_layout.push_back( nl );
}*/
data_layout = l;

chunksz = data_layout[data_layout.size() -1] . pos + data_layout[data_layout.size() -1].len;
data.ptr = new uint8_t [size * chunksz];
memset(data.ptr, 0, chunksz * extra_size);


}

const vector <layout_t> & get_layout(void) const
{
return data_layout;
}

htable & operator = ( htable & h);


htable(const htable & h)
{
*this = h;
}

typedef struct pool_info
{
uint8_t *ptr;
size_t count;
pool_info ():ptr(NULL), count(0)
{}
}
data_pool_t ;

private:


size_t h(size_t n)const

{
//printf("%d:%d\n", n, n%size);
return n%size;
}
size_t extra_size ;
//for overflow's extra data
vector <layout_t> data_layout; //
size_t size;//the length of hash table
size_t chunksz;

vector<size_t> base_pool_count;//for hnode's pool count

hnode<T> *base;

data_pool_t data;


vector<hnode<T> *> base_pool;//memory pool for overflow
vector<data_pool_t> data_pool;//data pool for memory manage

};

template <typename T>
class copy_visitor:public hashvisitor<T>
{
public:
copy_visitor(htable <T> *const to,const vector<layout_t> &lo )
:ht(to),l(lo)
{}

virtual void visit(T *t)
{
ht->insert(t, l);

}


private:
vector <layout_t> l;
htable <T> *ht;

};

...全文
411 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
taodm 2007-08-24
  • 打赏
  • 举报
回复
看来你做得很完备,很满足你的需要嘛。那就用吧。
lbaby 2007-08-23
  • 打赏
  • 举报
回复
http://www.esnips.com/doc/4eff99d0-49c3-49f1-a9d0-cf161f86069b/dfdemore
带有re版本的
lbaby 2007-08-23
  • 打赏
  • 举报
回复
在现实的项目中,要查找的数据是动态更新的,
数据的更新由另一个程序完成,然后,查找程序会检查时间戳然后加载数据

lbaby 2007-08-23
  • 打赏
  • 举报
回复
struct strfnmatch:public comparestr
{

bool operator () (const char *pattern, const char *str, size_t n)
{
return !fnmatch(pattern,str,0);

}
};


struct strregexp:public comparestr
{

bool operator () (const char *pattern, const char *str, size_t n)
{

regex_t re;

int i = 0;
if( i = regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB)){
char ermsg[256] ;
string ts;
ts = "Invalid regular expression: ";
regerror(i,&re,ermsg,sizeof ermsg);
ts += ermsg;
throw invalid_argument(ts.c_str());
}

bool ret = regexec(&re, str, (size_t) 0, NULL, 0);
regfree(&re);
return !ret;

}



事实上,查找的类是不知道比较算法的,因此,我们可以自定义查找规则,
上边的查找规则是shell通配符和正则表达式的,
在我机器(linux)上表现如下:
shell通配
[ofen@lbaby dfdemo]$ ./dfdemo c 2 fm '1[90]'
1900
1900|19|长沙|湖南
re表达式:
[ofen@lbaby dfdemo]$ ./dfdemo c 3 re '长[春沙]'
1900
1900|19|长沙|湖南
taodm 2007-08-23
  • 打赏
  • 举报
回复
通配呢,比如南*,要通配南京/南昌....

貌似你不需要动态修改的功能。那,自己写hash是可行的。
lbaby 2007-08-23
  • 打赏
  • 举报
回复
回复人:taodm((不能收CSDN社区短信息,请莫浪费精力)) ( 两星(中级)) 信誉:100 2007-08-23 13:15:28 得分:0
?
多任务并发呢?数据动态变化呢?数据量超过你的物理内存呢?

---------
多任务并发可以通过数据共享来完成,但是,目前的情况我们通过多起同样的进程就可以解决

数据动态变化:上边的程序里已有动态加载功能
数据量超过内存的情况现在还不存在,因为我们的应用的数据量也就几百万条记录,
主机的内存是10GB(64~94GB)级别的


这个数据应用的主要原因是,查找次数太多,每天要进行上百亿次以上的查询,
并且,对时间的要求比较高


taodm 2007-08-23
  • 打赏
  • 举报
回复
能查找第一列是X,第二列不是Y的行么?
lbaby 2007-08-23
  • 打赏
  • 举报
回复
举例子:
QQ的安装目录里就有这些数据:
\QQAddrDat下是一些以'|'分隔的数据,如:
citylist.dat
00|0|北京|北京
001|0|怀柔县|北京
002|0|大兴县|北京
003|0|顺义县|北京
004|0|延庆县|北京
005|0|密云县|北京
006|0|昌平县|北京
007|0|平谷县|北京
008|0|通州区|北京
009|0|燕山|北京
100|1|天津|天津
101|1|宝坻县|天津
102|1|静海县|天津
103|1|武清县|天津
104|1|宁河县|天津
105|1|蓟县|天津
200|2|上海|上海
201|2|上海县|上海
202|2|南汇县|上海
203|2|青浦县|上海
204|2|嘉定县|上海
205|2|宝山县|上海
206|2|奉贤县|上海
207|2|崇明县|上海
208|2|松江县|上海
209|2|川沙县|上海
210|2|金山县|上海
300|3|重庆|重庆
400|4|石家庄|河北
401|4|邯郸|河北
402|4|武安|河北
403|4|临漳|河北
404|4|磁县|河北
405|4|涉县|河北
406|4|成安|河北
407|4|永年|河北
408|4|鸡泽|河北
409|4|曲周|河北
410|4|丘县|河北
411|4|馆陶|河北

可以这样来测试:
dfdemo citylist.dat
然后输入:
1900
输出:
1900|19|长沙|湖南


dfdemo citylist.dat 2 gt 18
(对第二个域限定其值大于18)

然后输入:
1900
输出:
1900|19|长沙|湖南


dfdemo citylist.dat 2 lt 20 3 eq 长沙
(对第二个域限定其值小于20 且第三个域等于长沙)

然后输入:
1900
输出:
1900|19|长沙|湖南

大小关系允许的取值:
gt 大于
ge 大于等于
eq 等于
lt 小于
le 小于等于
ne 不等于


taodm 2007-08-23
  • 打赏
  • 举报
回复
多任务并发呢?数据动态变化呢?数据量超过你的物理内存呢?
lbaby 2007-08-23
  • 打赏
  • 举报
回复

回复人:taodm((不能收CSDN社区短信息,请莫浪费精力)) ( 两星(中级)) 信誉:100 2007-8-6 8:55:25 得分:0
?

楼主,你现在的代码比数据库快了多少?
对数据发生变化后,尤其是格式发生变化后,修改工作量又多少?
---------------------------------------------------------
taodm老大问的问题得回,呵呵
查找速度是数据库的10倍数量级别的

格式发生变化后,几乎不用修改代码,新增的数据也可以用不超过20行的代码搞定,

下边是代码,有一个可执行的demo(windows版本),能对这种以'|'分隔的任意数据进行查找
如果windows下装有dev-cpp(cygwin)的朋友可以直接通过
make -f makefile.linux来生成可执行文件

http://www.esnips.com/nsdoc/2d744952-060e-4124-a738-b5e4fcccc720



taodm 2007-08-06
  • 打赏
  • 举报
回复
楼主,你现在的代码比数据库快了多少?
对数据发生变化后,尤其是格式发生变化后,修改工作量又多少?
xbt746 2007-08-06
  • 打赏
  • 举报
回复
代码太大了阿。。。。。。。。。。。。。。。。。
lbaby 2007-08-04
  • 打赏
  • 举报
回复
有兴趣的给我发邮件地址吧,我发完整的代码包,
csdn上使用firefox会让缩进全部错乱。。。
lbaby 2007-08-04
  • 打赏
  • 举报
回复
因为数据库太慢
iambic 2007-08-04
  • 打赏
  • 举报
回复
情况看得不是太懂,为什么不用数据库?
iambic 2007-08-04
  • 打赏
  • 举报
回复
推荐楼主找个地方把文件上载……
lbaby 2007-08-04
  • 打赏
  • 举报
回复

//Makefile:
CXXFLAGS = -c -g -D_USING_NAMESPACE_STD -D_NEED_STDINT -I. -D_DATAFILE_MAIN -DDYNAMIC_LOAD #-D_HTABLE_MAIN
LDFLAGS = -g -lstdc++

AR=ar
ARFLAGS= rsv

DATAFILELIB=libdatafile.a

all:datafile
$(DATAFILELIB):datafile.o
$(AR) $(ARFLAGS) $@ $<

all:$(BINS)
#htable.o:htable.cpp htable.h
#ht:htable.o
# g++ -o ht htable.o -g

clean:
rm -f *.o core* $(BINS)

datafile.o:datafile.cpp datafile.h htable.

lbaby 2007-08-04
  • 打赏
  • 举报
回复
//datafile.cpp

#include <datafile.h>


size_t proper_layout(size_t n)
{
size_t i;
for ( i = 0; i < num_layout; i ++) {
if(layout_list[i] >= n) {
break;
}
}

if(i == num_layout) {
throw invalid_argument("can not find a proper layout:please enlarge your max layout limit");
}

return layout_list[i];
}

const char *trimsp(char *s)
{
char *nsp =NULL;
char *rs =s;
const char sp=' ';
while(*s ) {
if(*s == sp) {
if(!nsp) {
nsp = s;
}
} else {
nsp = NULL;
}
++s;
}

if(nsp) {
*nsp= '\0';
}

return rs;
}

const lo_t combin_layout(const lo_t &a, const lo_t &b)
{
lo_t l;
if(a.size() > b.size()) {
l = a;
for (int i = 0 ; i < b.size() ; i ++) {
if(l[i].len < b[i].len) {
l[i].len = b[i].len;
}
if(l[i].pos < b[i].pos) {
l[i].pos = b[i].pos;
}
}
} else {
l = b;
for (int i = 0 ; i < a.size() ; i ++) {
if(l[i].len < a[i].len) {
l[i].len = a[i].len;
}
if(l[i].pos < a[i].pos) {
l[i].pos = a[i].pos;
}
}
}

return l;


}

size_t findchr(const char *s, char c, size_t pos= 0)
{
size_t l = 0;
while(*(s+pos +l)) {
if(*(s + pos +l) == c) {
break;
}
++l;
}

return pos +l;

}


const char *format_layout(char *ns, lo_t nl,
char *os, lo_t ol)
{
for(int i = 0 ; i < ol.size(); i++) {
memcpy(ns+nl[i].pos, os + ol[i].pos, ol[i].len);
}

return ns;
}

const char *do_layout(char *s, const lo_t &l)
{
for (int i = 0; i < l.size(); i++) {
*(s + l[i].pos + l[i].len -1 ) = '\0';
}
return s;
}


const lo_t & decide_layout(lo_t &l,
const char *str,
const char separator='|')
{
int len = strlen(str);
layout lo;
size_t pos = 0;

do {

lo.pos = pos;
size_t np =findchr(str,separator, pos);
lo.len = np -pos +1 ;
pos = np + 1;
l.push_back(lo);
} while(pos < len);

if(len == pos) {
lo.pos = pos;
lo.len = pos -len +1 ;
l.push_back(lo);
}


return l;

}




void datafile::load(void)
{
struct stat dstat;

#ifdef DYNAMIC_LOAD

stat(fname.c_str(), &dstat);
isloaded = dstat.st_mtime <= load_time;
delete data;
data = 0;

#endif

if(isloaded) {
return;
}

stat(fname.c_str(), &dstat);

FILE *fp = fopen(fname.c_str(), "rt");
if(!fp) {
string e;
e="can not open" + fname;
throw runtime_error(e);
}

char buf[1024]= {0};

while(fgets(buf, sizeof(buf), fp)) {
if(buf[0] != '#') {
break;
}
}
//let's decide the data layout
//oo:estimate the lines in the file

size_t lsz = strlen(buf);
size_t lcount = dstat.st_size/lsz;//

size_t len = strlen(buf);
if(buf[len -1] == '\n') {
buf[len-1] = '\0';
}

data = new htable<char>(lcount);
decide_layout(l, buf,separator);
data->set_layout(l);

do {
if(buf[0] == '#') {
continue;
}

size_t len = strlen(buf);
if(buf[len -1] == '\n') {
buf[len-1] = '\0';
}
lo_t nl;
decide_layout(nl, buf,separator);
if(nl.size() > l.size() ) {
//do not accept different format in one file
throw runtime_error("invalid file format");
}

if(nl > l) {
htable<char> *nd = new htable<char>(lcount);

lo_t cl = combin_layout(nl, l);
nd->set_layout(cl);
*nd = *data;
l = cl;
delete data;
data = nd;

}

if(nl < l) {
char nbuf[1024] = {0} ;
do_layout(buf,nl);
trimsp(buf);
format_layout(nbuf, l, buf,nl);
data->insert((char *)nbuf, l);
} else {
do_layout(buf,l);
trimsp(buf);
data->insert((char *)buf, l);
}



memset(buf, 0, sizeof(buf));

} while(fgets(buf, sizeof(buf), fp));

//before we store the data
//we must set the layout


fclose(fp);
#ifdef DYNAMIC_LOAD
load_time = dstat.st_mtime ;
#endif
isloaded = true;


}


#ifdef _DATAFILE_MAIN

int main(void)
{
datafile adat("d.dat");
char s[1024] = {0};
adat.load();
compara_list_t chkrule;
streq eq;
strlt lt;
strgt gt;
compara p0 = {
0,
dynamic_cast<comparestr *> (&eq)
};

compara p1 = {
1,
dynamic_cast<comparestr *> (<)
};


compara p2 = {
2,
dynamic_cast<comparestr *> (>)
};

compara p3 = {
5,
dynamic_cast<comparestr *> (>)
};

compara p4 = {
6,
dynamic_cast<comparestr *> (<)
};



chkrule.push_back(p0);
chkrule.push_back(p1);
chkrule.push_back(p2);
chkrule.push_back(p3);
chkrule.push_back(p4);

strcpy(s + adat.get_layout()[0].pos, "123456");
strcpy(s + adat.get_layout()[1].pos, "SG");
strcpy(s + adat.get_layout()[2].pos, "D");
strcpy(s + adat.get_layout()[5].pos, "20070803235959");
strcpy(s + adat.get_layout()[6].pos, "20070803235959");

printf("%d:%d\n", adat.get_layout()[1].pos, adat.get_layout()[2].pos);
find_visitor<char> f(s,adat.get_layout(), chkrule);

adat.find(s).accept(f);
f.print();

/*printf("search:");
while(fgets(s, sizeof(s), stdin)) {
adat.load();
printf("search:");
if(s[strlen(s) -1] == '\n') {
s[strlen(s) -1] = '\0';
}
find_visitor<char> f(s,adat.get_layout());
adat.find(s).accept(f);
f.print();
printf("search:");
memset(s, 0 , sizeof(s));
}
*/

}
#endif

//datafile.cpp
lbaby 2007-08-04
  • 打赏
  • 举报
回复
//datafile.h
#ifndef DATAFILE_H_
#define DATAFILE_H_


#include <string>


#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>

#include <vector>

#include <htable.h>


#ifdef _USING_NAMESPACE_STD
using namespace std;
#endif





class datafile
{
public:
datafile(const char * const name,
const char sep='|'):fname(name),separator(sep),data(NULL)
{
#ifdef DYNAMIC_LOAD
load_time =0;
#endif

isloaded = false;

}


hnode <char> &
find(char *s)
{
if(!isloaded) {
throw runtime_error("can not search the data before you load it");
}
//we assume that the layout is the same as our htable
return data->find(hnode<char>(s));
}

~datafile()
{
delete data;
}

const vector<layout_t>
&get_layout(void)const
{
return l;
}

char get_separator(void)
{
return separator;
}

void load(void);

private:
string fname;


#ifdef DYNAMIC_LOAD

time_t load_time;
#endif

const char separator;
htable<char> *data;
vector<layout> l;
bool isloaded;

};

struct comparestr
{
virtual bool operator ()
(const char *str1, const char *str2, size_t n)
{
return false;
}

};

typedef struct compara
{
size_t pos;
comparestr *comp;
} compara_t;

typedef vector<compara_t> compara_list_t;

struct strlt:public comparestr
{
virtual bool operator () (const char *str1, const char *str2, size_t n)
{
//puts("lt");
return strncmp(str1,str2,n) < 0;
}
};

struct streq:public comparestr
{
bool operator () (const char *str1, const char *str2, size_t n)
{
//puts("eq");
return !strncmp(str1,str2,n);
}
};

struct strgt:public comparestr
{

bool operator () (const char *str1, const char *str2, size_t n)
{
//puts("gt");
return strncmp(str1,str2,n)>0;

}
};

static streq _strcompare_default;

static compara _compara_default =
{
0,
dynamic_cast<comparestr *> (&_strcompare_default)
};

static compara_list_t _compara_list_default(1, _compara_default);
template <typename T>
class find_visitor :public hashvisitor<T>
{};

template <>
class find_visitor <char> :public hashvisitor<char>
{
public:
find_visitor
(char *s
, const vector<layout_t> &al
,const compara_list_t &df=_compara_list_default)
:isdone(false),str(s),l(al),para(df)
{}

virtual void visit(char *t)
{


if(!t) {
return;
}
bool isdone = true;
for (int ck = 0; ck < para.size(); ++ck) {
// puts("visit");
if( (*para[ck].comp)(str +l[para[ck].pos].pos, t + l[para[ck].pos].pos, l[para[ck].pos].len-1)) {
//isdone = true;
/*
printf("OK::comp:%s:%s:%d\n",
str +l[para[ck].pos].pos,
t + l[para[ck].pos].pos,
l[para[ck].pos].len-1);*/
}else{
isdone = false;
/*
printf("FAILcomp:%s:%s:%d\n",
str +l[para[ck].pos].pos,
t + l[para[ck].pos].pos,
l[para[ck].pos].len-1);
break;
*/

}

}
if(isdone){
data.push_back(t);
}
}

void print(void)
{
int m = l.back().len + l.back().pos;
vector <char *> ::const_iterator itr;
for(itr = data.begin(); itr != data.end(); ++itr) {
printf("data:");
for(int i = 0; i < l.size(); ++i) {
printf(*itr +l[i].pos);
}
putchar('\n');
}
}


virtual bool done(void)
{
return isdone;
}


private:
char *str;
vector <layout_t> l;
vector <char *> data;
compara_list_t para;
bool isdone;

};







const lo_t & decide_layout(lo_t &l,
const char *str,
const char separator);

const char *format_layout(char *ns, lo_t nl,
char *os, lo_t ol);

const char *do_layout(char *s, const lo_t &l);






#endif /*DATAFILE_H_*/

// end of datafile.h

lbaby 2007-08-04
  • 打赏
  • 举报
回复

//
template<typename T>
void htable<T>::purge(void)
{
delete []base;
base = NULL;
delete []data.ptr;
data.ptr = NULL;
data.count = 0;
size_t i;
for( i = 0 ; i < base_pool.size(); ++i) {
delete []base_pool[i];

}
base_pool.clear();

for( i = 0 ; i < data_pool.size(); ++i) {
delete []data_pool[i].ptr;
}
data_pool.clear();
}



//when you resize the chunk , you get a new hash table
//set the layout, then copy the data from argument
//NOTE:this hashtable act as an auto_ptr, when you copy the data
//from one ptr, the ptr is purged.
template<typename T>
htable<T>
& htable<T>::operator = ( htable<T> & ht)
{
if(this == & ht) {
return *this;
}

//necessary check
if(data_layout.empty() || ht.data_layout.empty() ) {
throw logic_error("Please set data layout before you use this hash table");
}

if(data_layout.size() < ht.data_layout.size()) {
throw out_of_range("Please specific a bigger data(or equal) chunk num than the old one");
}
size_t i;
for( i = 0; i < ht.data_layout.size(); i ++) {
if(data_layout[i].len < ht.data_layout[i].len) {
throw out_of_range("Please specific a bigger chunk size than the old one");
}
}


copy_visitor<T> cv(this, ht.get_layout());

//note: we have copy all the node --including
for ( i = 0 ; i < ht.size ; i ++) {
if(ht.base[i].value()) {
ht.base[i].accept(cv);
}
}



return *this;
}



template<class T>
const
hnode<T> &
htable<T>::insert(const hnode<T> &hn)
{

size_t pos = h(hn.hashvalue());
hnode<T> *insert_point = base + pos;
hnode<T> *insert_node = NULL;
T * dat;

if(insert_point->value()) {//there is one element hold the position
//ok , let's look for the extra pool to put the hnode
insert_point=insert_point->back();

//get a node on overflow data area
size_t pool;
for(pool = 0 ; pool < base_pool_count.size(); ++ pool) {
if(base_pool_count[pool] < extra_size) {
break;
}
}

if(pool == base_pool_count.size()) {//all the pool is full
//let's get new one
hnode<T> *p = new hnode<T> [extra_size];
base_pool.push_back(p);
base_pool_count.push_back(0);
}
insert_node = base_pool[pool] + (base_pool_count[pool] ++);

} else {//the position is empty()
insert_node = insert_point;

}


if(data.count == size) {//data
//look for a memory area in data area
size_t data_pool_pos;
for(data_pool_pos = 0; data_pool_pos < data_pool.size(); ++data_pool_pos) {
if(this->data_pool[data_pool_pos].count <= extra_size -1) {
break;
}
}
//full data area
if(data_pool_pos == data_pool.size()) {
data_pool_t dp;
dp.ptr = new uint8_t [chunksz * extra_size];
memset(dp.ptr, 0, chunksz * extra_size);
data_pool.push_back(dp);
}

dat = reinterpret_cast<T* >
(
data_pool[data_pool_pos].ptr
+ chunksz * ( data_pool[data_pool_pos].count++)
);
} else {
dat = reinterpret_cast<T * >
(
data.ptr
+ chunksz * ( data.count++)
);
}

memcpy(dat, hn.value(), chunksz);
insert_node->set_value(dat);

if(insert_node != insert_point) {
insert_point->set_next(insert_node);
}

return *insert_node;
}



template<class T>
const
hnode<T> &

htable<T>::insert(T *t, const vector<layout_t> &l)
{
if(data_layout.size() <l.size()) {
throw out_of_range("Please specific a bigger data(or equal) chunk num than the old one");
}
size_t i;

for(i = 0; i < l.size(); i ++) {
if(data_layout[i].len < l[i].len) {
throw out_of_range("Please specific a bigger chunk size than the old one");
}
}
if(l == data_layout) {
return insert(hnode<T>(t));
}

uint8_t * tmp = new uint8_t[chunksz];

for(i = 0 ; i < l.size(); i++) {
memcpy(tmp+data_layout[i].pos, reinterpret_cast<uint8_t *>(t) + l[i].pos, l[i].len);
}

const hnode<T> &hn = insert(hnode<char>((char*)tmp));
delete []tmp;
return hn;

}

template<class T>
hnode<T> &
htable<T>::find( const hnode<T> &hn)
{
return base[ h(hn.hashvalue()) ];
}





#endif /*HASH_TABLE_H*/

//end of htable.h

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧