//#OPTIONS: CPP // encode a string constant function h$str(s) { var enc = null; return function() { if(enc === null) { enc = h$encodeModifiedUtf8(s); } return enc; } } // encode a packed string // since \0 is used to separate strings (and a common occurrence) // we add the following mapping: // - \0 -> \cz\0 // - \cz -> \cz\cz // // decoding to bytes, the following is produced: // - \cz\0 -> C0 80 // - \cz\cz -> 1A // // additionally, for dealing with raw binary data we have an escape sequence // to pack base64 encoded runs: // // - \cz\xNN -> followed by NN-0x1f (31 decimal) bytes of base64 encoded // data. supported range: 0x20 .. 0x9f (1-128 bytes data) // function h$pstr(s) { var enc = null; return function() { if(enc === null) { enc = h$encodePackedUtf8(s); } return enc; } } // encode a raw string from bytes function h$rstr(d) { var enc = null; return function() { if(enc === null) { enc = h$rawStringData(d); } return enc; } } // these aren't added to the CAFs, so the list stays in mem indefinitely, is that a problem? #ifdef GHCJS_PROF function h$strt(str, cc) { return MK_LAZY_CC(function() { return h$toHsString(str, cc); }, cc); } function h$strta(str, cc) { return MK_LAZY_CC(function() { return h$toHsStringA(str, cc); }, cc); } function h$strtb(arr, cc) { return MK_LAZY_CC(function() { return h$toHsStringMU8(arr, cc); }, cc); } #else function h$strt(str) { return MK_LAZY(function() { return h$toHsString(str); }); } function h$strta(str) { return MK_LAZY(function() { return h$toHsStringA(str); }); } function h$strtb(arr) { return MK_LAZY(function() { return h$toHsStringMU8(arr); }); } #endif // unpack strings without thunks #ifdef GHCJS_PROF function h$ustra(str, cc) { return h$toHsStringA(str, cc); } function h$ustr(str, cc) { return h$toHsString(str, cc); } // utf8 string, string argument function h$urstra(arr, cc) { return h$toHsList(arr, cc); } // ascii string, array of codepoints argument function h$urstr(arr, cc) { return h$toHsStringMU8(arr, cc); } // utf8 string, array of bytes argumnt #else function h$ustra(str) { return h$toHsStringA(str); } function h$ustr(str) { return h$toHsString(str); } function h$urstra(arr) { return h$toHsList(arr); } function h$urstr(arr) { return h$toHsStringMU8(arr); } #endif function h$caseMapping(x) { return (x%2)?-((x+1)>>1):(x>>1); } var h$toUpper = null; function h$u_towupper(ch) { if(h$toUpper == null) { h$toUpper = h$decodeMapping(h$toUpperMapping, h$caseMapping); } return ch+(h$toUpper[ch]|0); } var h$toLower = null; function h$u_towlower(ch) { if(h$toLower == null) { h$toLower = h$decodeMapping(h$toLowerMapping, h$caseMapping); } return ch+(h$toLower[ch]|0); } var h$toTitle = null; function h$u_towtitle(ch) { if(h$toTitle == null) { h$toTitle = h$decodeMapping(h$toTitleMapping, h$caseMapping); } return ch+(h$toTitle[ch]|0); } var h$alpha = null; function h$u_iswalpha(a) { if(h$alpha == null) { h$alpha = h$decodeRLE(h$alphaRanges); } return h$alpha[a]|0; } var h$alnum = null; function h$u_iswalnum(a) { if(h$alnum == null) { h$alnum = h$decodeRLE(h$alnumRanges); } return h$alnum[a] == 1 ? 1 : 0; } // var h$spaceChars = [9,10,11,12,13,32,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8239,8287,12288]; function h$isSpace(a) { if(a<5760) return a===32||(a>=9&&a<=13)||a===160; return (a>=8192&&a<=8202)||a===5760||a===8239||a===8287||a===12288; } function h$u_iswspace(a) { return h$isSpace(a)?1:0; } var h$lower = null; function h$u_iswlower(a) { if(h$lower == null) { h$lower = h$decodeRLE(h$lowerRanges); } if(a < 0x30000) return h$lower[a]|0; if(a < 0xE0000) return 0; return h$lower[a-0xB0000]|0; } var h$upper = null; function h$u_iswupper(a) { if(h$upper == null) { h$upper = h$decodeRLE(h$upperRanges); } if(a < 0x30000) return h$upper[a]|0; if(a < 0xE0000) return 0; return h$upper[a-0xB0000]|0; } var h$cntrlChars = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159]; var h$cntrl = null; function h$u_iswcntrl(a) { if(h$cntrl === null) { h$cntrl = []; for(var i=0;i<=159;i++) h$cntrl[i] = (h$cntrlChars.indexOf(i) !== -1) ? 1 : 0; } return a <= 159 ? h$cntrl[a] : 0; } var h$print = null; function h$u_iswprint(a) { if(h$print == null) { h$print = h$decodeRLE(h$printRanges); } if(a < 0x30000) return h$print[a]|0; if(a < 0xE0000) return 0; return h$print[a-0xB0000]|0; } // decode a packed string (Compactor encoding method) to an array of numbers function h$decodePacked(s) { function f(o) { var c = s.charCodeAt(o); return c<34?c-32:c<92?c-33:c-34; } var r=[], i=0; while(i < s.length) { var c = s.charCodeAt(i); if(c < 124) r.push(f(i++)); else if(c === 124) { i += 3; r.push(90+90*f(i-2)+f(i-1)); } else if(c === 125) { i += 4; r.push(8190+8100*f(i-3)+90*f(i-2)+f(i-1)); } else throw ("h$decodePacked: invalid: " + c); } return r; } // decode string with encoded character ranges function h$decodeRLE(str) { var r = [], x = 0, i = 0, j = 0, v, k, a = h$decodePacked(str); while(i < a.length) { v = a[i++]; if(v === 0) { // alternating k = a[i++]; while(k--) { r[j++] = x; r[j++] = 1-x; } } else { if(v <= 2) { k = (a[i]<<16)+a[i+1]; i+=2; } else k = (v-1)>>1; if(v%2) { r[j++] = x; x = 1-x; } while(k--) r[j++] = x; x = 1-x; } } r.shift(); return r; } function h$decodeMapping(str, f) { var r = [], i = 0, j = 0, k, v, v2, a = h$decodePacked(str); while(i < a.length) { v = a[i++]; if(v === 0) { // alternating k = a[i]; v = f(a[i+1]); v2 = f(a[i+2]); while(k--) { r[j++] = v; r[j++] = v2; } i+=3; } else { if(v === 2) { k = (a[i] << 16) + a[i+1]; v = a[i+2]; i += 3; } else if(v%2) { k = 1; v = v>>1; } else { k = (v>>1)-1; v = a[i++]; } v = f(v); while(k--) r[j++] = v; } } return r; } var h$unicodeCat = null; function h$u_gencat(a) { if(h$unicodeCat == null) h$unicodeCat = h$decodeMapping(h$catMapping, function(x) { return x; }); // private use if(a >= 0xE000 && a <= 0xF8FF || a >= 0xF0000 & a <= 0xFFFFD || a >= 0x100000 && a <= 0x10FFFD) return 28; var c = a < 0x30000 ? (h$unicodeCat[a]|0) : (a < 0xE0000 ? 0 : (h$unicodeCat[a-0xB0000]|0)); return c?c-1:29; } function h$localeEncoding() { // h$log("### localeEncoding"); RETURN_UBX_TUP2(h$encodeUtf8("UTF-8"), 0); // offset 0 } function h$wcwidth(wch) { return 1; // XXX: add real implementation } function h$rawStringData(str) { var v = h$newByteArray(str.length+1); var u8 = v.u8; for(var i=0;i 192 128 // packed: encode \cz\cz -> 26 // \cz\0 -> 192 128 function h$encodeUtf8Internal(str, modified, packed) { var i, j, c, low, b64bytes, b64chars; function base64val(cc) { if(cc >= 65 && cc <= 90) return cc - 65; // A-Z if(cc >= 97 && cc <= 122) return cc - 71; // a-z if(cc >= 48 && cc <= 57) return cc + 4; // 0-9 if(cc === 43) return 62; // + if(cc === 47) return 63; // / if(cc === 61) return 0; // = (treat padding as zero) throw new Error("invalid base64 value: " + cc); } var n = 0; var czescape = false; for(i=0;i 26 n+=1; } else if(c === 0) { // \cz\0 -> 192 128 n+=2 } else if(c >= 0x20 && c <= 0x9f) { b64bytes = c - 0x1f; // number of bytes in base64 encoded run b64chars = ((b64bytes + 2) / 3) << 2; n += b64bytes; i += b64chars; } else { throw new Error("invalid cz escaped character: " + c); } czescape = false; } else { if(c === 26 && packed) { czescape = true; } else if(c === 0 && modified) { n+=2; } else if(c <= 0x7F) { n++; } else if(c <= 0x7FF) { n+=2; } else if(c <= 0xFFFF) { n+=3; } else if(c <= 0x1FFFFF) { n+=4; } else if(c <= 0x3FFFFFF) { n+=5; } else { n+=6; } } } var v = h$newByteArray(n+1); var u8 = v.u8; n = 0; for(i=0;i= 0x20 && c <= 0x9f) { b64bytes = c - 0x1f; while(b64bytes > 0) { var c1 = base64val(str.charCodeAt(i+1)), c2 = base64val(str.charCodeAt(i+2)), c3 = base64val(str.charCodeAt(i+3)), c4 = base64val(str.charCodeAt(i+4)); i+=4; u8[n] = (c1<<2)|(c2>>4); n++; if(b64bytes >= 2) { u8[n] = ((c2&0xf)<<4)|(c3 >> 2); n++; } if(b64bytes >= 3) { u8[n] = ((c3&0x3)<<6)|c4; n++; } b64bytes -= 3; } } else { u8[n] = c; n++; } czescape = false; } else if(c <= 0x7F) { u8[n] = c; n++; } else if(c <= 0x7FF) { u8[n] = (c >> 6) | 0xC0; u8[n+1] = (c & 0x3F) | 0x80; n+=2; } else if(c <= 0xFFFF) { u8[n] = (c >> 12) | 0xE0; u8[n+1] = ((c >> 6) & 0x3F) | 0x80; u8[n+2] = (c & 0x3F) | 0x80; n+=3; } else if(c <= 0x1FFFFF) { u8[n] = (c >> 18) | 0xF0; u8[n+1] = ((c >> 12) & 0x3F) | 0x80; u8[n+2] = ((c >> 6) & 0x3F) | 0x80; u8[n+3] = (c & 0x3F) | 0x80; n+=4; } else if(c <= 0x3FFFFFF) { u8[n] = (c >> 24) | 0xF8; u8[n+1] = ((c >> 18) & 0x3F) | 0x80; u8[n+2] = ((c >> 12) & 0x3F) | 0x80; u8[n+3] = ((c >> 6) & 0x3F) | 0x80; u8[n+4] = (c & 0x3F) | 0x80; n+=5; } else { u8[n] = (c >>> 30) | 0xFC; u8[n+1] = ((c >> 24) & 0x3F) | 0x80; u8[n+2] = ((c >> 18) & 0x3F) | 0x80; u8[n+3] = ((c >> 12) & 0x3F) | 0x80; u8[n+4] = ((c >> 6) & 0x3F) | 0x80; u8[n+5] = (c & 0x3F) | 0x80; n+=6; } } u8[v.len-1] = 0; // terminator // h$log("### encodeUtf8: " + str); // h$log(v); return v; } // encode a javascript string to a zero terminated utf16 byte array function h$encodeUtf16(str) { var n = 0; var i; for(i=0;i> 10, true); dv.setUint16(n+2, c0 & 0x3FF, true); n+=4; } } dv.setUint8(v.len-1,0); // terminator return v; } /* function h$encodeUtf16(str) { var b = new DataView(new ArrayBuffer(str.length * 2)); for(var i=str.length-1;i>=0;i--) { b.setUint16(i<<1, str.charCodeAt(i)); } h$ret1 = 0; return b; } var h$eU16 = h$encodeUtf16; function h$decodeUtf16(v,start) { return h$decodeUtf16(v, v.byteLength - start, start); } function h$decodeUtf16z(v,start) { var len = v.byteLength - start; for(var i=start;i>1] = v.dv.getUint16(i+start,true); } return h$charCodeArrayToString(arr); } var h$dU16 = h$decodeUtf16; // decode a buffer with UTF-8 chars to a JS string // stop at the first zero function h$decodeUtf8z(v,start) { var n = start; var max = v.len; while(n < max) { if(v.u8[n] === 0) { break; } n++; } return h$decodeUtf8(v,n,start); } // decode a buffer with Utf8 chars to a JS string // invalid characters are ignored function h$decodeUtf8(v,n0,start) { // h$log("### decodeUtf8"); // h$log(v); var n = n0 || v.len; var arr = []; var i = start || 0; var code; var u8 = v.u8; // h$log("### decoding, starting at: " + i); while(i < n) { var c = u8[i]; while((c & 0xC0) === 0x80) { c = u8[++i]; } // h$log("### lead char: " + c); if((c & 0x80) === 0) { code = (c & 0x7F); i++; } else if((c & 0xE0) === 0xC0) { code = ( ((c & 0x1F) << 6) | (u8[i+1] & 0x3F) ); i+=2; } else if((c & 0xF0) === 0xE0) { code = ( ((c & 0x0F) << 12) | ((u8[i+1] & 0x3F) << 6) | (u8[i+2] & 0x3F) ); i+=3; } else if ((c & 0xF8) === 0xF0) { code = ( ((c & 0x07) << 18) | ((u8[i+1] & 0x3F) << 12) | ((u8[i+2] & 0x3F) << 6) | (u8[i+3] & 0x3F) ); i+=4; } else if((c & 0xFC) === 0xF8) { code = ( ((c & 0x03) << 24) | ((u8[i+1] & 0x3F) << 18) | ((u8[i+2] & 0x3F) << 12) | ((u8[i+3] & 0x3F) << 6) | (u8[i+4] & 0x3F) ); i+=5; } else { code = ( ((c & 0x01) << 30) | ((u8[i+1] & 0x3F) << 24) | ((u8[i+2] & 0x3F) << 18) | ((u8[i+3] & 0x3F) << 12) | ((u8[i+4] & 0x3F) << 6) | (u8[i+5] & 0x3F) ); i+=6; } // h$log("### decoded codePoint: " + code + " - " + String.fromCharCode(code)); // String.fromCodePoint(code)); // need to deal with surrogate pairs if(code > 0xFFFF) { var offset = code - 0x10000; arr.push(0xD800 + (offset >> 10), 0xDC00 + (offset & 0x3FF)); } else { arr.push(code); } } return h$charCodeArrayToString(arr); } // fixme what if terminator, then we read past end function h$decodeUtf16(v) { var n = v.len; var arr = []; var dv = v.dv; for(var i=0;i " + toStr); // return 1; // fixme? } function h$hs_iconv_close(iconv) { return 0; } // convert JavaScript String to a Haskell String #ifdef GHCJS_PROF function h$toHsString(str, cc) { #else function h$toHsString(str) { #endif if(typeof str !== 'string') return HS_NIL; var i = str.length - 1; var r = HS_NIL; while(i>=0) { var cp = str.charCodeAt(i); if(cp >= 0xDC00 && cp <= 0xDFFF && i > 0) { --i; cp = (cp - 0xDC00) + (str.charCodeAt(i) - 0xD800) * 1024 + 0x10000; } r = MK_CONS_CC(cp, r, cc); --i; } return r; } // string must have been completely forced first function h$fromHsString(str) { var xs = ''; while(IS_CONS(str)) { var h = CONS_HEAD(str); xs += String.fromCharCode(UNWRAP_NUMBER(h)); str = CONS_TAIL(str); } return xs; } // list of JSVal to array, list must have been completely forced first function h$fromHsListJSVal(xs) { var arr = []; while(IS_CONS(xs)) { arr.push(JSVAL_VAL(CONS_HEAD(xs))); xs = CONS_TAIL(xs); } return arr; } // ascii only version of the above #ifdef GHCJS_PROF function h$toHsStringA(str, cc) { #else function h$toHsStringA(str) { #endif if(typeof str !== 'string') return HS_NIL; var i = str.length - 1; var r = HS_NIL; while(i>=0) { r = MK_CONS_CC(str.charCodeAt(i), r, cc); --i; } return r; } // convert array with modified UTF-8 encoded text #ifdef GHCJS_PROF function h$toHsStringMU8(arr, cc) { #else function h$toHsStringMU8(arr) { #endif var i = arr.length - 1, accept = false, b, n = 0, cp = 0, r = HS_NIL; while(i >= 0) { b = arr[i]; if(!(b & 128)) { cp = b; accept = true; } else if((b & 192) === 128) { cp += (b & 32) * Math.pow(64, n) } else { cp += (b&((1<<(6-n))-1)) * Math.pow(64, n); accept = true; } if(accept) { r = MK_CONS_CC(cp, r, cc); cp = 0 n = 0; } else { n++; } accept = false; i--; } return r; } #ifdef GHCJS_PROF function h$toHsList(arr, cc) { #else function h$toHsList(arr) { #endif var r = HS_NIL; for(var i=arr.length-1;i>=0;i--) { r = MK_CONS_CC(arr[i], r, cc); } return r; } // array of JS values to Haskell list of JSVal #ifdef GHCJS_PROF function h$toHsListJSVal(arr, cc) { #else function h$toHsListJSVal(arr) { #endif var r = HS_NIL; for(var i=arr.length-1;i>=0;i--) { r = MK_CONS_CC(MK_JSVAL(arr[i]), r, cc); } return r; } // unpack ascii string, append to existing Haskell string #ifdef GHCJS_PROF function h$appendToHsStringA(str, appendTo, cc) { #else function h$appendToHsStringA(str, appendTo) { #endif var i = str.length - 1; var r = appendTo; while(i>=0) { r = MK_CONS_CC(str.charCodeAt(i), r, cc); --i; } return r; } // throw e wrapped in a GHCJS.Prim.JSException in the current thread function h$throwJSException(e) { // create a JSException object and wrap it in a SomeException // adding the Exception dictionary var strVal; if(typeof e === 'string') { strVal = e; } else if(e instanceof Error) { strVal = e.toString() + '\n' + Array.prototype.join.call(e.stack, '\n'); } else { strVal = "" + e; } var someE = MK_SOMEEXCEPTION(HS_JSEXCEPTION_EXCEPTION, MK_JSEXCEPTION(MK_JSVAL(e), h$toHsString(strVal)) ); return h$throw(someE, true); }