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 :

Conversion structure fichier binaire big-endian


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné Avatar de Tchetch
    Inscrit en
    Mars 2002
    Messages
    401
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Mars 2002
    Messages : 401
    Par défaut Conversion structure fichier binaire big-endian
    Bonjour,

    Je vais faire simple, j'ai la structure suivante :
    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
     
    struct ffb_init0 {
        unsigned long long fileID; /* 48 bits */
        unsigned short clientID; /* 16 bits */
        unsigned long long blockNumbers; /* use only 45 bits */
        unsigned long packetNumbers; /* 32 bits */
        unsigned long long magicValue; /* 64 bits */
        unsigned long long fileHash[4]; /* at least 512 bits */
        unsigned char hashMethod; /* 8 bits */
        unsigned char protocolVersion; /* use only 4 bits */
        unsigned long long fileTime; /* use only 48 bits, hold unixtime */
        unsigned long long dataBlockPayload; /* 64 bits */
        unsigned char hasMetadata; /* 1 bit */
        unsigned char uft8Filename[69]; /* 552 bits for utf8 filename */
        /* 6 bits left to pad at 0x0 */
    };

    Je veux la convertir en tableau de bits, alors j'ai commencé comme suit :
    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
     
        unsigned char barr_p[175];
     
        /* FileID */
        barr_p[0] = (p->fileID >> 40) & 0xff;
        barr_p[1] = (p->fileID >> 32) & 0xff;
        barr_p[2] = (p->fileID >> 24) & 0xff;
        barr_p[3] = (p->fileID >> 16) & 0xff;
        barr_p[4] = (p->fileID >> 8) & 0xff;
        barr_p[5] = p->fileID & 0xff;
     
        /* clientID */
        barr_p[6] = (p->clientID >> 8) & 0xff;
        barr_p[7] = p->clientID  & 0xff;
     
     
        /* blockNumbers */
        barr_p[8] = (p->blockNumbers >> 37) & 0xff;
        barr_p[9] = (p->blockNumbers >> 29) & 0xff
        barr_p[10] = (p->blockNumbers >> 21) & 0xff;
        barr_p[11] = (p->blockNumbers >> 13) & 0xff;
        barr_p[12] = (p->blockNumbers >> 5) & 0xff;
        /* Start to mix data in a byte as blockNumbers is 45 bits, so 3 bits are
         * used in the last byte and so we have to complete with the five bits of
         * the next value in the structure.
         */
        barr_p[13] = (((p->blockNumbers << 3) & 0xff) +
                ((p->packetNumbers >> 29) & 0xff)) & 0xff;
        barr_p[14] = (p->packetNumbers >> 21) & 0xff;
        barr_p[15] = (p->packetNumbers >> 13) & 0xff;
        barr_p[16] = (p->packetNumbers >> 5) & 0xff;

    Le problèmes est bien le suivant, j'ai 175 cases de tableaux à remplir comme ça, avec un décalage (champs 45 bits), et je me demandais si quelqu'un a juste une idée pour automatiser un peu ça.

  2. #2
    Membre Expert
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 414
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dév. Java & C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 414
    Par défaut
    Bonjour,

    On pourrait utiliser une macro pour "alléger" la lecture

    (non testé)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
    #define EXTRACTBIT(f,nb) ((f) >> (nb) & 0xff)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
        unsigned char barr_p[175];
     
        /* FileID */
        barr_p[0] = EXTRACTBIT(p->fileID, 40);
        barr_p[1] = EXTRACTBIT(p->fileID, 32);
        barr_p[2] = EXTRACTBIT(p->fileID, 24);
        barr_p[3] = EXTRACTBIT(p->fileID, 16);
        barr_p[4] = EXTRACTBIT(p->fileID, 8) ;
        barr_p[5] = EXTRACTBIT(p->fileID, 0);
     
        /* clientID */
        ....

    Ce ne sont que 175 lignes....

    Petite remarque: Tu utilises l'opérateur + pour combiner deux champs, pour ma part j'utiliserai plutôt le OU Logique |

  3. #3
    Membre chevronné Avatar de Tchetch
    Inscrit en
    Mars 2002
    Messages
    401
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Mars 2002
    Messages : 401
    Par défaut
    Ouais la macro, c'est clair, j'y ai même pas pensé ...
    Citation Envoyé par jowo
    Ce ne sont que 175 lignes....
    J'ai plusieurs structures au final.
    Citation Envoyé par jowo
    Petite remarque: Tu utilises l'opérateur + pour combiner deux champs, pour ma part j'utiliserai plutôt le OU Logique |
    Juste, merci.

    Citation Envoyé par Médinoc
    Et tu appelles les bonnes fonctions pour les bons membres de la structure.
    J'y ai pensé, mais le problème est à partir du décalage. Je penses peut-être faire d'abord des morceaux de 64 bits (unsigned long long) à l'aide d'une fonction générique du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    unsigned long long (unsigned long long val1, int startVal1, int lenVal1, ...) {
    }
    Et ensuite je peux rassembler ces morceaux en gros bloc de 1400 bits ... Ce serait une solution ...

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Ah, je vois, c'est un tableau de bits qu'il te faut et non d'octets...
    Enfin, tu peux sûrement faire à peu près la même chose.
    Essaie de te faire une fonction générique de ce genre:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    void CopyBits(unsigned char *dest, size_t iBitDest, unsigned char const *src, size_t iBitSrc, size_t nBits);
    Et bien sûr, optimisée pour éviter de copier les bits un par un.
    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. #5
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Tchetch Voir le message

    Je veux la convertir en tableau de bits, alors j'ai commencé comme suit :
    ..
    Le problèmes est bien le suivant, j'ai 175 cases de tableaux à remplir comme ça, avec un décalage (champs 45 bits), et je me demandais si quelqu'un a juste une idée pour automatiser un peu ça.
    Citation Envoyé par Tchetch Voir le message
    ...
    J'y ai pensé, mais le problème est à partir du décalage. Je penses peut-être faire d'abord des morceaux de 64 bits (unsigned long long) à l'aide d'une fonction générique du genre :
    ..
    Et ensuite je peux rassembler ces morceaux en gros bloc de 1400 bits ... Ce serait une solution ...
    D'après le contenu de la structure, es-tu sûr que ce soit des tableaux de bits que tu veuilles ?

    et non avoir en entrée un tableau de unsigned char (lecture du buffer envoyé/reçu), et le décomposer suivant les paramètres des structures ?

    Si c'est le cas, j'aurais plutôt tendance à avoir quelque chose comme :

    Decode_Int ( adr, offset, longueur, &i );
    Decode_Float ( adr, offset, longueur, &fl );
    ....

    adr étant l'adresse d'un octet, offset le nombre de bits de décalage, longueur le nombre de bits où la varaible est stockée, et ensuite l'adresse où stocker...

    (certains formats compressés sont faits comme ça)

  6. #6
    Membre chevronné Avatar de Tchetch
    Inscrit en
    Mars 2002
    Messages
    401
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Mars 2002
    Messages : 401
    Par défaut
    Citation Envoyé par Médinoc
    Ah, je vois, c'est un tableau de bits qu'il te faut et non d'octets...
    Je change le boutisme de mes valeurs. Donc c'est au niveau des octets. Je crois qu'il faut que je prenne le problème différemment :

    - Changer le boutisme de toute la structure
    - Empaqueter sans espacement d'alignement.

    Je vais faire ça je crois, c'est plus logique en fait.

  7. #7
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    il y a les fonctions

    htonl htons etc etc et leurs inverses ntohl ntohs ... (Host To Netwrok et Network To Host)

  8. #8
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Avec 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
    37
    38
    /* Sérialisation d'entier 64 bits "unchecked" */
    void SerializeU64_u(unsigned char *pbuffer, size_t *pIndex, unsigned long long u64)
    {
    	/* Note: On peut aussi faire une boucle */
    	pBuffer[(*pIndex)++] = (u64 >> 56) & 0xff;
    	pBuffer[(*pIndex)++] = (u64 >> 48) & 0xff;
    	pBuffer[(*pIndex)++] = (u64 >> 40) & 0xff;
    	pBuffer[(*pIndex)++] = (u64 >> 32) & 0xff;
    	pBuffer[(*pIndex)++] = (u64 >> 24) & 0xff;
    	pBuffer[(*pIndex)++] = (u64 >> 16) & 0xff;
    	pBuffer[(*pIndex)++] = (u64 >>  8) & 0xff;
    	pBuffer[(*pIndex)++] = (u64 >>  0) & 0xff;
    }
     
    /* Sérialisation d'entier 64 bits */
    int SerializeU64(unsigned char *pbuffer, size_t *pIndex, unsigned long long u64, size_t tailleBuffer)
    {
    	const size_t TAILLE = sizeof u64;
    	/* --- Contrôle des paramètres --- */
    	/* pIndex n'est jamais nul, en C++ ce serait une référence */
    	assert(pIndex != NULL);
    	/* Buffer nul+taille nulle: Calcul de la taille nécessaire */
    	if(pBuffer == NULL && tailleBuffer == 0)
    	{
    		(*pIndex) += TAILLE;
    		return 0;
    	}
    	/* Buffer nul ou insuffisant: Erreur */
    	if(pBuffer == NULL)
    		return -1;
    	if((*pIndex) + TAILLE > tailleBuffer)
    		return -1;
     
    	SerializeU64_u(pBuffer, pIndex, u64);
    	return 0;
    }
     
    /* Etc. */
    Et tu appelles les bonnes fonctions pour les bons membres de la structure.
    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.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 26/12/2012, 11h19
  2. Réponses: 6
    Dernier message: 14/03/2007, 14h36
  3. [LabView-MATLAB] Conversion de fichier binaire
    Par flzox dans le forum LabVIEW
    Réponses: 3
    Dernier message: 20/01/2007, 18h42
  4. Comment écrire en big endian dans un fichier ?
    Par j3d dans le forum VB 6 et antérieur
    Réponses: 11
    Dernier message: 24/07/2005, 21h50

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