ghcjs-base-0.2.0.0: jsbits/jsstring.js
#include <ghcjs/rts.h>
/*
* Support code for the Data.JSString module. This code presents a JSString
* as a sequence of code points and hides the underlying encoding ugliness of
* the JavaScript strings.
*
* Use Data.JSString.Raw for direct access to the JSThis makes the operations more expen
*/
/*
* Some workarounds here for JS engines that do not support proper
* code point access
*/
#ifdef GHCJS_TRACE_JSSTRING
#define TRACE_JSSTRING(args...) h$log("jsstring: ", args);
#else
#define TRACE_JSSTRING(args...)
#endif
#define IS_ASTRAL(cp) ((cp)>=0x10000)
#define IS_HI_SURR(cp) ((cp|1023)===0xDBFF)
#define IS_LO_SURR(cp) ((cp|1023)===0xDFFF)
#define FROM_SURR(hi,lo) ((((hi)-0xD800)<<10)+(lo)-0xDC00+0x10000)
#define HI_SURR(cp) ((((cp)-0x10000)>>>10)+0xDC00)
#define LO_SURR(cp) (((cp)&0x3FF)+0xD800)
var h$jsstringEmpty = MK_JSVAL('');
var h$jsstringHead, h$jsstringTail, h$jsstringCons,
h$jsstringSingleton, h$jsstringSnoc, h$jsstringUncons,
h$jsstringIndex, h$jsstringUncheckedIndex;
var h$fromCodePoint;
if(String.prototype.fromCodePoint) {
h$fromCodePoint = String.fromCodePoint;
} else {
// polyfill from https://github.com/mathiasbynens/String.fromCodePoint (MIT-license)
h$fromCodePoint =
(function() {
var stringFromCharCode = String.fromCharCode;
var floor = Math.floor;
return function(_) {
var MAX_SIZE = 0x4000;
var codeUnits = [];
var highSurrogate;
var lowSurrogate;
var index = -1;
var length = arguments.length;
if (!length) {
return '';
}
var result = '';
while (++index < length) {
var codePoint = Number(arguments[index]);
if (
!isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
codePoint < 0 || // not a valid Unicode code point
codePoint > 0x10FFFF || // not a valid Unicode code point
floor(codePoint) != codePoint // not an integer
) {
throw RangeError('Invalid code point: ' + codePoint);
}
if (codePoint <= 0xFFFF) { // BMP code point
codeUnits.push(codePoint);
} else { // Astral code point; split in surrogate halves
// https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
codePoint -= 0x10000;
highSurrogate = (codePoint >> 10) + 0xD800;
lowSurrogate = (codePoint % 0x400) + 0xDC00;
codeUnits.push(highSurrogate, lowSurrogate);
}
if (index + 1 == length || codeUnits.length > MAX_SIZE) {
result += stringFromCharCode.apply(null, codeUnits);
codeUnits.length = 0;
}
}
return result;
}
})();
}
if(String.prototype.codePointAt) {
h$jsstringSingleton = function(ch) {
TRACE_JSSTRING("(codePointAt) singleton: " + ch);
return String.fromCodePoint(ch);
}
h$jsstringHead = function(str) {
TRACE_JSSTRING("(codePointAt) head: " + str);
var cp = str.codePointAt(0);
return (cp === undefined) ? -1 : (cp|0);
}
h$jsstringTail = function(str) {
TRACE_JSSTRING("(codePointAt) tail: " + str);
var l = str.length;
if(l===0) return null;
var ch = str.codePointAt(0);
if(ch === undefined) return null;
// string length is at least two if ch comes from a surrogate pair
return str.substr(IS_ASTRAL(ch)?2:1);
}
h$jsstringCons = function(ch, str) {
TRACE_JSSTRING("(codePointAt) cons: " + ch + " '" + str + "'");
return String.fromCodePoint(ch)+str;
}
h$jsstringSnoc = function(str, ch) {
TRACE_JSSTRING("(codePointAt) snoc: '" + str + "' " + ch);
return str+String.fromCodePoint(ch);
}
h$jsstringUncons = function(str) {
TRACE_JSSTRING("(codePointAt) uncons: '" + str + "'");
var l = str.length;
if(l===0) {
RETURN_UBX_TUP2(-1, null);
}
var ch = str.codePointAt(0);
if(ch === undefined) {
RETURN_UBX_TUP2(-1, null);
}
RETURN_UBX_TUP2(ch, str.substr(IS_ASTRAL(ch)?2:1));
}
// index is the first part of the character
h$jsstringIndex = function(i, str) {
TRACE_JSSTRING("(codePointAt) index: " + i + " '" + str + "'");
var ch = str.codePointAt(i);
if(ch === undefined) return -1;
return ch;
}
h$jsstringUncheckedIndex = function(i, str) {
TRACE_JSSTRING("(codePointAt) uncheckedIndex: " + i + " '" + str.length + "'");
return str.codePointAt(i);
}
} else {
h$jsstringSingleton = function(ch) {
TRACE_JSSTRING("(no codePointAt) singleton: " + ch);
return (IS_ASTRAL(ch)) ? String.fromCharCode(HI_SURR(ch), LO_SURR(ch))
: String.fromCharCode(ch);
}
h$jsstringHead = function(str) {
TRACE_JSSTRING("(no codePointAt) head: " + str);
var l = str.length;
if(l===0) return -1;
var ch = str.charCodeAt(0);
if(IS_HI_SURR(ch)) {
return (l>1) ? FROM_SURR(ch, str.charCodeAt(1)) : -1;
} else {
return ch;
}
}
h$jsstringTail = function(str) {
TRACE_JSSTRING("(no codePointAt) tail: " + str);
var l = str.length;
if(l===0) return null;
var ch = str.charCodeAt(0);
if(IS_HI_SURR(ch)) {
return (l>1)?str.substr(2):null;
} else return str.substr(1);
}
h$jsstringCons = function(ch, str) {
TRACE_JSSTRING("(no codePointAt) cons: " + ch + " '" + str + "'");
return ((IS_ASTRAL(ch)) ? String.fromCharCode(HI_SURR(ch), LO_SURR(ch))
: String.fromCharCode(ch))
+ str;
}
h$jsstringSnoc = function(str, ch) {
TRACE_JSSTRING("(no codePointAt) snoc: '" + str + "' " + ch);
return str + ((IS_ASTRAL(ch)) ? String.fromCharCode(HI_SURR(ch), LO_SURR(ch))
: String.fromCharCode(ch));
}
h$jsstringUncons = function(str) {
TRACE_JSSTRING("(no codePointAt) uncons: '" + str + "'");
var l = str.length;
if(l===0) {
RETURN_UBX_TUP2(-1, null);
}
var ch = str.charCodeAt(0);
if(IS_HI_SURR(ch)) {
if(l > 1) {
RETURN_UBX_TUP2(FROM_SURR(ch, str.charCodeAt(1)), str.substr(2));
} else {
RETURN_UBX_TUP2(-1, null);
}
} else {
RETURN_UBX_TUP2(ch, str.substr(1));
}
}
// index is the first part of the character
h$jsstringIndex = function(i, str) {
// TRACE_JSSTRING("(no codePointAt) index: " + i + " '" + str + "'");
var ch = str.charCodeAt(i);
if(ch != ch) return -1; // NaN test
return (IS_HI_SURR(ch)) ? FROM_SURR(ch, str.charCodeAt(i+1)) : ch;
}
h$jsstringUncheckedIndex = function(i, str) {
TRACE_JSSTRING("(no codePointAt) uncheckedIndex: " + i + " '" + str.length + "'");
var ch = str.charCodeAt(i);
return (IS_HI_SURR(ch)) ? FROM_SURR(ch, str.charCodeAt(i+1)) : ch;
}
}
function h$jsstringUnsnoc(str) {
TRACE_JSSTRING("unsnoc: '" + str + "'");
var l = str.length;
if(l===0) {
RETURN_UBX_TUP2(-1, null);
}
var ch = str.charCodeAt(l-1);
if(IS_LO_SURR(ch)) {
if(l !== 1) {
RETURN_UBX_TUP2(FROM_SURR(str.charCodeAt(l-2),ch), str.substr(0,l-2));
} else {
RETURN_UBX_TUP2(-1, null);
}
} else {
RETURN_UBX_TUP2(ch, str.substr(0,l-1));
}
}
function h$jsstringPack(xs) {
var r = '', i = 0, a = [], c;
while(IS_CONS(xs)) {
c = CONS_HEAD(xs);
a[i++] = UNWRAP_NUMBER(c);
if(i >= 60000) {
r += h$fromCodePoint.apply(null, a);
a = [];
i = 0;
}
xs = CONS_TAIL(xs);
}
if(i > 0) r += h$fromCodePoint.apply(null, a);
TRACE_JSSTRING("pack: '" + r + "'");
return r;
}
function h$jsstringPackReverse(xs) {
var a = [], i = 0, c;
while(IS_CONS(xs)) {
c = CONS_HEAD(xs);
a[i++] = UNWRAP_NUMBER(c);
xs = CONS_TAIL(xs);
}
if(i===0) return '';
var r = h$jsstringConvertArray(a.reverse());
TRACE_JSSTRING("packReverse: '" + r + "'");
return r;
}
function h$jsstringPackArray(arr) {
TRACE_JSSTRING("pack array: " + arr);
return h$jsstringConvertArray(arr);
}
function h$jsstringPackArrayReverse(arr) {
TRACE_JSSTRING("pack array reverse: " + arr);
return h$jsstringConvertArray(arr.reverse());
}
function h$jsstringConvertArray(arr) {
if(arr.length < 60000) {
return h$fromCodePoint.apply(null, arr);
} else {
var r = '';
for(var i=0; i<arr.length; i+=60000) {
r += h$fromCodePoint.apply(null, arr.slice(i, i+60000));
}
return r;
}
}
function h$jsstringInit(str) {
TRACE_JSSTRING("init: '" + str + "'");
var l = str.length;
if(l===0) return null;
var ch = str.charCodeAt(l-1);
var o = IS_LO_SURR(ch)?2:1;
var r = str.substr(0, l-o);
return r;
}
function h$jsstringLast(str) {
TRACE_JSSTRING("last: '" + str + "'");
var l = str.length;
if(l===0) return -1;
var ch = str.charCodeAt(l-1);
if(IS_LO_SURR(ch)) {
return (l>1) ? FROM_SURR(str.charCodeAt(l-2), ch) : -1;
} else return ch;
}
// index is the last part of the character
function h$jsstringIndexR(i, str) {
TRACE_JSSTRING("indexR: " + i + " '" + str + "'");
if(i < 0 || i > str.length) return -1;
var ch = str.charCodeAt(i);
return (IS_LO_SURR(ch)) ? FROM_SURR(str.charCodeAt(i-1), ch) : ch;
}
function h$jsstringNextIndex(i, str) {
TRACE_JSSTRING("nextIndex: " + i + " '" + str + "'");
return i + (IS_HI_SURR(str.charCodeAt(i))?2:1);
}
function h$jsstringTake(n, str) {
TRACE_JSSTRING("take: " + n + " '" + str + "'");
if(n <= 0) return '';
var i = 0, l = str.length, ch;
if(n >= l) return str;
while(n--) {
ch = str.charCodeAt(i++);
if(IS_HI_SURR(ch)) i++;
if(i >= l) return str;
}
return str.substr(0,i);
}
function h$jsstringDrop(n, str) {
TRACE_JSSTRING("drop: " + n + " '" + str + "'");
if(n <= 0) return str;
var i = 0, l = str.length, ch;
if(n >= l) return '';
while(n--) {
ch = str.charCodeAt(i++);
if(IS_HI_SURR(ch)) i++;
if(i >= l) return '';
}
return str.substr(i);
}
function h$jsstringSplitAt(n, str) {
TRACE_JSSTRING("splitAt: " + n + " '" + str + "'");
if(n <= 0) {
RETURN_UBX_TUP2("", str);
} else if(n >= str.length) {
RETURN_UBX_TUP2(str, "");
}
var i = 0, l = str.length, ch;
while(n--) {
ch = str.charCodeAt(i++);
if(IS_HI_SURR(ch)) i++;
if(i >= l) {
RETURN_UBX_TUP2(str, "");
}
}
RETURN_UBX_TUP2(str.substr(0,i),str.substr(i));
}
function h$jsstringTakeEnd(n, str) {
TRACE_JSSTRING("takeEnd: " + n + " '" + str + "'");
if(n <= 0) return '';
var l = str.length, i = l-1, ch;
if(n >= l) return str;
while(n-- && i > 0) {
ch = str.charCodeAt(i--);
if(IS_LO_SURR(ch)) i--;
}
return (i<0) ? str : str.substr(i+1);
}
function h$jsstringDropEnd(n, str) {
TRACE_JSSTRING("dropEnd: " + n + " '" + str + "'");
if(n <= 0) return str;
var l = str.length, i = l-1, ch;
if(n >= l) return '';
while(n-- && i > 0) {
ch = str.charCodeAt(i--);
if(IS_LO_SURR(ch)) i--;
}
return (i<0) ? '' : str.substr(0,i+1);
}
function h$jsstringIntercalate(x, ys) {
TRACE_JSSTRING("intercalate: '" + x + "'");
var a = [], i = 0;
while(IS_CONS(ys)) {
if(i) a[i++] = x;
a[i++] = JSVAL_VAL(CONS_HEAD(ys));
ys = CONS_TAIL(ys);
}
return a.join('');
}
function h$jsstringIntersperse(ch, ys) {
TRACE_JSSTRING("intersperse: " + ch + " '" + ys + "'");
var i = 0, l = ys.length, j = 0, a = [], ych;
if(IS_ASTRAL(ch)) {
while(j < l) {
if(i) a[i++] = ch;
ych = ys.charCodeAt(j++);
a[i++] = ych;
if(IS_HI_SURR(ych)) a[i++] = ys.charCodeAt(j++);
}
} else {
while(j < l) {
if(i) a[i++] = ch;
ych = ys.charCodeAt(j++);
a[i++] = ych;
if(IS_HI_SURR(ych)) a[i++] = ys.charCodeAt(j++);
}
}
return h$jsstringConvertArray(a);
}
function h$jsstringConcat(xs) {
TRACE_JSSTRING("concat");
var a = [], i = 0;
while(IS_CONS(xs)) {
a[i++] = JSVAL_VAL(CONS_HEAD(xs));
xs = CONS_TAIL(xs);
}
return a.join('');
}
var h$jsstringStripPrefix, h$jsstringStripSuffix,
h$jsstringIsPrefixOf, h$jsstringIsSuffixOf,
h$jsstringIsInfixOf;
if(String.prototype.startsWith) {
h$jsstringStripPrefix = function(p, x) {
TRACE_JSSTRING("(startsWith) stripPrefix: '" + p + "' '" + x + "'");
if(x.startsWith(p)) {
return MK_JUST(MK_JSVAL(x.substr(p.length)));
} else {
return HS_NOTHING;
}
}
h$jsstringIsPrefixOf = function(p, x) {
TRACE_JSSTRING("(startsWith) isPrefixOf: '" + p + "' '" + x + "'");
return x.startsWith(p);
}
} else {
h$jsstringStripPrefix = function(p, x) {
TRACE_JSSTRING("(no startsWith) stripPrefix: '" + p + "' '" + x + "'");
if(x.indexOf(p) === 0) { // this has worse complexity than it should
return MK_JUST(MK_JSVAL(x.substr(p.length)));
} else {
return HS_NOTHING;
}
}
h$jsstringIsPrefixOf = function(p, x) {
TRACE_JSSTRING("(no startsWith) isPrefixOf: '" + p + "' '" + x + "'");
return x.indexOf(p) === 0; // this has worse complexity than it should
}
}
if(String.prototype.endsWith) {
h$jsstringStripSuffix = function(s, x) {
TRACE_JSSTRING("(endsWith) stripSuffix: '" + s + "' '" + x + "'");
if(x.endsWith(s)) {
return MK_JUST(MK_JSVAL(x.substr(0,x.length-s.length)));
} else {
return HS_NOTHING;
}
}
h$jsstringIsSuffixOf = function(s, x) {
TRACE_JSSTRING("(endsWith) isSuffixOf: '" + s + "' '" + x + "'");
return x.endsWith(s);
}
} else {
h$jsstringStripSuffix = function(s, x) {
TRACE_JSSTRING("(no endsWith) stripSuffix: '" + s + "' '" + x + "'");
var i = x.lastIndexOf(s); // this has worse complexity than it should
var l = x.length - s.length;
if(i !== -1 && i === l) {
return MK_JUST(MK_JSVAL(x.substr(0,l)));
} else {
return HS_NOTHING;
}
}
h$jsstringIsSuffixOf = function(s, x) {
TRACE_JSSTRING("(no endsWith) isSuffixOf: '" + s + "' '" + x + "'");
var i = x.lastIndexOf(s); // this has worse complexity than it should
return i !== -1 && i === x.length - s.length;
}
}
if(String.prototype.includes) {
h$jsstringIsInfixOf = function(i, x) {
TRACE_JSSTRING("(includes) isInfixOf: '" + i + "' '" + x + "'");
return x.includes(i);
}
} else {
h$jsstringIsInfixOf = function(i, x) {
TRACE_JSSTRING("(no includes) isInfixOf: '" + i + "' '" + x + "'");
return x.indexOf(i) !== -1; // this has worse complexity than it should
}
}
function h$jsstringCommonPrefixes(x, y) {
TRACE_JSSTRING("commonPrefixes: '" + x + "' '" + y + "'");
var lx = x.length, ly = y.length, i = 0, cx;
var l = lx <= ly ? lx : ly;
if(lx === 0 || ly === 0 || x.charCodeAt(0) !== y.charCodeAt(0)) {
return HS_NOTHING;
}
while(++i<l) {
cx = x.charCodeAt(i);
if(cx !== y.charCodeAt(i)) {
if(IS_LO_SURR(cx)) i--;
break;
}
}
if(i===0) return HS_NOTHING;
return MK_JUST(MK_TUP3( MK_JSVAL((i===lx)?x:((i===ly)?y:x.substr(0,i)))
, (i===lx) ? h$jsstringEmpty : MK_JSVAL(x.substr(i))
, (i===ly) ? h$jsstringEmpty : MK_JSVAL(y.substr(i))
));
}
function h$jsstringBreakOn(b, x) {
TRACE_JSSTRING("breakOn: '" + b + "' '" + x + "'");
var i = x.indexOf(b);
if(i===-1) {
RETURN_UBX_TUP2(x, "");
}
if(i===0) {
RETURN_UBX_TUP2("", x);
}
RETURN_UBX_TUP2(x.substr(0,i), x.substr(i));
}
function h$jsstringBreakOnEnd(b, x) {
TRACE_JSSTRING("breakOnEnd: '" + b + "' '" + x + "'");
var i = x.lastIndexOf(b);
if(i===-1) {
RETURN_UBX_TUP2("", x);
}
i += b.length;
RETURN_UBX_TUP2(x.substr(0,i), x.substr(i));
}
function h$jsstringBreakOnAll1(n, b, x) {
TRACE_JSSTRING("breakOnAll1: " + n + " '" + b + "' '" + x + "'");
var i = x.indexOf(b, n);
if(i===0) {
RETURN_UBX_TUP3(b.length, "", x);
}
if(i===-1) {
RETURN_UBX_TUP3(-1, null, null);
}
RETURN_UBX_TUP3(i+b.length, x.substr(0,i), x.substr(i));
}
function h$jsstringBreakOnAll(pat, src) {
TRACE_JSSTRING("breakOnAll");
var a = [], i = 0, n = 0, r = HS_NIL, pl = pat.length;
while(true) {
var x = src.indexOf(pat, n);
if(x === -1) break;
a[i++] = MK_TUP2(MK_JSVAL(src.substr(0,x)), MK_JSVAL(src.substr(x)));
n = x + pl;
}
while(--i >= 0) r = MK_CONS(a[i], r);
return r;
}
function h$jsstringSplitOn1(n, p, x) {
TRACE_JSSTRING("splitOn1: " + n + " '" + p + "' '" + x + "'");
var i = x.indexOf(p, n);
if(i === -1) {
RETURN_UBX_TUP2(-1, null);
}
var r1 = (i==n) ? "" : x.substr(n, i-n);
RETURN_UBX_TUP2(i + p.length, r1);
}
function h$jsstringSplitOn(p, x) {
TRACE_JSSTRING("splitOn: '" + p + "' '" + x + "'");
var a = x.split(p);
var r = HS_NIL, i = a.length;
while(--i>=0) r = MK_CONS(MK_JSVAL(a[i]), r);
return r;
}
// returns -1 for end of input, start of next token otherwise
// word in h$ret1
// this function assumes that there are no whitespace characters >= 0x10000
function h$jsstringWords1(n, x) {
TRACE_JSSTRING("words1: " + n + " '" + x + "'");
var m = n, s = n, l = x.length;
if(m >= l) return -1;
// skip leading spaces
do {
if(m >= l) return -1;
} while(h$isSpace(x.charCodeAt(m++)));
// found start of word
s = m - 1;
while(m < l) {
if(h$isSpace(x.charCodeAt(m++))) {
// found end of word
var r1 = (m-s<=1) ? "" : x.substr(s,m-s-1);
RETURN_UBX_TUP2(m, r1);
}
}
// end of string
if(s < l) {
var r1 = s === 0 ? x : x.substr(s);
RETURN_UBX_TUP2(m, r1);
}
RETURN_UBX_TUP2(-1, null);
}
function h$jsstringWords(x) {
TRACE_JSSTRING("words: '" + x + "'");
var a = null, i = 0, n, s = -1, m = 0, w, l = x.length, r = HS_NIL;
outer:
while(m < l) {
// skip leading spaces
do {
if(m >= l) { s = m; break outer; }
} while(h$isSpace(x.charCodeAt(m++)));
// found start of word
s = m - 1;
while(m < l) {
if(h$isSpace(x.charCodeAt(m++))) {
// found end of word
w = (m-s<=1) ? h$jsstringEmpty
: MK_JSVAL(x.substr(s,m-s-1));
if(i) a[i++] = w; else { a = [w]; i = 1; }
s = m;
break;
}
}
}
// end of string
if(s !== -1 && s < l) {
w = MK_JSVAL(s === 0 ? x : x.substr(s));
if(i) a[i++] = w; else { a = [w]; i = 1; }
}
// build resulting list
while(--i>=0) r = MK_CONS(a[i], r);
return r;
}
// returns -1 for end of input, start of next token otherwise
// line in h$ret1
function h$jsstringLines1(n, x) {
TRACE_JSSTRING("lines1: " + n + " '" + x + "'");
var m = n, l = x.length;
if(n >= l) return -1;
while(m < l) {
if(x.charCodeAt(m++) === 10) {
// found newline
if(n > 0 && n === l-1) return -1; // it was the last character
var r1 = (m-n<=1) ? "" : x.substr(n,m-n-1);
RETURN_UBX_TUP2(m, r1);
}
}
// end of string
RETURN_UBX_TUP2(m, x.substr(n));
}
function h$jsstringLines(x) {
TRACE_JSSTRING("lines: '" + x + "'");
var a = null, m = 0, i = 0, l = x.length, s = 0, r = HS_NIL, w;
if(l === 0) return HS_NIL;
outer:
while(true) {
s = m;
do {
if(m >= l) break outer;
} while(x.charCodeAt(m++) !== 10);
w = (m-s<=1) ? h$jsstringEmpty : MK_JSVAL(x.substr(s,m-s-1));
if(i) a[i++] = w; else { a = [w]; i = 1; }
}
if(s < l) {
w = MK_JSVAL(x.substr(s));
if(i) a[i++] = w; else { a = [w]; i = 1; }
}
while(--i>=0) r = MK_CONS(a[i], r);
return r;
}
function h$jsstringGroup(x) {
TRACE_JSSTRING("group: '" + x + "'");
var xl = x.length;
if(xl === 0) return HS_NIL;
var i = xl-1, si, ch, s=xl, r=HS_NIL;
var tch = x.charCodeAt(i--);
if(IS_LO_SURR(tch)) tch = FROM_SURR(x.charCodeAt(i--), tch);
while(i >= 0) {
si = i;
ch = x.charCodeAt(i--);
if(IS_LO_SURR(ch)) {
ch = FROM_SURR(x.charCodeAt(i--), ch);
}
if(ch != tch) {
tch = ch;
r = MK_CONS(MK_JSVAL(x.substr(si+1,s-si)), r);
s = si;
}
}
return MK_CONS(MK_JSVAL(x.substr(0,s+1)), r);
}
function h$jsstringChunksOf1(n, s, x) {
TRACE_JSSTRING("chunksOf1: " + n + " " + s + " '" + x + "'");
var m = s, c = 0, l = x.length, ch;
if(n <= 0 || l === 0 || s >= l) return -1
while(++m < l) {
ch = x.charCodeAt(m - 1);
if(IS_HI_SURR(ch)) ++m;
if(++c >= n) break;
}
var r1 = (m >= l && s === c) ? x : x.substr(s,m-s);
RETURN_UBX_TUP2(m, r1);
}
function h$jsstringChunksOf(n, x) {
TRACE_JSSTRING("chunksOf: " + n + " '" + x + "'");
var l = x.length;
if(l===0 || n <= 0) return HS_NIL;
if(l <= n) return MK_CONS(MK_JSVAL(x), HS_NIL);
var a = [], i = 0, s = 0, ch, m = 0, c, r = HS_NIL;
while(m < l) {
s = m;
c = 0;
while(m < l && ++c <= n) {
ch = x.charCodeAt(m++);
if(IS_HI_SURR(ch)) ++m;
}
if(c) a[i++] = x.substr(s, m-s);
}
while(--i>=0) r = MK_CONS(MK_JSVAL(a[i]), r);
return r;
}
function h$jsstringCount(pat, src) {
TRACE_JSSTRING("count: '" + pat + "' '" + src + "'");
var i = 0, n = 0, pl = pat.length, sl = src.length;
while(i<sl) {
i = src.indexOf(pat, i);
if(i===-1) break;
n++;
i += pl;
}
return n;
}
function h$jsstringReplicate(n, str) {
TRACE_JSSTRING("replicate: " + n + " '" + str + "'");
if(n === 0 || str == '') return '';
if(n === 1) return str;
var r = '';
do {
if(n&1) r+=str;
str+=str;
n >>= 1;
} while(n > 1);
return r+str;
}
// this does not deal with combining diacritics, Data.Text does not either
var h$jsstringReverse;
if(Array.from) {
h$jsstringReverse = function(str) {
TRACE_JSSTRING("(Array.from) reverse: '" + str + "'");
return Array.from(str).reverse().join('');
}
} else {
h$jsstringReverse = function(str) {
TRACE_JSSTRING("(no Array.from) reverse: '" + str + "'");
var l = str.length, a = [], o = 0, i = 0, c, c1, s = '';
while(i < l) {
c = str.charCodeAt(i);
if(IS_HI_SURR(c)) {
a[i] = str.charCodeAt(i+1);
a[i+1] = c;
i += 2;
} else a[i++] = c;
if(i-o > 60000) {
s = String.fromCharCode.apply(null, a.reverse()) + s;
o = -i;
a = [];
}
}
return (i===0) ? s : String.fromCharCode.apply(null,a.reverse()) + s;
}
}
function h$jsstringUnpack(str) {
TRACE_JSSTRING("unpack: '" + str + "'");
var r = HS_NIL, i = str.length-1, c;
while(i >= 0) {
c = str.charCodeAt(i--);
if(IS_LO_SURR(c)) c = FROM_SURR(str.charCodeAt(i--), c)
r = MK_CONS(c, r);
}
return r;
}
#if __GLASGOW_HASKELL__ >= 800
function h$jsstringDecInteger(val) {
TRACE_JSSTRING("decInteger");
if(IS_INTEGER_S(val)) {
return '' + INTEGER_S_DATA(val);
} else if(IS_INTEGER_Jp(val)) {
return h$ghcjsbn_showBase(INTEGER_J_DATA(val), 10);
} else {
return '-' + h$ghcjsbn_showBase(INTEGER_J_DATA(val), 10);
}
}
#else
function h$jsstringDecInteger(val) {
TRACE_JSSTRING("decInteger");
if(IS_INTEGER_S(val)) {
return '' + INTEGER_S_DATA(val);
} else {
return INTEGER_J_DATA(val).toString();
}
}
#endif
function h$jsstringDecI64(hi,lo) {
TRACE_JSSTRING("decI64: " + hi + " " + lo);
var lo0 = (lo < 0) ? lo+4294967296:lo;
if(hi < 0) {
if(hi === -1) return ''+(lo0-4294967296);
lo0 = 4294967296 - lo0;
var hi0 = -1 - hi;
var x0 = hi0 * 967296;
var x1 = (lo0 + x0) % 1000000;
var x2 = hi0*4294+Math.floor((x0+lo0-x1)/1000000);
return '-' + x2 + h$jsstringDecIPadded6(x1);
} else {
if(hi === 0) return ''+lo0;
var x0 = hi * 967296;
var x1 = (lo0 + x0) % 1000000;
var x2 = hi*4294+Math.floor((x0+lo0-x1)/1000000);
return '' + x2 + h$jsstringDecIPadded6(x1);
}
}
function h$jsstringDecW64(hi,lo) {
TRACE_JSSTRING("decW64: " + hi + " " + lo);
var lo0 = (lo < 0) ? lo+4294967296 : lo;
if(hi === 0) return ''+lo0;
var hi0 = (hi < 0) ? hi+4294967296 : hi;
var x0 = hi0 * 967296;
var x1 = (lo0 + x0) % 1000000;
var x2 = hi0*4294+Math.floor((x0+lo0-x1)/1000000);
return '' + x2 + h$jsstringDecIPadded6(x1);
}
#if __GLASGOW_HASKELL__ >= 800
function h$jsstringHexInteger(val) {
TRACE_JSSTRING("hexInteger");
if(IS_INTEGER_S(val)) {
return '' + INTEGER_S_DATA(val);
} else {
// we assume it's nonnegative. this condition is checked by the Haskell code
return h$ghcjsbn_showBase(INTEGER_J_DATA(val), 16);
}
}
#else
function h$jsstringHexInteger(val) {
TRACE_JSSTRING("hexInteger");
if(IS_INTEGER_S(val)) {
return '' + INTEGER_S_DATA(val);
} else {
return INTEGER_J_DATA(val).toRadix(16);
}
}
#endif
function h$jsstringHexI64(hi,lo) {
var lo0 = lo<0 ? lo+4294967296 : lo;
if(hi === 0) return lo0.toString(16);
return ((hi<0)?hi+4294967296:hi).toString(16) + h$jsstringHexIPadded8(lo0);
}
function h$jsstringHexW64(hi,lo) {
var lo0 = lo<0 ? lo+4294967296 : lo;
if(hi === 0) return lo0.toString(16);
return ((hi<0)?hi+4294967296:hi).toString(16) + h$jsstringHexIPadded8(lo0);
}
// n in [0, 1000000000)
function h$jsstringDecIPadded9(n) {
TRACE_JSSTRING("decIPadded9: " + n);
if(n === 0) return '000000000';
var pad = (n>=100000000)?'':
(n>=10000000)?'0':
(n>=1000000)?'00':
(n>=100000)?'000':
(n>=10000)?'0000':
(n>=1000)?'00000':
(n>=100)?'000000':
(n>=10)?'0000000':
'00000000';
return pad+n;
}
// n in [0, 1000000)
function h$jsstringDecIPadded6(n) {
TRACE_JSSTRING("decIPadded6: " + n);
if(n === 0) return '000000';
var pad = (n>=100000)?'':
(n>=10000)?'0':
(n>=1000)?'00':
(n>=100)?'000':
(n>=10)?'0000':
'00000';
return pad+n;
}
// n in [0, 2147483648)
function h$jsstringHexIPadded8(n) {
TRACE_JSSTRING("hexIPadded8: " + n);
if(n === 0) return '00000000';
var pad = (n>=0x10000000)?'':
(n>=0x1000000)?'0':
(n>=0x100000)?'00':
(n>=0x10000)?'000':
(n>=0x1000)?'0000':
(n>=0x100)?'00000':
(n>=0x10)?'000000':
'0000000';
return pad+n.toString(16);
}
function h$jsstringZeroes(n) {
var r;
switch(n&7) {
case 0: r = ''; break;
case 1: r = '0'; break;
case 2: r = '00'; break;
case 3: r = '000'; break;
case 4: r = '0000'; break;
case 5: r = '00000'; break;
case 6: r = '000000'; break;
case 7: r = '0000000';
}
for(var i=n>>3;i>0;i--) r = r + '00000000';
return r;
}
function h$jsstringDoubleToFixed(decs, d) {
if(decs >= 0) {
if(Math.abs(d) < 1e21) {
var r = d.toFixed(Math.min(20,decs));
if(decs > 20) r = r + h$jsstringZeroes(decs-20);
return r;
} else {
var r = d.toExponential();
var ei = r.indexOf('e');
var di = r.indexOf('.');
var e = parseInt(r.substr(ei+1));
return r.substring(0,di) + r.substring(di,ei) + h$jsstringZeroes(di-ei+e) +
((decs > 0) ? ('.' + h$jsstringZeroes(decs)) : '');
}
}
var r = Math.abs(d).toExponential();
var ei = r.indexOf('e');
var e = parseInt(r.substr(ei+1));
var m = d < 0 ? '-' : '';
r = r.substr(0,1) + r.substring(2,ei);
if(e >= 0) {
return (e > r.length) ? m + r + h$jsstringZeroes(r.length-e-1) + '.0'
: m + r.substr(0,e+1) + '.' + r.substr(e+1);
} else {
return m + '0.' + h$jsstringZeroes(-e-1) + r;
}
}
function h$jsstringDoubleToExponent(decs, d) {
var r;
if(decs ===-1) {
r = d.toExponential().replace('+','');
} else {
r = d.toExponential(Math.max(1, Math.min(20,decs))).replace('+','');
}
if(r.indexOf('.') === -1) {
r = r.replace('e', '.0e');
}
if(decs > 20) r = r.replace('e', h$jsstringZeroes(decs-20)+'e');
return r;
}
function h$jsstringDoubleGeneric(decs, d) {
var r;
if(decs === -1) {
r = d.toString(10).replace('+','');
} else {
r = d.toPrecision(Math.max(decs+1,1)).replace('+','');
}
if(decs !== 0 && r.indexOf('.') === -1) {
if(r.indexOf('e') !== -1) {
r = r.replace('e', '.0e');
} else {
r = r + '.0';
}
}
return r;
}
function h$jsstringAppend(x, y) {
TRACE_JSSTRING("append: '" + x + "' '" + y + "'");
return x+y;
}
function h$jsstringCompare(x, y) {
TRACE_JSSTRING("compare: '" + x + "' '" + y + "'");
return (x<y)?-1:((x>y)?1:0);
}
function h$jsstringUnlines(xs) {
var r = '';
while(IS_CONS(xs)) {
r = r + JSVAL_VAL(CONS_HEAD(xs)) + '\n';
xs = CONS_TAIL(xs);
}
return r;
}
function h$jsstringUnwords(xs) {
if(IS_NIL(xs)) return '';
var r = JSVAL_VAL(CONS_HEAD(xs));
xs = CONS_TAIL(xs);
while(IS_CONS(xs)) {
r = r + ' ' + JSVAL_VAL(CONS_HEAD(xs));
xs = CONS_TAIL(xs);
}
return r;
}
function h$jsstringReplace(pat, rep, src) {
TRACE_JSSTRING("replace: '" + pat + "' '" + rep + "' '" + src + "'");
var r = src.replace(pat, rep, 'g');
// the 'g' flag is not supported everywhere, check and fall back if necessary
if(r.indexOf(pat) !== -1) {
r = src.split(pat).join(rep);
}
return r;
}
function h$jsstringReplicateChar(n, ch) {
TRACE_JSSTRING("replicateChar: " + n + " " + ch);
return h$jsstringReplicate(n, h$jsstringSingleton(ch));
}
function h$jsstringIsInteger(str) {
return /^-?\d+$/.test(str);
}
function h$jsstringIsNatural(str) {
return /^\d+$/.test(str);
}
function h$jsstringReadInt(str) {
if(!/^-?\d+/.test(str)) return null;
var x = parseInt(str, 10);
var x0 = x|0;
return (x===x0) ? x0 : null;
}
function h$jsstringLenientReadInt(str) {
var x = parseInt(str, 10);
var x0 = x|0;
return (x===x0) ? x0 : null;
}
function h$jsstringReadWord(str) {
if(!/^\d+/.test(str)) return null;
var x = parseInt(str, 10);
var x0 = x|0;
if(x0<0) return (x===x0+2147483648) ? x0 : null;
else return (x===x0) ? x0 : null;
}
function h$jsstringReadDouble(str) {
return parseFloat(str, 10);
}
function h$jsstringLenientReadDouble(str) {
return parseFloat(str, 10);
}
function h$jsstringReadInteger(str) {
TRACE_JSSTRING("readInteger: " + str);
if(!/^(-)?\d+$/.test(str)) {
return null;
} else if(str.length <= 9) {
return MK_INTEGER_S(parseInt(str, 10));
} else {
#if __GLASGOW_HASKELL__ >= 800
return h$ghcjsbn_readInteger(str);
#else
return MK_INTEGER_J(new BigInteger(str, 10));
#endif
}
}
function h$jsstringReadInt64(str) {
if(!/^(-)?\d+$/.test(str)) {
RETURN_UBX_TUP3(0, 0, 0);
}
if(str.charCodeAt(0) === 45) { // '-'
return h$jsstringReadValue64(str, 1, true);
} else {
return h$jsstringReadValue64(str, 0, false);
}
}
function h$jsstringReadWord64(str) {
if(!/^\d+$/.test(str)) {
RETURN_UBX_TUP3(0, 0, 0);
}
return h$jsstringReadValue64(str, 0, false);
}
var h$jsstringLongs = null;
function h$jsstringReadValue64(str, start, negate) {
var l = str.length, i = start;
while(i < l) {
if(str.charCodeAt(i) !== 48) break;
i++;
}
if(i >= l) RETURN_UBX_TUP3(1, 0, 0); // only zeroes
if(h$jsstringLongs === null) {
h$jsstringLongs = [];
for(var t=10; t<=1000000000; t*=10) {
h$jsstringLongs.push(goog.math.Long.fromInt(t));
}
}
var li = l-i;
if(li < 10 && !negate) {
RETURN_UBX_TUP3(1, 0, parseInt(str.substr(i), 10));
}
var r = goog.math.Long.fromInt(parseInt(str.substr(li,9),10));
li += 9;
while(li < l) {
r = r.multiply(h$jsstringLongs[Math.min(l-li-1,8)])
.add(goog.math.Long.fromInt(parseInt(str.substr(li,9), 10)));
li += 9;
}
if(negate) {
r = r.negate();
}
RETURN_UBX_TUP3(1, r.getHighBits(), r.getLowBits());
}
function h$jsstringExecRE(i, str, re) {
re.lastIndex = i;
var m = re.exec(str);
if(m === null) return -1;
var a = [], x, j = 1, r = HS_NIL;
while(true) {
x = m[j];
if(typeof x === 'undefined') break;
a[j-1] = x;
j++;
}
j-=1;
while(--j>=0) r = MK_CONS(MK_JSVAL(a[j]), r);
RETURN_UBX_TUP3(m.index, m[0], r);
}
function h$jsstringReplaceRE(pat, replacement, str) {
return str.replace(pat, replacement);
}
function h$jsstringSplitRE(limit, re, str) {
re.lastIndex = i;
var s = (limit < 0) ? str.split(re) : str.split(re, limit);
var i = s.length, r = HS_NIL;
while(--i>=0) r = MK_CONS(MK_JSVAL(a[i]), r);
return r;
}