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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut Petite aide à la sérialisation
    Voici le genre de chose que je faisais et fais encore
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #pragma pack(1)
    struct record
    {
    char name[20];
    unsigned id,seq;
    };
     
    record r;
    strcpy(r.name,s.c_str());// bof bof...
    r.id=25;
    r.seq=10;
    ...
    file.write(&r,sizeof(record));
    A la longue c'est fastidieux et on se retrouve avec des dizaines si pas des centaines de structures en tout genre avec à chaque fois des kilomètres de code pas très fiable associés à chaque structure. Bref, c'est du C, pas vraiment du C++.

    J'ai vu un peu comment était construit boost::serialize avec la méthode intrusive serialize(). Le principe est très sympa.
    J'aimerais m'en inspirer pour généraliser quelque chose de ce genre:
    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
    struct record
    {
    std::string name;
    unsigned id,seq;
     
    void serialize_record(archive_record & a)
    {
     a & name & id;
    }
     
    void serialize_keysort(archive_keysort & a,int keynumber)
    {
     switch (keynumber)
     {
      case 0: a & id; break;
      case 1: a & name & seq; break;
     }
    }
     
    void serialize_keysearch(archive_keysearch & a,int keynumber)
    {
     switch (keynumber)
     {
      case 0: a & id; break;
      case 1: a & name; break;
     }
    }
    };
    En gros, j'ai des records à stocker avec une ou plusieurs clé de tri (et donc de recherche). Dans l'exemple j'ai "name" et "id" qui sont des infos utiles à stocker, et les deux participent chacune dans une clé de tri. Au delà, il y a aussi "seq" mais qui n'est utile que pour imposer une sequencement ordonné dans une des clés, après je n'en ai plus besoin.

    Un petite aide pour poursuivre ma réflexion serait bienvenue. Et surtout s'il existe déjà du tout fait, c'est encore mieux
    Merci.

  2. #2
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Bon ben il semble que cela n'inspire personne
    Vous ne faites jamais de la gestion de fichiers un peu élaborée, ou de bd "custom" ?

    Bah, j'ai un peu simplifié mon modéle de réflexion. Mon truc avec les clés est un peu compliqué, j'ai simplifié en ceci pour n'avoir qu'une clé par structure:
    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
    struct record
    {
    std::string name;
    unsigned id;
     
    template <class archive_record>
    void serialize_record(archive_record & a)
    {
     a & name & id;
    }
     
    template <class archive_key>
    void serialize_key(archive_key & a)
    {
      a & id;
    }
    };

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

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    En général, vu le niveau auquel je travaille (bas niveau), j'applique le plus souvent deux choses totalement disjointes :
    • Je sérialise "brutalement" un attribut de ma classe, qui est la plupart du temps une structure packed servant de container interne à la classe, via la surcharge de "<<" et ">>" sur la classe elle-même, ou carrément via des fread/fwrite (je sais, c'est mal, m'en fous). Ça, c'est pour ce qui tourne tout le temps, genre stockage brutal, communications réseau intensives, etc.
    • Si c'est de la configuration initiale, j'utilise plutôt de l'XML avec des wrappers automatiques depuis le schéma XSD, qui valide au maximum possible les fichiers XML afin de m'éviter d'avoir à le faire au niveau applicatif.
    Si ça peut t'aider...
    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. #4
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    OK, merci.

    Je vais me débrouiller et je ferai part de mes résutats si ça intéresse quelqu'un

    J'aimerais cependant un petite aide pour sérializer en binaire tous les types courants de sorte que
    memcmp(v1,v2,min(v1.length(),v2.length()))
    renvoit la bonne valeur quoiqu'il y ait dans v1 et v2. Par exemple:
    v1 << int(5) << std::wstring(L"abc") << float(23.7).
    v2 << int(-7) << std::wstring(L"xyzt") << float(-0.095).
    je suppose que ce n'est qu'un problème d'ordre "endian" et rien d'autre.

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

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Quant on sérialise, par définition, on DOIT tenir compte de l'endianness et de l'alignement si l'on désire avoir quelque chose de transmissible à une autre machine.

    Dans ton cas, il faut bien sûr s'assurer de la taille des données, de l'endianness (little-endian sur un PC, mais big-endian sur un réseau en général), et du padding entre les divers éléments quand ils sont en mémoire.

    Sur ton exemple, comme les chaînes de caractère sont de taille différente, ça n'aura jamais de sens : le champ flottant ne sera aligné avec celui d'une autre structure que par miracle. Si tu veux éviter ça, il faut utiliser une taille constante sur les chaînes, et remplir la partie non-utilisée de zéros. Par contre, tu vas perdre de la place, forcément...
    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

  6. #6
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Sur ton exemple, comme les chaînes de caractère sont de taille différente, ça n'aura jamais de sens : le champ flottant ne sera aligné avec celui d'une autre structure que par miracle. Si tu veux éviter ça, il faut utiliser une taille constante sur les chaînes, et remplir la partie non-utilisée de zéros. Par contre, tu vas perdre de la place, forcément...
    Tu peux aussi préfixer la chaîne de caractère par sa taille. Ca permet de perdre moins de place, par contre, ça t'oblige à décoder la structure séquentiellement (plus possible d'accéder directement à un champ sans avoir lu tous les précédents).

  7. #7
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Les chaines de caractères seront terminées par zéro, cela devrait permettre de comparer des flux binaire de longueur quelconque avec du texte en milieu de flux (pas besoin d'aligner les champs donc).
    Cependant, il faut aussi sur PC respecter le bon "endian":
    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
    #include "tchar.h"
    #include <iostream>
    #include <sstream>
    #include <functional>
     
    template <typename T>
    bool cmp(T v1,T v2)
    {
    	return memcmp(&v1,&v2,sizeof(T))<0;
    }
     
    int _tmain(int argc, _TCHAR* argv[])
    {
    	std::wcout << std::less<int>()(-10,1000000000) << std::endl;
    	std::wcout << cmp(-10,1000000000) << std::endl;
    	return 0;
    }
    Le résultat devrait être le même, mais il ne l'est pas. Résultat
    1
    0

  8. #8
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Il me semblait bien...
    Citation Envoyé par camboui Voir le message
    je suppose que ce n'est qu'un problème d'ordre "endian" et rien d'autre.
    L'affirmation ci-dessus de mon précédant post est donc fausse

    Je repose donc la question:
    comment sérializer en binaire tous les types courants de sorte que
    memcmp(v1.void_ptr(),v2.void_ptr(),min(v1.length(),v2.length()))
    renvoit la bonne valeur quoiqu'il y ait dans v1 et v2 ?

  9. #9
    screetch
    Invité(e)
    Par défaut
    ca dépend de ce que tu veux tester. Si tu veux tester l'égalité, le memcmp fonctionne
    si tu veux tester a < b quel que soit le type de a et b ca ne marchera jamais, puisque ca dépend de la représentation binaire du type.

  10. #10
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    C'est mort à mon avis. memcpy compare de la mémoire, c'est tout. Pour une comparaison sémantique, il faut des types et l'opérateur <.

    Donc, étape suivant, on remonte au besoin. Que cherches-tu à faire exactement ?

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