Two additional quick notes:


1.      The static const arrays may be const only when dealing with a fixed 
character set. For some products I’ve worked on, the initialization of the 
arrays occurs during startup and after a character set option has been selected.
2.      (len % 2 == 1), while syntactically correct, does not optimize on 
several compilers for performance. The fastest all around is ((len & 1u)).





From: Mark L. Gaubatz via Oorexx-devel <> 
Sent: Thursday, April 18, 2019 11:05 AM
To: 'Open Object Rexx Developer Mailing List' 
Cc: Mark L. Gaubatz <>
Subject: Re: [Oorexx-devel] An alternative algorithm for x2c()




Too many comparisons are being done from a performance perspective; a minimal 
comparison for validation and no comparison for translation is the fastest. 
Actual translation should be done with a pair of 256-byte arrays for speed AND 
portability across character sets. Speed varies according to caching levels on 
each chipset as compared to ANSI specific translation that can be accomplished 
with just register operations. I will note that in some of my speed tests on a 
commercial product using newer Intel chipsets, caching brings only the cache 
lines of the trio of 256-byte tables used for translation into faster operation 
than the register operations. In addition, both upper- and lower-case A-F are 
handled with no performance impact.


    static const char trinvalid[256] = {… invalid character table …      }; // 
0x00 for valid characters, non-zero for invalid characters

    static const char trhigh   [256] = {… high order nibble translations … };

    static const char trlow    [256] = {… low order nibble translations …  };



        char    c1 = hexdata[i];

        char    c2 = hexdata[i+1];

        if ((trinvalid[c1] | trinvalid[c2])) // Yes, the | symbol is correct to 
drop to a single comparison operation


            data[0] = 0x00;

            return false;


        data[dIdx++] = trhigh[c1] | trlow[c2];

        i += 2;






From: Rony G. Flatscher < 
<> > 
Sent: Thursday, April 18, 2019 9:04 AM
To: Open Object Rexx Developer Mailing List < 
<> >
Subject: [Oorexx-devel] An alternative algorithm for x2c()


While experimenting a little bit with C code to decode hex strings I came up 
with the following code:

boolean hex2char(CSTRING hexData, size_t len, char *data)
    if (len % 2 == 1)   // not an even number of hex characters
        return false;
    size_t dIdx=0;
    for (size_t i=0; i<len; )
        char tmp='\0';
        switch (hexData[i++])
        case '0':         break;
        case '1': tmp= 1; break;
        case '2': tmp= 2; break;
        case '3': tmp= 3; break;
        case '4': tmp= 4; break;
        case '5': tmp= 5; break;
        case '6': tmp= 6; break;
        case '7': tmp= 7; break;
        case '8': tmp= 8; break;
        case '9': tmp= 9; break;
        case 'A': tmp=10; break;
        case 'B': tmp=11; break;
        case 'C': tmp=12; break;
        case 'D': tmp=13; break;
        case 'E': tmp=14; break;
        case 'F': tmp=15; break;
        default:        // illegal character
            return false;
        tmp<<=4;        // shift to high order nibble
        switch (hexData[i++])
        case '0':           break;
        case '1': tmp |=  1; break;
        case '2': tmp |=  2; break;
        case '3': tmp |=  3; break;
        case '4': tmp |=  4; break;
        case '5': tmp |=  5; break;
        case '6': tmp |=  6; break;
        case '7': tmp |=  7; break;
        case '8': tmp |=  8; break;
        case '9': tmp |=  9; break;
        case 'A': tmp |= 10; break;
        case 'B': tmp |= 11; break;
        case 'C': tmp |= 12; break;
        case 'D': tmp |= 13; break;
        case 'E': tmp |= 14; break;
        case 'F': tmp |= 15; break;
        default:        // illegal character
            return false;
    return true;        // success
RexxRoutine1( RexxStringObject, cppX2C, CSTRING, hexData  )
    size_t len=strlen(hexData);
    char *data=(char *) malloc (len+1);
    boolean res=hex2char(hexData,len,data);  // true, if translated; false, else
    if (res==false)
        return NULLOBJECT;      // for now: do not return a result, evoking a 
runtime error 
    RexxStringObject rso=context->String(data, len/2);
    return rso;

Comparing the duration of x2c() with the above cppX2C() 1,000 times on a 512KB 
string ( xrange("00"x,"FF"x)~copies(1000)~c2x ) the implementation of 
hex2char() seems to be about 3,8 faster than x2c(). (This was tested on 
Windows, 32-bit ooRexx.) Left the RexxRoutine1 cppX2C() in the above pasted 
code, such that you could double-check it by merely copying and pasting the 
above code and test it for yourself. 





Oorexx-devel mailing list

Reply via email to