From 5df79c53745fde5d6c3340a2979b1429cd5892c1 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sat, 8 Oct 2011 20:30:28 +0200 Subject: Initial import of htcd system 1.0 Signed-off-by: Henrik Rydberg --- src/lang/db.cc | 237 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 src/lang/db.cc (limited to 'src/lang/db.cc') diff --git a/src/lang/db.cc b/src/lang/db.cc new file mode 100644 index 0000000..9192d09 --- /dev/null +++ b/src/lang/db.cc @@ -0,0 +1,237 @@ +/************************************************************************* + * + * HTCd - Copyright (C) 1998-2006 Henrik Rydberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +static dbmap* GetDB(Env& env) throw(merror_t) { + if(!env.db) THROW("htc: no open database"); + return env.db; +} + +static int eval(Env& env,expr_t* x,int mod=OP_ALL) { + mswrite out; + if(x->status&OP_PARSE) env.parse(out,x->expr); else x->eval(out,env,mod); + return atob(out.str()); +} + +//////////////////////////////////////////////////////////////////////////// + +TOK_IMPL(create) { + dbref_t* ref=DBRef(*env.toks,env[0],ms_empty,tok_t::PUBLIC,1); + ref->db.Open("/dev/zero",1); + sref first,rest=env[1]; int n=0; + while(Split(first,rest)) ref->db.InsertTable(n++,first); + ref->db.Order(env[2],env[3]); +} + +TOK_IMPL(sort) { + dbref_t* ref=(dbref_t*)env.toks->get_this(env[0]); + if(env.is_clear(ref)&&ref->is_dbref()) { + ref->db.remap(); + ref->db.Sort(env[1],env[2]); + } + else THROW("htc: "<get(env[0]); + if(env.is_clear(ref)&&ref->is_dbref()) { + ref->db.remap(); + Env(env,ref->db).parse(out,env.arg(1)); + } + else THROW("htc: "<=0&&env.req->is_running()&&nenv.dbatsize()) { + int size=db->size(); + if(eval(nenv,x[0],OP_LOCAL)) nenv.parse(out,x[1]); + if(db->size()==size) nenv.dbat++; + } +} + +TOK_IMPL(find_rec) { + dbmap* db=GetDB(env); + Env nenv(env,*db); + nenv.dbat=db->Find(env[0]); + if(nenv.dbat>=0&&nenv.dbatsize()) nenv.parse(out,env.arg(1)); + else env.parg(out,2); +} + +//////////////////////////////////////////////////////////////////// + +TOK_IMPL(first_rec) { env.dbat=0; } +TOK_IMPL(prev_rec) { if(env.dbat>0) env.dbat--; } +TOK_IMPL(next_rec) { if(env.dbatsize()) env.dbat++; } +TOK_IMPL(exist_rec) { out<=0&&env.dbatsize()); } + +TOK_IMPL(rem_rec) { + dbmap* db=GetDB(env); + if(env.dbat>=0&&env.dbatsize()) db->Rem(env.dbat); +} + +//////////////////////////////////////////////////////////////////// + +TOK_IMPL(lastkey) { + dbmap* db=GetDB(env); + if(!db->empty()) out<at(db->size()-1,db->Index()); +} + +TOK_IMPL(prevkey) { + dbmap* db=GetDB(env); + if(env.dbat>0&&env.dbat<=db->size()) out<at(env.dbat-1,db->Index()); +} + +TOK_IMPL(nextkey) { + dbmap* db=GetDB(env); + if(env.dbat>=0&&env.dbat+1size()) out<at(env.dbat+1,db->Index()); +} + +TOK_IMPL(qprevkey) { + dbmap* db=GetDB(env); + expr_t* x=env.arg(0); + Env nenv(env,*db); + nenv.dbat=env.dbat-1; + while(nenv.dbat>=0&&env.req->is_running()&&nenv.dbatsize()) { + if(eval(nenv,x,OP_LOCAL)) { out<at(nenv.dbat,db->Index()); break; } + else nenv.dbat--; + } +} + +TOK_IMPL(qnextkey) { + dbmap* db=GetDB(env); + expr_t* x=env.arg(0); + Env nenv(env,*db); + nenv.dbat=env.dbat+1; + while(nenv.dbat>=0&&env.req->is_running()&&nenv.dbatsize()) { + if(eval(nenv,x,OP_LOCAL)) { out<at(nenv.dbat,db->Index()); break; } + else nenv.dbat++; + } +} + +//////////////////////////////////////////////////////////////////// + +void envAddDB(tokmap& T) +{ + TOK_ADD(create,"xxxx",tok_t::SYSONLY, + "%Create a new database\n" + "%Syntax: \\create{varname}{tables}{index}{comp}\n" + "%\n" + "%Index is the unique, ordered table.\n" + "%Comp is the compare function.\n" + "%A maxmimum of 32 tables are allowed in HDB/1.2\n" + ); + TOK_ADD(sort,"xxx",tok_t::PRIVATE, + "%Sort a database\n" + "%Syntax: \\sort{varname}{index}{comp}\n" + "%\n" + "%Note that only globals on the current level are sortable.\n" + ); + + //////////////////////////////////////////////////////// + + TOK_ADD(db,"xr",tok_t::PRIVATE, + "%Set current database\n" + "%Syntax: \\db{varname}{body}\n" + "%\n" + "%Within body, all database functions apply.\n" + ); + TOK_ADD(query,"xr",tok_t::PRIVATE, + "%Query current database\n" + "%Syntax: \\query{test}{body}\n" + "%\n" + "%Evaluates body for all record where test is true.\n" + "%\n" + "%optimizes globals; it is ok to use full function\n" + "%expressions in the query. Turned out to be better after all.\n" + ); + TOK_ADD(find_rec,"xr?",tok_t::PRIVATE, + "%Find record by key, in current database\n" + "%Syntax: \\find.rec{key}{body}\n" + "%\n" + "%Evaluates body if key is found in the current ordering.\n" + "%Otherwise, evaluates , if exist.\n" + ); + + //////////////////////////////////////////////////////// + + TOK_ADD(first_rec,"",tok_t::PRIVATE, + "%Go to first record\n" + "%Syntax: \\first.rec\n" + ); + TOK_ADD(exist_rec,"",tok_t::PRIVATE, + "%True if current record exist\n" + "%Syntax: \\exist.rec\n" + ); + TOK_ADD(next_rec,"",tok_t::PRIVATE, + "%Go to next record\n" + "%Syntax: \\next.rec\n" + ); + TOK_ADD(prev_rec,"",tok_t::PRIVATE, + "%Go to previous record\n" + "%Syntax: \\prev.rec\n" + ); + TOK_ADD(rem_rec,"",tok_t::SYSONLY, + "%Remove current record\n" + "%Syntax: \\rem.rec\n" + ); + + //////////////////////////////////////////////////////// + + TOK_ADD(lastkey,"",tok_t::PRIVATE, + "%Last key of current order\n" + "%Syntax: \\lastkey\n" + "%\n" + "%Silently ignored if not found.\n" + ); + TOK_ADD(prevkey,"",tok_t::PRIVATE, + "%Previous key of current order\n" + "%Syntax: \\prevkey\n" + "%\n" + "%Silently ignored if not found.\n" + ); + TOK_ADD(nextkey,"",tok_t::PRIVATE, + "%Next key of current order\n" + "%Syntax: \\nextkey\n" + "%\n" + "%Silently ignored if not found.\n" + ); + + //////////////////////////////////////////////////////// + + TOK_ADD(qprevkey,"r",tok_t::PRIVATE, + "%Previous key of current order, satisfying query\n" + "%Syntax: \\qprevkey\n" + "%\n" + "%Silently ignored if not found.\n" + ); + TOK_ADD(qnextkey,"r",tok_t::PRIVATE, + "%Next key of current order, satisfying query\n" + "%Syntax: \\qnextkey\n" + "%\n" + "%Silently ignored if not found.\n" + ); + +} -- cgit v1.2.3