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

 Delphi Discussion :

[D7] conversion d'un Array of AnsiChar


Sujet :

Delphi

  1. #1
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 344
    Points : 3 119
    Points
    3 119
    Par défaut [D7] conversion d'un Array of AnsiChar
    Bonjour,

    Question de débutant :
    je voudrais faire une fonction qui converti A, un Array of AnsiChar en Int64 :

    Par exemple :

    A : D0 D6 02 00 codé en little-endian soit 00 02 D6 D0 à traduire en Int64

    Je dois donc faire :

    0 * 1 + 13 * 16 + 6 * 16^2 + 13 * 16^3 + 2 * 16^4 ==> 186064

    Je dois donc convertir D0 soit Ord(A[0] = 208 en 13 * 16 + 0
    ou D6 soit Ord[A[1] = 214 en 13 * 16 + 6
    ...

    Est ce qu'il n'y a pas une méthode plus simple ou une fonction toute faite en D7 ?

    Merci
    A+
    Charly

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    tu veux dire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      i := StrToInt('$D0D60200');
    ?
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 344
    Points : 3 119
    Points
    3 119
    Par défaut
    Oui, c'est ça j'ai bricolé ceci :

    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    { =================================================================== }
    Function Byte2Hexa(Val: Byte) : String;
    Var
      h   : string ;
      h2  : string ;
      n   : integer ;
      b   : integer ;
    Begin
      b := Val Mod 16 ;
      n := Val div 16   ;
      Case b of
              0 : h := '0';
              1 : h := '1';
              2 : h := '2';
              3 : h := '3';
              4 : h := '4';
              5 : h := '5';
              6 : h := '6';
              7 : h := '7';
              8 : h := '8';
              9 : h := '9';
              10 : h := 'A';
              11 : h := 'B';
              12 : h := 'C';
              13 : h := 'D';
              14 : h := 'E';
              15 : h := 'F';
      End;
      Case n of
              0 : h2 := '0';
              1 : h2 := '1';
              2 : h2 := '2';
              3 : h2 := '3';
              4 : h2 := '4';
              5 : h2 := '5';
              6 : h2 := '6';
              7 : h2 := '7';
              8 : h2 := '8';
              9 : h2 := '9';
              10 : h2 := 'A';
              11 : h2 := 'B';
              12 : h2 := 'C';
              13 : h2 := 'D';
              14 : h2 := 'E';
              15 : h2 := 'F';
      End;
      Result := h2 + h ;
     end;
    { ======================================================================== }
    Function TailleFich( Const a: Array of Char) : String ;
    Var
      L   : Integer ;
      Ch  : String ;
      i   : Integer ;
      Res : Int64 ;
    Begin
      L := Length(a) ;
      if L = 4 Then
        Begin
          Ch := '$' ;
          For i := L-1 DownTo 0 Do
            Begin
              Ch := Ch + Byte2Hexa(Ord(a[i])) ;
            End ;
          Res := StrToInt64(Ch) ;
          Result := IntToStr(Res) ;
        End
      else
        Result := '0';
    End ;
     
    { ======================================================================== }
    pour obtenir la chaine '0002D6D0' que je converti en entier

    mais je dois n’emmêler les pinceaux ?

    A+
    Charly

  4. #4
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Bonjour,

    2 approches 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
    function ByteSwap(const a: integer): integer;
    asm
      bswap eax
    end;
     
    procedure TForm4.Button3Click(Sender: TObject);
    var
      A: string;
      Ap: array of AnsiChar;
    begin
      SetLength(A, 4);
      SetLength(Ap, 4);
      A := #$D0 + #$D6 + #$02 + #$00;
      string(Ap) := #$00 + #$02 + #$D6 + #$D0;
      Caption := IntToStr(PInt64(pbyte(@A[1]))^);
      Caption := Caption + '  ' + IntToStr(ByteSwap(PInt64(pbyte(@string(Ap)[1]))^));
    end;
    si ça peut aider

    Cordialement,

    @+

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 844
    Points
    24 844
    Par défaut
    Citation Envoyé par Charly910 Voir le message
    mais je dois n’emmêler les pinceaux ?
    Nous aussi
    As-tu un tableau qui contient déjà un binaire donc "Array of AnsiChar" dont chaque octet correspond à une valeur numérique de 0 à 255
    ou alors plutôt un tableau qui contient un texte donc "Array of AnsiChar" dont chaque couple d'octet contient un duo de caractère de '0' à 'F'

    Dans SysUtils
    Non parce que BinToHex et HexToBin font le travail de conversion de base
    Il y a aussi IntToHex et la petite subtilité de StrToInt qui comme le souligne Paul TOTH, le préfixe $ permet le support de Hexadécimal au lieu d'un Décimal
    D'ailleurs, le préfixe '0x' est aussi supporté pour être plus générique car c'est une notation hexa plus répandu que $D0D60200 ou 0$D0D60200 soit 0xD0D60200


    Faudrait voir ce qui appelle "TailleFich" car je devine un code inutilement compliqué


    Pour complèter le ByteSwap


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function ByteSwap(const a : Int64) : int64;
    asm
    {$IFDEF CPUX64}
      BSWAP RCX;
      MOV RAX, RCX;
    {$ELSE}
      MOV EDX,[EBP+$08];
      MOV EAX,[EBP+$0C];
      BSWAP EAX;
      BSWAP EDX;
    {$ENDIF CPUX64}
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  6. #6
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 344
    Points : 3 119
    Points
    3 119
    Par défaut
    Merci

    @Cirec : oui, je connais le fonction ByteSwap que j'ai vu sur le net . Je vais tester ton code qui est beaucoup plus simple que le mien

    @Shai : oui, mon code est surement trop compliqué, mais il fonctionne. J'appelle la fonction TailleFich comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      ShowMessage(Format('Taille du fichier : %s octets',[TailleFich(Taille1)]) ;
    Taille1 étant un Array[0..3] of AnsiChar

    Bien sûr je pourrai aussi laisser TailleFic en Integer ce qui éviterai une conversion inutile.


    A+
    Charly

  7. #7
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    Citation Envoyé par Charly910 Voir le message
    Merci


    Taille1 étant un Array[0..3] of AnsiChar

    Bien sûr je pourrai aussi laisser TailleFic en Integer ce qui éviterai une conversion inutile.
    euh la question serait plutôt pourquoi le déclares-tu comme un array of ansichar ?!

    sinon Integer(Taille1) suffit également si c'est effectivement un Integer
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  8. #8
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 344
    Points : 3 119
    Points
    3 119
    Par défaut
    la fonction de Cirec marche bien, mais pas avec le ByteSwap de Shai ?

    A+
    Charly

  9. #9
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 344
    Points : 3 119
    Points
    3 119
    Par défaut
    Je lis un fichier binaire caractère par caractère et j'en extrait des portions (mes Array of AnsiChar)

    A+
    Charly

  10. #10
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 844
    Points
    24 844
    Par défaut
    Citation Envoyé par Charly910 Voir le message
    Je lis un fichier binaire caractère par caractère et j'en extrait des portions (mes Array of AnsiChar)
    Suffit de lire le buffer d'un seul coup, avec des record (packed), tout le parsage pourra être fait sans effort si le format binaire est bien défini

    Avec un Integer, suffit de le lire d'un coup
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Stream.ReadRead(MonInteger, SizeOf(MonInteger));
    FileRead(MonFichier, MonInteger, SizeOf(MonInteger));
    BlockRead(MonFichier, MonInteger, SizeOf(MonInteger));
    Citation Envoyé par Charly910 Voir le message
    la fonction de Cirec marche bien, mais pas avec le ByteSwap de Shai ?
    Version 64Bits et sur un compilateur D10S ... que l'ancien D7 ne soit pas compatible, rien de surprenant


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Array[0..3] of AnsiChar
    c'est soit Integer ou un Cardinal mais pourquoi parler de Int64 ?
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  11. #11
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 344
    Points : 3 119
    Points
    3 119
    Par défaut
    Oui c'est un integer et non un int64.

    En fait, je charge le fichier dans un TMemoryStream, puis je lis des records de Array of Char que je traite ensuite.

    Pour TailleFic, je vais conserver la version de Cirec qui est beaucoup compacte que la mienne !

    Mon problème est résolu, merci

    A+
    Charly

  12. #12
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Version 64Bits et sur un compilateur D10S ... que l'ancien D7 ne soit pas compatible, rien de surprenant
    mais le code ne fonctionne pas en D10.3 en 32bits !
    d'ailleurs le simple fait de passer Result de Integer en Int64 (sur ma fonction ByteSwap) fausse le résultat !

    autre surprise j'étais habitué à ce que:
    tout ce que le compilateur de D7 acceptait était de fait accepté par les compilateurs suivants !! (sauf pour le passage à l'UNICODE évidement)
    ben il semblerait que non

    Ainsi en D7 je peux faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    var
      Ap: array of AnsiChar;
    begin
      {Version D7}
      SetLength(Ap, 4);
      AnsiString(Ap) := #$00 + #$02 + #$D6 + #$D0;
      Caption := Caption + '  ' + IntToStr(ByteSwap(PInt(@AnsiString(Ap)[1])^));
    end;
    Mais le code plante en D10 (opération de pointeur incorrecte)

    et inversement ce code passe en D10 et plante en D7 (violation d'accès mais affiche quand même la bonne réponse !!!)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    var
      Ap: array of AnsiChar;
    begin
      {Version D10.3}
      SetLength(Ap, 4);
      PAnsiChar(Ap) := #$00 + #$02 + #$D6 + #$D0;
      Caption := Caption + '  ' + IntToStr(ByteSwap(PInt(@Ap[0])^));
    end;
    donc ici il n'y pas d'inter-compatibilité pour un code simple pour ne pas dire de base !!!
    Mais j'ai peut être loupé un truc

    si quelqu'un a une idée ...

    Cordialement,

    @

  13. #13
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 844
    Points
    24 844
    Par défaut
    Perso, je n'ai rien fait d'aussi compliqué, et cela fonctionne en D10S 32/64

    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
    function ByteSwap(const a : Int64) : int64;
    asm
    {$IFDEF CPUX64}
      BSWAP RCX;
      MOV RAX, RCX;
    {$ELSE}
      MOV EDX,[EBP+$08];
      MOV EAX,[EBP+$0C];
      BSWAP EAX;
      BSWAP EDX;
    {$ENDIF CPUX64}
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      ShowMessage(IntToHex(ByteSwap($00010021), 16));
      ShowMessage(IntToHex(ByteSwap(ByteSwap($00010021)), 16));
    end;

    Si l'on maitrise l'ASM pourquoi pas mais l'utiliser en général, c'est assez imprudent, mieux vaut un code pascal plus simple ...
    et évitez des manipulations de pointeurs si l'on peut faire plus simple,
    j'ai pu voir des codes D7 en PChar qui performait à l'époque et réécrit en code tout simple était bien meilleur en D10 32Bits voire excellent en 64Bits, le compilateur, la RTL, le gestionnaire de mémoire ayant fait de chemin depuis que nos optimisations ne le sont plus du tout.


    Sinon, je reste persuadé que ce sujet pourrait être résolu par une lecture de l'entier en une seule passe
    Faudrait voir le fichier binaire et sa structure mais on peut optimiser les lectures binaires de façon surprenante
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  14. #14
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 679
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 679
    Points : 13 083
    Points
    13 083
    Par défaut
    Citation Envoyé par Cirec Voir le message
    si quelqu'un a une idée ...
    Dans le premier cas, il serait logique que AnsiString(Ap) := veuille écrire l'entête de la chaîne à l'offset-8 => VA. Cette entête (compteur de référence et longueur) n'existait pas sous D7.

    Dans le deuxième cas, le comportement n'est pas celui que tu crois

    #$00 + #$02 + #$D6 + #$D0 est une constante et sous D10 PAnsiChar(Ap) := va modifier le pointeur Ap pour qu'il pointe sur cette constante. SetLength(Ap, 4) est inutile et va au contraire entraîner un memory leak.

    Plus difficile à dire ce qui se passe sous D7 (pas installé chez moi) mais le pointeur est peut-être simplement le résultat de cette adition.

    A noter que toutes ces conversions sont inutiles : IntToStr(PInt(Ap)^) devrait suffire.

  15. #15
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 344
    Points : 3 119
    Points
    3 119
    Par défaut
    Très intéressant tout ceci, mais finalement je vais au plus simple et qui fonctionne partout ;

    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
    29
    30
    { =================================================================== }
    Function Byte2Hexa(Const Val: Byte) : String;
    Const
      Lettre : Array[0..15] of String = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F') ;
    Var
      n, b   : integer ;
    Begin
      b := Val Mod 16 ;
      n := Val div 16   ;
      Result := Lettre[n] + Lettre[b] ;
     end;
    { ======================================================================== }
    Function TailleFich( Const a: Array of Char) : Integer ;
    Var
      L   : Integer ;
      Ch  : String ;
      i   : Integer ;
    Begin
      L := Length(a) ;
      if L = 4 Then
        Begin
          Ch := '$' ;
          For i := L-1 DownTo 0 Do
              Ch := Ch + Byte2Hexa(Ord(a[i])) ;
          Result := StrToIntDef(Ch, 0) ;
        End
      else
        Result :=  0 ;
    End ;
    { ======================================================================== }
    Comme ça pas de problème de pointeurs qui pointent un peu partout

    A+
    Charly

  16. #16
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Perso, je n'ai rien fait d'aussi compliqué, et cela fonctionne en D10S 32/64

    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
    function ByteSwap(const a : Int64) : int64;
    asm
    {$IFDEF CPUX64}
      BSWAP RCX;
      MOV RAX, RCX;
    {$ELSE}
      MOV EDX,[EBP+$08];
      MOV EAX,[EBP+$0C];
      BSWAP EAX;
      BSWAP EDX;
    {$ENDIF CPUX64}
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      ShowMessage(IntToHex(ByteSwap($00010021), 16));
      ShowMessage(IntToHex(ByteSwap(ByteSwap($00010021)), 16));
    end;

    Si l'on maitrise l'ASM pourquoi pas mais l'utiliser en général, c'est assez imprudent, mieux vaut un code pascal plus simple ...
    et évitez des manipulations de pointeurs si l'on peut faire plus simple,
    j'ai pu voir des codes D7 en PChar qui performait à l'époque et réécrit en code tout simple était bien meilleur en D10 32Bits voire excellent en 64Bits, le compilateur, la RTL, le gestionnaire de mémoire ayant fait de chemin depuis que nos optimisations ne le sont plus du tout.


    Sinon, je reste persuadé que ce sujet pourrait être résolu par une lecture de l'entier en une seule passe
    Faudrait voir le fichier binaire et sa structure mais on peut optimiser les lectures binaires de façon surprenante
    j'aurais du y penser,
    ton code est bon
    pour qu'il donne "le bon résultat" quand on a besoin d'un Integer et non d'un Int64 il faut le prévoir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      ShowMessage(IntToStr(ByteSwap($D0D6020000000000)));
      // ou encore
      ShowMessage(IntToHex(ByteSwap($D0D60200)shr 32));
    l'ASM je suis pas fan mais pour un swap sur un entier on risque rien

    ici les pointeurs m'ont permis de fournir un exemple qui respecte les conditions de départ
    à savoir traiter l'info à partir d'un array of AnsiChar.
    Il est vrai que le compilateur fournit un code de plus en plus performant
    mais c'est sans compter sur de vielles habitudes de programmations qui ont la vie dure

    Et je suis du même avis la lecture directe dans un entier serait plus simple.

    Cordialement,

    @+

  17. #17
    Membre actif
    Homme Profil pro
    libre
    Inscrit en
    Juin 2019
    Messages
    205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : libre

    Informations forums :
    Inscription : Juin 2019
    Messages : 205
    Points : 292
    Points
    292
    Par défaut Charly
    Très intéressant tout ceci, mais finalement je vais au plus simple et qui fonctionne partout ;
    Tu peux utiliser la structure LongRec ou Int64Rec pour inverser manuellement l'ordre des octets.

    un truc du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
       with LongRec(Result) do
       begin
         Bytes[3]:=Ord(a[0]));
         Bytes[2]:=Ord(a[1]));
         Bytes[1]:=Ord(a[2]));
         Bytes[0]:=Ord(a[3]));
       end;

  18. #18
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Dans le premier cas, il serait logique que AnsiString(Ap) := veuille écrire l'entête de la chaîne à l'offset-8 => VA. Cette entête (compteur de référence et longueur) n'existait pas sous D7.

    Dans le deuxième cas, le comportement n'est pas celui que tu crois

    #$00 + #$02 + #$D6 + #$D0 est une constante et sous D10 PAnsiChar(Ap) := va modifier le pointeur Ap pour qu'il pointe sur cette constante. SetLength(Ap, 4) est inutile et va au contraire entraîner un memory leak.

    Plus difficile à dire ce qui se passe sous D7 (pas installé chez moi) mais le pointeur est peut-être simplement le résultat de cette adition.

    A noter que toutes ces conversions sont inutiles : IntToStr(PInt(Ap)^) devrait suffire.
    @Andnotor:
    Merci pour ton éclaircissement
    pour le premier cas je me doutais bien qu'il y avait quelque chose de ce style.

    Mais en ce qui concerne le deuxième tu as entièrement raison
    ce n'est pas le comportement que je croyais!
    je ne m'attendais pas à créer une fuite de mémoire ici !!!!

    Tu viens de jeter un pavé dans ma mare
    Mais tout ceci m'étonne quand même !
    utiliser un tableau dynamique sans l'initialiser revient à le transformer en pointeur !
    tu me diras si je me trompe encore,
    d'ailleurs on ne peut plus y accéder en tant que tableau (Ex. Length(Ap) renvoi un truc farfelu et Ap[0] provoque une violation d'accès)

    dans ce cas il serait plus simple et plus lisible d'utiliser un pointeur
    et du coup le code devient compatible de D7 à D10.3:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    var
      App: Pointer;
     begin
      PAnsiChar(App) := #$00 + #$02 + #$D6 + #$D0;
      Caption := Caption + '  ' + IntToStr(ByteSwap(PInt(App)^));
    end;
    Tout comme ce code également compatible de D7 à D10.3
    en utilisant un array of AnsiChar en tant que tel:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    var
      Ap: array of AnsiChar;
    begin
      SetLength(Ap, 4);
      Move(PAnsiChar(#$00 + #$02 + #$D6 + #$D0)^, Ap[0], 4);
      Caption := Caption + '  ' + IntToStr(ByteSwap(PInt(Ap)^));
    end;
    pour le dernier point je ne sais pas pourquoi je continue à faire ces conversions de manière explicite
    alors que le compilateur le fait implicitement
    je ne sais même pas si elles ont été nécessaires à une époque
    je dirais que c'est l'expression du cheminement, issue de mon cerveau, que le compilateur doit emprunter afin
    d'arriver au résultat que je souhaite.

    en tous cas merci pour tes explications

    Cordialement,

    @+

  19. #19
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 679
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 679
    Points : 13 083
    Points
    13 083
    Par défaut
    Citation Envoyé par Cirec Voir le message
    utiliser un tableau dynamique sans l'initialiser revient à le transformer en pointeur !
    Un tableau dynamique est un pointeur et il n'existera que lorsqu'on lui aura donné une certaine taille.


    Après, D7 je ne m'en préoccupe plus trop

    Actuellement, on l'écrirait ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    var
      Ap: array of AnsiChar;
     
    begin
      Ap := [#$00, #$02, #$D6, #$D0];
    end;

  20. #20
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 344
    Points : 3 119
    Points
    3 119
    Par défaut
    Sous D7 seul ceci compile :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Var
      Ap: Set of AnsiChar;
    Begin
      Ap := [#$00, #$02, #$D6, #$D0];
    End ;
    A+
    Charly

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [RegEx] Trier une conversation dans un array
    Par shonan dans le forum Langage
    Réponses: 1
    Dernier message: 12/12/2011, 16h47
  2. [Toutes versions] conversion doc -> pdf -> array byte
    Par Horny2 dans le forum VBA Word
    Réponses: 2
    Dernier message: 18/05/2009, 14h19
  3. conversion d'un Array List vers un type de donnée
    Par msahli3 dans le forum Windows Forms
    Réponses: 2
    Dernier message: 19/03/2009, 17h44
  4. Créer un array of AnsiChar d'un String
    Par Nulenprogra dans le forum Langage
    Réponses: 6
    Dernier message: 03/07/2008, 12h55
  5. Comment transformer "array of ansiChar" en "ansiString" ?
    Par SchpatziBreizh dans le forum Langage
    Réponses: 2
    Dernier message: 24/07/2005, 02h12

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