Schnelles Konvertieren von Hex-Nibbles in Character

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Regenduft
Beiträge: 574
Registriert: 25.03.2008 15:07
Wohnort: THE LÄÄÄND!

Schnelles Konvertieren von Hex-Nibbles in Character

Beitrag von Regenduft »

Hi liebe Leutz,

ich schreibe gerade einen Parser wo ich möglichst flott Escape-Sequenzen - genauer "\u[Hexwert]" und "\x[Hexwert]" - ersetzen will. Mit ein bisschen Hirnschmalz habe ich das ganze ohne Sprünge hinbekommen und zwei Makros draus geschustert. Diese wollte ich hiermit zum einen der PB-Gemeinde zur Verfügung stellen und zum anderen fragen was die "Vollprofies" hier davon halten, d.h. ob jemand z.B. Fehler oder Optimierungsmöglichkeiten sieht.

Der Testcode stellt übrigens nicht meinen Parser dar, sondern ist wirklich nur ein Testcode! <)
Für korrekte Ergebnisse bitte als Unicode-Executeable kompilieren!

Code: Alles auswählen

Macro NyblCharsToUnicodeChar(n3, n2, n1, n0)
  (((n3)&$F|((n3)&$40)>>3+(n3)>>6)<<12|((n2)&$F|((n2)&$40)>>3+(n2)>>6)<<8|((n1)&$F|((n1)&$40)>>3+(n1)>>6)<<4|((n0)&$F|((n0)&$40)>>3+(n0)>>6))
EndMacro

Macro NyblCharsToAsciiChar(n1, n0)
  (((n1)&$F|((n1)&$40)>>3+(n1)>>6)<<4|((n0)&$F|((n0)&$40)>>3+(n0)>>6))
EndMacro


; ##### TEST-CODE #####

EnableExplicit

Structure CharacterArray
  c.c[0]
EndStructure

Define a$ = "blablabla \u00D6 trulalala \u00C4 fideralala" ; <- \u#### = C-Escape-Sequenz für Unicode-Zeichen
Define b$ = Space(Len(a$))
Define *a.CharacterArray = @a$
Define *b.Character = @b$
Define i, check

While *a\c
  
  If *a\c = '\' And *a\c[1] = 'u'
  
    check = 0
    For i = 2 To 5
      Select *a\c[i] | $20
      Case '0' To '9', 'a' To 'f'
        check + 1
      Default
        Break
      EndSelect
    Next
    
    If check = 4
      *b\c = NyblCharsToUnicodeChar(*a\c[2],*a\c[3],*a\c[4],*a\c[5])
      *a + SizeOf(Character)*5
    EndIf
    
  Else
    
    *b\c = *a\c
    
  EndIf
  
  *a + SizeOf(Character)
  *b + SizeOf(Character)
  
Wend
*b\c = #NUL

Debug b$
PureBasic 5.73 LTE x86/x64 | Windows 7 (x64)
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Schnelles Konvertieren von Hex-Nibbles in Character

Beitrag von Danilo »

Code: Alles auswählen

  If check = 4
      *b\c = NyblCharsToUnicodeChar(*a\c[2],*a\c[3],*a\c[4],*a\c[5])
      *a + SizeOf(Character)*5
    EndIf
Wenn check <>4, dann geht Text verloren. Probier mal folgende Eingaben:

Code: Alles auswählen

a$ = "c:\unicode"    ; path
a$ = "c:\u\u\u.file" ; path
a$ = "\u01"          ; 2-stellige Unicode-Zahl
a$ = "\u"            ; Ende des Strings
Oder falls Du doppeltes Backslash verwendest:

Code: Alles auswählen

a$ = "c:\\unicode\\"
Ob Du die 2 Macros noch verstehen wirst, wenn Du ein paar Monate nicht mehr an dem Projekt gearbeitet hast? ;)

Code: Alles auswählen

Macro NyblCharsToUnicodeChar(n3, n2, n1, n0)
  (((n3)&$F|((n3)&$40)>>3+(n3)>>6)<<12|((n2)&$F|((n2)&$40)>>3+(n2)>>6)<<8|((n1)&$F|((n1)&$40)>>3+(n1)>>6)<<4|((n0)&$F|((n0)&$40)>>3+(n0)>>6))
EndMacro

Macro NyblCharsToAsciiChar(n1, n0)
  (((n1)&$F|((n1)&$40)>>3+(n1)>>6)<<4|((n0)&$F|((n0)&$40)>>3+(n0)>>6))
EndMacro
Hast Du die Geschwindigkeit schon gegenüber anderen Versionen getestet? Mit so vielen Shifts, &, |, ...
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
Regenduft
Beiträge: 574
Registriert: 25.03.2008 15:07
Wohnort: THE LÄÄÄND!

Re: Schnelles Konvertieren von Hex-Nibbles in Character

Beitrag von Regenduft »

Danke für die Hinweise!

Ja... der Test-Code ist nur auf die schnelle hingeschmiert, absolut nicht durchdacht und sollte nur verdeutlichen, wozu die Macros überhaupt gut sind. Bei Gelegenheit werde ich ihn mal überarbeiten. Trotzdem nett, dass Du ein Auge drauf geworfen hast! Habe mich wohl nicht gut ausgedrückt, worauf es mir ankommt...
Danilo hat geschrieben:Ob Du die 2 Macros noch verstehen wirst, wenn Du ein paar Monate nicht mehr an dem Projekt gearbeitet hast? ;)
Ganz bestimmt nicht! Zumindest nicht auf die schnelle! Templates auf, Code rein, Deckel drauf. Ja... ganz schlechter Stil... aber ich habe die Macros gründlich abgeklopft und sie erscheinen mir 100%ig zuverlässig. :mrgreen:
Danilo hat geschrieben:Hast Du die Geschwindigkeit schon gegenüber anderen Versionen getestet? Mit so vielen Shifts, &, |, ...
Kommt darauf an was Du mit "anderen Versionen" meinst.
Aus fremden Quellen: Nein, habe ich nicht getestet, da ich keine kenne.
Eingene andere Versionen: Ja, habe ich getestet, aber mir sind sonst nur Lösungen mit Verzweigung eingefallen und die waren (was mich sehr gewundert hatte) immer deutlich langsamer. Die vielen Shifts und bitweisen Unds sind da um langsamere Aktionen wie Sprünge, Multiplikationen und Divisionen zu umgehen.

Code: Alles auswählen

<<  >>   2...4 Maschinenzyklen
        
 &  |    1...3 Maschinenzyklen
    
  *      13...42 Maschinenzyklen
    
  /      19...43 Maschinenzyklen
    
Sprung   3...*hust-blicknicht* Maschinenzyklen
Das meiste an "Rechenleistung" geht für die Lücke zwischen '9' und 'A' bzw. 'a' drauf. Als ich nicht wusste wie ich den Code "optimieren" (im Sinne von beschleunigen :wink:) kann bin ich einfach so vorgegangen:
  1. '0' bis '9', 'A' bis 'F' und 'a' bis 'f' binär im Debugger ausgegeben
  2. Als Schaltalgebra-Formel niedergeschrieben
  3. So weit vereinfacht wie es mir möglich war
Die bloße Idee für einen besseren Ansatz (oder einfach nur anderen, zum ausprobieren) würde ich auch Dankbar annehmen!
PureBasic 5.73 LTE x86/x64 | Windows 7 (x64)
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Schnelles Konvertieren von Hex-Nibbles in Character

Beitrag von STARGÅTE »

Regenduft hat geschrieben:Das meiste an "Rechenleistung" geht für die Lücke zwischen '9' und 'A' bzw. 'a' drauf.
Verstehe ich nicht ganz.
Verwende für das Umwandeln von Char -> Nummer doch einfach eine Hash-Tabelle:

Code: Alles auswählen

Dim HexFromChar.i(255)
HexFromChar('0') = 0
HexFromChar('1') = 1
;...
HexFromChar('9') = 9
HexFromChar('A') = 10
HexFromChar('a') = 10
HexFromChar('B') = 11
;...
Dein Zeichen wäre dann einfach:

Code: Alles auswählen

Unicode = HexFromChar(*a\c[0])<<12|HexFromChar(*a\c[1])<<8|HexFromChar(*a\c[2])<<4|HexFromChar(*a\c[3])
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Regenduft
Beiträge: 574
Registriert: 25.03.2008 15:07
Wohnort: THE LÄÄÄND!

Re: Schnelles Konvertieren von Hex-Nibbles in Character

Beitrag von Regenduft »

Danke Stargate! Vielleicht konnte man es bis hinter Berlin hören wie ich mir bei Karlsruhe gerade an die Stirn geklatsch habe. Manmanman bin ich da auf der Leitung gestanden! Das macht die ganze Sache mal viel flotter!

(*grummel*... und ich Vollpfosten habe an anderer Stelle in meinem Projekt sogar bereits mit Hashtabelle gearbeitet...)
<- :lamer:
PureBasic 5.73 LTE x86/x64 | Windows 7 (x64)
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Schnelles Konvertieren von Hex-Nibbles in Character

Beitrag von Danilo »

Habe mir nicht angeschaut wie PB den Teil:

Code: Alles auswählen

     Select *a\c[i] | $20
      Case '0' To '9', 'a' To 'f'
in ASM generiert. Kann man aber auch über ein Array machen:

Code: Alles auswählen

Macro NyblCharsToUnicodeChar(n3, n2, n1, n0)
    (((n3)&$F|((n3)&$40)>>3+(n3)>>6)<<12|((n2)&$F|((n2)&$40)>>3+(n2)>>6)<<8|((n1)&$F|((n1)&$40)>>3+(n1)>>6)<<4|((n0)&$F|((n0)&$40)>>3+(n0)>>6))
EndMacro

Macro NyblCharsToAsciiChar(n1, n0)
    (((n1)&$F|((n1)&$40)>>3+(n1)>>6)<<4|((n0)&$F|((n0)&$40)>>3+(n0)>>6))
EndMacro


; ##### TEST-CODE #####

EnableExplicit

Structure CharacterArray
    c.c[0]
EndStructure

Global Dim HexChars.a(255)                ; Hex Array
Define i.i
For i = '0' To '9' : HexChars(i)=1 : Next ; Init Hex Array
For i = 'A' To 'F' : HexChars(i)=1 : Next
For i = 'a' To 'f' : HexChars(i)=1 : Next


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
        
    CompilerIf #PB_Compiler_Unicode
        While *a\c < 256 And HexChars( *a\c ) ; Unicode char < 256 und Hex char gefunden
    CompilerElse
        While HexChars( *a\c )                ; Hex char gefunden
    CompilerEndIf
            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 = NyblCharsToUnicodeChar(*a\c[-3],*a\c[-2],*a\c[-1],*a\c[0])
        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$
Musst Du mal testen was schneller ist.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
Shardik
Beiträge: 746
Registriert: 25.01.2005 12:19

Re: Schnelles Konvertieren von Hex-Nibbles in Character

Beitrag von Shardik »

Regenduft hat geschrieben:Das meiste an "Rechenleistung" geht für die Lücke zwischen '9' und 'A' bzw. 'a' drauf. Als ich nicht wusste wie ich den Code "optimieren" (im Sinne von beschleunigen :wink:) kann bin ich einfach so vorgegangen:

'0' bis '9', 'A' bis 'F' und 'a' bis 'f' binär im Debugger ausgegeben
Als Schaltalgebra-Formel niedergeschrieben
So weit vereinfacht wie es mir möglich war


Die bloße Idee für einen besseren Ansatz (oder einfach nur anderen, zum ausprobieren) würde ich auch Dankbar annehmen!
Der kürzestmögliche Code (aber nicht unbedingt der schnellste!) für die Umwandlung eines Nibble in ein ASCII-Zeichen von "0" bis "9" und "A" bis "F" mit Überwindung der "Lücke" zwischen "9" und "A" ohne die Nutzung einer Tabelle dürfte der folgende sein, den ich seit seiner Vorstellung in der Zeitschrift 80 Microcomputing 8/1981 nutze (dort ist er als Gewinner eines Wettbewerbs zur effizientesten Lösung genau dieses Problems für den Z-80 Prozessor aufgeführt, er läßt sich aber auch wie unten entsprechend angepaßt für Intel x86-Prozessoren übernehmen):

Code: Alles auswählen

Procedure ConvertNibbleToHexString(ByteValue.L)
  !MOV  EAX,DWORD[ESP+4]
  !ADD  AL,$90
  !DAA
  !ADC  AL,$40
  !DAA
  ProcedureReturn
EndProcedure

For i = 0 To 15
  HexBytes = ConvertNibbleToHexString(i)
  Debug Chr(HexBytes & $FF)
Next i
Zuletzt geändert von Shardik am 04.09.2013 19:46, insgesamt 1-mal geändert.
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Re: Schnelles Konvertieren von Hex-Nibbles in Character

Beitrag von PMV »

Ich hab das in meinem JSON-Parser ja recht einfach gelöst.
Angepasst an dein Beispiel hier sähe das so aus:

Code: Alles auswählen

;...
If check = 4
  *a + SizeOf(CHARACTER) * 2
  Define hexDigit.s = "$" + PeekS(*a, 4)
  *b\c = Val(hexDigit)
  *a + SizeOf(CHARACTER) * 3
Else ;...
aber einen ganzen String erstellen ist natürlich aufwendig.
Wenns am ende der Diskussion was wesentlich schnelleres
raus kommt, als das ... würd ich das auch glatt bei zeiten
in meinen JSON-Parser einbauen. :allright:

MFG PMV
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Schnelles Konvertieren von Hex-Nibbles in Character

Beitrag von NicTheQuick »

Ich hab auch mal Lust gehabt hier ein paar Bitschiebereien zu basteln, wobei ich glaube, dass die Array-Methode immer noch die schnellste ist, weil das die CPU auch super Cachen kann. Dennoch hier mein Versuch. Leider optimiert PB das nicht ganz so gut, aber wenn jemand will, bastel ich es auch noch in ASM um, dann aber nur für x64.

Code: Alles auswählen

CompilerIf #PB_Compiler_Unicode
	Procedure.c convertHexToChar(*mem.Quad)
		Protected q.q = *mem\q
		Debug RSet(Hex(q, #PB_Quad), 16, "0")
		q & $00DF00DF00DF00DF	;Bitmaske, damit a-f zu A-F umgewandelt wird
		Debug RSet(Hex(q, #PB_Quad), 16, "0")
		;Nutze das höchste Bit von A-F aus um 39 vom ASCII-Wert abzuziehen und
		;normalisiere anschließend das Ergebnis durch Abziehen von $10 pro Byte
		q - (((q >> 6) & $0001000100010001) * 39 + $0010001000100010)
		Debug RSet(Hex(q, #PB_Quad), 16, "0")
		;Schiebe alle halben Bytes an die richtige Position
		q = (q << 12) | (q >> 8)
		Debug RSet(Hex(q, #PB_Quad), 16, "0")
		q | (q >> 40)
		Debug RSet(Hex(q, #PB_Quad), 16, "0")
		ProcedureReturn q 
	EndProcedure
CompilerElse
	Procedure.c convertHexToChar(*mem.Unicode)
		Protected u.u = *mem\u
		Debug RSet(Hex(u, #PB_Unicode), 4, "0")
		u & $DFDF
		Debug RSet(Hex(u, #PB_Unicode), 4, "0")
		u - (((u >> 6) & $0101) * 39 + $1010)
		Debug RSet(Hex(u, #PB_Unicode), 4, "0")
		u = (u << 4) | (u >> 8)
		ProcedureReturn u
	EndProcedure
CompilerEndIf

CompilerIf #PB_Compiler_Unicode
	Define input.s = "Ab38"		;HexString für Unicode-Modus (chinesisches Zeichen)
CompilerElse
	Define input.s = "c4"		;HexString für Ascii-Modus	(Ö)
CompilerEndIf

Debug "Eingabe: " + input
Define u.c = convertHexToChar(@input)
Debug RSet(Hex(u), SizeOf(Character) * 2, "0")
Debug Chr(u)
Die Debugs hab ich extra drin gelassen, falls es jemanden interessiert, was da passiert
Benutzeravatar
Regenduft
Beiträge: 574
Registriert: 25.03.2008 15:07
Wohnort: THE LÄÄÄND!

Re: Schnelles Konvertieren von Hex-Nibbles in Character

Beitrag von Regenduft »

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) :allright:
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? :o

@ 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... :wink: 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. :cry:
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. :wink:
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...
PureBasic 5.73 LTE x86/x64 | Windows 7 (x64)
Antworten