| 12
 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