IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Petite aide à la sérialisation


Sujet :

C++

  1. #21
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ton raisonnement me parait viable (même si je trouve que l'implémentation de bin_int laisse à désirer).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  2. #22
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par camboui Voir le message
    Et pourquoi les flottants float/double poseraient problème ? Ne sont-ils pas normalisés par une directive IEEE machin-chose ?
    Il suffit de faire comme si on avait deux entiers consécutifs, le premier serait l'exposant, le second la mantisse.
    Si c'était aussi simple, on pourrait faire des égalités entre flottants sans se préoccuper de l'epsilon... Or, ce n'est pas le cas.
    Le problème de ta sérialisation, c'est qu'elle est bien plus complexe que la redéfinition d'un opérateur de comparaison sur la structure complète, en utilisant donc les champs de façon native.

    Citation Envoyé par camboui Voir le message
    toute structure ordonnable par operator<() le sera par memcmp() moyennant une sérialization binaire ad-hoc.
    Je l'ai prouvé pour int et unsigned (c'est semblable pour toutes les tailles d'entiers sur 2, 4, 8 octets, etc).
    Et c'est faux pour la plupart des autres types, pour ne pas dire "tous". Je te cite l'extrait de l'aide de memcmp :
    Citation Envoyé par man memcmp
    The memcmp() function returns an integer less than, equal to, or greater than zero if the first n bytes of s1 is found, respectively, to be less than, to match, or be greater than the first n bytes of s2.
    C'est à dire que memcmp retourne le résultat de comparaison dès la première différence rencontrée. Il ne retourne zéro (égalité) qu'après parcours intégral des N octets à comparer.
    Donc, pour comparer par exemple deux flottants, tu vas devoir partir des principes suivants :
    • Normalisation du flottant sous forme ASCII, avec tous les zéros non-significatifs. Cela doit représenter facilement 300 ou 400 chiffres, je pense.
    • Prier pour que la précision inhérente aux flottants ne perturbe pas ladite représentation ASCII (et c'est déjà mal barré...).
    • En cas d'égalité, ton memcmp sera "juste" cent fois plus lent qu'une comparaison directe de float à float. En cas d'inégalité, tu ne gagneras pas spécialement beaucoup plus de temps.

    De plus, ta sérialisation devra être stockée en mémoire, et à force ça va être coûteux en temps machine comme en place utilisée si tu effectues une sérialisation complète permettant un ordre total.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  3. #23
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    (Désolé du double post, mon réseau refuse de laisser passer le message complet...)

    Citation Envoyé par camboui Voir le message
    Si vous n'aimez pas memcmp(), c'est ok, mais alors dites-moi comment juste décrire une clé assicoée à une structure sans devoir la coder implicitement dans un fastidieux operator<() ?
    Ben j'utilise une "std::map<int,struct>", pour laquelle l'entier représente ma clé, pourquoi ?
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  4. #24
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    La phrase clé ici étant "moyennant une sérialization binaire ad-hoc".
    Citation Envoyé par Mac LAK Voir le message
    Donc, pour comparer par exemple deux flottants, tu vas devoir partir des principes suivants :[list][*]Normalisation du flottant sous forme ASCII, avec tous les zéros non-significatifs. Cela doit représenter facilement 300 ou 400 chiffres, je pense.[*]Prier pour que la précision inhérente aux flottants ne perturbe pas ladite représentation ASCII (et c'est déjà mal barré...).[*]En cas d'égalité, ton memcmp sera "juste" cent fois plus lent qu'une comparaison directe de float à float. En cas d'inégalité, tu ne gagneras pas spécialement beaucoup plus de temps.
    Ben non: Il suffit de sérialiser l'exposant avant la mantisse. Ainsi, la mantisse ne sera comparée que si les exposants sont égaux, supprimant ainsi la nécessité de normalisation.
    De plus, il faut également sérialiser le signe avant l'exposant.

    En clair, si tu sérialises en big-endian un flottant IEEE, tu as tout ça de déjà fait pour toi (sauf peut-être pour les infinis et NaNs).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #25
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Citation Envoyé par screetch Voir le message
    tu pourrais avoir l'égalité binaire entre un flottant et un entier sans que les deux soient égaux (un représente 1.0 et l'autre 1069547520)
    Oui, et alors ?
    Dans mon propos je souhaite comparer des flux binaires construits dans une même séquence donnée (fallait-il le préciser, c'est quand même évident, non ?). Il n'est pas question de comparer des int avec des float, mais des int avec des int, des float avec des float, etc, avec, dans tous les cas, la même fonction de comparaison (et memcmp() me semble convenir).
    Citation Envoyé par Médinoc Voir le message
    Ton raisonnement me parait viable (même si je trouve que l'implémentation de bin_int laisse à désirer).
    Ouf ! L'honeur est sauf. Mon raisonnement n'est pas faux, c'est déjà ça

    Mais bon, le code brut proposé n'est là que pour illustrer le concept que j'essaye de mettre en place. Voici déjà une toute petite évolution qui ajoute les notions ASC et DESC (comme en SQL):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    struct bin_int
    {
    	union
    	{
    		int i;
    		char bin[sizeof(int)];
    	};
    	bin_int(int _i):i(_i) {}
    	bin_int & ascending()
    	{
    		i-=INT_MIN;
    		std::swap(bin[0],bin[3]);
    		std::swap(bin[1],bin[2]);
    		return *this;
    	}
    	bin_int & descending()
    	{
    		i-=INT_MIN;
    		i=UINT_MAX-i;
    		std::swap(bin[0],bin[3]);
    		std::swap(bin[1],bin[2]);
    		return *this;
    	}
    	unsigned size() const
    		{ return sizeof(int); }
    };

  6. #26
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Franchement, j'ai du mal à voir comment tu comptes utiliser ascending et descending ici.

    De plus, pour moi, tu ne devrais avoir qu'une seule valeur: les quatre octets.

    En fait, j'imagine un truc de ce genre:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    //Pour ntohs()/ntohl()
    #ifdef _WIN32
    	#include <winsock2.h>
    	#ifdef _MSC_VER
    		#pragma comment(lib, "ws2_32.lib")
    	#endif
    #else
    	#include <arpa/inet.h>
    #endif
     
    class be_int
    {
    private:
    	char bytes[sizeof(int)];
    public:
    	void SetBE(int beVal)
    	{ *reinterpret_cast< int* >(bytes) = beVal; }
    	int GetBE() const
    	{
    		int beVal = *reinterpret_cast< int const* >(bytes);
    		return beVal;
    	}
     
    	void SetHost(int hostVal)
    	{ SetBE(htonl(hostVal)); }
    	int GetHost() const
    	{ return ntohl(GetBE()); }
     
    	byte const *GetBytes() const { return bytes;}
    	static size_t SGetSize() { return sizeof bytes; }
     
    	be_int(int hostVal)
    	{
    		SetHost(hostVal);
    	}
    };
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #27
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    La phrase clé ici étant "moyennant une sérialization binaire ad-hoc".
    C'est à dire (exprimé différemment) "moyennant une tripaille absolument pas portable et totalement dépendante de l'implémentation"... Mouais... Je préfère gérer un opérateur, pour ma part.

    Citation Envoyé par Médinoc Voir le message
    Ben non: Il suffit de sérialiser l'exposant avant la mantisse. Ainsi, la mantisse ne sera comparée que si les exposants sont égaux, supprimant ainsi la nécessité de normalisation.
    De plus, il faut également sérialiser le signe avant l'exposant.
    Je cite :
    Citation Envoyé par Format IEEE-754
    * simple précision (32 bits : 1 bit de signe, 8 bits d'exposant (-126 à 127), 23 bits de mantisse),
    * simple précision étendue (≥ 43 bits, peu utilisé),
    * double précision (64 bits : 1 bit de signe, 11 bits d'exposant (-1022 à 1023), 52 bits de mantisse),
    * double précision étendue (≥ 79 bits, souvent implémenté avec 80 bits : 1 bit de signe, 15 bits d'exposant (-16382 à 16383), 64 bits de mantisse).
    Donc, déjà, va falloir faire les cas pour chaque type de flottant, découper à des valeurs différentes des mots-machine (23 bits, 52 bits, etc..), inverser le bit de signe (ben oui : 1=négatif, 0=positif => logique inverse), tenir compte du décalage de l'exposant, et enfin gérer tout ça avec une endianness différente de la plus courante (little-endian sur PC, pour mémoire). Je passe sur le problème de conversion / normalisation des flottants invalides, mais qui est malgré tout un vrai problème.

    Je suis le seul à trouver que faire un opérateur sur la structure, qui sera en plus portable, sera bien plus simple, plus rapide et plus efficace que cette usine à gaz potentielle ???
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  8. #28
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    +1 avec Mac LAK

  9. #29
    screetch
    Invité(e)
    Par défaut
    +1 aussi, ca me parait bancal et pas sûr

    disons que sur le papier, ca marche, mais que l'implémentation risque d'être illisible sans commentaires de partout, dangereuse et très difficile a débugger. lorsqu'elle se trompera dans la comparaison, tu pourrais passer des jours a trouver le problème
    plus le fait que tu vas avoir besoin d'une implémentation différente pour chaque type, ce qui va te faire ecrire pas mal de code au final.

  10. #30
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    +1, mais surtout je vois mal où est la lourdeur d'un op< redéfini par rapport à l'usine à gaz que ça va être là...
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  11. #31
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Les "pluzun" c'est pour dire que quelques petits décalages de bit font peur ?
    La discussion a quelque peu dérivé sur les float alors qu'ils ne sont pas importants sur le fond.
    Mon orgueil en a pris un coup suite à vos interventions, et pourtant j'ai le sentiment que vous n'avez pas compris le concept que j'ai essayé d'exprimer dans le premier post de cette discussion. J'ai sans doute du mal à faire passer mon message

    J'ai donc retroussé mes manches et j'ai repris le problème depuis le début. Pas de babla, du code.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    #include "tchar.h"
    #include <climits>
    #include <iostream>
    #include <iomanip>
    #include <sstream>
    #include <functional>
    #include <vector>
    #include <set>
    #include <algorithm>
     
    struct endian_key
    {
    	std::string s;
     
    	char *buffer(size_t size)
    	{
    		size_t l=s.length();
    		s.resize(s.length()+size);
    		std::string::iterator b=s.begin();
    		std::advance(b,l);
    		return &*b;
    	}
     
    	template<typename T>
    	endian_key & asc(T const & v)
    	{
    		ascending(*this,v);
    		return *this;
    	}
     
    	template<typename T>
    	endian_key & desc(T const & v)
    	{
    		descending(*this,v);
    		return *this;
    	}
     
    	endian_key & asc(int v);
    	endian_key & desc(int v);
     
    	endian_key & asc(unsigned v);
    	endian_key & desc(unsigned v);
    };
     
    struct endian_key_pred
    {
    	int index;
    	endian_key_pred(int i):index(i) {}
    	template<typename T>
    	bool operator()(T const & v1,T const & v2) const
    	{
    		endian_key sk1,sk2;
    		v1.make_key(sk1,index);
    		v2.make_key(sk2,index);
    		return ::memcmp(sk1.s.c_str(),sk2.s.c_str(),std::min(sk1.s.length(),sk2.s.length())) < 0;
    	}
    };
     
    //struct bin_int_trait
    //{
    //	typedef int type;
    inline void ascending(endian_key & sk,int i)
    {
    	char *ptr=sk.buffer(sizeof(int));
    	i-=INT_MIN;
    	char *bin=(char *)&i;
    	std::swap(bin[0],bin[3]);
    	std::swap(bin[1],bin[2]);
    	memcpy(ptr,bin,sizeof(int));
    }
    inline void descending(endian_key & sk,int i)
    {
    	char *ptr=sk.buffer(sizeof(int));
    	i-=INT_MIN;
    	i=UINT_MAX-i;
    	char *bin=(char *)&i;
    	std::swap(bin[0],bin[3]);
    	std::swap(bin[1],bin[2]);
    	memcpy(ptr,bin,sizeof(int));
    }
    //};
     
    inline endian_key & endian_key::asc(int v)
    {
    	ascending(*this,v);
    	return *this;
    }
    inline endian_key & endian_key::desc(int v)
    {
    	descending(*this,v);
    	return *this;
    }
     
    inline void ascending(endian_key & sk,unsigned u)
    {
    	char *ptr=sk.buffer(sizeof(unsigned));
    	char *bin=(char *)&u;
    	std::swap(bin[0],bin[3]);
    	std::swap(bin[1],bin[2]);
    	memcpy(ptr,bin,sizeof(unsigned));
    }
    inline void descending(endian_key & sk,unsigned u)
    {
    	char *ptr=sk.buffer(sizeof(unsigned));
    	u=UINT_MAX-u;
    	char *bin=(char *)&u;
    	std::swap(bin[0],bin[3]);
    	std::swap(bin[1],bin[2]);
    	memcpy(ptr,bin,sizeof(unsigned));
    }
     
    inline endian_key & endian_key::asc(unsigned v)
    {
    	ascending(*this,v);
    	return *this;
    }
    inline endian_key & endian_key::desc(unsigned v)
    {
    	descending(*this,v);
    	return *this;
    }
     
    inline void ascending(endian_key & sk,std::string const & s)
    {
    	size_t len=s.length()+1;
    	char *ptr=sk.buffer(len);
    	::memcpy(ptr,s.c_str(),len);
    }
    inline void descending(endian_key & sk,std::string const & s)
    {
    	size_t len=s.length()+1;
    	char *ptr=sk.buffer(len);
    	::memcpy(ptr,s.c_str(),len);
    	unsigned char *uptr=reinterpret_cast<unsigned char *>(ptr);
    	for(;*uptr;++uptr)
    		*uptr=UCHAR_MAX-*uptr;
    	*uptr=UCHAR_MAX;
    }
     
    // c'est à partir d'ici qu'on bénéficie du brol qui précède
     
    struct MyRecord
    {
    	int m_i;
    	std::string m_s;
     
    	void make_key(endian_key & sk,int index) const
    	{
    		switch (index)
    		{
    		case 0:
    			// syntaxe qui fait penser à "CREATE INDEX idx_0 ON MyRecord (m_i ASC, m_s DESC)"
    			sk.asc(m_i).desc(m_s);
    		case 1:
    			// syntaxe qui fait penser à "CREATE INDEX idx_1 ON MyRecord (m_s ASC)"
    			sk.asc(m_s);
    		};
    	}
     
    	//operator<(), à la "mode" STL
    	friend bool operator<(MyRecord const & v1,MyRecord const & v2)
    	{
    		return v1.m_s < v2.m_s;
    		//note: l'operator<() entre deux std::string fait appel à... memcmp() !
    		//fichier include <iosfwd> ligne 436 de VS2005
    	}
    };
     
     
     
    int _tmain(int argc, _TCHAR* argv[])
    {
    	std::vector<MyRecord> vec;
     
    	MyRecord r;
    		r.m_i=-7;	r.m_s="roej";
    	vec.push_back(r);
    		r.m_i=4;	r.m_s="ane";
    	vec.push_back(r);
    		r.m_i=-7;	r.m_s="zie";
    	vec.push_back(r);
    		r.m_i=1;	r.m_s="tup";
    	vec.push_back(r);
    		r.m_i=4;	r.m_s="bobar";
    	vec.push_back(r);
    		r.m_i=-7;	r.m_s="tup";
    	vec.push_back(r);
    		r.m_i=1;	r.m_s="axyze";
    	vec.push_back(r);
    		r.m_i=-7;	r.m_s="taron";
    	vec.push_back(r);
     
    	//tri suivant l'index 0
    	std::sort(vec.begin(),vec.end(),endian_key_pred(0));
     
    	for (std::vector<MyRecord>::iterator it=vec.begin();it!=vec.end();++it)
    		std::wcout << it->m_i << " - " << it->m_s.c_str() << std::endl;
    	std::wcout << std::endl;
     
    	//tri suivant l'index 1
    	std::sort(vec.begin(),vec.end(),endian_key_pred(1));
     
    	for (std::vector<MyRecord>::iterator it=vec.begin();it!=vec.end();++it)
    		std::wcout << it->m_i << " - " << it->m_s.c_str() << std::endl;
    	std::wcout << std::endl;
     
    	//retri suivant l'index 0
    	std::sort(vec.begin(),vec.end(),endian_key_pred(0));
     
    	for (std::vector<MyRecord>::iterator it=vec.begin();it!=vec.end();++it)
    		std::wcout << it->m_i << " - " << it->m_s.c_str() << std::endl;
    	std::wcout << std::endl;
     
    	//tri suivant operator<(), équivalent au tri suivant l'index 1
    	std::sort(vec.begin(),vec.end());
     
    	for (std::vector<MyRecord>::iterator it=vec.begin();it!=vec.end();++it)
    		std::wcout << it->m_i << " - " << it->m_s.c_str() << std::endl;
    	std::wcout << std::endl;
     
    	//un autre conteneur
    	std::set<MyRecord,endian_key_pred> tree(vec.begin(),vec.end(),endian_key_pred(1));
     
    	for (std::set<MyRecord,endian_key_pred>::iterator it=tree.begin();it!=tree.end();++it)
    		std::wcout << it->m_i << " - " << it->m_s.c_str() << std::endl;
    	std::wcout << std::endl;
     
    	return 0;
    }
    Usine à gaz, non portable, illisible... rien de tout ça me semble-t-il, et je répond à ce je souhaitais au départ: sérializer une clé de manière descriptive et non pas procédurale. Une sorte de mix entre SQL et boost::serialize en somme.

    3 étapes dans ce code.
    1. Une structure de serialisation (endian_key) avec le code explicite de trois types de base: int, unsigned et std::string. La paire de fonction ascending() et descending() est conceptuellement semblable à l'operator<<() des iostream associés aux manipulateurs (setw, setprec, setbase, etc).
    2. Un exemple de structure MyRecord dans laquelle les clés à sérialiser sont "décrites". Je trouve que c'est très explicite et lisible. Pour montrer l'analogie que je viens de faire avec les iostream, à la place de sk.asc(m_i).desc(m_s); on aurait pu imaginer une syntaxe comme sk << asc() << m_i << desc() << m_s; par exemple.
    3. Un exemple de code montrant l'usage des clés par l'intermédiaire de deux conteneurs. A noter l'usage d'un seul et unique prédicat indépendant de la structure (endian_key_pred).

    Ceci n'est que le premier jet concret d'une reflexion. Le mérite est que ça fonctionne et que ça me permet d'avoir une base appliquée pour la suite: quid des performances, est-ce une bonne approche conceptuel, est-ce utile, etc ?
    De toutes façons, en tant que simple défi à écrire du C++ (du vrai ! ) c'est déjà une réussite
    Citation Envoyé par Médinoc Voir le message
    Franchement, j'ai du mal à voir comment tu comptes utiliser ascending et descending ici.
    J'espère que tu vois maintenant

  12. #32
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    C'est toujours un bordel monstre et j'y comprends toujours rien.
    Tu es toujours incapable d'utiliser (ou au moins reproduire) un vrai htonl()/ntohl(), ton code dépend toujours de l'endianness...

    De plus, à ma connaissance on n'est pas supposé pouvoir obtenir un pointeur non-const sur l'intérieur du buffer d'une string...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #33
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par camboui Voir le message
    quid des performances, est-ce une bonne approche conceptuel, est-ce utile, etc ?
    Comme je te l'ai déjà dit, c'est une "usine à gaz" parce que c'est excessivement complexe pour, au final, une simple comparaison d'entiers et de chaînes !
    Côté performances, vu le nombre de swaps (forcément non-alignés, donc coûteux) et de traitements de copie que tu fais subir à tes données, ça m'étonnerait beaucoup que tu puisses obtenir des performances fulgurantes sur de gros volumes de données...

    Cela reste un avis personnel, mais quand on se sent "obligé" de se calquer sur un principe existant, mais "étranger" au langage que l'on utilise, c'est que l'on a fait une erreur de conception : soit en prenant le mauvais langage à la base, soit parce que l'on n'a pas su trouver la méthode "native" adéquate.
    En exagérant à peine, cela me fait penser aux plaintes sur le C++ comme quoi il ne possède pas l'équivalent de la fonction "eval" si chère aux langages interprétés : cela montre que l'on a des raisonnements qui restent ancrés dans un "autre monde" et qui ne sont pas forcément adaptés au langage manipulé.


    En guide de boutade :
    Citation Envoyé par camboui Voir le message
    Les "pluzun" c'est pour dire que quelques petits décalages de bit font peur ?
    Pour ma part, je bosse dans l'embarqué temps réel, je "bouffe" des décalages de bits, des registres, des contrôleurs et des protocoles réseau à longueur de temps. Donc, non, ce ne sont pas quelques opérations dépendantes de la plate-forme matérielle qui me gênent, loin de là. C'est plutôt que je n'en vois pas l'utilité à un si haut niveau de code, où c'est plus nuisible qu'autre chose.

    La preuve : tu n'as pas une seule ligne de gestion de l'endianness courante de la machine. Ton code ne fonctionnerait pas sur un processeur big-endian, tout comme il est presque certain qu'il ne fonctionnerait pas non plus sur une machine 64 bits. Rajouter cette gestion alourdirait énormément ton code, le rendant donc encore plus volumineux et donc encore moins performant... Vois-tu mieux pourquoi je dis que c'est une usine ?


    Après, soyons bien clairs : je ne t'en veux pas personnellement, non je n'ai pas juré de descendre ton code, ni quoi que ce soit d'autre à ton encontre.
    C'est juste que ton code semble être une brique primaire de ton projet. Or, quand on commence à faire des usines ou des mikados sur les briques élémentaires d'un projet, à la fin, ça fait surtout une gigantesque masse de spaghettis mêlée de poulpes amoureux. Cela devient totalement inmaintenable. C'est une situation que j'ai déjà vécue, et franchement, je n'ai pas apprécié des masses le démêlage de la tripaille.
    Je cherche juste à te faire comprendre ça pour t'éviter une erreur qui aura des conséquences plus ou moins fâcheuses.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  14. #34
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    C'est toujours un bordel monstre et j'y comprends toujours rien.
    Je comprend qu'on puisse ne pas comprendre
    Citation Envoyé par Médinoc Voir le message
    Tu es toujours incapable d'utiliser (ou au moins reproduire) un vrai htonl()/ntohl(), ton code dépend toujours de l'endianness...
    C'est du détail d'implémentation. C'est bien sûr à revoir, le code que j'ai posté en exemple n'est justement qu'un... exemple. Ca permet pour l'instant de "visualiser" le concept.
    Ceci dit, je suis preneur d'une version inline et/ou asm pour x86/x64 de htonl()/ntohl() et htons()/ntohs() (et pareil pour les mots en 64bits). Pour les autres processeurs on verra dans une autre vie...
    Citation Envoyé par Médinoc Voir le message
    De plus, à ma connaissance on n'est pas supposé pouvoir obtenir un pointeur const sur l'intérieur du buffer d'une string...
    Encore une fois, c'est du détail d'implémentation. C'est vrai que j'aurais pu utiliser un std::vector<char> par exemple, mais le string est tellement facile. Et puis en pratique, même si ce n'est pas "officiel", je pense bien que toute les implémentations de string utilisent un buffer continu en mémoire.

  15. #35
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par camboui Voir le message
    Je comprend qu'on puisse ne pas comprendre
    C'est du détail d'implémentation. C'est bien sûr à revoir, le code que j'ai posté en exemple n'est justement qu'un... exemple. Ca permet pour l'instant de "visualiser" le concept.
    Ceci dit, je suis preneur d'une version inline et/ou asm pour x86/x64 de htonl()/ntohl() et htons()/ntohs() (et pareil pour les mots en 64bits). Pour les autres processeurs on verra dans une autre vie...
    Traditionnellement, j'utilise un truc de ce genre:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    inline unsigned short my_htons(unsigned short u)
    {
    	unsigned char b[2] = {
    		static_cast<unsigned char>(u >> 8),
    		static_cast<unsigned char>(u)
    	};
    	return *reinterpret_cast<unsigned short*>(b);
    }
     
    inline unsigned long my_htonl(unsigned long u)
    {
    	unsigned char b[4] = {
    		static_cast<unsigned char>(u >> 24),
    		static_cast<unsigned char>(u >> 16),
    		static_cast<unsigned char>(u >> 8),
    		static_cast<unsigned char>(u)
    	};
    	return *reinterpret_cast<unsigned long*>(b);
    }
    C'est indépendant de l'endianness.

    Encore une fois, c'est du détail d'implémentation. C'est vrai que j'aurais pu utiliser un std::vector<char> par exemple, mais le string est tellement facile. Et puis en pratique, même si ce n'est pas "officiel", je pense bien que toute les implémentations de string utilisent un buffer continu en mémoire.
    Pardon, lapsus. Je voulais dire un pointeur non-const.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  16. #36
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Traditionnellement, j'utilise un truc de ce genre:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    inline unsigned short my_htons(unsigned short u)
    {
    	unsigned char b[2] = {
    		static_cast<unsigned char>(u >> 8),
    		static_cast<unsigned char>(u)
    	};
    	return *reinterpret_cast<unsigned short*>(b);
    }
     
    inline unsigned long my_htonl(unsigned long u)
    {
    	unsigned char b[2] = {
    		static_cast<unsigned char>(u >> 24),
    		static_cast<unsigned char>(u >> 16),
    		static_cast<unsigned char>(u >> 8),
    		static_cast<unsigned char>(u)
    	};
    	return *reinterpret_cast<unsigned long*>(b);
    }
    C'est indépendant de l'endianness.
    .
    ca l'est vraiment ??

  17. #37
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    C'est juste que ton code semble être une brique primaire de ton projet.
    Il ne semble pas, C'EST une petite brique. Non pas d'un projet précis, mais d'une réflexion ludique et conceptuelle.

    Je comprend maintenant les réactions du forum: elles sont économiques ou productives alors que j'ai une approche bien plus détachée.

  18. #38
    screetch
    Invité(e)
    Par défaut
    (c'est aussi, accessoirement, assez lent)

  19. #39
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par screetch Voir le message
    ca l'est vraiment ??
    À ma connaissance, oui: Sur une machine little-endian, ça inverse, et sur une machine big-endian, l'ordre est conservé.
    Mais je me doute que ça doit être lent, car je vois mal un compilo optimiser ça.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  20. #40
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Citation Envoyé par screetch Voir le message
    ca l'est vraiment ??
    Oui, ça m'a bien l'air de l'être.
    C'est pas mal d'ailleurs

Discussions similaires

  1. petite aide sur une requete INSERT INTO
    Par bonneti dans le forum Langage SQL
    Réponses: 3
    Dernier message: 14/03/2005, 15h17
  2. petite aide sur les transactions et triggers SVP
    Par CharleLéo dans le forum Débuter
    Réponses: 4
    Dernier message: 15/11/2004, 20h43
  3. Petite aide pour gros problème : libstdc++
    Par Info-Rital dans le forum Linux
    Réponses: 5
    Dernier message: 30/08/2004, 19h17
  4. Petite aide sur les triggers ?
    Par krimson dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 16/04/2004, 16h28
  5. Une petite aide pour les API ?
    Par Yop dans le forum Windows
    Réponses: 2
    Dernier message: 04/04/2002, 21h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo