On 19.04.2019 13:09, Rick McGuire wrote:
> Well, you're missing all of the logic that allows for blanks at the 
> boundaries and you're also
> assuming that you have an even number of digits to convert. If you remove all 
> of the things that
> x2c() has to account for, then yes, you can do a faster conversion.

OK, this version caters for illegal leading and trailing whitespace making sure 
an even number of
digits gets processed; it is still appr. 4,8 faster than the current x2c:

    /* A Rexx hex string may include any number of whitespace after even hex 
characters, e.g.
             "00 01   02"x
             but no leading or trailing blanks like " 00 01   02 "x
    */
    int64_t hex2char(RexxCallContext *rcc, CSTRING hexData, size_t len, char 
*data)
    {
        // check for trailing whitespace
        char tmp=(hexData[len-1]);      // get last character (must not be 
whitespace)
        if (tmp==' ' || tmp=='\t')
            rcc->ThrowException1(93931, rcc->UnsignedInt64ToObject(len));

        size_t dIdx=0;

        for (size_t i=0; i<len; i++)
        {

            if      (hexData[i]>='0' && hexData[i]<='9') tmp=hexData[i]-'0';
            else if (hexData[i]>='A' && hexData[i]<='F') tmp=hexData[i]-'A'+10;
            else if (hexData[i]>='a' && hexData[i]<='f') tmp=hexData[i]-'a'+10;
            else
            {
                // check for leading whitespace
                if (dIdx==0 && (hexData[i]==' ' || hexData[i]=='\t') )
                    rcc->ThrowException1(93931, rcc->Int32ToObject(1));

                if (hexData[i]==' ' || hexData[i]=='\t') continue; // skip on 
whitespace

                // illegal hex digit
                char buf[64];
                snprintf(buf, 64, "%c\0", hexData[i]);
                rcc->ThrowException1(93933, rcc->NewStringFromAsciiz(buf));
            }
            tmp<<=4;    // shift to high order nibble
            i++;        // position on next hex digit

            if (i==len) // we are beyond the hex string and missing the second 
hex digit
            {
                char buf[256];
                snprintf(buf, 256, "Hexadecimal string incomplete: hexadecimal 
pair starting with the character \"%c\" in position %zd is missing the second 
hexadecimal digit\0", hexData[i-1], len);
                rcc->ThrowException1(93900,rcc->NewStringFromAsciiz(buf));
            }


            if      (hexData[i]>='0' && hexData[i]<='9') tmp|=hexData[i]-'0';
            else if (hexData[i]>='A' && hexData[i]<='F') tmp|=hexData[i]-'A'+10;
            else if (hexData[i]>='a' && hexData[i]<='f') tmp|=hexData[i]-'a'+10;
            else if (hexData[i]==' ' || hexData[i]=='\t')  // also whitespace 
not allowed in between of a hex pair
                    rcc->ThrowException1(93931, rcc->UnsignedInt64ToObject(i));
            else // illegal hex digit
            {
                char buf[64];
                snprintf(buf, 64, "%c\0", hexData[i]);
                rcc->ThrowException1(93933, rcc->NewStringFromAsciiz(buf));
            }
            data[dIdx++]=tmp;
        }
        data[dIdx]='\0';
        return (int64_t)dIdx;            // return number or characters in data
    }


    RexxRoutine1( RexxStringObject, cppX2C, CSTRING, hexData  )
    {
        size_t len=strlen(hexData);
        char *data=(char *) malloc (len+1);
        int64_t res=(int64_t) hex2char(context, hexData,len,data);  // true, if 
translated; false, else
        RexxStringObject rso=context->String(data, (size_t) res);
        free(data);
        return rso;
    }

Here the hexadecimal test strings checked against the x2c()-BIF and the above 
hex2char():

    .context~package~local~lineal="1234+6789|"~copies(7)

    hexStrings=("Ab00ff00ff00ff12"                  , -
                "Ab 00 ff 00 ff 00 ff 12"           , -
                "AB  00  ff  00  ff  00  ff  12"    , -
                "AB  00  ff  00  ff  00  ff  1"    , -    -- not ok: hex-digit 
missing
                "AB  00  ff  00  f   00  ff  12"    , -   -- not ok: whitespace 
in wrong position (actually hex-digit missing)
                "Ab  0 0  ff  00  ff  00  ff  12"   , -   -- not ok: pairs may 
not contain whitespace
                "Ab != 00  ff  00  ff  00  ff  12"  , -   -- not ok: illegal 
characters "!="
                "aB 0X 00  ff  00  ff  00  ff  12"  , -   -- not ok: illegal 
characters "!="
                "  aB  00  ff  00  ff  00  ff  12"  , -   -- not ok: leading 
whitespace
                "aB  00  ff  00  ff  00  ff  12  "  )     -- not ok: trailing 
whitespace
    do h over hexStrings
       call testHexStringWithX2c    h
       say
       call testHexStringWithCppX2C h
       say
       say "="~copies(79)
    end

The x2c()-BIF has two wrong error messages:

  * the hexadecimal string "Ab  0 0  ff  00  ff  00  ff  12" has an illegal 
whitespace in position
    5, x2c() reports wrongly position 6 instead,

  * the hexadecimal string "AB 00 ff 00 ff 00 ff 1" is an incomplete 
hexadecimal string (last hex
    digit missing), x2c() reprots wrongly: "/SYNTAX 93.931 Incorrect location 
of whitespace
    character in position 28 in hexadecimal string./"

    Here a rexxtry.rex-script with two different error messages (both wrong):

    G:\oorexx.tmp\enrico2\win32>rexxtry
    REXX-ooRexx_5.0.0(MT)_32-bit 6.05 16 Apr 2019
      rexxtry.rex lets you interactively try REXX statements.
        Each string is executed when you hit Enter.
        Enter 'call tell' for a description of the features.
      Go on - try a few...            Enter 'exit' to end.

    say "AB  00  ff  00  ff  00  ff  1"*x*
      Oooops ! ... try again.     Invalid hexadecimal or binary string.
                                  Only 0-9, a-f, A-F, and whitespace characters 
are valid in a hexadecimal string; found " ".
      rc = 15.3 ................................. rexxtry.rex on WindowsNT

    say "AB  00  ff  00  ff  00  ff  1"~x2c
      Oooops ! ... try again.     Incorrect call to method.
                                  Incorrect location of whitespace character in 
position 28 in hexadecimal string.
      rc = 93.931 ............................... rexxtry.rex on WindowsNT

    say x2c("AB  00  ff  00  ff  00  ff  1")
      Oooops ! ... try again.     Incorrect call to method.
                                  Incorrect location of whitespace character in 
position 28 in hexadecimal string.
      rc = 93.931 ............................... rexxtry.rex on WindowsNT


    The above version reports "/SYNTAX 93.900 Hexadecimal string incomplete: 
hexadecimal pair
    starting with the character "1" in position 29 is missing the second 
hexadecimal digit./" to
    make the problem clear to the user.

---

The new ThrowException*()-APIs are really *very* handy!

---rony


_______________________________________________
Oorexx-devel mailing list
Oorexx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-devel

Reply via email to