campo-sirio/src/fp/fplib05.cpp

409 lines
8.7 KiB
C++
Raw Normal View History

#include "fplib.h"
#include <fpcust.h>
#include <fpccaus.h>
#include <fpcart.h>
#include <fpcadg.h>
void TFP_custom::init()
{
add_file(LF_FPCCAUS, FPCCAUS_NRIGA);
add_file(LF_FPCART, FPCART_NRIGA);
add_file(LF_FPCADG, FPCADG_NRIGA);
}
int TFP_custom::write_rewrite(TBaseisamfile& f, bool re) const
{
return TMultiple_rectype::write_rewrite(f, re);
}
bool TFP_custom::load(const char* codcust)
{
// Metto il codice nel rectype principale ed effettuo una read
put(FPCUST_CODICE, codcust);
return _loaded = TMultiple_rectype::read() == NOERR;
}
void TFP_custom::autoload(const TSheet_field& sf, const int file) const
{
switch(file)
{
case LF_FPCCAUS:
{
TRecord_array& rcaus = body(file);
rcaus.destroy_rows();
FOR_EACH_SHEET_ROW(sf, r, row)
{
TRectype& rec_row = rcaus.row(-1, true);
rec_row.put(FPCCAUS_VALORE, row->get(0));
rec_row.put(FPCCAUS_COND, row->get());
}
}
break;
case LF_FPCART:
{
TRecord_array& rart = body(file);
rart.destroy_rows();
FOR_EACH_SHEET_ROW(sf, r, row)
{
TRectype& rec_row = rart.row(-1, true);
rec_row.put(FPCART_TIPO, row->get(0));
rec_row.put(FPCART_VALORE, row->get());
rec_row.put(FPCART_COND, row->get());
}
}
break;
case LF_FPCADG:
{
TRecord_array& radg = body(file);
radg.destroy_rows();
FOR_EACH_SHEET_ROW(sf, r, row)
{
TRectype& rec_row = radg.row(-1, true);
rec_row.put(FPCADG_TIPODATO, row->get(0));
rec_row.put(FPCADG_RTESTO, row->get());
rec_row.put(FPCADG_RNUMERO, row->get());
rec_row.put(FPCADG_RDATA, row->get());
rec_row.put(FPCADG_TIPORIGA, row->get());
rec_row.put(FPCADG_SPLIT, row->get());
rec_row.put(FPCADG_COND, row->get());
}
}
break;
default:
fatal_box("File non riconosciuto %d", file);
break;
}
}
TFP_custom::TFP_custom() : TMultiple_rectype(LF_FPCUST), _codcust(""), _loaded(false)
{
init();
}
TFP_custom::TFP_custom(const TRectype& rec) : TMultiple_rectype(rec)
{
_codcust = get(FPCUST_CODICE);
_loaded = _codcust.full();
init();
}
TFP_custom::TFP_custom(const char* codcust) : TFP_custom()
{
init();
load(codcust);
}
/*
* Sintassi:
* READ(TABELLA, CAMPO) -> legge dalle tabelle predefinite
* SEARCH(TABELLA, CAMPO, RICERCA) -> legge da una tabella qualsiasi
* SEARCH e READ sono diverse sotto richiesta di Ilaria per avere una sintassi pi<EFBFBD> chiara
* resto: TExpr_documento()
*/
const TVariant TFP_expression::parse_expression(const TString& expr, TRiga_documento& rdoc)
{
const TToken_string exprs(expr, '+');
TVariant result;
TExpr_documento expr_documento(_mixexpr, &rdoc.doc(), &rdoc);
FOR_EACH_STR_TOKEN(exprs, str)
{
// Come prima cosa trimmo la vita
str.trim();
if (str.starts_with("READ(", true))
{
result.add(parse_read(str, rdoc));
}
else if (str.starts_with("SEARCH(", true))
{
result.add(parse_search(str, rdoc));
}
else
{
// Controllo non sia una ricerca a DB con il punto
if (expr.contains("->"))
{
// Se contiene una freccia non posso fare un TToken_string easy
// Non esistono campi con -> vero?
str.replace("->", ".");
}
// Questo diventa true se sono passato sopra o effettivamente ha un punto dall'inizio
if (expr.contains('.'))
{
TToken_string simple_field(expr, '.');
result.add(do_read(simple_field.get(0), simple_field.get(), rdoc));
}
// Se inizia come una stringa o non contiene parentesi -> no expr
else if (str.starts_with("\"") || !(str.contains("(") && str.contains(")")))
{
str.replace("\"", "");
// Cerchiamo di capire che <20>
result.add(parse_var(str));
}
else
{
expr_documento.set(str, _mixexpr);
result.add(expr_documento.as_string());
}
}
}
return result;
}
bool TFP_expression::check_condition(const TString& cond, TRiga_documento& rdoc)
{
TString cond_sx, cond_dx;
TFP_operator symb;
split_condition(cond, cond_sx, cond_dx, symb);
const TVariant value_sx = parse_expression(cond_sx, rdoc);
const TVariant value_dx = parse_expression(cond_dx, rdoc);
switch(symb)
{
case eq:
return value_sx == value_dx;
case neq:
return value_sx != value_dx;
case gt:
return value_sx > value_dx;
case ls:
return value_sx < value_dx;
case gteq:
return value_sx >= value_dx;
case lseq:
return value_sx <= value_dx;
default:
return false;
}
}
void TFP_expression::extract_info(const TString& expr, TString& tabella, TString& campo, TToken_string* search)
{
// Prendo la stringa pulita della parte sinistra
TString clean_expr = expr.mid(expr.find('(') + 1);
// Tolgo eventuali spazi ai lati
clean_expr.trim();
// Tolgo la virgola finale
clean_expr.rtrim(1);
TToken_string info(clean_expr, ',');
// Trimmare sempre come se non sapessi fare altro nella vita
tabella.cut(0) << info.remove(0); tabella.trim();
campo.cut(0) << info.remove(0); campo.trim();
if (search != nullptr)
{
// Prendo il resto
search->cut(0) << info;
search->trim();
search->restart();
}
}
bool TFP_expression::calc_table(const TString& tabella, int& file)
{
file = atoi(tabella);
if (file == 0)
file = table2logic(tabella);
return is_multi_table(file);
}
void TFP_expression::split_condition(const TString& cond, TString& cond_sx, TString& cond_dx, TFP_operator& symb)
{
// Cerchiamo di capire che condizione ho
TString4 symbol;
if(cond.contains(" == "))
{
symb = eq;
symbol = " == ";
}
else if(cond.contains(" != "))
{
symb = neq;
symbol = " != ";
}
else if (cond.contains(" >= "))
{
symb = gteq;
symbol = " >= ";
}
else if (cond.contains(" <= "))
{
symb = lseq;
symbol = " <= ";
}
else if (cond.contains(" > "))
{
symb = gt;
symbol = " > ";
}
else if (cond.contains(" < "))
{
symb = ls;
symbol = " < ";
}
if(symb != error)
{
cond_sx = cond.left(cond.find(symbol));
cond_dx = cond.right(cond.len() - (cond.find(symbol) + symbol.len()));
}
else
{
// Considero come se <20> true o no il campo in generale
symb = gt;
cond_sx = cond;
cond_dx.cut(0);
}
}
// Questa funzione potrebbe diventare standard per TRectype
TVariant& TFP_expression::get_value(const TRectype& rec, const TString& campo)
{
TVariant& ret = get_tmp_var();
switch(rec.type(campo))
{
case _intfld:
ret.set(rec.get_int(campo));
break;
case _longfld:
ret.set(rec.get_long(campo));
break;
case _realfld:
ret.set(rec.get_real(campo));
break;
case _datefld:
ret.set(rec.get_date(campo));
break;
case _wordfld:
ret.set(rec.get_word(campo));
break;
case _charfld:
ret.set(rec.get_char(campo));
break;
case _boolfld:
ret.set(rec.get_bool(campo));
break;
case _nullfld:
case _alfafld:
case _intzerofld:
case _longzerofld:
case _memofld:
ret.set(rec.get(campo));
break;
}
return ret;
}
TVariant& TFP_expression::parse_var(const TString& str)
{
TVariant& ret = get_tmp_var();
// Come prima cosa leggo la stringa e cerco di capire se ci sono numeri o no
bool is_real = false, is_string = false;
for(int i = 0; i < str.len() && !is_string; i++)
{
const char val = str[i];
if(val < '0' || val > '9')
{
if (val == '.' || val == ',')
is_real = true;
else
is_string = true;
}
}
// Una volta che ho capito che ho davanti tento il trick!
if (is_string)
{
// Tento la data
const TDate pop(str);
if (pop.ok())
ret.add(pop);
else
ret.add(str);
}
else if (is_real)
ret.add(real(str));
else
{
char* err;
const long long_val = strtol(str, &err, 10);
// Ho avuto un errore? Il controllo ha fallito!
if(err && *err)
{
ret.add(str);
}
else
{
ret.add(long_val);
}
}
return ret;
}
TVariant& TFP_expression::parse_read(const TString& str, TRiga_documento& rdoc)
{
TString tabella, campo;
extract_info(str, tabella, campo, nullptr);
return do_read(tabella, campo, rdoc);
}
TVariant& TFP_expression::do_read(const TString& tabella, const TString& campo, TRiga_documento& rdoc)
{
int file;
calc_table(tabella, file);
switch (file)
{
case LF_DOC:
return get_value(rdoc.doc(), campo);
case LF_RIGHEDOC:
return get_value(rdoc, campo);
case LF_CLIFO:
return get_value(rdoc.doc().clifor(), campo);
case LF_CFVEN:
return get_value(rdoc.doc().clifor().vendite(), campo);
case LF_LETINT:
return get_value(rdoc.doc().clifor().lettera(), campo);
case LF_ANAMAG:
return get_value(rdoc.articolo(), campo);
default:
static TVariant null_var(EMPTY_STRING);
return null_var;
}
}
TVariant& TFP_expression::parse_search(const TString& str, TRiga_documento& rdoc)
{
TString tabella, campo;
TToken_string input_search, search;
int file;
extract_info(str, tabella, campo, &input_search);
const bool multi_table = calc_table(tabella, file);
// Parso ogni singolo token della ricerca
FOR_EACH_TOKEN(input_search, tok)
{
search.add(parse_expression(tok, rdoc).as_string());
}
if (multi_table)
{
return get_value(cache().get(tabella, search), campo);
}
else
{
return get_value(cache().get(file, search), campo);
}
}