/* Essai de faire un template qui remplacerait ceci. auto tb = str_splitline(line,','); if (tb.size() == 3){ int a1 = atoi(tb[0].c_str()); const char *a2 = tb[1].c_str(); int a3 = atoi(tb[0].c_str()); ... } auto [ err,a1,a2,a3 ] = splitline(line,',',int,char*,int); if (!err){ } Finalement, on a choisit int a1,a2; unsigned a3; string msg; if (splitline(line,',',a1,a2,a3,msg)){ } On a ajouté les pseudo fonction limits et enums qui permette de restreindre les valeurs acceptables. */ #include #include #include #include #include #include #include #include #include using namespace std; void assign(bool &ok, unsigned &a, const string &v) { if (isdigit(v[0])){ a = atoi(v.c_str()); }else{ a = 0; ok = false; } } void assign(bool &ok, int &a, const string &v) { if (isdigit(v[0]) || v[0] == '-'){ a = atoi(v.c_str()); }else{ a = 0; ok = false; } } void assign(bool &ok, bool &a, const string &v) { if (v == "true"){ a = true; }else if (v == "false"){ a = false; }else{ a = false; ok = false; } } inline void assign(bool &ok, string &a, const string &v) { a = v; } inline void reset (unsigned &a) { a = 0; } inline void reset (int &a) { a = 0; } inline void reset (string &a) { a.clear(); } inline void reset (bool &a) { a = false; } #if 0 template bool is_any_of(T t, T1 t1, Ts ... ts){ return is_any_of(t,t1) || is_any_of(t,ts...); } #endif #if 0 template<> tuple splitline(const vector &tb,unsigned off) { printf ("bool off=%u\n",off); return {true}; } #endif #if 0 template tuple tb_splitline(const vector &tb, unsigned off) { T1 a1; bool ok = false; if (tb.size()==off+1){ ok = true; assign(ok,a1,tb[0]); }else{ reset (a1); } return {ok,a1}; } #endif #if 0 template tuple tb_splitline(const vector &tb,unsigned off) { printf ("bool,... off=%u\n",off); tuple ret; T1 a1; get<0>(ret) = false; if (tb.size()>off){ get<0>(ret) = true; assign(get<0>(ret),a1,tb[off]); auto s = tb_splitline(tb,off+1); if (!get<0>(s)) get<0>(ret) = false; }else{ reset (a1); } return ret; } template tuple splitline(const char *line, char split) { auto tb = str_splitline(line,split); return tb_splitline(tb,0); } #endif #if 0 template tuple tb_splitline(const vector &tb, unsigned off) { printf ("bool,... off=%u\n",off); tuple ret; get<0>(ret) = false; if (tb.size()>off){ get<0>(ret) = true; assign(get<0>(ret),get<1>(ret),tb[off]); }else{ reset (get<1>(ret)); } return ret; } template tuple splitline(const char *line, char split) { auto tb = str_splitline(line,split); return tb_splitline(tb,0)...; } #endif template class enums_t; template enums_t enums(T &val, std::initializer_list elements); template class enums_t{ public: T &val; std::initializer_list vals; private: friend enums_t enums (T &_val, std::initializer_list elements); enums_t(T &_val, std::initializer_list elements):val(_val),vals(elements){} }; template enums_t enums(T &val, std::initializer_list elements){ return enums_t(val,elements); } template void assign(bool &ok, enums_t &a, const string &v) { assign(ok,a.val,v); if (ok && find(a.vals.begin(),a.vals.end(),a.val)==a.vals.end()) ok = false; } template inline void reset (enums_t &a) { reset(a.val); } #if 0 template class limits_t{ public: T &val; T min; T max; limits_t(T &_val, T _min, T _max):val(_val),min(_min),max(_max){ printf ("c1 val=%p\n",&val); } #if 0 limits_t() = delete; limits_t(const limits_t &t):val(t.val),min(t.min),max(t.max){ printf ("c2 val=%p\n",&val); } limits_t & operator = (const limits_t &) = delete; #endif }; #endif template void assign(bool &ok, limits_t &a, const string &v) { assign(ok,a.val,v); if (ok && (a.val < a.min || a.val > a.max)) ok = false; } template inline void reset (limits_t &a) { reset(a.val); } #if 0 template limits_t limits(T &a, T min, T max){ return limits_t(a,min,max); } #endif bool tb_splitline (const vector &tb, unsigned off) { //printf ("tb0 %s\n",__PRETTY_FUNCTION__); return tb.size() == off; } template bool tb_splitline (const vector &tb, unsigned off, T & v, TS&& ... vs) { //printf ("tb1 off=%u tb.size()=%lu %s\n",off,tb.size(),__PRETTY_FUNCTION__); bool ok = false; if (off < tb.size()){ ok = true; assign (ok,v,tb[off]); if (ok) ok = tb_splitline(tb,off+1,vs...); } return ok; } template bool splitline (const char *line, char split, TS&& ... vs) { auto tb = str_splitline(line,split); return tb_splitline (tb,0,forward(vs)...); } int main (int argc, char *argv[]) { glocal int ret = -1; glocal const char *split = ","; glocal.ret = (argc,argv); setproginfo ("","0.0","..."); setarg ('s',"split","split",glocal.split,false); int ret = -1; for (int i=0; i lima2(a2,1,10); #if 0 enums_t enuma2 (a2,{1u,3u,5u}); printf ("enuma2 %p %p size=%lu\n",&a2,&enuma2.val,enuma2.vals.size()); for (auto u:enuma2.vals) printf ("vals %u\n",u); #endif printf ("a2=%p lima2=%p\n",&a2,&lima2.val); if (splitline(line,glocal.split[0],a1,s,limits(a2,1u,10u))){ printf ("%u %s %d\n",a1,s.c_str(),a2); }else{ printf ("Echec\n"); } #if 0 if (splitline(line,glocal.split[0],a1,s,enuma2)){ printf ("%u %s %d\n",a1,s.c_str(),a2); }else{ printf ("Echec\n"); } #endif if (splitline(line,glocal.split[0],a1,s,enums(a2,{10u,12u,14u}))){ printf ("%u %s %d\n",a1,s.c_str(),a2); }else{ printf ("Echec\n"); } } #if 0 { auto v = splitline(line,','); if (get<0>(v)){ printf ("%d %s %d\n",get<1>(v),get<2>(v).c_str(),get<3>(v)); }else{ printf ("Echec\n"); } } { auto [ok,a,b,c] = splitline(line,','); if (ok){ printf ("%d %s %d\n",a,b.c_str(),c); }else{ printf ("Echec\n"); } } { bool ok; int a,c; string b; tie(ok,a,b,c) = splitline(line,','); if (ok){ printf ("%d %s %d\n",a,b.c_str(),c); }else{ printf ("Echec\n"); } } #endif } return ret; return glocal.ret; }