On Sunday, 16 October 2016 at 10:05:37 UTC, Patrick Schluter wrote:

Next step will be to loop for length 2,3,4, with or without your table.

Ok now the looped version which doesn't need the lookup table. This one assembles in 72 lines of assembly (25 lines only for the exception code).

dchar myFront5(ref char[] str)
 {
   byte c0 = str[0];
   if(c0 >= 0) {
     return c0;
   }
   else {
     if(((c0!=-64) & (c0!=-63)) && c0 <= -12 ) {
         auto l = str.length;

     int idx = 1;
     dchar mask0 = 0;
     dchar c1=c0&0x3f;
     int lim = -64;
     while(l--) {
         if(c0<lim) {
           if(c1 >0x10FFFF) break;
           return c1;
         }
         lim >>= 1 ;
         c1 = ((c1<<6) | (str.ptr[idx++]&0x3F)) & ~mask0;
         mask0 = 1 << (idx*6 + 7-idx);
       }
     }
   }
   Linvalid:
      throw new Exception("yadayada");
 }

Explanations of the tricks used:
1. the first character is read as signed byte with sign extension, this allows to compare it to the lim variable which is used to do mainly what the lookup table was doing. 2. there 2 loop escapes, if l, the variable holding the length of the string, is 0 which means that the string is too short or when the lim is bigger than the 1st character (see 1.) 3. Using the same 0x3f mask to extract the data bits from all bytes in the loop has the drawback of adding spurious bits coming from the 1st byte for 3 and 4 long sequences. The mask0 variable is used to "shoot" that bit in the next loop. 4. 2 simple tests allow to eliminate a lot of invalid cases (overlongs on 3 and 4 sequences are not tested yet though but I think there's a simple way of doing it but I'm too tired now to exlore it).

Reply via email to