/************************************************************************* * * 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" ); }