Leute ihr seid echt genial! Auch nach Jahren bin ich immer wieder von der Aktivität und Hilfsbereitschaft der Community begeistert! (Und das obwohl ich kein Dauergast bin)
Danilo hat geschrieben:Code: Alles auswählen
NyblCharsToUnicodeChar(*a\c[-3],*a\c[-2],*a\c[-1],*a\c[0])
Wow, man kann negative Indizes verwenden?
@ Shardik: Wenn die 8 in
80 Microcomputing 8/1981 den Monat meint, dann hatte ich's leider verpasst. Mit 4 Monaten konnte ich noch nicht lesen...

Ansonsten: Geiler Code, wenn's auf Größe UND Geschwindigkeit ankommt! Nur leider gibt's da ein kleines Problem...
Code: Alles auswählen
---------------------------
PureBasic - Assembler error
---------------------------
PureBasic.asm [87]:
DAA
error: illegal instruction.
...scheint unter x64 nicht mehr zu funktionieren.

Seltsam... wurden im x64-Modus die BCD-Anweisungen deaktiviert? Kann doch eigentlich nicht sein, da die doch gerade für Stringumwandlungen ständig verwendet werden, oder?
PMV hat geschrieben:Ich hab das in meinem JSON-Parser ja recht einfach gelöst.
Dreimal darfst Du raten wofür ich meinen Parser (hauptsächlich) schreibe.

Ist das gute Stück Open Source? Wenn ja würde ich gerne mal spicken...
(Will aber schon meinen eigenen schreiben, Zwecks Lernerfolg)
@ NicTheQuick: direkt mit Quads zu arbeiten ist natürlich auch 'ne Idee!
Ich habe mal aus den ganzen Inspirationen versucht ein wiederverwertbares Modul zu stricken, was allerdings Probleme mit sich gebracht hat (siehe ganz unten). Um einen Initialisierungscode zu vermeiden arbeite ich mit zwei Übersetzungstabellen-Includes (Ascii und Unicode). Hier erst mal ein kleines Tool um diese zu erstellen (habe beim Pfadfehlerabfangen nur Windows berücksichtigt):
Code: Alles auswählen
EnableExplicit
Define *mem = AllocateMemory(65536)
If *mem=0 : CallDebugger : End : EndIf
Define i
FillMemory(*mem, 65536, #SUB, #PB_Byte)
For i = '0' To '9' : PokeA(*mem+i, i-'0' ) : Next
For i = 'A' To 'F' : PokeA(*mem+i, i-'A'+10) : Next
For i = 'a' To 'f' : PokeA(*mem+i, i-'a'+10) : Next
Define pfad$ = PathRequester("",#PB_Compiler_FilePath)
If pfad$=#NUL$ Or pfad$="\"
CallDebugger : End
EndIf
SetCurrentDirectory(pfad$)
If CreateFile(0,"NybleCharsToUnicodeChar.raw") = #False
CallDebugger : End
EndIf
WriteData(0,*mem,65536)
CloseFile(0)
If CreateFile(0,"NyblCharsToAsciiChar.raw") = #False
CallDebugger : End
EndIf
WriteData(0,*mem,256)
CloseFile(0)
Und hier der Hauptcode. Die Includes müssen sich im selben Verzeichnis befinden. Als Basis für den Test-Code habe ich einfach Danilos angepassten Code wiederum angepasst:
Code: Alles auswählen
DeclareModule CharacterConvert
CompilerSelect #PB_Compiler_Unicode
CompilerCase #True : Macro StrNyblToChar(n3, n2, n1, n0) : StrNyblToChar4(n3, n2, n1, n0) : EndMacro
CompilerCase #False : Macro StrNyblToChar(n3, n2, n1, n0) : StrNyblToChar2(n1, n0) : EndMacro
CompilerEndSelect
Declare.u StrNyblToChar4(n3, n2, n1, n0)
Declare.c StrNyblToChar2(n1, n0)
Declare.c StrNyblToChar1(n)
EndDeclareModule
Module CharacterConvert
EnableExplicit
Structure AsciiArray
a.a[0] ; reicht auch für Unicode (theoretisch würde 1 Nibble reichen, wenn's einfach adressierbar wäre)
EndStructure
Global *a.AsciiArray = ?CharTable
Procedure.u StrNyblToChar4(n3, n2, n1, n0)
ProcedureReturn *a\a[n3]<<12 | *a\a[n2]<<8 | *a\a[n1]<<4 | *a\a[n0]
EndProcedure
Procedure.c StrNyblToChar2(n1, n0)
ProcedureReturn *a\a[n1]<<4 | *a\a[n0]
EndProcedure
Procedure.c StrNyblToChar1(n)
ProcedureReturn *a\a[n]
EndProcedure
DataSection
CharTable:
CompilerIf #PB_Compiler_Unicode
IncludeBinary #PB_Compiler_FilePath + "NybleCharsToUnicodeChar.raw"
CompilerElse
IncludeBinary #PB_Compiler_FilePath + "NyblCharsToAsciiChar.raw"
CompilerEndIf
EndDataSection
EndModule
; ##### TEST-CODE #####
EnableExplicit
UseModule CharacterConvert
Structure CharacterArray
c.c[0]
EndStructure
Define a$ = "blablabla \u00d6 trulalala \u00C4 fideralala" ; <- \u#### = C-Escape-Sequenz für Unicode-Zeichen
;a$ = "c:\unicode" ; path
;a$ = "c:\u\u\u.file" ; path
;a$ = "\u01" ; 2-stellige Unicode-Zahl
;a$ = "\u" ; Ende des Strings
Define b$ = Space(Len(a$))
Define *a.CharacterArray = @a$
Define *b.Character = @b$
Define i, check
Define *temp
While *a\c
If *a\c = '\' And *a\c[1] = 'u'
*temp = *a
*a + SizeOf(Character) * 2
check = 0
While StrNyblToChar1( *a\c ) ! #SUB ; #SUB = Ersetzungszeichen (genutzt weil 0 vergeben)
check + 1 ; Hex char gefunden: check + 1
*a + SizeOf(Character) ; nächster char
Wend
If check = 4 ; 4 Hex chars gefunden
*a - SizeOf(Character)
*b\c = StrNyblToChar(*a\c[-3],*a\c[-2],*a\c[-1],*a\c[0]) ; bei Ascii wird das H.O.-Byte ignoriert
Else
*a = *temp ; keine 4 gültigen Hex chars gefunden
*b\c = *a\c ; normales kopieren
EndIf
Else
*b\c = *a\c
EndIf
*a + SizeOf(Character)
*b + SizeOf(Character)
Wend
*b\c = #NUL
Debug b$
Mir wurde schon oft gesagt ich solle nicht so "speichergeizig" sein, aber ist eine 64KB Include (Unicode) noch OK?
Leider ist der Modul-Code jetzt aber doch wieder etwas langsamer geworden, weil es ja kein "DeclareMacro" gibt und ich somit Prozeduren verwenden musste. Alternativ hätte ich noch ALLES in den DeclareModule-Block schreiben können, aber dann hätte ich ja wiederum das Modul-Prinzip ad absurdum geführt, da ALLES öffentlich wäre...
Irgendwie ist das unbefriedigend...
Hat jemand vielleicht eine kreative Idee?
Wenn nicht werde ich's wohl "klassisch" mit Kilometerlangen Unikatnamen machen müssen, denn SO habe ich mein "Sprunglosziel" verfehlt...