--- parser3/src/classes/table.C 2001/09/07 12:46:19 1.111 +++ parser3/src/classes/table.C 2001/10/09 13:17:45 1.124 @@ -2,10 +2,10 @@ Parser: @b table parser class. Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) - Author: Alexander Petrosyan (http://design.ru/paf) + + $Id: table.C,v 1.124 2001/10/09 13:17:45 parser Exp $ */ -static const char *RCSId="$Id: table.C,v 1.111 2001/09/07 12:46:19 parser Exp $"; #include "classes.h" #include "pa_config_includes.h" @@ -65,7 +65,7 @@ static void _set(Request& r, const Strin while(i.has_next()) { Array& row=*new(pool) Array(pool); const String& string=*i.next_string(); - // remove empty lines + // remove comment lines if(!string.size()) continue; @@ -80,11 +80,11 @@ static void _set(Request& r, const Strin static void _load(Request& r, const String& method_name, MethodParams *params) { Pool& pool=r.pool(); // filename is last parameter - const String& filename=params->as_string(params->size()-1, + Value& vfilename=params->as_no_junction(params->size()-1, "file name must not be code"); // loading text - char *data=file_read_text(pool, r.absolute(filename)); + char *data=file_read_text(pool, r.absolute(vfilename.as_string())); // parse columns Array *columns; @@ -110,7 +110,8 @@ static void _load(Request& r, const Stri Table& table=*new(pool) Table(pool, &method_name, columns); char *row_chars; while(row_chars=getrow(&data)) { - if(!*row_chars) // remove empty lines + // remove empty&comment lines + if(!*row_chars || *row_chars == '#') continue; Array *row=new(pool) Array(pool); while(char *cell_chars=lsplit(&row_chars, '\t')) { @@ -128,120 +129,6 @@ static void _load(Request& r, const Stri static_cast(r.self)->set_table(table); } -static Table *fill_month_days(Request& r, - const String& method_name, MethodParams *params, bool rus){ - Pool& pool=r.pool(); - Table *result=new(pool) Table(pool, &method_name, 0/*&columns*/); - - int year=params->as_int(1, r); - int month=max(1, min(params->as_int(2, r), 12)) -1; - - tm tmIn={0, 0, 0, 1, month, year-1900}; - time_t t=mktime(&tmIn); - if(t<0) - PTHROW(0, 0, - &method_name, - "invalid date"); - tm *tmOut=localtime(&t); - - int weekDay1=tmOut->tm_wday; - if(rus) - weekDay1=weekDay1?weekDay1-1:6; //sunday last - int monthDays=getMonthDays(year, month); - - for(int _day=1-weekDay1; _day<=monthDays;) { - Array& row=*new(pool) Array(pool, 7); - for(int wday=0; wday<7; wday++, _day++) { - String *cell=new(pool) String(pool); - if(_day>=1 && _day<=monthDays) { - char *buf=(char *)pool.malloc(2+1); - cell->APPEND_CLEAN(buf, sprintf(buf, "%02d", _day), - method_name.origin().file, method_name.origin().line); - } - row+=cell; - } - *result+=&row; - } - - return result; -} - -static Table *fill_week_days(Request& r, - const String& method_name, MethodParams *params, bool rus){ - Pool& pool=r.pool(); - Array& columns=*new(pool) Array(pool, 4); - columns+=new(pool) String(pool, "year"); - columns+=new(pool) String(pool, "month"); - columns+=new(pool) String(pool, "day"); - columns+=new(pool) String(pool, "weekday"); - Table *result=new(pool) Table(pool, &method_name, &columns); - - int year=params->as_int(1, r); - int month=max(1, min(params->as_int(2, r), 12)) -1; - int day=params->as_int(3, r); - - tm tmIn={0, 0, 18, day, month, year-1900}; - time_t t=mktime(&tmIn); - if(t<0) - PTHROW(0, 0, - &method_name, - "invalid date"); - tm *tmOut=localtime(&t); - - int baseWeekDay=tmOut->tm_wday; - if(rus) - baseWeekDay=baseWeekDay?baseWeekDay-1:6; //sunday last - - t-=baseWeekDay*SECS_PER_DAY; - - for(int curWeekDay=0; curWeekDay<7; curWeekDay++, t+=SECS_PER_DAY) { - tm *tmOut=localtime(&t); - Array& row=*new(pool) Array(pool, 4); -#define WDFILL(size, value) { \ - char *buf=(char *)pool.malloc(size+1); \ - String *cell=new(pool) String(pool); \ - cell->APPEND_CLEAN(buf, sprintf(buf, "%0"#size"d", value), \ - method_name.origin().file, \ - method_name.origin().line); \ - row+=cell; \ - } - WDFILL(4, 1900+tmOut->tm_year); - WDFILL(2, 1+tmOut->tm_mon); - WDFILL(2, tmOut->tm_mday); - WDFILL(2, tmOut->tm_wday); - *result+=&row; - } - - return result; -} - -static void _calendar(Request& r, const String& method_name, MethodParams *params) { - Pool& pool=r.pool(); - - const String& what=params->as_string(0, "format must be strig"); - bool rus=false; - if(what=="rus") - rus=true; - else if(what=="eng") - rus=false; - else - PTHROW(0, 0, - &what, - "must be rus|eng"); - - Table *result=0; - if(params->size()==1+2) - result=fill_month_days(r, method_name, params, rus); - else // 1+3 - result=fill_week_days(r, method_name, params, rus); - - // replace any previous table value - static_cast(r.self)->set_table(*result); -} - - - - static void _save(Request& r, const String& method_name, MethodParams *params) { Pool& pool=r.pool(); Value& vtable_name=params->as_no_junction(params->size()-1, @@ -320,7 +207,7 @@ static void _offset(Request& r, const St static void _menu(Request& r, const String& method_name, MethodParams *params) { Value& body_code=params->as_junction(0, "body must be code"); - Value *delim_code=params->size()==2?¶ms->get(1):0; + Value *delim_maybe_code=params->size()>1?¶ms->get(1):0; VTable& vtable=*static_cast(r.self); Table& table=vtable.table(); @@ -331,10 +218,10 @@ static void _menu(Request& r, const Stri table.set_current(row); Value& processed_body=r.process(body_code); - if(delim_code) { // delimiter set? + if(delim_maybe_code) { // delimiter set? const String *string=processed_body.get_string(); if(need_delim && string && string->size()) // need delim & iteration produced string? - r.write_pass_lang(r.process(*delim_code)); + r.write_pass_lang(r.process(*delim_maybe_code)); need_delim=true; } r.write_pass_lang(processed_body); @@ -342,13 +229,6 @@ static void _menu(Request& r, const Stri table.set_current(saved_current); } -static void _empty(Request& r, const String& method_name, MethodParams *params) { - Pool& pool=r.pool(); - Table& table=static_cast(r.self)->table(); - - r.write_no_lang(*new(pool) VBool(pool, table.size()==0)); -} - #ifndef DOXYGEN struct Row_info { Table *table; @@ -378,34 +258,38 @@ static void table_row_to_hash(Array::Ite } static void _hash(Request& r, const String& method_name, MethodParams *params) { Pool& pool=r.pool(); - Table& table=static_cast(r.self)->table(); + Table& self_table=static_cast(r.self)->table(); Value& result=*new(pool) VHash(pool); - if(const Array *columns=table.columns()) + if(const Array *columns=self_table.columns()) if(columns->size()>1) { - const String& key_field_name=params->as_no_junction(0, "key field name must not be code").as_string(); - int key_field=table.column_name2index(key_field_name, true); - int value_fields_count=params->size()-1; - bool value_fields_by_params=value_fields_count!=0; - if(!value_fields_by_params) - value_fields_count=columns->size()-1; // all columns except key - Array value_fields(pool, value_fields_count); - if(value_fields_by_params) { - for(int i=1; isize(); i++) { - const String& value_field_name=params->as_no_junction(i, - "value field name must not be code").as_string(); - value_fields+=table.column_name2index(value_field_name, true); - } - } else { // by all columns except key + int key_field=self_table.column_name2index(key_field_name, true); + + Array value_fields(pool); + if(params->size()>1) { + Value& value_fields_param=params->as_no_junction(1, "value field(s) must not be code"); + if(value_fields_param.is_string()) { + value_fields+=self_table.column_name2index(value_fields_param.as_string(), true); + } else if(Table *value_fields_table=value_fields_param.get_table()) { + for(int i=0; isize(); i++) { + const String& value_field_name= + *static_cast(value_fields_table->get(i))->get_string(0); + value_fields+=self_table.column_name2index(value_field_name, true); + } + } else + PTHROW(0, 0, + &method_name, + "value field(s) must be string or self_table" + ); + } else { // by all columns, including key for(int i=0; isize(); i++) - if(i!=key_field) - value_fields+=i; + value_fields+=i; } // integers: key_field & value_fields - Row_info row_info={&table, key_field, &value_fields, result.get_hash()}; - table.for_each(table_row_to_hash, &row_info); + Row_info row_info={&self_table, key_field, &value_fields, result.get_hash()}; + self_table.for_each(table_row_to_hash, &row_info); } result.set_name(method_name); r.write_no_lang(result); @@ -440,7 +324,7 @@ static void _sort(Request& r, const Stri Pool& pool=r.pool(); Value& key_maker=params->as_junction(0, "key-maker must be code"); - bool reverse=params->size()==2/*..[desc|asc|]*/? + bool reverse=params->size()>1/*..[desc|asc|]*/? reverse=params->as_no_junction(1, "order must not be code").as_string()=="desc": false; // default=asc @@ -477,7 +361,8 @@ static void _sort(Request& r, const Stri for(i=0; i(r.self)->set_table(new_table); } static void _locate(Request& r, const String& method_name, MethodParams *params) { @@ -486,8 +371,9 @@ static void _locate(Request& r, const St VTable& vtable=*static_cast(r.self); Table& table=vtable.table(); Value& result=*new(pool) VBool(pool, table.locate( - params->get(0).as_string(), - params->get(1).as_string())); + params->as_string(0, "column name must be string"), + params->as_string(1, "value must be string") + )); result.set_name(method_name); r.write_no_lang(result); } @@ -696,10 +582,6 @@ MTable::MTable(Pool& apool) : Methoded(a // ^table:load[nameless;file] add_native_method("load", Method::CT_DYNAMIC, _load, 1, 2); - // ^table:calendar[month|montheng;year;month] - // ^table:calendar[week|weekeng;year;month;day] - add_native_method("calendar", Method::CT_DYNAMIC, _calendar, 3, 4); - // ^table.save[file] // ^table.save[nameless;file] add_native_method("save", Method::CT_DYNAMIC, _save, 1, 2); @@ -718,12 +600,9 @@ MTable::MTable(Pool& apool) : Methoded(a // ^table.menu{code}[delim] add_native_method("menu", Method::CT_DYNAMIC, _menu, 1, 2); - // ^table.empty[] - add_native_method("empty", Method::CT_DYNAMIC, _empty, 0, 0); - // ^table:hash[key field name] - // ^table:hash[key field name][value field name;...] - add_native_method("hash", Method::CT_DYNAMIC, _hash, 1, 1000); + // ^table:hash[key field name][value field name(s) string/table] + add_native_method("hash", Method::CT_DYNAMIC, _hash, 1, 2); // ^table.sort{string-key-maker} ^table.sort{string-key-maker}[desc|asc] // ^table.sort(numeric-key-maker) ^table.sort(numeric-key-maker)[desc|asc]