Cher journal, imaginons que j'ai un programme qui doivent exploiter des données binaires structurées. Genre des paquets avec un header structuré, des données arbitraires de taille variable spécifiée dans le header, et un footer structuré. Structures connues et tout. Imaginons que je veuille accéder (lecture/écriture) aux différents champs contenus dans les différentes structures. "Facile" qu'on peut répondre : il suffit de définir les struct { }; qui vont bien en C et le compilateur fait le reste...
Certes, mais ce n'est pas suffisant. Car il faut compter sur les indiens, qui ne sont pas gentils quand les champs font plus de 8 bits de large. Bref, en pratique on se retrouve avec un programme tout beau tout simple mais qui interprète les indiens de travers. Existe-t'il un "__attribute__" gcc qui permet de spécifier l'endianness d'une structure ? Ou un système qui génère du code C ou C++ permettant d'accéder aux champs des structures (décrites elles-mêmes sous forme de struct C ou dans un langage spécifique) en prenant soin de s'occuper de l'endianness ?
En ce qui me concerne, la limitation principale n'est pas vraiment cette histoire d'indiens sur des mots simples (ntoh*/hton*, après tout ce n'est pas la mer à boire). C'est surtout que j'ai des mots qui contiennent des champs de bits, et ça c'est un peu casse-pied puisqu'il faut "cuisiner" et c'est pas très joli.
Pour l'instant, j'ai choisi le générateur de code http://morcandel.free.fr/mimine pour le C. Mais cela ne satisfait qu'à moitié mes exigences de flemmardise. J'ai aussi eu vent de NetPDL (http://www.nbee.org/doku.php?id=netpdl:index) mais est-ce bien utilisable en mode génération de code ? J'avais aussi un peu suivi DEVIL (http://phoenix.labri.fr/software/devil/) mais je ne suis pas convaincu que ça corresponde à ce qui m'intéresse, ni que ce soit encore très actif. J'ai aussi vu http://nmedit.sourceforge.net/subprojects/libpdl.html mais j'ai cru comprendre que l'overhead CPU pouvait être important (utilisation de dictionnaires pour caser les champs, parsing en-ligne de la description, etc.).
Des idées pour éclairer ma lanterne ? Comment font les gens de wireshark ?
# buffer
Posté par goeb . Évalué à 1.
je suppose qu'il faut que tu remplisses ton buffer local avec les ntoh*, et ensuite tu travailles sur ton buffer local en parcourant les champs de bits.
en résumé : en entrée, avant toute autre manipulation, tu convertis tout ton buffer avec ntoh*.
[^] # Re: buffer
Posté par David Decotigny (site web personnel) . Évalué à 1.
[^] # Re: buffer
Posté par Étienne . Évalué à 1.
Le principe est assez simple, tu a une classe endian templatée par le type d'endian, le type C représenté et la taille du champ. La donnée stockée sera toujours dans le format de l'endian que tu as fourni.
Ensuite les différents opérateurs sont implémentés pour fournir une interface identique à un entier mais qui fait la conversion dans le format de ta machine à chaque fois.
Étienne
[^] # Re: buffer
Posté par David Decotigny (site web personnel) . Évalué à 1.
# Ca devient un beau foutoir le C ...
Posté par totof2000 . Évalué à 3.
Depuis quelques années, avec les "optimisations" des CPU ou des compilateurs, le code compilé ne correspond absolument plus au code généré. On se retrouve avec des octets "de bourage" dans les structures pour que celles ci soient alignées sur 32/64 bits ...
Je pense que, de nos jours, il est possible via une directive fourni au compilo, de ne pas activer ces "optimisations" et de travailler "à l'ancienne". Un man de GCC devrait t'en dire plus (il me semble avoir cherché il y a quelques mois sur ce sujet).
[^] # Re: Ca devient un beau foutoir le C ...
Posté par David Decotigny (site web personnel) . Évalué à 3.
Je ne suis pas convaincu que ce soit une tare du C (enfin : de gcc en l'espèce) que de réarranger la structure effective et l'alignement des choses en mémoire afin d'"optimiser" ou tout simplement afin de s'adapter aux contraintes d'alignement des CPU.
Après tout, la notion de structure est davantage sémantique dans un langage "de haut niveau", que véritablement physique. Parlez-en à un électronicien, pour lui le C est bien un langage de haut niveau ;)
[^] # Re: Ca devient un beau foutoir le C ...
Posté par totof2000 . Évalué à 2.
Le C d' origine n'était rien de mieux qu'un assembleur amélioré .... Et ce n'est qu'au fur et à mesure de ses diverses évolutions qu'il es devenu un réel langage de haut niveau.
Est-ce bien ou non ? Peut-être, peut-être pas. Toujurs est-il qu'aujourd'hui ce n'est pas évident de s'y retrouver ....
Pour info je ne suis pas électronicien de métier mais je fais de l'électronique .... Et pour moi le C est un assembleur amélioré (en tout cas le C d'origine).
Je ne suis pas convaincu que ce soit une tare du C (enfin : de gcc en l'espèce) que de réarranger la structure effective et l'alignement des choses en mémoire afin d'"optimiser" ou tout simplement afin de s'adapter aux contraintes d'alignement des CPU.
Les compilateurs que j'utilisais il y a 12 ans ne le faisaient pas systématiquement. c'était pratique quand on faisait de la programmation hardware, on ne se posait pas trop de questions, et dans ce domaine l'optimisation systématique peut être problématique.
# Mini-framework
Posté par pasBill pasGates . Évalué à 2.
IntegerField: Classe derivee de Field -> Integer qui implemente support pour les petits et grands indiens et offre un parametre pour decider
Classe derivee de IntegerField (tu fais un template en 5 minutes) pour chaque entier de 8 a 64bit
Classe String derivee de Field qui gere Unicode/UTF8/ANSI
Classe "Buffer" derivee de Field qui gere des buffers quelconques
Classe Container derivee de Field qui est un container(permet d'y ajouter des champs a l'interieur, et la methode read va de l'un a l'autre)
Classe BitField derivee de Container qui permet d'inclure des IntegerField, specifier combien de bits sont assignes a chaque IntegerField, et dont la methode Read s'occupe de passer la valeur qu'il faut a coup de masque a chaque champ
Une fois que t'as fait ca, ben c'est fini, t'as plus qu'a construire ta structure avec ces objets et c'est regle. Tu peux meme t'amuser a ajouter les dependances entre champs apres (genre tu specifies que la longueur de ce champs texte est la valeur du champs d'avant, les checksums, etc...) voire la compression/encryption des champs.
Le jour ou t'as un champs totalement different, suffit de rajouter l'objet qui le represente.
Je t'assures que ca fonctionne tres tres bien, j'ai cree un systeme de ce type il y a des annees, et je l'utilises quasiment tous les jours, il represente sans problemes des formats plutot complexes(mp3, PNG, etc...) et cela assez facilement
[^] # Re: Mini-framework
Posté par David Decotigny (site web personnel) . Évalué à 1.
Ce que je verrais bien, c'est qu'après avoir décrit la structure de tes données sous la forme d'objets "champs" comme tu présentes, tu utilises cette description pour générer le code C++ "optimisé" qui définit de nouvelles classes coquilles (genre beans avec get_/set_ sur chacun des champs que tu as décrits). Ensuite tu utilises ces objets coquille pour travailler avec tes données brutes.
C'est un peu cette dernière approche "génération de code légère" que je recherche et je me demandais surtout si qqch comme cela existait déjà et était répandu.
[^] # Re: Mini-framework
Posté par pasBill pasGates . Évalué à 1.
Une fois cela fait, tu peux lire tes structs, et tu peux les generer en y mettant les valeurs que tu veux et t'as meme pas besoin de t'occuper de rafraichir les champs de longueur/checksum/compression ... quand tu changes les donnees avec un systeme pareil, l'appel a Generate sur l'objet pere se charge de tout.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.