besoin d'encoder et de décoder l'octet-flux (contenant des caractères non ascii éventuellement), de / dans UINT16, UINT32, UINT64 (leur signification typique C / C ++), prenant soin de l'endansion. Qu'est-ce qu'un moyen de plate-forme inter-plate-forme efficace et d'espoir à faire une telle chose à Lua? P>
My Target Arch est 64 bits X86_64, mais je voudrais le garder portable (si cela ne m'a pas coûté sur le front de performance). P>
E.g. P>
décodage (dire actuellement dans une chaîne Lua) - 0x00, 0x1d, 0xFF, 0x23, 0x44, 0x32 (Petite Endian) comme - uint16: (0x1d00) = 7424 uint32: (0x324423ff) = 843326463 P>
serait formidable si quelqu'un peut expliquer avec un exemple. p>
3 Réponses :
pour la conversion des octets à l'INT (en prenant soin de l'endansement au niveau des octets et de la signature): et pendant que nous sommes aussi l'autre direction: P> < PRE> XXX PRE> Toutes les remarques sont les bienvenues, il est testé, mais pas trop soigneusement ... p> p>
Très pédagogique. Il me semble avoir appris une charge de Lua à travers votre exemple illustratif, sérieusement.
En fonction de la fonction bytes_to_int, la ligne n = (n> 2 ^ (# t-1) -1) et (n-2 ^ # t) ou n je pense que cela devrait être # t * 8 à la place ou #t. Est le nombre de bits que vous voulez, pas d'octets.
Il semble que tu as raison! Merci pour la suggestion, je l'ai corrigé dans ma réponse.
@jpjacobs - merci beaucoup. Fonction INT_TO_BYTES a également besoin de correction lors de la gestion des numéros signés: si signé et num <0 puis b>, la ligne suivante 2 ^ n b> doit être num = num + 2 ^ ( 8 * n) b>
int_to_bytes b> ne manipule pas toujours les numéros signés correctement (lorsque exp de frexp est multiple de 8). Par exemple, -32769 B> doit être 0xFF 0XFF 0xFF 0x00 0x00 B>, mais la fonction telle qu'elle est renvoie 0x7f 0xFF b>.
De plus, pour les chiffres dépassant 16 bits, int_to_bytes b> ne renvoie pas nécessairement un nombre même d'octets, de sorte que le résultat pour les numéros signés ne peut pas être portable à d'autres applications (par exemple, pour un numéro signé dans Big Endian retour dans 3 octets, le premier octet est supposé être 0x00 au lieu de 0xFF). Ma solution pour les deux problèmes manque d'élégance concise du code ci-dessus ... peut-être qu'un véritable programmeur peut aider!
Jetez un oeil à la struct et LPACK bibliothèques.
Dans cet exemple, j'utilise le structure.unpack code> Pour décoder une chaîne Lua en deux entiers avec codage de petite endan forcé: p>
Semble très simple et élégant, mais je ne semble pas avoir un module d'extension «Struct». Luarocks échoue à bâtir / l'installer avec une erreur. Va essayer de résoudre ça et d'essayer ceci. Merci!
@ Michal-Kottman, essayé le code après avoir fixé des Luarocks et installer 'Struct' mais pour les berceaux Lua sur le deuxième paramètre à déballer (c'est-à-dire STR) ne pas être une chaîne. Pour déboguer, j'ai essayé ce petit code (qui ne berce pas, mais ne semble pas fonctionner comme prévu non plus - > str = string.char (0x00, 0xff) code>
> local u16 = struct.unpack ('
> print (u16) code>
nil code>
@ Michal-Kottman, désolé! corrigé ça. Un léger changement était nécessaire à Lua 5.1 (au moins sur mon système). Il suffit de faire un: struct = nécessite ("struct") code>
Étrange, j'ai testé le code présenté comme à Lua 5.1, et cela a fonctionné correctement (peut-être que j'ai eu une version plus ancienne de struct code>), mais je suis content que cela fonctionne pour vous maintenant, c'est un très Outil pratique pour les données binaires ...
Ma suggestion pour un «INT16TOBYTE» -Fonction sans vérification des paramètres:
function Int16ToBytes(num, endian) if num < 0 then num = num & 0xFFFF end highByte = (num & 0xFF00) >> 8 lowByte = num & 0xFF if endian == "little" then lowByte, highByte = highByte, lowByte end return string.char(highByte,lowByte) end