/* Essai de faire une classe constexpr analysant la chaine de controle d'un printf But: Faire comme un printf Permettre de passer des types arbitraires pourront facilement être compatible (juste à ajouter une fonction non member myfcnv) Validation à la compilation de la chaîne de contrôle et du nombre d'arguments Si la chaîne de contrôle n'est pas une constante, le nombre d'argument est validable lors de l'exécution et les paramètres sont correctement formattés. Pas encore fait. Uniquement la chaîne constante est faite. Il faut que ça soit facile de créer ses propres fonctions 'à la printf' en utilisant ce projet. Pas encore fait. Requiert c++17. On doit utiliser un lambda pour passer la chaîne de contrôle. La performance est proche de printf. */ #include #include #include #include #include #include #include #include #include "getnow.h" using namespace std; struct PARSEELM{ enum ELMTYPE {is_sequence,is_int,is_unsigned,is_bool,is_string, is_float} type; size_t pos; size_t skip; short val1; unsigned short val2; #if 0 PARSEELM(){ type = is_sequence; val1 = 0; val2 = 0; } #endif }; using arrayctl = array; constexpr arrayctl parse (const char *s) { arrayctl ret={{{PARSEELM::is_sequence,0,0,0,0}}}; //,{PARSEELM::is_sequence,0,0,0,0},{PARSEELM::is_sequence,0,0,0,0},{PARSEELM::is_sequence,0,0,0,0},{PARSEELM::is_sequence,0,0,0,0}}}; const char *start = s; for (unsigned n=0; n f; myfarg(){} myfarg(std::function &&_f) : f(move(_f)){} }; static FILE *fout = stdout; static bool no_output = false; //int myfdo(const PARSE &p, const vector &args) int myfdo(const PARSE &p, const myfarg args[]) { size_t lastpos = 0; for (unsigned i=0; i int myf(F f, T1 v1) { constexpr PARSE p(f()); static_assert(p.nbelm()==1,"nbelm != 1"); myfarg args[]={ myfarg([&v1](short p1,short p2){ myfcnv(p1,p2,v1);}), }; myfdo(p,args); return 0; } template int myf(F f, T1 v1, T2 v2) { constexpr PARSE p(f()); static_assert(p.nbelm()==2,"nbelm != 2"); myfarg args[]={ myfarg([&v1](short p1,short p2){ myfcnv(p1,p2,v1);}), myfarg([&v2](short p1,short p2){ myfcnv(p1,p2,v2);}) }; myfdo(p,args); return 0; } template int myf(F f, T1 v1, T2 v2, T3 v3) { constexpr PARSE p(f()); static_assert(p.nbelm()==3,"nbelm != 3"); myfarg args[]={ myfarg([&v1](short p1,short p2){ myfcnv(p1,p2,v1);}), myfarg([&v2](short p1,short p2){ myfcnv(p1,p2,v2);}), myfarg([&v3](short p1,short p2){ myfcnv(p1,p2,v3);}) }; myfdo(p,args); return 0; } template int myf(F f, T1 v1, T2 v2, T3 v3, T4 v4) { constexpr PARSE p(f()); static_assert(p.nbelm()==4,"nbelm != 4"); myfarg args[]={ myfarg([&v1](short p1,short p2){ myfcnv(p1,p2,v1);}), myfarg([&v2](short p1,short p2){ myfcnv(p1,p2,v2);}), myfarg([&v3](short p1,short p2){ myfcnv(p1,p2,v3);}), myfarg([&v4](short p1,short p2){ myfcnv(p1,p2,v4);}) }; myfdo(p,args); return 0; } static void testmy(unsigned nbrep) { for (unsigned i=0; i int main (int argc, char *argv[]) { glocal int ret = -1; glocal unsigned nbrep = 1000; glocal bool tonull = false; glocal.ret = (argc,argv); setproginfo ("","0.0","..."); setarg ('n',"nbrep","Nombre de repetition",glocal.nbrep,false); setarg ('o',"tonull","Output to /dev/null",glocal.tonull,false); setarg ('N',"nooutput","No call to write anything",no_output,false); if (glocal.tonull) fout = fopen ("/dev/null","w"); #if 0 constexpr arrayctl p = parse ("allo %d %u s=%15s total=%5.2f"); for (auto &v:p) printf ("type=%u pos=%lu skip=%lu val1=%u val2=%u\n",v.type,v.pos,v.skip,v.val1,v.val2); myf (p,"allo %d %u s=%15s total=%5.2f\n",1,2); #endif //constexpr PARSE p2 = parse2("allo %d %u s=%15s total=%5.2f\n"); constexpr PARSE p3("allo %d %u s=%15s total=%5.2f\n"); //p2.dump("p2"); p3.dump("p3"); STRING2 s2("allo","comment"); myf([](){return "s2=%30sXXX\n";},s2); myf([](){return "s2=%-30sXXX\n";},s2); { testmy(glocal.nbrep); long long start = getnow(); testmy(glocal.nbrep); long long end = getnow(); showtime ("myf",start,end); } { testprintf (glocal.nbrep); long long start = getnow(); testprintf (glocal.nbrep); long long end = getnow(); showtime ("printf",start,end); } return 0; int ret = -1; return ret; return glocal.ret; }