Skip to content

Instantly share code, notes, and snippets.

@skial
Created October 5, 2020 13:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skial/c5bd1375c617e1f5dbb99174a465a18e to your computer and use it in GitHub Desktop.
Save skial/c5bd1375c617e1f5dbb99174a465a18e to your computer and use it in GitHub Desktop.
Ascii string to decimal parser, 0-9 are the only valid characters. Why? Because an itch HAD to be scratched 🤷‍♀️ Its not worth using and its most likely hugely unoptimized from a bitwise standpoint. Just use a regular expression!
package ;
class StringParser {
public static function parseDecimal(v:String):RawInt {
var result:RawInt = 0;
var code = 0;
var base = 1;
var index = v.length;
var start = v.fastCodeAt(0);
var isMinus = -((start & 1) & ((start & 4) >> 2) & ((start & 8) >> 3) & ((start & 32) >> 5) & ((~start & 15) >> 1));
var sign = ((isMinus) | (~isMinus & 1));
while (index > 0) {
code = v.fastCodeAt(index-1);
/**
Binary `0000` needs to be inverted to match against something `& 15`
limit to lowest 4 bits or a sinlge nibble, which is `15` or `1111`.
**/
var zeroMask = ~code & 15;
/**
Is it `0010` & `code` inverted matching `0101`? Means the top
4 bits are `0010` which is always less than char `0` or decimal 48.
**/
var lessThanZero = -(((code & 32) >> 5) & ((~code & 80) >> 4));
/**
Combined with `lessThanZero`, this reduces the chance of a
false positive getting through.
**/
var isZero = -((zeroMask & 1) & ((zeroMask & 2) >> 1) & ((zeroMask & 4) >> 2) & ((zeroMask & 8) >> 3)) & ~lessThanZero;
/**
Check the top 4 bits matches `0100` which means the ASCII character
is `@` or decimal 64 which is too large.
**/
var greaterThanQuestionMark = -((code & 64) >> 6);
//var maybe09 = -((code & 48) >> 5);
/**
If any of the top 3 bits of the lowest 4 bits are set its too large.
**/
var gte9 = -(((code & 8) >> 3) & ((code & 4) >> 2) & ((code & 2) >> 1));
/**
Handles the `0` character, which at this point is binary `0000`.
**/
var z = (isZero & code) | (~isZero & 0);
var a = (lessThanZero & 0) | (~lessThanZero & code);
var b = (greaterThanQuestionMark & 0) | (~greaterThanQuestionMark & code);
//var c = (maybe09 & code) | (~maybe09 & 0);
var d = (gte9 & 0) | (~gte9 & code);
code = z | a & b & /*c &*/ d & 15;
/**
Determines if the `base` should be increased.
**/
var delta = code & 1;
delta |= (code & 2) >> 1;
delta |= (code & 4) >> 2;
delta |= (code & 8) >> 3;
delta |= (isZero & 1);
delta = -delta;
result += sign * (base * code);
base = (delta & (base * 10) | (~delta & base));
index--;
}
return result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment