![]() |
Codeschnipsel von GO zu Delphi übersetzen.
Hallo Werte Delphianer,
ich hab hier ein paar Zeilen Code die in GO geschrieben sind. Ich möchte dies in meinem Delphi XE3 nachbilden. Mir fehlt das Verständnis für GO deswegen würde ich mich über Hilfe sehr freuen. GO Code: Adds non-Steam games that have been registered locally.
Code:
Der Code ist Opensource und hat zum Ziel für die Plattform Steam einen Unique Hash aus Dateipfad und Name zu berechnen.
// This information is in the file config/shortcuts.vdf, in binary format.
// It contains the non-Steam games with names, target (exe location) and // tags/categories. To create a grid image we must compute the Steam ID, which // is just crc32(target + label) + "02000000", using IEEE standard polynomials. func addNonSteamGames(user User, games map[string]*Game) { shortcutsVdf := filepath.Join(user.Dir, "config", "shortcuts.vdf") if _, err := os.Stat(shortcutsVdf); err != nil { return } shortcutBytes, err := ioutil.ReadFile(shortcutsVdf) if err != nil { return } // The actual binary format is known, but using regexes is way easier than // parsing the entire file. If I run into any problems I'll replace this. gamePattern := regexp.MustCompile("(?i)appname\x00(.+?)\x00\x01exe\x00(.+?)\x00\x01.+?\x00tags\x00(.*?)\x08\x08") tagsPattern := regexp.MustCompile("\\d\x00(.+?)\x00") for _, gameGroups := range gamePattern.FindAllSubmatch(shortcutBytes, -1) { gameName := gameGroups[1] target := gameGroups[2] uniqueName := bytes.Join([][]byte{target, gameName}, []byte("")) // Does IEEE CRC32 of target concatenated with gameName, then convert // to 64bit Steam ID. No idea why Steam chose this operation. top := uint64(crc32.ChecksumIEEE(uniqueName)) | 0x80000000 gameId := strconv.FormatUint(top<<32|0x02000000, 10) game := Game{gameId, string(gameName), []string{}, "", nil} games[gameId] = &game tagsText := gameGroups[3] for _, tagGroups := range tagsPattern.FindAllSubmatch(tagsText, -1) { tag := tagGroups[1] game.Tags = append(game.Tags, string(tag)) } } } Ich bin die Sache so angegangen das ich einen string mit crc32 gehashed habe. Das Ergebnis ist ein DWord mit 10 stellen. Im oberen Code wird daraus ein 64 bit Unisgned Integer gemacht. Hier fehlen mir die Kenntnisse. Wie bilde ich das in Delphi ab? Im Grunde möchte ich also die gameid ermitteln. Gruß |
AW: Codeschnipsel von GO zu Delphi übersetzen.
Zitat:
Delphi-Quellcode:
Ggf. musst du ein mit den Anzahl der Stellen bei der IntToHex-Funktion experimentieren.
var
Hash: IdHashCRC.TIdHashCRC32; uniqueName: string; gameID: string; HashedValue: UInt32; top: UInt64; begin uniqueName := 'Beispiel_Name'; Hash := TIdHashCRC32.Create; try HashedValue := Hash.HashValue(uniqueName); finally Hash.Free; end; top := HashedValue or $80000000; top := top shl 32 or $02000000; gameID := System.SysUtils.IntToHex(top, 10); gameID := System.SysUtils.LowerCase(gameID); end; Die Verwendung von LowerCase deswegen, weil die FormatUint-Funktion Kleinbuchstaben zurückliefert : ![]() |
AW: Codeschnipsel von GO zu Delphi übersetzen.
Danke erstmal für die Ausführungen,
leider komme ich auf nach wie vor falsche Ergebnisse. (immerhin jetzt aber wohl in 64 bit string;))
Code:
Diese Zeile bereitet mir Kopfschmerzen.
uniqueName := bytes.Join([][]byte{target, gameName}, []byte(""))
Ich habe das in Delphi einfach uniqueName := target+gameName und das Ergebnis dann gehashed. Eigenartiger weise bekomme ich in xe3 nach shl 32 or $02000000 oftmal negative Werte - wie kann das sein? Muss ich die Strings erst in ein ByteArray zerlegen und die Summen adderen? |
AW: Codeschnipsel von GO zu Delphi übersetzen.
Zitat:
Vielen hier, also auch mir, sind weder die Programmierung gegen die Steam-API noch die Programmiersprache Go bekannt, so dass wir ein bisschen mehr Informationen benötigen. Hier wäre eine Aufstellung nach "gegeben" und "gesucht" hilfreich. Also welche Eingangsparameter hast du und was erwartest du als Ausgangswert? Beispiele! Zitat:
Ich nahm an, das dies schon gelöst war. Zitat:
Ist dir klar was die Operatoren shl und or bewirken sollen? Hast du dich mit den Go-Quelltext mal auseinandergesetzt? Google bietet mit dem Playground ja die schnelle Möglichkeit des Ausprobierens: ![]() Teste doch mal folgenden Quelltext im Playground, vielleicht wird dir dann klarer, wie du weiter vorgehen musst.
Code:
package main
import ( "bytes" "fmt" ) func main() { target := []byte("Hello") gameName := []byte(" World!") uniqueName := bytes.Join([][]byte{target, gameName}, []byte("")) fmt.Println("uniqueName") fmt.Println(" ") fmt.Println("as byte array:") fmt.Println(uniqueName) fmt.Println(" ") fmt.Println("as string:") fmt.Println(string(uniqueName)) } |
AW: Codeschnipsel von GO zu Delphi übersetzen.
Zitat:
|
AW: Codeschnipsel von GO zu Delphi übersetzen.
Also,
im Grunde sind alle Probleme behoben. Byte.join setzt einfach nur einen String zusammen und setzt "" als Delimiter. Genau da lag das Problem. Das hab ich überlesen. Ich habe also einen inkorrekten string gehashed. shl 32 versetzt die bytes nach links um einen Uint64 erhalten. Das klappt soweit. Ich muss mich mehr mit den Typen wie int,uint,dword auseinandersetzen. Da hab ich deutlich nachhole Bedarf. Gelöst hab ich das nun wie oben im Beispiel von TiGü beschrieben.
Code:
Code ist hier in FreePascal so lauffähig und funktioniert.
function TForm1.HashIt(PathWithQuotesAndNameString : string) : string;
var //Hash: IdHashCRC.TIdHashCRC32; HashedValue: DWord; top111: UInt64; Hex : string; begin result := 'NO HASH'; //PathWithQuotesAndNameString := '"C:\Program Files\Games\Fifa 14\fifa14.exe"FIFA 14'; CalcStringCRC32(PathWithQuotesAndNameString, HashedValue); top111 := HashedValue or $80000000; top111 := top111 shl 32 or $02000000; result := IntToStr(top111); end; // Ergibt im Beispiel result = 10849726566762545152 Danke TiGü Ps. In XE3 nutze ich das Firemonkey Framework. Könnte da der Fehler in IntToStr(top111) mit den negativen Werten liegen? |
AW: Codeschnipsel von GO zu Delphi übersetzen.
Das liegt nicht an Firemonkey. Verwende lieber explizit UIntToStr.
|
AW: Codeschnipsel von GO zu Delphi übersetzen.
Zitat:
Nehme besser die UIntToStr-Funktion! Zu jedem Datentyp die passende Funktion wählen! |
AW: Codeschnipsel von GO zu Delphi übersetzen.
Also ich stehe inzwischen noch mehr auf dem Schlauch..
Code:
unit core;
{$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, StrUtils; const Table: array[0..255] of DWORD = ($00000000, $77073096, $EE0E612C, $990951BA, $076DC419, $706AF48F, $E963A535, $9E6495A3, $0EDB8832, $79DCB8A4, $E0D5E91E, $97D2D988, $09B64C2B, $7EB17CBD, $E7B82D07, $90BF1D91, $1DB71064, $6AB020F2, $F3B97148, $84BE41DE, $1ADAD47D, $6DDDE4EB, $F4D4B551, $83D385C7, $136C9856, $646BA8C0, $FD62F97A, $8A65C9EC, $14015C4F, $63066CD9, $FA0F3D63, $8D080DF5, $3B6E20C8, $4C69105E, $D56041E4, $A2677172, $3C03E4D1, $4B04D447, $D20D85FD, $A50AB56B, $35B5A8FA, $42B2986C, $DBBBC9D6, $ACBCF940, $32D86CE3, $45DF5C75, $DCD60DCF, $ABD13D59, $26D930AC, $51DE003A, $C8D75180, $BFD06116, $21B4F4B5, $56B3C423, $CFBA9599, $B8BDA50F, $2802B89E, $5F058808, $C60CD9B2, $B10BE924, $2F6F7C87, $58684C11, $C1611DAB, $B6662D3D, $76DC4190, $01DB7106, $98D220BC, $EFD5102A, $71B18589, $06B6B51F, $9FBFE4A5, $E8B8D433, $7807C9A2, $0F00F934, $9609A88E, $E10E9818, $7F6A0DBB, $086D3D2D, $91646C97, $E6635C01, $6B6B51F4, $1C6C6162, $856530D8, $F262004E, $6C0695ED, $1B01A57B, $8208F4C1, $F50FC457, $65B0D9C6, $12B7E950, $8BBEB8EA, $FCB9887C, $62DD1DDF, $15DA2D49, $8CD37CF3, $FBD44C65, $4DB26158, $3AB551CE, $A3BC0074, $D4BB30E2, $4ADFA541, $3DD895D7, $A4D1C46D, $D3D6F4FB, $4369E96A, $346ED9FC, $AD678846, $DA60B8D0, $44042D73, $33031DE5, $AA0A4C5F, $DD0D7CC9, $5005713C, $270241AA, $BE0B1010, $C90C2086, $5768B525, $206F85B3, $B966D409, $CE61E49F, $5EDEF90E, $29D9C998, $B0D09822, $C7D7A8B4, $59B33D17, $2EB40D81, $B7BD5C3B, $C0BA6CAD, $EDB88320, $9ABFB3B6, $03B6E20C, $74B1D29A, $EAD54739, $9DD277AF, $04DB2615, $73DC1683, $E3630B12, $94643B84, $0D6D6A3E, $7A6A5AA8, $E40ECF0B, $9309FF9D, $0A00AE27, $7D079EB1, $F00F9344, $8708A3D2, $1E01F268, $6906C2FE, $F762575D, $806567CB, $196C3671, $6E6B06E7, $FED41B76, $89D32BE0, $10DA7A5A, $67DD4ACC, $F9B9DF6F, $8EBEEFF9, $17B7BE43, $60B08ED5, $D6D6A3E8, $A1D1937E, $38D8C2C4, $4FDFF252, $D1BB67F1, $A6BC5767, $3FB506DD, $48B2364B, $D80D2BDA, $AF0A1B4C, $36034AF6, $41047A60, $DF60EFC3, $A867DF55, $316E8EEF, $4669BE79, $CB61B38C, $BC66831A, $256FD2A0, $5268E236, $CC0C7795, $BB0B4703, $220216B9, $5505262F, $C5BA3BBE, $B2BD0B28, $2BB45A92, $5CB36A04, $C2D7FFA7, $B5D0CF31, $2CD99E8B, $5BDEAE1D, $9B64C2B0, $EC63F226, $756AA39C, $026D930A, $9C0906A9, $EB0E363F, $72076785, $05005713, $95BF4A82, $E2B87A14, $7BB12BAE, $0CB61B38, $92D28E9B, $E5D5BE0D, $7CDCEFB7, $0BDBDF21, $86D3D2D4, $F1D4E242, $68DDB3F8, $1FDA836E, $81BE16CD, $F6B9265B, $6FB077E1, $18B74777, $88085AE6, $FF0F6A70, $66063BCA, $11010B5C, $8F659EFF, $F862AE69, $616BFFD3, $166CCF45, $A00AE278, $D70DD2EE, $4E048354, $3903B3C2, $A7672661, $D06016F7, $4969474D, $3E6E77DB, $AED16A4A, $D9D65ADC, $40DF0B66, $37D83BF0, $A9BCAE53, $DEBB9EC5, $47B2CF7F, $30B5FFE9, $BDBDF21C, $CABAC28A, $53B39330, $24B4A3A6, $BAD03605, $CDD70693, $54DE5729, $23D967BF, $B3667A2E, $C4614AB8, $5D681B02, $2A6F2B94, $B40BBE37, $C30C8EA1, $5A05DF1B, $2D02EF8D); type { TForm1 } TForm1 = class(TForm) ComputeButton: TButton; ResultBox: TEdit; PathEdit: TEdit; NameEdit: TEdit; Label1: TLabel; Label2: TLabel; Label3: TLabel; procedure ComputeButtonClick(Sender: TObject); private { private declarations } public function HashIt(PathWithQuotesAndNameString : string) : string; { public declarations } end; var Form1: TForm1; implementation {$R *.lfm} // Use CalcCRC32 as a procedure so CRCValue can be passed in but // also returned. This allows multiple calls to CalcCRC32 for // the "same" CRC-32 calculation. procedure CalcCRC32(p: Pointer; ByteCount: DWORD; var CRCValue: DWORD); // The following is a little cryptic (but executes very quickly). // The algorithm is as follows: // 1. exclusive-or the input byte with the low-order byte of // the CRC register to get an INDEX // 2. shift the CRC register eight bits to the right // 3. exclusive-or the CRC register with the contents of Table[INDEX] // 4. repeat steps 1 through 3 for all bytes var i: DWORD; q: ^BYTE; begin q := p; for i := 0 to ByteCount - 1 do begin CRCvalue := (CRCvalue shr 8) xor Table[q^ xor (CRCvalue and $000000FF)]; Inc(q) end end {CalcCRC32}; function CalcStringCRC32(s: string; out CRC32: DWORD): Boolean; var CRC32Table: DWORD; begin // Verify the table used to compute the CRCs has not been modified. // Thanks to Gary Williams for this suggestion, Jan. 2003. CRC32Table := $FFFFFFFF; CalcCRC32(Addr(Table[0]), SizeOf(Table), CRC32Table); CRC32Table := not CRC32Table; if CRC32Table <> $6FCF9E13 then ShowMessage('CRC32 Table CRC32 is ' + IntToHex(Crc32Table, 8) + ', expecting $6FCF9E13') else begin CRC32 := $FFFFFFFF; // To match PKZIP if Length(s) > 0 // Avoid access violation in D4 then CalcCRC32(Addr(s[1]), Length(s), CRC32); CRC32 := not CRC32; // To match PKZIP end; end; procedure TForm1.ComputeButtonClick(Sender: TObject); begin ResultBox.Text := HashIt(PathEdit.Text+NameEdit.Text); end; function TForm1.HashIt(PathWithQuotesAndNameString : string) : string; var //Hash: IdHashCRC.TIdHashCRC32; HashedValue: DWord; top111: UInt64; Hex : string; begin result := 'NO HASH'; //uniqueName := '"C:\Program Files\DEPOCAM 13.0\DEPOCAM.exe"DepoCam 13'; CalcStringCRC32(PathWithQuotesAndNameString, HashedValue); top111 := HashedValue or $80000000; top111 := top111 shl 32 or $02000000; result := IntToStr(top111); end; end. Läuft Perfekt unter Lazarus/FreePascal und bringt die richtigen Werte - ein UIntToStr ist mir hier nicht bekannt.
Code:
Jetzt das ganze nochmal unter XE3 und ich erhalte falsche Werte. Ich kann zwischen diesen beiden keinerlei Unterschiede außer UIntToStr und IntToStr feststellen,
unit Unit1;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TForm1 = class(TForm) ComputeButton: TButton; PathEdit: TEdit; NameEdit: TEdit; SteamIDEdit: TEdit; Label1: TLabel; Label2: TLabel; procedure ComputeButtonClick(Sender: TObject); private { Private-Deklarationen } public function HashIt(PathWithQuotesAndNameString : string) : string; { Public-Deklarationen } end; const Table: ARRAY[0..255] OF DWORD = ($00000000, $77073096, $EE0E612C, $990951BA, $076DC419, $706AF48F, $E963A535, $9E6495A3, $0EDB8832, $79DCB8A4, $E0D5E91E, $97D2D988, $09B64C2B, $7EB17CBD, $E7B82D07, $90BF1D91, $1DB71064, $6AB020F2, $F3B97148, $84BE41DE, $1ADAD47D, $6DDDE4EB, $F4D4B551, $83D385C7, $136C9856, $646BA8C0, $FD62F97A, $8A65C9EC, $14015C4F, $63066CD9, $FA0F3D63, $8D080DF5, $3B6E20C8, $4C69105E, $D56041E4, $A2677172, $3C03E4D1, $4B04D447, $D20D85FD, $A50AB56B, $35B5A8FA, $42B2986C, $DBBBC9D6, $ACBCF940, $32D86CE3, $45DF5C75, $DCD60DCF, $ABD13D59, $26D930AC, $51DE003A, $C8D75180, $BFD06116, $21B4F4B5, $56B3C423, $CFBA9599, $B8BDA50F, $2802B89E, $5F058808, $C60CD9B2, $B10BE924, $2F6F7C87, $58684C11, $C1611DAB, $B6662D3D, $76DC4190, $01DB7106, $98D220BC, $EFD5102A, $71B18589, $06B6B51F, $9FBFE4A5, $E8B8D433, $7807C9A2, $0F00F934, $9609A88E, $E10E9818, $7F6A0DBB, $086D3D2D, $91646C97, $E6635C01, $6B6B51F4, $1C6C6162, $856530D8, $F262004E, $6C0695ED, $1B01A57B, $8208F4C1, $F50FC457, $65B0D9C6, $12B7E950, $8BBEB8EA, $FCB9887C, $62DD1DDF, $15DA2D49, $8CD37CF3, $FBD44C65, $4DB26158, $3AB551CE, $A3BC0074, $D4BB30E2, $4ADFA541, $3DD895D7, $A4D1C46D, $D3D6F4FB, $4369E96A, $346ED9FC, $AD678846, $DA60B8D0, $44042D73, $33031DE5, $AA0A4C5F, $DD0D7CC9, $5005713C, $270241AA, $BE0B1010, $C90C2086, $5768B525, $206F85B3, $B966D409, $CE61E49F, $5EDEF90E, $29D9C998, $B0D09822, $C7D7A8B4, $59B33D17, $2EB40D81, $B7BD5C3B, $C0BA6CAD, $EDB88320, $9ABFB3B6, $03B6E20C, $74B1D29A, $EAD54739, $9DD277AF, $04DB2615, $73DC1683, $E3630B12, $94643B84, $0D6D6A3E, $7A6A5AA8, $E40ECF0B, $9309FF9D, $0A00AE27, $7D079EB1, $F00F9344, $8708A3D2, $1E01F268, $6906C2FE, $F762575D, $806567CB, $196C3671, $6E6B06E7, $FED41B76, $89D32BE0, $10DA7A5A, $67DD4ACC, $F9B9DF6F, $8EBEEFF9, $17B7BE43, $60B08ED5, $D6D6A3E8, $A1D1937E, $38D8C2C4, $4FDFF252, $D1BB67F1, $A6BC5767, $3FB506DD, $48B2364B, $D80D2BDA, $AF0A1B4C, $36034AF6, $41047A60, $DF60EFC3, $A867DF55, $316E8EEF, $4669BE79, $CB61B38C, $BC66831A, $256FD2A0, $5268E236, $CC0C7795, $BB0B4703, $220216B9, $5505262F, $C5BA3BBE, $B2BD0B28, $2BB45A92, $5CB36A04, $C2D7FFA7, $B5D0CF31, $2CD99E8B, $5BDEAE1D, $9B64C2B0, $EC63F226, $756AA39C, $026D930A, $9C0906A9, $EB0E363F, $72076785, $05005713, $95BF4A82, $E2B87A14, $7BB12BAE, $0CB61B38, $92D28E9B, $E5D5BE0D, $7CDCEFB7, $0BDBDF21, $86D3D2D4, $F1D4E242, $68DDB3F8, $1FDA836E, $81BE16CD, $F6B9265B, $6FB077E1, $18B74777, $88085AE6, $FF0F6A70, $66063BCA, $11010B5C, $8F659EFF, $F862AE69, $616BFFD3, $166CCF45, $A00AE278, $D70DD2EE, $4E048354, $3903B3C2, $A7672661, $D06016F7, $4969474D, $3E6E77DB, $AED16A4A, $D9D65ADC, $40DF0B66, $37D83BF0, $A9BCAE53, $DEBB9EC5, $47B2CF7F, $30B5FFE9, $BDBDF21C, $CABAC28A, $53B39330, $24B4A3A6, $BAD03605, $CDD70693, $54DE5729, $23D967BF, $B3667A2E, $C4614AB8, $5D681B02, $2A6F2B94, $B40BBE37, $C30C8EA1, $5A05DF1B, $2D02EF8D); var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.ComputeButtonClick(Sender: TObject); begin SteamIDEdit.Text := HashIt(PathEdit.Text+NameEdit.Text); end; // Use CalcCRC32 as a procedure so CRCValue can be passed in but // also returned. This allows multiple calls to CalcCRC32 for // the "same" CRC-32 calculation. procedure CalcCRC32(p: Pointer; ByteCount: DWORD; var CRCValue: DWORD); // The following is a little cryptic (but executes very quickly). // The algorithm is as follows: // 1. exclusive-or the input byte with the low-order byte of // the CRC register to get an INDEX // 2. shift the CRC register eight bits to the right // 3. exclusive-or the CRC register with the contents of Table[INDEX] // 4. repeat steps 1 through 3 for all bytes var i: DWORD; q: ^BYTE; begin q := p; for i := 0 to ByteCount - 1 do begin CRCvalue := (CRCvalue shr 8) xor Table[q^ xor (CRCvalue and $000000FF)]; Inc(q) end end {CalcCRC32}; function CalcStringCRC32(s: string; out CRC32: DWORD): Boolean; var CRC32Table: DWORD; begin // Verify the table used to compute the CRCs has not been modified. // Thanks to Gary Williams for this suggestion, Jan. 2003. CRC32Table := $FFFFFFFF; CalcCRC32(Addr(Table[0]), SizeOf(Table), CRC32Table); CRC32Table := not CRC32Table; if CRC32Table <> $6FCF9E13 then ShowMessage('CRC32 Table CRC32 is ' + IntToHex(Crc32Table, 8) + ', expecting $6FCF9E13') else begin CRC32 := $FFFFFFFF; // To match PKZIP if Length(s) > 0 // Avoid access violation in D4 then CalcCRC32(Addr(s[1]), Length(s), CRC32); CRC32 := not CRC32; // To match PKZIP end; end; function TForm1.HashIt(PathWithQuotesAndNameString : string) : string; var HashedValue: DWord; top111: UInt64; begin result := 'NO HASH'; CalcStringCRC32(PathWithQuotesAndNameString, HashedValue); top111 := HashedValue or $80000000; top111 := top111 shl 32 or $02000000; result := UIntToStr(top111); end; end. hat da jemand Rat und vorallem warum ist das so? |
AW: Codeschnipsel von GO zu Delphi übersetzen.
Zitat:
Was für Werte erhälst du denn jeweils bei welchen Eingangswerten? Kennst du dich mit Debuggen aus? Gehe in jeder IDE Schritt für Schritt durch und vergleiche bspw. ob HashedValue von der jeweiligen CalcStringCRC32 Version korrekt und gleich gebildet wird. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:36 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz