1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| //Fonction à mettre quelque part en dur
enum TypeCode
{
FmtError = -1,
FmtInt32,
FmtInt64,
FmtUInt32,
FmtUInt64,
FmtDouble,
FmtLongDouble,
FmtString
};
TypeCode getPercentCode(char const *fmt, size_t &offset)
{
char const *pPercent = strchr(fmt+offset, '%');
if(pPercent==NULL)
return TypeCode; //Erreur, trop d'arguments
char c;
int cptSmallL = 0;
int cptBigL = 0;
for(offset =(fmt-pPercent)+1 ; fmt[offset++] != '\0' ; )
{
switch(c)
{
case '\0': return FmtError;
case 'f': return (cptBigL >= 1 ? FmtLongDouble : FmtDouble);
case 'd': return (cptSmallL >= 2 || (cptSmallL >= 1 && sizeof(long)!=sizeof(int))) ? FmtInt64 : FmtInt32;
case 'x':
case 'u': return (cptSmallL >= 2 || (cptSmallL >= 1 && sizeof(long)!=sizeof(int))) ? FmtUInt64 : FmtUInt32;
case 's': return FmtString;
//etc.
//Note: Sur une plate-forme 64-bits, il faudrait aussi gérer les préfixes de longueur,
//et peut-être retourner une lettre majuscule pour les long / long long...
case '%':
//Cas spécial, il faut recommencer l'analyse
//car ce n'était pas un champ correspondant à un argument:
pPercent = strchr(fmt+offset, '%');
if(pPercent==NULL)
return FmtError; //Erreur, trop d'arguments
offset = (fmt-pPercent)+1;
}
}
offset = strlen(fmt); //Pour être sûr de ne pas pointer derrière le caractère nul terminal.
return FmtError;
}
template< class T >
struct FormatForType { };
template<> struct FormatForType<int> { static const TypeCode fmt=FmtInt32; };
template<> struct FormatForType<unsigned int> { static const TypeCode fmt=FmtUint32; };
template<> struct FormatForType<double> { static const TypeCode fmt=FmtDouble; }
template<> struct FormatForType<std::string> { static const TypeCode fmt=FmtString; }
template<> struct FormatForType<char const*> { static const TypeCode fmt=FmtString; }
template<> struct FormatForType<char*> { static const TypeCode fmt=FmtString; }
//etc.
void throwFormatError(int argNum, TypeCode inFormat, TypeCode inType);
template<typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7, typename Type8, typename Type9>
void tracer9(const char * fmt, Type1 type1, Type2 type2, Type3 type3, Type4 type4, Type5 type5, Type6 type6, Type7 type7, Type8 type8, Type9 type9)
{
char code;
size_t offset = 0;
if((code=getPercentCode(fmt, offset)) != FormatForType<Type1>::fmt) { throwFormatError(1, code, FormatForType<Type1>::fmt); }
if((code=getPercentCode(fmt, offset)) != FormatForType<Type2>::fmt) { throwFormatError(2, code, FormatForType<Type2>::fmt); }
if((code=getPercentCode(fmt, offset)) != FormatForType<Type3>::fmt) { throwFormatError(3, code, FormatForType<Type3>::fmt); }
if((code=getPercentCode(fmt, offset)) != FormatForType<Type4>::fmt) { throwFormatError(4, code, FormatForType<Type4>::fmt); }
if((code=getPercentCode(fmt, offset)) != FormatForType<Type5>::fmt) { throwFormatError(5, code, FormatForType<Type5>::fmt); }
if((code=getPercentCode(fmt, offset)) != FormatForType<Type6>::fmt) { throwFormatError(6, code, FormatForType<Type6>::fmt); }
if((code=getPercentCode(fmt, offset)) != FormatForType<Type7>::fmt) { throwFormatError(7, code, FormatForType<Type7>::fmt); }
if((code=getPercentCode(fmt, offset)) != FormatForType<Type8>::fmt) { throwFormatError(8, code, FormatForType<Type8>::fmt); }
if((code=getPercentCode(fmt, offset)) != FormatForType<Type9>::fmt) { throwFormatError(9, code, FormatForType<Type9>::fmt); }
if(strchr(fmt+offset, '%') != NULL)
throw std::invalid_argument("Il y a plus de pourcents dans le format que d'arguments passés à la fonction!");
tracer(fmt, type1, type2, type3, type4, type5, type6, type7, type8, type9);
} |
Partager