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 :

Language permettant de gérer des structures de données "exotiques".


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite Avatar de valefor
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    711
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 711
    Par défaut Language permettant de gérer des structures de données "exotiques".
    Bonjour.

    Dans le cadre d'un projet perso consistant à lire un fichier de données d'un vieux jeux vidéo, j'ai été amené à développer une "nouvelle classe d'entier".

    Les contraintes étant de pouvoir déclarer des structures dont :
    - les données ne sont pas alignées,
    - les données peuvent être en little ou en big.
    Le code de lecture devant être fonctionnel sur toutes architectures.

    J'en suis arrivé au résultat en PJ. Je vous le soumet pour commentaires mais mes questions sont les suivantes :
    - Existait-t-il déjà des patterns pour réaliser cela (sous quel nom) ?
    - Y-a-t-il un langage prenant en compte ce genre de problématiques ?

    Je me suis aperçut que cela manquait aussi au boulot. Par exemple pour définir des trames (ne parlons même pas de la gestion des champs de bits).

    Merci de partager vos idées.

    Edit : à l'origine, j'avais posté ce message dans une rubrique "langages" en général. Je ne pense pas forcément à une solution c++, mais comme mon implémentation actuelle est en c++ et qu'elle est discutable, elle devrait avoir sa place ici.
    Fichiers attachés Fichiers attachés
    • Type de fichier : h Int.h (3,0 Ko, 107 affichages)

  2. #2
    Membre émérite
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Par défaut
    Je dirais que pas mal n'importe quel langage à typage dynamique de haut niveau va te permettre d'avoir des structures de données ad-hoc.

  3. #3
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Par défaut
    Citation Envoyé par GnuVince Voir le message
    Je dirais que pas mal n'importe quel langage à typage dynamique de haut niveau va te permettre d'avoir des structures de données ad-hoc.
    pas tout à fait d'accord... tout dépend de la sureté de typage que l'on souhaite.


    j'aimerais bien des explications plus compréhensibles qu'une template c++ (que je n'ai pas envie de lire )
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  4. #4
    Membre émérite Avatar de valefor
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    711
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 711
    Par défaut
    Par exemple il faut lire un bloc dont la structure est la suivante (pour faire simple on a que des entiers) :
    offset 0, big endian, entier non signé sur 4 octets
    offset 32, little endian, entier non signé sur 2 octets
    offset 48, little endian, entier non signé sur 4 octets

    En c j'aurai tendance à déclarer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    struct 
    {
      unsigned int a;
      unsigned short b;
      unsigned int c;
    }
    Mais le problème est que c'est faux :
    (1) Si je ne suis pas sur du 32 bits
    (2) Si le compilo ne tasse pas la structure
    (3) Dans tous les cas à cause de l'endianess

    Les solutions sont donc :
    (1) Utiliser uint16_t, et uint32_t (ça c'est pas trop dégueulasse c'est du C99 il me semble).
    (2) Utiliser l'attribut "packing" ou je ne sais plus quoi (ça c'est pas portable d'un compilo à l'autre, sous MSVC++ je crois que ce sont des pragmas... bref).
    (3) Faire une fonction/macro que l'on appelle swap, ou mieux read/write_little/big. Là ça va faire du code illisible à la fin.


    Dans l'implémentation que je propose on déclare :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    struct 
    {
      be_uint32_t a;
      le_uint16_t b;
      le_uint32_t c;
    } foo;
    La structure sera bonne partout. Comme c'est du c++ quand on accedera aux champs la conversion d'endianess se fera automatiquement.

    Je me demandais si il n'y avait pas moyen d'optimiser ce que j'avais fait en l'intégrant au langage. Les compilos pourraient générer le code d'accès au champ et ce serait utilisable même en c.

    Voila

  5. #5
    Membre émérite Avatar de valefor
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    711
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 711
    Par défaut
    Je me permet de remonter le sujet, j'aimerais vraiment avoir vos retours.

  6. #6
    Membre chevronné

    Inscrit en
    Août 2007
    Messages
    300
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 300
    Par défaut
    - Le compilateur n'est pas du tout obligé d'éliminer les portions mortes de code, ce qui peut être gênant puisque tout est inline. La façon portable de le faire est de faire des spécialisations partielles.
    - très dommage de ne pas court-circuiter l'opérator T lorsque l'architecture d'exécution correspond à celle des données. Avec spécialisation partielle, on pourrait en effet ne souffrir aucune pénalité par rapport à du code natif quand elles coïncident.
    - pourquoi _x est-il public?
    - sur le principe, est-il rigoureusement nécessaire d'arranger en mémoire les octets comme ils figurent sur le fichier? Pourquoi ne pas tout simplement gérer les E/S classiquement, et utiliser les types de taille garantie (uint16_t...) pour le compactage? Pour les structures composées, toutes les librairies de serialisation que je connais (Eternity, Boost.Serialization, MFC et autres), imposent de toute façon un archivage membre à membre, je ne vois donc pas l'intérêt de répliquer en mémoire la disposition sur fichier.

  7. #7
    Membre émérite

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Par défaut
    Pourquoi chercher à dupliquer le format du fichier en mémoire ? Un format de fichier c'est une chose, une structure de donnée c'est autre chose, les contraintes sont souvent différentes.

    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
    unsigned long readUInt32BE(std::istream& src)
    {
      unsigned long result = static_cast<unsigned long>(src.get());
      result = (result << 8) | static_cast<unsigned long>(src.get());
      result = (result << 8) | static_cast<unsigned long>(src.get());
      result = (result << 8) | static_cast<unsigned long>(src.get());
      return result;
    }
     
    unsigned readUInt16BE(std::istream& src)
    {
      unsigned long result = static_cast<unsigned long>(src.get());
      result = (result << 8) | static_cast<unsigned long>(src.get());
      return result;
    }
     
    struct
    {
      unsigned long a;
      unsigned b;
      unsigned long c;
    } s;
     
    s.a = readUInt32BE(src);
    s.b = readUInt16BE(src);
    s.c = readUInt32BE(src);
    Code 100% portable et sans utiliser de #pragma et autre typedef.

  8. #8
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Pour la question initiale: Ada a des clauses de representation permettant une partie de ce que tu veux, mais vraisemblablement pas tout (en particulier la gestion de la boutitude n'est pas presente).

Discussions similaires

  1. Présentation des structures de données arborescentes
    Par PRomu@ld dans le forum Algorithmes et structures de données
    Réponses: 0
    Dernier message: 30/01/2009, 14h39
  2. Réponses: 2
    Dernier message: 15/01/2009, 18h45
  3. Files Mapping pour stocker des structures de données
    Par Targan dans le forum Débuter
    Réponses: 0
    Dernier message: 27/12/2007, 11h38
  4. redim Imbrication des structures de données
    Par totoche dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 28/11/2007, 15h23
  5. combobox et me permette le choix des bases de données
    Par crash override dans le forum Composants VCL
    Réponses: 6
    Dernier message: 21/10/2005, 16h28

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