Main Menu

Recent posts

#2
A Bubble - comparable the New Market Bubble - is very likely.
But when exactly it will pop?
#6
It would be ok if we  would be an official part of USA with the right also to vote for the US-President.
But USA keeps Germany as well as other countries as Vassal states with no rights other then to payy billions.
Thats what people do not like.
See download.pngBesa1.jpg
#7
The UK gets even harsher treatment from this author:


Why The UK Economy Is Broken (The End of Empire)

#8
I read somewhere that UK is US colony  ;D
#10
Source Code and Discussions / Re: PowerBasic Winsock-Library
Last post by Theo Gottwald - November 29, 2025, 08:53:40 PM
'########################################################################
' FUNCTION: W_JSON_EscapeString (Pointer-Optimized)
'------------------------------------------------------------------------
' Purpose:  Escapes a WSTRING for JSON compliance.
'           - Uses BYREF U01 for fastest read speed.
'           - Uses Pointer arithmetic for high-speed filling.
' Parameters:
'   U01 (WSTRING) : Input String (BYREF)
'   U02 (LONG)    : Escape Slash Flag (1=Yes, 0=No) (BYVAL)
' Returns:
'   WSTRING       : Escaped JSON String
'########################################################################
' FUNCTION: W_JSON_EscapeString (FINAL LOGIC FIX)
'------------------------------------------------------------------------
' Purpose:  Ensures perfect JSON compliance and fixes the Test 1 failure.
'########################################################################
FUNCTION W_JSON_EscapeString(BYREF U01 AS WSTRING,OPT BYVAL U02 AS LONG) COMMON AS WSTRING
    ' --- 1. Variable Declarations ---
    LOCAL pIn     AS WORD PTR
    LOCAL pEnd    AS WORD PTR
    LOCAL pOut    AS WORD PTR
    LOCAL S01     AS WSTRING  ' Output Buffer
    LOCAL T01     AS LONG     ' Input Length
    LOCAL T02     AS LONG     ' Output Length
    LOCAL T03     AS WORD     ' Current Char
    LOCAL S02     AS STRING   ' Hex Helper
    ' --- 2. Input Validation ---
    T01 = LEN(U01)
    IF T01 = 0 THEN
        S01 = ""
        GOTO EndFunction
    END IF
    ' --- 3. PASS 1: Calculate Required Output Length ---
    pIn  = STRPTR(U01)
    pEnd = pIn + (T01 * 2)
    T02  = 0
    DO WHILE pIn < pEnd
        T03 = @pIn
        SELECT CASE T03
            CASE 34, 92
                T02 = T02 + 2
            CASE 47
                IF U02 THEN T02 = T02 + 2 ELSE T02 = T02 + 1
            CASE 8, 9, 10, 12, 13
                T02 = T02 + 2
            CASE 32 TO 126
                T02 = T02 + 1
            CASE ELSE
                T02 = T02 + 6
        END SELECT
        INCR pIn
    LOOP
    ' --- 4. Allocation ---
    S01 = SPACE$(T02)
    pIn  = STRPTR(U01)
    pOut = STRPTR(S01)
    ' --- 5. PASS 2: Build Escaped String ---
    DO WHILE pIn < pEnd
        T03 = @pIn
        SELECT CASE AS LONG T03
            CASE 34, 92           ' " and \
                @pOut = 92 : INCR pOut   ' Write \
                @pOut = T03: INCR pOut   ' Write " or \
            CASE 47               ' /
                IF U02 THEN
                    @pOut = 92 : INCR pOut ' Write \
                END IF
                @pOut = 47 : INCR pOut     ' Write /
            CASE 8  : @pOut = 92 : INCR pOut : @pOut = 98  : INCR pOut ' \b
            CASE 9  : @pOut = 92 : INCR pOut : @pOut = 116 : INCR pOut ' \t
            CASE 10 : @pOut = 92 : INCR pOut : @pOut = 110 : INCR pOut ' \n
            CASE 12 : @pOut = 92 : INCR pOut : @pOut = 102 : INCR pOut ' \f
            CASE 13 : @pOut = 92 : INCR pOut : @pOut = 114 : INCR pOut ' \r
            CASE 32 TO 126        ' Safe ASCII
                @pOut = T03 : INCR pOut
            CASE ELSE             ' \uXXXX format (Covers BMP Unicode and Controls 0-7, 11, 14-31)
                @pOut = 92  : INCR pOut ' \
                @pOut = 117 : INCR pOut ' u
                S02 = HEX$(T03, 4)
                @pOut = ASC(S02, 1) : INCR pOut
                @pOut = ASC(S02, 2) : INCR pOut
                @pOut = ASC(S02, 3) : INCR pOut
                @pOut = ASC(S02, 4) : INCR pOut
        END SELECT
        INCR pIn
    LOOP
EndFunction:
    FUNCTION = S01
END FUNCTION             
'########################################################################
' FUNCTION: HTP_Encode_Base64
'------------------------------------------------------------------------
' Purpose:  Encodes raw binary data into Base64 (RFC 4648).
'           Uses High-Speed Inline ASM.
' Parameters:
'   U01 (InBuf)   - Input String (Binary Data)
'   U02 (nGroups) - Line break interval (0 = None, standard for APIs)
'   U03 (OutBuf)  - Output String (Base64) - Will be resized automatically
' Returns:
'   LONG          - Actual length of the encoded string.
'########################################################################
FUNCTION HTP_Encode_Base64(BYREF U01 AS STRING, BYVAL U02 AS LONG, BYREF U03 AS STRING) COMMON AS LONG
    ' Local Variables
    LOCAL E01 AS LONG       ' Input Length
    LOCAL E02 AS LONG       ' Output Buffer Size
    LOCAL U04 AS DWORD      ' pIn
    LOCAL U05 AS DWORD      ' pOut
    LOCAL U06 AS DWORD      ' pTbl (Lookup Table)
    LOCAL U07 AS DWORD      ' pEnd (Input End)
    LOCAL T01 AS LONG       ' Temp
    LOCAL T_LineCtr AS LONG ' Line Counter for Groups
    E01 = LEN(U01)
    IF E01 = 0 THEN U03 = "" : EXIT FUNCTION
    ' --- 1. Calculate Output Size ---
    ' Base size: (Len + 2) / 3 * 4
    E02 = ((E01 + 2) \ 3) * 4

    ' Add Line Breaks if nGroups > 0
    IF U02 > 0 THEN
        ' Add 2 bytes (CRLF) for every nGroups * 4 chars
        E02 = E02 + ((E02 \ (U02 * 4)) * 2) + 2 ' +2 Safety margin
    END IF
    ' Pre-allocate Output
    U03 = SPACE$(E02)
    ' --- 2. Initialize Lookup Table ---
    STATIC S_Tbl AS STRING
    IF LEN(S_Tbl) = 0 THEN
        S_Tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    END IF
    ' --- 3. Setup Pointers ---
    U04 = STRPTR(U01)       ' Source
    U05 = STRPTR(U03)       ' Dest
    U06 = STRPTR(S_Tbl)     ' Table
    U07 = U04 + E01         ' End of Source
    T_LineCtr = U02         ' Init Line Counter
    ' --- 4. ASM Encoding Loop ---
    ! PUSH ESI
    ! PUSH EDI
    ! PUSH EBX
    ! MOV ESI, U04          ; ESI = Input
    ! MOV EDI, U05          ; EDI = Output
    ! MOV EBX, U06          ; EBX = Table
    ! MOV ECX, U07          ; ECX = End of Input
EncLoop:
    ! CMP ESI, ECX          ; Check if we reached end
    ! JAE DoneASM
    ' Check if we have at least 3 bytes remaining
    ! MOV EAX, ECX
    ! SUB EAX, ESI
    ! CMP EAX, 3
    ! JL  PartialBlock
    ' --- Process Full 3-Byte Block ---
    ' Read 3 bytes: [ESI], [ESI+1], [ESI+2]
    ' Produce 4 chars

    ' Byte 1 (Src[0]) -> Out[0] (Top 6 bits)
    ! MOV AL, [ESI]
    ! SHR AL, 2
    ! XLAT                  ; Translate
    ! MOV [EDI], AL
    ! INC EDI
    ' Byte 1+2 -> Out[1] (Bot 2 bits of Src[0] + Top 4 bits of Src[1])
    ! MOV AL, [ESI]
    ! AND AL, 3             ; Keep last 2 bits
    ! SHL AL, 4             ; Move to top
    ! MOV AH, [ESI+1]       ; Load Byte 2
    ! SHR AH, 4             ; Get top 4 bits
    ! OR  AL, AH            ; Combine
    ! XLAT
    ! MOV [EDI], AL
    ! INC EDI
    ' Byte 2+3 -> Out[2] (Bot 4 bits of Src[1] + Top 2 bits of Src[2])
    ! MOV AL, [ESI+1]
    ! AND AL, 15            ; Keep last 4 bits
    ! SHL AL, 2             ; Move to top
    ! MOV AH, [ESI+2]       ; Load Byte 3
    ! SHR AH, 6             ; Get top 2 bits
    ! OR  AL, AH            ; Combine
    ! XLAT
    ! MOV [EDI], AL
    ! INC EDI
    ' Byte 3 -> Out[3] (Bot 6 bits of Src[2])
    ! MOV AL, [ESI+2]
    ! AND AL, 63            ; Keep last 6 bits
    ! XLAT
    ! MOV [EDI], AL
    ! INC EDI
    ! ADD ESI, 3            ; Advance Input
    ' --- Handle Line Breaks (Only if nGroups > 0) ---
    ' PowerBasic check: accessing U02 variable
    ! MOV EAX, U02
    ! CMP EAX, 0
    ! JE  EncLoop           ; If nGroups == 0, skip

    ! DEC T_LineCtr         ; Decrement counter
    ! JNZ EncLoop           ; If not zero, continue

    ! MOV EAX, U02          ; Reset Counter
    ! MOV T_LineCtr, EAX

    ' Insert CRLF
    ! MOV BYTE PTR [EDI], 13
    ! INC EDI
    ! MOV BYTE PTR [EDI], 10
    ! INC EDI
    ! JMP EncLoop
PartialBlock:
    ' Handle remaining 1 or 2 bytes
    ! CMP EAX, 1
    ! JE  Rem1Byte
    ' --- Remaining 2 Bytes ---
    ' Src[0], Src[1] -> Out[0], Out[1], Out[2], "="

    ' Out[0]
    ! MOV AL, [ESI]
    ! SHR AL, 2
    ! XLAT
    ! MOV [EDI], AL
    ! INC EDI
    ' Out[1]
    ! MOV AL, [ESI]
    ! AND AL, 3
    ! SHL AL, 4
    ! MOV AH, [ESI+1]
    ! SHR AH, 4
    ! OR  AL, AH
    ! XLAT
    ! MOV [EDI], AL
    ! INC EDI
    ' Out[2] (Bot 4 bits of Src[1] shifted left 2)
    ! MOV AL, [ESI+1]
    ! AND AL, 15
    ! SHL AL, 2
    ! XLAT
    ! MOV [EDI], AL
    ! INC EDI
    ' Out[3] Padding
    ! MOV BYTE PTR [EDI], 61 ; '='
    ! INC EDI

    ! ADD ESI, 2
    ! JMP DoneASM
Rem1Byte:
    ' --- Remaining 1 Byte ---
    ' Src[0] -> Out[0], Out[1], "=", "="
    ' Out[0]
    ! MOV AL, [ESI]
    ! SHR AL, 2
    ! XLAT
    ! MOV [EDI], AL
    ! INC EDI
    ' Out[1] (Bot 2 bits of Src[0] shifted left 4)
    ! MOV AL, [ESI]
    ! AND AL, 3
    ! SHL AL, 4
    ! XLAT
    ! MOV [EDI], AL
    ! INC EDI
    ' Padding
    ! MOV BYTE PTR [EDI], 61 ; '='
    ! INC EDI
    ! MOV BYTE PTR [EDI], 61 ; '='
    ! INC EDI

    ! INC ESI
DoneASM:
    ! MOV U05, EDI          ; Save final pointer

    ! POP EBX
    ! POP EDI
    ! POP ESI
    ' --- 5. Final Resize ---
    T01 = U05 - STRPTR(U03)
    U03 = LEFT$(U03, T01)

    FUNCTION = T01
END FUNCTION
                 

'########################################################################
' FUNCTION: HTP_DecodeBase64
'------------------------------------------------------------------------
' Purpose:  Decodes a Base64-encoded string (RFC 4648).
'           Uses high-performance pointer logic and static lookup table
'           for maximum speed, and handles MIME headers and whitespace.
' Parameters:
'   U01 (b64In AS STRING): The Base64 string to decode. May include
'                          optional MIME header (e.g., "data:image/..").
' Returns:
'   AS STRING: The decoded binary string. Empty string on error or empty input.
'########################################################################
FUNCTION HTP_DecodeBase64(BYVAL U01 AS STRING) COMMON AS STRING
    REGISTER T01 AS LONG, T02 AS LONG ' i, k (General purpose LONGs)

    LOCAL E01 AS LONG ' L (Input Length)
    LOCAL T03 AS LONG, T04 AS LONG, T05 AS LONG, T06 AS LONG ' b1, b2, b3, b4 (Decoded 6-bit values)
    LOCAL D01 AS LONG, D02 AS LONG ' t1, t2 (Temporary shift LONGs)
    LOCAL S01 AS STRING ' sOut (Output buffer string)
    LOCAL U02 AS BYTE PTR ' pIn (Input string pointer)
    LOCAL U03 AS BYTE PTR ' pOut (Output string pointer)
    LOCAL U04 AS BYTE PTR ' pEnd (End of input string pointer)
    ' --- 1. Strip MIME Header if present (Bulletproofing) ---
    IF LEFT$(U01, 5) = "data:" THEN
        T01 = INSTR(U01, "base64,")
        IF T01 > 0 THEN U01 = MID$(U01, T01 + 7)
    END IF
    E01 = LEN(U01)
    IF E01 = 0 THEN EXIT FUNCTION
    ' --- 2. Initialize Reverse Lookup Table (STATIC = Fast) ---
    STATIC TblE() AS BYTE ' E01 for 'Extra' datatypes
    IF UBOUND(TblE) = -1 THEN
        REDIM TblE(255)
        FOR T01 = 0 TO 255 : TblE(T01) = 255 : NEXT T01 ' Initialize to 255 (Invalid)
        FOR T01 = 65 TO 90 : TblE(T01) = T01 - 65 : NEXT T01       ' A(65)-Z(90) -> 0-25
        FOR T01 = 97 TO 122: TblE(T01) = T01 - 71 : NEXT T01       ' a(97)-z(122) -> 26-51
        FOR T01 = 48 TO 57 : TblE(T01) = T01 + 4 : NEXT T01        ' 0(48)-9(57) -> 52-61
        TblE(43) = 62 ' + (43)
        TblE(47) = 63 ' / (47)
        TblE(61) = 255 ' = (61) - Treat padding as invalid for lookup (we check separately)
    END IF
    ' --- 3. Pre-allocate Output Buffer ---
    ' Maximum output size: 3 bytes per 4 input characters.
    S01 = STRING$((E01 \ 4) * 3 + 3, 0)
    U02 = STRPTR(U01)
    U03 = STRPTR(S01)
    U04 = U02 + E01
    ' --- 4. Fast Decode Loop ---
    DO WHILE U02 < U04
        ' Skip non-Base64 chars (CR/LF/Space/Tabs - ASCII 1-32)
        DO WHILE (U02 < U04) AND (@U02 <= 32) : INCR U02 : LOOP
        IF U02 >= U04 THEN EXIT LOOP
        ' Fetch 4 bytes and convert to 6-bit values
        ' Use T01 for current byte value, then TblE for 6-bit value
        T03 = TblE(@U02) : IF @U02 = 61 THEN T03 = 255       ' b1: Must not be padding (=)
        INCR U02
        T04 = TblE(@U02) : IF @U02 = 61 THEN T04 = 255       ' b2: Can be 6-bit value or 255
        INCR U02
        T05 = TblE(@U02) : IF @U02 = 61 THEN T05 = 255 ELSE IF T05 = 255 THEN EXIT LOOP   ' b3: 6-bit value, or 255 (Padding/Invalid)
        INCR U02
        T06 = TblE(@U02) : IF @U02 = 61 THEN T06 = 255 ELSE IF T06 = 255 THEN EXIT LOOP   ' b4: 6-bit value, or 255 (Padding/Invalid)
        INCR U02
        ' Check for any invalid character that slipped past the skip loop and was not padding
        IF T03 = 255 OR T04 = 255 THEN EXIT LOOP

        ' Decode 3 bytes:
        ' Byte 1: b1(6) + b2(2)
        D01 = T03 : SHIFT LEFT D01, 2
        D02 = T04 : SHIFT RIGHT D02, 4
        @U03 = D01 OR D02
        INCR U03                                       ' <-- FIX: Increment the pointer
        IF T05 = 255 THEN EXIT LOOP                     ' Padding found (e.g., XX==) - Stop here
        ' Byte 2: b2(4) + b3(4)
        D01 = T04 AND 15 : SHIFT LEFT D01, 4
        D02 = T05        : SHIFT RIGHT D02, 2
        @U03 = D01 OR D02
        INCR U03                                       ' <-- FIX: Increment the pointer
        IF T06 = 255 THEN EXIT LOOP                     ' Padding found (e.g., XXX=) - Stop here
        ' Byte 3: b3(2) + b4(6)
        D01 = T05 AND 3 : SHIFT LEFT D01, 6
        @U03 = D01 OR T06
        INCR U03                                       ' <-- FIX: Increment the pointer
    LOOP
    ' --- 5. Resize to Actual Length ---
    T02 = U03 - STRPTR(S01) ' Calculate actual length by pointer difference
    FUNCTION = LEFT$(S01, T02)
END FUNCTION   

Tested.