acl/lib_acl_cpp/samples/diff/main.cpp

279 lines
6.6 KiB
C++

#include "stdafx.h"
#include <getopt.h>
#include "mail_object.h"
struct DIFF_RES
{
int equal;
int added;
int deleted;
int updated;
};
static void print_objs(const std::vector<acl::diff_object*>& objs,
const char* prompt, int max)
{
int i = 0;
for (std::vector<acl::diff_object*>::const_iterator cit = objs.begin();
cit != objs.end() && i++ < max; ++cit)
{
printf(">>%s->%d: key: %s, val: %s\r\n",
prompt, i, (*cit)->get_key(), (*cit)->get_val());
}
}
static void print_objs(
const std::vector<std::pair<acl::diff_object*, acl::diff_object*> >& objs,
const char* prompt, int max)
{
int i = 0;
for (std::vector<std::pair<acl::diff_object*, acl::diff_object*> >
::const_iterator cit = objs.begin();
cit != objs.end() && i++ < max; ++cit)
{
printf(">>%s->%d: key: %s, new val: %s, old val: %s\r\n",
prompt, i, (*cit).first->get_key(),
(*cit).first->get_val(),
(*cit).second->get_val());
}
}
static int load_objs(acl::diff_manager& manager, const char* filepath,
std::vector<acl::diff_object*>& new_objs)
{
acl::ifstream in;
// 以只读方式打开数据文件
if (in.open_read(filepath) == false)
{
printf("open %s error %s\r\n", filepath, acl::last_serror());
return -1;
}
// 从比较器中获得内存池对象,以便于下面分配内存
acl::dbuf_guard& dbuf = manager.get_dbuf();
int linenum = 0;
acl::string line;
int nobjs = 0;
while (!in.eof())
{
line.clear();
// 从文件中读取一行数据
if (in.gets(line) == false)
break;
linenum++;
// 分析该行数据,提取 key 和 value 值
char* key = line.c_str();
char* val = strrchr(key, '|');
// 检查数据的有效性
if (val == NULL || val == key || *(val + 1) == 0)
{
printf("invalid line: %s in %s, linenum: %d\r\n",
key, filepath, linenum);
continue;
}
*val++ = 0;
// 创建 diff 对象,并置入对象集合中
mail_object* obj = new (dbuf.dbuf_alloc(sizeof(mail_object)))
mail_object(manager, key, val);
new_objs.push_back(obj);
nobjs++;
}
return nobjs;
}
static bool check_diff(const char* new_file, const char* old_file,
const DIFF_RES* res = NULL)
{
// 首先定义差集比较器
acl::diff_manager manager;
// 存放当前对象
std::vector<acl::diff_object*> cur_objs;
// 存放旧的对象
std::vector<acl::diff_object*> old_objs;
// 先从文件中读取当前的对象至新对象集合中
int n = load_objs(manager, new_file, cur_objs);
if (n < 0)
{
printf("load curr objs error from %s\r\n", new_file);
return false;
}
printf("cur objs: %d\r\n", n);
// 再从文件中读取旧的对象至旧对象集合中
n = load_objs(manager, old_file, old_objs);
if (n < 0)
{
printf("load old objs error from %s\r\n", old_file);
return false;
}
struct timeval begin;
gettimeofday(&begin, NULL);
// 开始进行差集比较,并获得最终新增对象人个数
manager.diff_changes(cur_objs, old_objs);
struct timeval end;
gettimeofday(&end, NULL);
double spent = acl::stamp_sub(end, begin);
printf("spent: %.4f ms\r\n", spent);
printf("-------------------------------------------------------\r\n");
// 获得新增对象集合
const std::vector<acl::diff_object*>& new_objs = manager.get_new();
// 打印新增对象至屏幕,限定最大输出 10 个
print_objs(new_objs, "new objs", 10);
printf("new nobjs: %d\r\n", (int) new_objs.size());
printf("-------------------------------------------------------\r\n");
// 获得被删除的对象集合
const std::vector<acl::diff_object*>& del_objs = manager.get_deleted();
// 打印删除的对象至屏幕,限定最大输出 10 个
print_objs(del_objs, "deleted objs", 10);
printf("deleted objs: %d\r\n", (int) del_objs.size());
printf("-------------------------------------------------------\r\n");
// 获得变化的对象集合
const std::vector<std::pair<acl::diff_object*, acl::diff_object*> >&
upd_objs = manager.get_updated();
// 打印变化的对象至屏幕,限定最大输出 10 个
print_objs(upd_objs, "updated objs", 10);
printf("updated objs: %d\r\n", (int) upd_objs.size());
printf("-------------------------------------------------------\r\n");
// 获得相同的对象集合
const std::vector<acl::diff_object*>& equ_objs = manager.get_same();
print_objs(equ_objs, "equal objs", 10);
printf("equal objs: %d\r\n", (int) equ_objs.size());
printf("-------------------------------------------------------\r\n");
// 本函数返回则 manager 对象及内部自建内存池自动销毁
if (res == NULL)
return true;
if (res->equal != (int) equ_objs.size())
{
printf("invalid equal: %d, %lu\r\n", res->equal, equ_objs.size());
return false;
}
if (res->updated != (int) upd_objs.size())
{
printf("invalid updated: %d, %lu\r\n",
res->updated, equ_objs.size());
return false;
}
if (res->deleted != (int) del_objs.size())
{
printf("invalid deleted: %d, %lu\r\n",
res->deleted, del_objs.size());
return false;
}
if (res->added != (int) new_objs.size())
{
printf("invalid added: %d, %lu\r\n",
res->added, new_objs.size());
return false;
}
return true;
}
static void usage(const char* procname)
{
printf("usage: %s -h [help] -n new_file -o old_file\r\n"
" -N new_objs_count\r\n"
" -U update_objs_count\r\n"
" -D delete_objs_count\r\n"
" -E equal_objs_count\r\n",
procname);
}
int main(int argc, char* argv[])
{
int ch;
acl::string new_file, old_file;
DIFF_RES res;
res.deleted = -1;
res.updated = -1;
res.added = -1;
res.equal = -1;
while ((ch = getopt(argc, argv, "hn:o:N:U:D:E:")) > 0)
{
switch (ch)
{
case 'h':
usage(argv[0]);
return 0;
case 'n':
new_file = optarg;
break;
case 'o':
old_file = optarg;
break;
case 'N':
res.added = atoi(optarg);
break;
case 'U':
res.updated = atoi(optarg);
break;
case 'D':
res.deleted = atoi(optarg);
break;
case 'E':
res.equal = atoi(optarg);
break;
default:
break;
}
}
if (new_file.empty() || old_file.empty())
{
usage(argv[0]);
return -1;
}
// 如果设置了完整的期望结果集数值,则传入校验差集结果
if (check_diff(new_file, old_file,
res.updated >= 0 && res.deleted >= 0
&& res.added >= 0 && res.equal >= 0 ? &res : NULL) == true)
{
printf("check diff ok, new_file: %s, old_file: %s\r\n",
new_file.c_str(), old_file.c_str());
}
else
{
printf("check error, new_file: %s, old_file: %s\r\n",
new_file.c_str(), old_file.c_str());
return 1;
}
return 0;
}