#include #include #include #include #include #include #include class TPianoconti_tree : public TBidirectional_tree { TArray _cursor; // Gruppi, Conti, Sottoconti, Clienti, Fornitori int _curindex; TToken_string _curnode; private: TCursor& cursor() const { return (TCursor&)_cursor[_curindex]; } TCursor& cursor(int n) const { return (TCursor&)_cursor[n]; } bool update_curr(); void restore_curr(); protected: virtual void node2id(const TObject* node, TString& id) const; public: virtual bool has_root() const; virtual bool goto_root(); virtual bool has_son() const; virtual bool goto_firstson(); virtual bool has_rbrother() const; virtual bool goto_rbrother(); virtual bool has_father() const; virtual bool goto_father(); virtual bool has_lbrother() const; virtual bool goto_lbrother(); virtual bool goto_node(const TString &id); virtual TObject* curr_node() const; virtual bool get_description(TString& desc) const; TPianoconti_tree(); virtual ~TPianoconti_tree(); }; TPianoconti_tree::TPianoconti_tree() { for (int i = 0; i < 5; i++) { TRelation* rel = new TRelation(i < 3 ? LF_PCON : LF_CLIFO); TCursor* cur = NULL; switch (i) { case 0: cur = new TCursor(rel, "CONTO==0"); break; case 1: cur = new TCursor(rel, "(CONTO!=0)&&(SOTTOCONTO==0)"); break; case 2: cur = new TCursor(rel, "SOTTOCONTO!=0"); break; case 3: case 4: { TRectype rec(rel->curr()); rec.put("TIPOCF", i == 3 ? "C" : "F"); cur = new TCursor(rel, "", 1, &rec, &rec); } break; default: break; } CHECK(cur, "Invalid tree cursor"); _cursor.add(cur); } goto_root(); } TPianoconti_tree::~TPianoconti_tree() { for (int i = _cursor.last(); i >= 0; i--) { TRelation* rel = cursor(i).relation(); delete rel; } _cursor.destroy(); } bool TPianoconti_tree::update_curr() { _curnode.cut(0); _curnode.add(_curindex); _curnode.add(cursor(0).pos()); if (_curindex > 0) _curnode.add(cursor(1).pos()); if (_curindex > 1) _curnode.add(cursor().pos()); return TRUE; } void TPianoconti_tree::restore_curr() { _curindex = _curnode.get_int(0); cursor(0) = _curnode.get_long(); if (_curindex > 0) cursor(1) = _curnode.get_long(); if (_curindex > 1) cursor() = _curnode.get_long(); } void TPianoconti_tree::node2id(const TObject* node, TString& id) const { id = *(const TToken_string*)node; } TObject* TPianoconti_tree::curr_node() const { return &((TPianoconti_tree*)this)->_curnode; } bool TPianoconti_tree::goto_root() { for (int c = _cursor.last(); c >= 0; c--) { TCursor& cur = cursor(c); cur.freeze(FALSE); cur = 0L; cur.freeze(TRUE); } _curindex = 0; update_curr(); return cursor().items() > 0; } bool TPianoconti_tree::goto_firstson() { bool ok = _curindex < 2; if (ok) { if (_curindex == 0) { TCursor& cur = cursor(1); TRectype& curr = cur.curr(); const TString16 gruppo = cursor().curr().get("GRUPPO"); curr.zero(); curr.put("GRUPPO", gruppo); TRecnotype pos = cur.read(_isgteq); ok = pos >= 0 && curr.get("GRUPPO") == gruppo; if (ok) { _curindex = 1; update_curr(); } } else { char tipo = cursor().curr().get_char("TMCF"); if (tipo <= ' ') { TCursor& cur = cursor(2); TRectype& curr = cur.curr(); const TString16 gruppo = cursor().curr().get("GRUPPO"); const TString16 conto = cursor().curr().get("CONTO"); curr.zero(); curr.put("GRUPPO", gruppo); curr.put("CONTO", conto); TRecnotype pos = cur.read(_isgteq); ok = pos >= 0 && curr.get("GRUPPO") == gruppo && curr.get("CONTO") == conto; if (ok) { _curindex = 2; update_curr(); } } else { const int i = tipo == 'C' ? 3 : 4; ok = cursor(i).items() > 0; if (ok) { _curindex = i; cursor() = 0; update_curr(); } } } } return ok; } bool TPianoconti_tree::has_son() const { return _curindex < 2; } bool TPianoconti_tree::goto_rbrother() { TCursor& cur = cursor(); bool ok = cur.pos() < cur.items()-1; if (ok) { TRectype& curr = cur.curr(); TString16 gruppo, conto; if (_curindex == 1 || _curindex == 2) gruppo = curr.get("GRUPPO"); if (_curindex == 2) conto = curr.get("CONTO"); ++cur; if (_curindex == 1 || _curindex == 2) ok = curr.get("GRUPPO") == gruppo; if (ok && _curindex == 2) ok = curr.get("CONTO") == conto; if (ok) update_curr(); else --cur; } return ok; } bool TPianoconti_tree::has_rbrother() const { const TString old = _curnode; bool ok = ((TPianoconti_tree*)this)->goto_rbrother(); if (ok) ((TPianoconti_tree*)this)->goto_node(old); return ok; } bool TPianoconti_tree::has_root() const { return cursor(0).items() > 0; } bool TPianoconti_tree::has_father() const { return _curindex > 0; } bool TPianoconti_tree::has_lbrother() const { const TString old = _curnode; bool ok = ((TPianoconti_tree*)this)->goto_lbrother(); if (ok) ((TPianoconti_tree*)this)->goto_node(old); return ok; } bool TPianoconti_tree::goto_father() { bool ok = _curindex > 0; if (ok) { if (_curindex >= 2) _curindex = 1; else _curindex = 0; update_curr(); } return ok; } bool TPianoconti_tree::goto_lbrother() { TCursor& cur = cursor(); bool ok = cur.pos() > 0; if (ok) { TRectype& curr = cur.curr(); TString16 gruppo, conto; if (_curindex == 1 || _curindex == 2) gruppo = curr.get("GRUPPO"); if (_curindex == 2) conto = curr.get("CONTO"); --cur; if (_curindex == 1 || _curindex == 2) ok = curr.get("GRUPPO") == gruppo; if (ok && _curindex == 2) ok = curr.get("CONTO") == conto; if (ok) update_curr(); else ++cur; } return ok; } bool TPianoconti_tree::goto_node(const TString &id) { _curnode = id; restore_curr(); return TRUE; } bool TPianoconti_tree::get_description(TString& desc) const { desc = cursor(0).curr().get("GRUPPO"); if (_curindex > 0) desc << '.' << cursor(1).curr().get("CONTO"); const TRectype& curr = cursor().curr(); if (_curindex == 2) desc << '.' << curr.get("SOTTOCONTO"); else { if (_curindex > 2) desc << '.' << curr.get("CODCF"); } if (_curindex <= 2) desc << ' ' << curr.get("DESCR"); else desc << ' ' << curr.get("RAGSOC"); return TRUE; } /////////////////////////////////////////////////////////// class TTab_application : public TRelation_application { TMask* _msk; TRelation* _rel; protected: virtual TMask* get_mask(int mode); virtual TRelation* get_relation() const; virtual bool changing_mask(int mode); virtual bool user_create(); virtual bool user_destroy(); public: TTab_application(); virtual ~TTab_application(); }; // @cmember Costruttore TTab_application::TTab_application() : _msk(NULL), _rel(NULL) { } // @cmember Distruttore TTab_application::~TTab_application() { } // @cmember Indica se la futura ritornera' una maschera diversa // dalla corrente. bool TTab_application::changing_mask(int mode) { return FALSE; } // @cmember Richiede la maschera da usare TMask* TTab_application::get_mask(int mode) { CHECK(_msk, "Null mask"); return _msk; } // @cmember Ritorna la relazione da modificare TRelation* TTab_application::get_relation() const { CHECK(_rel, "Null relation"); return _rel; } bool TTab_application::user_create() { if (argc() < 3) return FALSE; TString16 tabname = argv(2); tabname.upper(); _rel = new TRelation(tabname); TString16 t(tabname); if (t[0] == '%') t.ltrim(1); TString16 m; m << "BATB" << t; _msk = new TMask(m) ; TString tit; _msk->get_caption(tit); set_title(tit); return TRUE; } bool TTab_application::user_destroy() { if (_msk) delete _msk; if (_rel) delete _rel; return TRUE; } /////////////////////////////////////////////////////////// // Test Relapp /////////////////////////////////////////////////////////// class TTestrel_application : public TRelation_application { const char* _maskname; const char* _num; TRelation* _rel; TMask* _msk; protected: virtual bool user_create(); virtual bool user_destroy(); virtual TMask* get_mask(int) { return _msk; } virtual bool changing_mask(int) { return FALSE;} virtual TRelation* get_relation() const { return _rel; } virtual int read(TMask& m); virtual int write(const TMask&); virtual int rewrite(const TMask&); virtual bool remove() { return FALSE; } public: TTestrel_application(const char* name, const char* num); }; TTestrel_application::TTestrel_application(const char* name, const char* num) : _maskname(name), _num(num), _msk(NULL), _rel(NULL) {} bool TTestrel_application::user_create() { const int id = atoi(_num); if (id > 0) _rel = new TRelation(id); else _rel = new TRelation(_num); _msk = new TMask(_maskname); return TRUE; } bool TTestrel_application::user_destroy() { delete _msk; delete _rel; return TRUE; } int TTestrel_application::read(TMask& m) { m.autoload(*_rel); return NOERR; } int TTestrel_application::write(const TMask& m) { m.autosave(*_rel); return NOERR; } int TTestrel_application::rewrite(const TMask& m) { m.autosave(*_rel); return NOERR; } /////////////////////////////////////////////////////////// // Testmask /////////////////////////////////////////////////////////// class TTest_application : public TSkeleton_application { TFilename _maskname; protected: virtual void main_loop(); static bool tree_handler(TMask_field& f, KEY k); public: void fill_trees(TMask& msk); TTest_application(const char* name) : _maskname(name) {} virtual~ TTest_application() {} }; bool TTest_application::tree_handler(TMask_field& f, KEY k) { if (k == K_SPACE || k == K_CTRL+K_SPACE) { TMask_field& next_field = f.mask().field(f.dlg()+1); if (next_field.class_id() == CLASS_BROWSEFILE_FIELD) { TTree_field& tf = (TTree_field&)f; TBrowsefile_field& bf = (TBrowsefile_field&)next_field; TString str; tf.tree()->get_description(str); str.insert(k == K_CTRL+K_SPACE ? "** " : "* ", 0); bf.add_line(str); } } return TRUE; } void TTest_application::fill_trees(TMask& msk) { for (int f = msk.fields()-1; f >= 0; f--) { if (msk.fld(f).is_kind_of(CLASS_TREE_FIELD)) { TTree* t = new TPianoconti_tree; TTree_field& tf = (TTree_field&)msk.fld(f); tf.set_tree(t); // tf.hide_leaves(); tf.set_handler(tree_handler); } } void TTest_application::main_loop() { TMask m(_maskname); #ifdef DBG fill_trees(m); #endif while (m.run() != K_QUIT); } /////////////////////////////////////////////////////////// class TBenchmark_application : public TSkeleton_application { clock_t _timer_start; double _sec; TString _text; protected: virtual void main_loop(); void initializing(); void start_test(const char* msg); void update_bar(long rec); void stop_test(); void test_relation_scan(); void test_cursor_scan(); void test_file_scan(); void test_file_random(); void test_file_write(); public: TBenchmark_application() { } virtual ~TBenchmark_application() { } }; void TBenchmark_application::main_loop() { TString test = argv(1); test.upper(); const bool test_all = test.find('*') >= 0; if (test_all || test.find('F') >= 0) test_file_scan(); if (test_all || test.find('R') >= 0) test_relation_scan(); if (test_all || test.find('C') >= 0) test_cursor_scan(); if (test_all || test.find('T') >= 0) test_file_random(); if (test_all || test.find('W') >= 0) test_file_write(); } void TBenchmark_application::initializing() { xvt_statbar_set("Initializing..."); do_events(); } void TBenchmark_application::start_test(const char* text) { _text = text; xvt_statbar_set(_text); do_events(); _sec = 0; clock_t t; _timer_start = clock(); do { t = clock(); } while (t == _timer_start); _timer_start = t; } void TBenchmark_application::stop_test() { const clock_t t = clock() - _timer_start; const double s = (double)t / CLOCKS_PER_SEC; TString msg; msg.format("%s\nTempo totale: %.1lf s", (const char*)_text, s); message_box(msg); } void TBenchmark_application::update_bar(long rec) { const double sec = double(clock() - _timer_start) / CLOCKS_PER_SEC; if (sec > _sec) { TString80 msg; unsigned long mem = xvt_sys_get_free_memory_kb(); rec++; msg.format("%ld record (%ld rec/sec) %lu Kb", rec, long(rec / sec), mem); xvt_statbar_set(msg); do_events(); _sec = ceil(sec); } } void TBenchmark_application::test_file_scan() { initializing(); TSystemisamfile comuni(LF_COMUNI); int err = comuni.open(_excllock); if (err == NOERR) { start_test("Scansione file COMUNI in modo esclusivo"); comuni.first(); for (TRecnotype rec = 0; comuni.good(); rec++) { comuni.next(); update_bar(rec); } comuni.close(); stop_test(); } } void TBenchmark_application::test_relation_scan() { initializing(); TRelation comuni(LF_COMUNI); start_test("Scansione relazione COMUNI"); comuni.first(); for (TRecnotype rec = 0; !comuni.eof(); rec++) { comuni.next(); update_bar(rec); } stop_test(); } void TBenchmark_application::test_cursor_scan() { initializing(); TRelation comuni(LF_COMUNI); TCursor cur(&comuni); TRecnotype tot = cur.items(); cur.freeze(); start_test("Scansione cursore COMUNI"); const TRecnotype tot = cur.items(); cur.freeze(); cur = 0L; for (TRecnotype c = 0; c < tot; c++) { ++cur; update_bar(c); } stop_test(); } void TBenchmark_application::test_file_random() { initializing(); TLocalisamfile comuni(LF_COMUNI); start_test("Lettura random del file COMUNI"); TRectype& rec = comuni.curr(); char code[8]; long found, notfound; for (long n = 0; n < 4000; n++) { const char l = 'A' + rand() % 26; const int c = rand() % 100; sprintf(code, "%c%03d", l, c); rec.zero(); rec.put("COM", code); if (comuni.read() == NOERR) found++; else notfound++; update_bar(n); } stop_test(); } void TBenchmark_application::test_file_write() { initializing(); TTable tab("GUY"); start_test("Scrittura della tabella GUY"); TString16 codtab; int err = NOERR; for (long n = 0; err == NOERR && n < 1000000L; n++) { codtab.format("%07ld", n); tab.put("CODTAB", codtab); tab.put("S0", codtab); err = tab.write(); update_bar(n); } stop_test(); } /////////////////////////////////////////////////////////// int main(int argc, char** argv) { TApplication::check_parameters(argc, argv); if (argc > 1 && *argv[1] == '-') { TBenchmark_application bma; bma.run(argc, argv, "Benchmark"); return 0; } if (argc < 3) { TFilename n = argv[1]; if (n.not_empty()) { TTest_application a(n); n = n.name(); n.insert("Test Mask ", 0); a.run(argc, argv, n); } } else { if (isdigit(argv[2][0])) { TTestrel_application a(argv[1], argv[2]); a.run(argc, argv, "Test Relation Application"); } else { TTab_application a; a.run(argc, argv, "Test Table Application"); } } return 0; }