UNPKG

interskiplist

Version:

Binary Search for Numeric & Character Intervals; great for CSS-Unicode-Range-like tasks

1,739 lines (1,700 loc) 80.1 kB
(function() { //########################################################################################################### var CND, ISL, alert, badge, debug, echo, find_ids_text, help, hex, info, list, log, rpr, s, show, test, urge, warn, whisper; CND = require('cnd'); rpr = CND.rpr.bind(CND); badge = 'INTERSKIPLIST/tests'; log = CND.get_logger('plain', badge); info = CND.get_logger('info', badge); whisper = CND.get_logger('whisper', badge); alert = CND.get_logger('alert', badge); debug = CND.get_logger('debug', badge); warn = CND.get_logger('warn', badge); help = CND.get_logger('help', badge); urge = CND.get_logger('urge', badge); echo = CND.echo.bind(CND); //........................................................................................................... test = require('guy-test'); ISL = require('./main'); //=========================================================================================================== // HELPERS //----------------------------------------------------------------------------------------------------------- hex = function(n) { return '0x' + n.toString(16); }; s = function(x) { return JSON.stringify(x); }; //----------------------------------------------------------------------------------------------------------- find_ids_text = function(me, ...P) { var R; R = ISL._find_ids_with_all_points(me, ...P); R.sort(); return R.join(','); }; // #----------------------------------------------------------------------------------------------------------- // find_names_text = ( me, points ) -> // # debug '8322', ISL._find_ids_with_all_points me, points // R = ISL.match_common me, points, pick: 'name' // R.sort() // return R.join ',' //----------------------------------------------------------------------------------------------------------- list = function(me) { var _, entry, i, key, len, ref, ref1, type, value; ref = ISL.entries_of(me); for (i = 0, len = ref.length; i < len; i++) { entry = ref[i]; [type, _] = ((ref1 = entry['name']) != null ? ref1 : '???/').split(':'); help((CND.grey(type + '/')) + (CND.steel('interval')) + ': ' + (CND.yellow(`${hex(entry['lo'])}-${hex(entry['hi'])}`))); for (key in entry) { value = entry[key]; // continue if key in [ 'lo', 'hi', 'id', ] help((CND.grey(type + '/')) + (CND.steel(key)) + ': ' + (CND.yellow(value))); } } return null; }; //----------------------------------------------------------------------------------------------------------- show = function(me) { var hi, hi_closed, id, left, lo, lo_closed, ref, results, right; echo(' 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 '); echo(' 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789'); ref = me['%self'].intervalsByMarker; // debug '4921', me[ 'min' ], me[ 'max' ] results = []; for (id in ref) { [lo, hi] = ref[id]; lo_closed = true; hi_closed = true; // [ lo, hi, ] = [ hi, lo, ] if lo > hi if (lo < 0) { lo = 0; lo_closed = false; } if (hi > 199) { hi = 199; hi_closed = false; } while (id.length < 20) { id += ' '; } if (lo > 199 && hi > 199) { echo(id(id + ' ' + (' '.repeat(199)) + '->')); continue; } if (lo === hi) { echo(id + ' ' + (' '.repeat(lo)) + 'H'); continue; } left = lo_closed ? '[' : '-'; right = hi_closed ? ']' : '-'; results.push(echo(id + ' ' + (' '.repeat(lo)) + left + ('-'.repeat(hi - lo - 1)) + right)); } return results; }; //=========================================================================================================== // TESTS //----------------------------------------------------------------------------------------------------------- this["test interval tree 1"] = function(T) { var hi, i, id, intervals, isl, len, lo; //......................................................................................................... isl = ISL.new(); intervals = [[1, 3, 'A'], [2, 14, 'B'], [3, 7, 'C'], [4, 4, 'D'], [5, 7, 'E'], [8, 12, 'F1'], [8, 12, 'F2'], [8, 22, 'G'], [10, 13, 'H']]; //......................................................................................................... for (i = 0, len = intervals.length; i < len; i++) { [lo, hi, id] = intervals[i]; ISL.add(isl, {lo, hi, id}); } show(isl); //......................................................................................................... // search() T.eq(find_ids_text(isl, 0), ''); T.eq(find_ids_text(isl, 1), 'A'); T.eq(find_ids_text(isl, 2), 'A,B'); T.eq(find_ids_text(isl, 3), 'A,B,C'); T.eq(find_ids_text(isl, 4), 'B,C,D'); T.eq(find_ids_text(isl, 5), 'B,C,E'); T.eq(find_ids_text(isl, 6), 'B,C,E'); T.eq(find_ids_text(isl, 7), 'B,C,E'); T.eq(find_ids_text(isl, 8), 'B,F1,F2,G'); T.eq(find_ids_text(isl, 9), 'B,F1,F2,G'); T.eq(find_ids_text(isl, 10), 'B,F1,F2,G,H'); T.eq(find_ids_text(isl, 11), 'B,F1,F2,G,H'); T.eq(find_ids_text(isl, 12), 'B,F1,F2,G,H'); T.eq(find_ids_text(isl, 13), 'B,G,H'); T.eq(find_ids_text(isl, 14), 'B,G'); T.eq(find_ids_text(isl, 15), 'G'); T.eq(find_ids_text(isl, 16), 'G'); T.eq(find_ids_text(isl, 17), 'G'); T.eq(find_ids_text(isl, 18), 'G'); // ISL.add isl, [ 10, 13, 'FF' ] // delete isl[ '%self' ] // debug '©29478', isl return null; }; //----------------------------------------------------------------------------------------------------------- this["test interval tree 2"] = function(T) { var hi, i, intervals, isl, len, lo, tag; //......................................................................................................... isl = ISL.new(); intervals = [[1, 3, 'orion'], [2, 14, 'orion'], [3, 7, 'orion'], [4, 4, 'orion'], [5, 7, 'cygnus'], [5, 7, 'orion'], [8, 12, 'aldebaran'], [-12, 8, 'aldebaran'], [8, 22, 'aldebaran'], [10, 13, 'aldebaran'], [11, 15, 'cygnus']]; //......................................................................................................... for (i = 0, len = intervals.length; i < len; i++) { [lo, hi, tag] = intervals[i]; ISL.add(isl, {lo, hi, tag}); } show(isl); //......................................................................................................... T.eq(ISL.match(isl, 0, { pick: 'tag' }), ["aldebaran"]); T.eq(ISL.match(isl, 1, { pick: 'tag' }), ["orion", "aldebaran"]); T.eq(ISL.match(isl, 2, { pick: 'tag' }), ["orion", "aldebaran"]); T.eq(ISL.match(isl, 3, { pick: 'tag' }), ["orion", "aldebaran"]); T.eq(ISL.match(isl, 4, { pick: 'tag' }), ["orion", "aldebaran"]); T.eq(ISL.match(isl, 5, { pick: 'tag' }), ["cygnus", "orion", "aldebaran"]); T.eq(ISL.match(isl, 6, { pick: 'tag' }), ["cygnus", "orion", "aldebaran"]); T.eq(ISL.match(isl, 7, { pick: 'tag' }), ["cygnus", "orion", "aldebaran"]); T.eq(ISL.match(isl, 8, { pick: 'tag' }), ["orion", "aldebaran"]); T.eq(ISL.match(isl, 9, { pick: 'tag' }), ["orion", "aldebaran"]); T.eq(ISL.match(isl, 10, { pick: 'tag' }), ["orion", "aldebaran"]); T.eq(ISL.match(isl, 11, { pick: 'tag' }), ["orion", "aldebaran", "cygnus"]); T.eq(ISL.match(isl, 12, { pick: 'tag' }), ["orion", "aldebaran", "cygnus"]); T.eq(ISL.match(isl, 13, { pick: 'tag' }), ["orion", "aldebaran", "cygnus"]); T.eq(ISL.match(isl, 14, { pick: 'tag' }), ["orion", "aldebaran", "cygnus"]); T.eq(ISL.match(isl, 15, { pick: 'tag' }), ["aldebaran", "cygnus"]); T.eq(ISL.match(isl, 16, { pick: 'tag' }), ["aldebaran"]); T.eq(ISL.match(isl, 17, { pick: 'tag' }), ["aldebaran"]); T.eq(ISL.match(isl, 18, { pick: 'tag' }), ["aldebaran"]); //......................................................................................................... // debug JSON.stringify ISL.match isl, 0, pick: 'tag' // debug JSON.stringify ISL.match isl, 1, pick: 'tag' // debug JSON.stringify ISL.match isl, 2, pick: 'tag' // debug JSON.stringify ISL.match isl, 3, pick: 'tag' // debug JSON.stringify ISL.match isl, 4, pick: 'tag' // debug JSON.stringify ISL.match isl, 5, pick: 'tag' // debug JSON.stringify ISL.match isl, 6, pick: 'tag' // debug JSON.stringify ISL.match isl, 7, pick: 'tag' // debug JSON.stringify ISL.match isl, 8, pick: 'tag' // debug JSON.stringify ISL.match isl, 9, pick: 'tag' // debug JSON.stringify ISL.match isl, 10, pick: 'tag' // debug JSON.stringify ISL.match isl, 11, pick: 'tag' // debug JSON.stringify ISL.match isl, 12, pick: 'tag' // debug JSON.stringify ISL.match isl, 13, pick: 'tag' // debug JSON.stringify ISL.match isl, 14, pick: 'tag' // debug JSON.stringify ISL.match isl, 15, pick: 'tag' // debug JSON.stringify ISL.match isl, 16, pick: 'tag' // debug JSON.stringify ISL.match isl, 17, pick: 'tag' // debug JSON.stringify ISL.match isl, 18, pick: 'tag' //......................................................................................................... // delete isl[ '%self' ] // debug '©29478', isl return null; }; //----------------------------------------------------------------------------------------------------------- this["test interval tree 3"] = function(T) { var entry, error_count, hi, i, intervals, isl, len, lo, name, type; isl = ISL.new(); intervals = [[17, 19, 'plane', 'A'], [5, 8, 'plane', 'B'], [21, 24, 'block', 'A'], [4, 8, 'block', 'D']]; for (i = 0, len = intervals.length; i < len; i++) { [lo, hi, type, name] = intervals[i]; ISL.add(isl, {lo, hi, type, name}); } show(isl); // ISL._decorate isl[ '%self' ][ 'root' ] // search() error_count = 0; // error_count += eq ( find_ids_text isl, 0 ), '' // debug rpr find_ids_text isl, [ 23, 25, ] # 'C' // debug rpr find_ids_text isl, [ 12, 14, ] # '' // debug rpr find_ids_text isl, [ 21, 23, ] # 'G,C' // debug rpr find_ids_text isl, [ 8, 9, ] # 'B,D,F' // debug rpr find_ids_text isl, [ 5, 8, ] // debug rpr find_ids_text isl, [ 21, 24, ] // debug rpr find_ids_text isl, [ 4, 8, ] T.eq(ISL.intersect(isl, [18, 22]), [ { "lo": 17, "hi": 19, "type": "plane", "name": "A", "idx": 0, "id": "A[0]", "size": 3 }, { "lo": 21, "hi": 24, "type": "block", "name": "A", "idx": 2, "id": "A[1]", "size": 4 } ]); T.eq((function() { var j, len1, ref, results; ref = ISL.intersect(isl, [18, 22]); results = []; for (j = 0, len1 = ref.length; j < len1; j++) { entry = ref[j]; if (entry['type'] === 'block') { results.push(entry); } } return results; })(), [ { "lo": 21, "hi": 24, "type": "block", "name": "A", "idx": 2, "id": "A[1]", "size": 4 } ]); T.eq(ISL.match(isl, [2, 30]), []); T.eq(ISL.intersect(isl, 18), [ { "lo": 17, "hi": 19, "type": "plane", "name": "A", "idx": 0, "id": "A[0]", "size": 3 } ]); T.eq(ISL.match(isl, 18), [ { "lo": 17, "hi": 19, "type": "plane", "name": "A", "idx": 0, "id": "A[0]", "size": 3 } ]); // debug s ISL.intersect isl, [ 18, 22, ] // debug s ( entry for entry in ISL.intersect isl, [ 18, 22, ] when entry[ 'type' ] is 'block' ) // debug s ISL.match isl, [ 2, 30, ] // debug s ISL.intersect isl, 18 // debug s ISL.match isl, 18 // search() // debug '4430', ISL.get_values isl //......................................................................................................... return null; }; //----------------------------------------------------------------------------------------------------------- this["characters as points 1"] = function(T) { var a_cid, entry, isl, z_cid; a_cid = 'a'.codePointAt(0); z_cid = 'z'.codePointAt(0); //......................................................................................................... isl = ISL.new(); ISL.add(isl, { lo: a_cid, hi: z_cid, name: 'Basic Latin:Lower Case' }); entry = (ISL.entries_of(isl))[0]; T.eq(entry['lo'], a_cid); T.eq(entry['hi'], z_cid); T.eq(isl['min'], a_cid); T.eq(isl['max'], z_cid); T.eq(isl['fmin'], a_cid); T.eq(isl['fmax'], z_cid); //......................................................................................................... isl = ISL.new(); ISL.add(isl, { lo: 'a', hi: 'z', name: 'Basic Latin:Lower Case' }); entry = (ISL.entries_of(isl))[0]; T.eq(entry['lo'], a_cid); T.eq(entry['hi'], z_cid); T.eq(isl['min'], a_cid); T.eq(isl['max'], z_cid); T.eq(isl['fmin'], a_cid); T.eq(isl['fmax'], z_cid); //......................................................................................................... return null; }; //----------------------------------------------------------------------------------------------------------- this["_characters as points 3"] = function(T) { var chr, i, isl, j, k, len, len1, len2, ref, ref1, ref2; throw new Error("not implemented"); isl = ISL.new(); ISL.add(isl, { lo: 0x00, hi: 0x7f, name: 'basic-latin' }); ISL.add(isl, { lo: 'a', hi: 'z', name: 'letter' }); ISL.add(isl, { lo: 'A', hi: 'Z', name: 'letter' }); ISL.add(isl, { lo: 'a', hi: 'z', name: 'lower' }); ISL.add(isl, { lo: 'A', hi: 'Z', name: 'upper' }); ref = 'aeiouAEIOU'; //......................................................................................................... for (i = 0, len = ref.length; i < len; i++) { chr = ref[i]; ISL.add(isl, { lo: chr, hi: chr, name: 'vowel' }); } ref1 = 'bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ'; for (j = 0, len1 = ref1.length; j < len1; j++) { chr = ref1[j]; ISL.add(isl, { lo: chr, hi: chr, name: 'consonant' }); } ref2 = '0123456789'; for (k = 0, len2 = ref2.length; k < len2; k++) { chr = ref2[k]; ISL.add(isl, { lo: chr, hi: chr, name: 'digit' }); } //......................................................................................................... // debug '4432', find_names_text isl, [ 'c', 'A', ] //......................................................................................................... T.eq(find_names_text(isl, ['c']), 'basic-latin,consonant,letter,lower'); T.eq(find_names_text(isl, ['C']), 'basic-latin,consonant,letter,upper'); T.eq(find_names_text(isl, ['c', 'C']), 'basic-latin,consonant,letter'); T.eq(find_names_text(isl, ['C', 'C']), 'basic-latin,consonant,letter,upper'); T.eq(find_names_text(isl, ['C', 'A']), 'basic-latin,letter,upper'); T.eq(find_names_text(isl, ['c', 'A']), 'basic-latin,letter'); T.eq(find_names_text(isl, ['A', 'e']), 'basic-latin,letter,vowel'); T.eq(find_names_text(isl, ['i', 'e']), 'basic-latin,letter,lower,vowel'); T.eq(find_names_text(isl, ['2', 'e']), 'basic-latin'); //......................................................................................................... return null; }; //----------------------------------------------------------------------------------------------------------- this["intervals_from_points"] = function(T) { var A_cid, B_cid, C_cid, X_cid, Y_cid, Z_cid, isl; isl = ISL.new(); // debug ISL.intervals_from_points isl, Array.from 'abcefg' T.eq(ISL.intervals_from_points(isl, [3, 4, 5]), [ { lo: 3, hi: 5 } ]); T.eq(ISL.intervals_from_points(isl, [3, 4, 5, 7, 8, 9, 10]), [ { lo: 3, hi: 5 }, { lo: 7, hi: 10 } ]); T.eq(ISL.intervals_from_points(isl, [7, 10]), [ { lo: 7, hi: 7 }, { lo: 10, hi: 10 } ]); A_cid = 'A'.codePointAt(0); B_cid = 'B'.codePointAt(0); C_cid = 'C'.codePointAt(0); X_cid = 'X'.codePointAt(0); Y_cid = 'Y'.codePointAt(0); Z_cid = 'Z'.codePointAt(0); T.eq(ISL.intervals_from_points(isl, Array.from('CBABAXZY')), [ { lo: A_cid, hi: C_cid }, { lo: X_cid, hi: Z_cid } ]); T.eq(ISL.intervals_from_points(isl, Array.from('CBABAXZY'), { name: 'foo' }), [ { lo: A_cid, hi: C_cid, name: 'foo' }, { lo: X_cid, hi: Z_cid, name: 'foo' } ]); //......................................................................................................... return null; }; //----------------------------------------------------------------------------------------------------------- this["intervals without ID, name"] = function(T) { var isl; isl = ISL.new(); ISL.add(isl, { lo: 'a', 'hi': 'z' }); ISL.add(isl, { lo: 'a', 'hi': 'k', id: 'lower-half' }); ISL.add(isl, { lo: 'l', 'hi': 'z', name: 'upper-half' }); // debug JSON.stringify ISL.intersect isl, [ 'c', 'm', ] T.eq(ISL.intersect(isl, ['c', 'm']), [ { "lo": 97, "hi": 122, "idx": 0, "id": "+[0]", "name": "+", "size": 26 }, { "lo": 97, "hi": 107, "id": "lower-half", "idx": 1, "name": "+", "size": 11 }, { "lo": 108, "hi": 122, "name": "upper-half", "idx": 2, "id": "upper-half[0]", "size": 15 } ]); return null; }; //----------------------------------------------------------------------------------------------------------- this["aggregation 1"] = function(T) { /* 《 0x300a */ var description, entries, entry, i, isl, len, replacers; entries = [ { //....................................................................................................... lo: 0x0, hi: 0x10ffff, type: 'style', name: 'fallback', tex: 'mktsRsgFb' }, { //....................................................................................................... lo: 0x0, hi: 0xffff, type: 'plane', name: 'Basic Multilingual Plane (BMP)' }, { //....................................................................................................... lo: 0x2e80, hi: 0x33ff, type: 'area', name: 'CJK Miscellaneous Area' }, { //....................................................................................................... lo: 0x3000, hi: 0x303f, type: 'block', name: 'CJK Symbols and Punctuation', rsg: 'u-cjk-sym', is_cjk: true, tex: 'cnsymOld' }, { //....................................................................................................... lo: 0x3000, hi: 0x303f, type: 'block', name: 'CJK Symbols and Punctuation', rsg: 'u-cjk-sym', is_cjk: true, tex: 'cnsymNew' }, { //....................................................................................................... lo: 0x300a, hi: 0x300a, type: 'style', name: 'glyph-0x300a', rsg: 'u-cjk-sym', style: { raise: -0.2 } } ]; //......................................................................................................... //....................................................................................................... isl = ISL.new(); for (i = 0, len = entries.length; i < len; i++) { entry = entries[i]; ISL.add(isl, entry); } //......................................................................................................... replacers = { fields: { type: 'list', style: 'list', tex: 'list', rsg: 'assign', name: 'assign' } }; //......................................................................................................... description = ISL.aggregate(isl, '《'.codePointAt(0), replacers); // debug JSON.stringify description help(description); T.eq(description, { type: ['style', 'plane', 'area', 'block', 'block', 'style'], name: 'glyph-0x300a', tex: ['mktsRsgFb', 'cnsymOld', 'cnsymNew'], rsg: 'u-cjk-sym', is_cjk: true, style: [ { raise: -0.2 } ] }); //......................................................................................................... return null; }; //----------------------------------------------------------------------------------------------------------- this["aggregation 2"] = function(T) { var isl, reducers; isl = ISL.new(); ISL.add(isl, { lo: 0, hi: 10, id: 'wide', count: 10, length: 10, foo: 'D' }); ISL.add(isl, { lo: 3, hi: 7, id: 'narrow', count: 4, length: 4, foo: 'UH' }); reducers = { fallback: 'list', fields: { id: 'list', lo: 'assign', hi: 'assign', name: 'assign', count: 'add', length: 'average', foo: function(values) { var value; return (((function() { var i, len, results; results = []; for (i = 0, len = values.length; i < len; i++) { value = values[i]; results.push(value.toLowerCase()); } return results; })()).join('')) + '!'; } } }; debug(JSON.stringify(ISL.aggregate(isl, 5, reducers))); T.eq(ISL.aggregate(isl, 5, reducers), { "lo": 3, "hi": 7, "id": ["wide", "narrow"], "count": 14, "name": "+", "length": 7, "foo": "duh!" }); return null; }; //----------------------------------------------------------------------------------------------------------- this["readme example 1"] = function(T) { var chr, consonants, digits, i, interval, isl, j, k, len, len1, len2, ref, ref1, ref2; isl = ISL.new(); ISL.add(isl, { lo: 0x00, hi: 0x7f, name: 'basic-latin' }); ISL.add(isl, { lo: 'a', hi: 'z', name: 'letter' }); ISL.add(isl, { lo: 'A', hi: 'Z', name: 'letter' }); ISL.add(isl, { lo: 'a', hi: 'z', name: 'lower' }); ISL.add(isl, { lo: 'A', hi: 'Z', name: 'upper' }); ref = 'aeiouAEIOU'; //......................................................................................................... for (i = 0, len = ref.length; i < len; i++) { chr = ref[i]; ISL.add(isl, { lo: chr, hi: chr, name: 'vowel' }); } consonants = Array.from('bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ'); ref1 = ISL.intervals_from_points(isl, consonants, { name: 'consonant' }); for (j = 0, len1 = ref1.length; j < len1; j++) { interval = ref1[j]; ISL.add(isl, interval); } digits = Array.from('0123456789'); ref2 = ISL.intervals_from_points(isl, digits, { name: 'digit' }); for (k = 0, len2 = ref2.length; k < len2; k++) { interval = ref2[k]; ISL.add(isl, interval); } //......................................................................................................... show(isl); //......................................................................................................... // console.log ISL.find_names_with_all_points isl, [ 'c' , ] // console.log ISL.find_names_with_all_points isl, [ 'C' , ] // console.log ISL.find_names_with_all_points isl, [ 'c', 'C', ] // console.log ISL.find_names_with_all_points isl, [ 'C', 'C', ] // console.log ISL.find_names_with_all_points isl, [ 'C', 'A', ] // console.log ISL.find_names_with_all_points isl, [ 'c', 'A', ] // console.log ISL.find_names_with_all_points isl, [ 'A', 'e', ] // console.log ISL.find_names_with_all_points isl, [ 'i', 'e', ] // console.log ISL.find_names_with_all_points isl, [ '2', 'e', ] //......................................................................................................... return null; }; //----------------------------------------------------------------------------------------------------------- this["readme example 2"] = function(T) { var replacers, samples; samples = ISL.new(); ISL.add(samples, { lo: 0x0000, hi: 0x10ffff, name: 'base', font_family: 'Arial' }); ISL.add(samples, { lo: 0x00, hi: 0xff, name: 'ascii', font_family: 'Arial' }); ISL.add(samples, { lo: 0x4e00, hi: 0x9fff, name: 'cjk', font_family: 'Sun-ExtA' }); ISL.add(samples, { lo: 0x3040, hi: 0x309f, name: 'cjk', font_family: 'Sun-ExtA' }); ISL.add(samples, { lo: 0x26, hi: 0x26, name: 'ampersand', font_family: 'Baskerville' }); // debug 'rx2-1', 'A', ISL.find_names_with_all_points samples, 'A' # --> [ 'latin' ] // debug 'rx2-2', '&', ISL.find_names_with_all_points samples, '&' # --> [ 'latin', 'ampersand' ] // debug 'rx2-3', '人', ISL.find_names_with_all_points samples, '人' # --> [ 'latin', 'cjk' ] // debug 'rx2-3', 'Abcd人', ISL.find_names_with_all_points samples, Array.from 'Abcd人' # --> [ 'latin', 'cjk' ] // debug 'rx2-3', '人はるのそらのした', ISL.find_names_with_all_points samples, Array.from '人はるのそらのした' # --> [ 'latin', 'cjk' ] // T.eq ( ISL.find_names_with_all_points samples, 'A' ), ( ISL.find_names samples, 'A' ) // T.eq ( ISL.find_names_with_all_points samples, '&' ), ( ISL.find_names samples, '&' ) // T.eq ( ISL.find_names_with_all_points samples, '人' ), ( ISL.find_names samples, '人' ) T.eq(ISL._find_ids_with_all_points(samples, 'A'), ISL.match(samples, 'A', { pick: 'id' })); T.eq(ISL._find_ids_with_all_points(samples, '&'), ISL.match(samples, '&', { pick: 'id' })); T.eq(ISL._find_ids_with_all_points(samples, '人'), ISL.match(samples, '人', { pick: 'id' })); // T.eq ( ISL.find_intervals_with_all_points samples, 'A' ), ( ISL.find_intervals samples, 'A' ) // T.eq ( ISL.find_intervals_with_all_points samples, '&' ), ( ISL.find_intervals samples, '&' ) // T.eq ( ISL.find_intervals_with_all_points samples, '人' ), ( ISL.find_intervals samples, '人' ) T.eq(ISL.intersect(samples, 'A'), ISL.match(samples, 'A')); T.eq(ISL.intersect(samples, '&'), ISL.match(samples, '&')); T.eq(ISL.intersect(samples, '人'), ISL.match(samples, '人')); urge('rx2-7', 'A', ISL.aggregate(samples, 'A')); //, { font_family: 'list', } urge('rx2-8', '&', ISL.aggregate(samples, '&')); //, { font_family: 'list', } urge('rx2-9', '人', ISL.aggregate(samples, '人')); //, { font_family: 'list', } replacers = { fallback: 'list', name: 'list' }; info('rx2-10', 'A', ISL.aggregate(samples, 'A', replacers)); info('rx2-11', '&', ISL.aggregate(samples, '&', replacers)); info('rx2-12', '人', ISL.aggregate(samples, '人', replacers)); //......................................................................................................... return null; }; //----------------------------------------------------------------------------------------------------------- this["demo discontiguous ranges"] = function(T) { var u; u = ISL.new(); ISL.add(u, { lo: 0x4e00, hi: 0x9fff, name: 'cjk', id: 'u-cjk' }); ISL.add(u, { lo: 0xff00, hi: 0xffef, name: 'cjk', id: 'u-halfull' }); ISL.add(u, { lo: 0x3400, hi: 0x4dbf, name: 'cjk', id: 'u-cjk-xa' }); ISL.add(u, { lo: 0x20000, hi: 0x2a6df, name: 'cjk', id: 'u-cjk-xb' }); ISL.add(u, { lo: 0x2a700, hi: 0x2b73f, name: 'cjk', id: 'u-cjk-xc' }); ISL.add(u, { lo: 0x2b740, hi: 0x2b81f, name: 'cjk', id: 'u-cjk-xd' }); ISL.add(u, { lo: 0x2b820, hi: 0x2ceaf, name: 'cjk', id: 'u-cjk-xe' }); ISL.add(u, { lo: 0xf900, hi: 0xfaff, name: 'cjk', id: 'u-cjk-cmpi1' }); ISL.add(u, { lo: 0x2f800, hi: 0x2fa1f, name: 'cjk', id: 'u-cjk-cmpi2' }); ISL.add(u, { lo: 0x2f00, hi: 0x2fdf, name: 'cjk', id: 'u-cjk-rad1' }); ISL.add(u, { lo: 0x2e80, hi: 0x2eff, name: 'cjk', id: 'u-cjk-rad2' }); ISL.add(u, { lo: 0x3000, hi: 0x303f, name: 'cjk', id: 'u-cjk-sym' }); ISL.add(u, { lo: 0x31c0, hi: 0x31ef, name: 'cjk', id: 'u-cjk-strk' }); ISL.add(u, { lo: 0x30a0, hi: 0x30ff, name: 'cjk', id: 'u-cjk-kata' }); ISL.add(u, { lo: 0x3040, hi: 0x309f, name: 'cjk', id: 'u-cjk-hira' }); ISL.add(u, { lo: 0xac00, hi: 0xd7af, name: 'cjk', id: 'u-hang-syl' }); ISL.add(u, { lo: 0x3200, hi: 0x32ff, name: 'cjk', id: 'u-cjk-enclett' }); //......................................................................................................... return null; }; //----------------------------------------------------------------------------------------------------------- this["unique names with priority conflict"] = function(T) { var isl; isl = ISL.new(); ISL.add(isl, { lo: 15, hi: 20, id: 'alpha-0', name: 'alpha' }); ISL.add(isl, { lo: 15, hi: 25, id: 'beta-0', name: 'beta' }); ISL.add(isl, { lo: 15, hi: 25, id: 'omega-0', name: 'omega' }); ISL.add(isl, { lo: 15, hi: 49, id: 'gamma-0', name: 'gamma' }); ISL.add(isl, { lo: 15, hi: 29, id: 'beta-1', name: 'beta' }); show(isl); // debug '3928', JSON.stringify ISL.match isl, 15, pick: 'id' // debug '3928', JSON.stringify ISL.find_names isl, 15 // urge '3928', JSON.stringify ISL.find_names_with_all_points isl, [ 15, 16, 30, ] // urge '3928', JSON.stringify ISL.find_names_with_any_points isl, [ 15, 16, 30, ] T.eq(ISL.match(isl, 15, { pick: 'id' }), ["alpha-0", "beta-0", "omega-0", "gamma-0", "beta-1"]); T.eq(ISL.match(isl, 15, { pick: 'name' }), ["alpha", "omega", "gamma", "beta"]); // T.eq ( ISL.match_common isl, [ 15, 16, 30, ], pick: 'name' ), ["gamma"] // T.eq ( ISL.match_common isl, [ 15, 16, 30, ], pick: 'name' ), ["alpha","omega","beta","gamma"] return null; }; //----------------------------------------------------------------------------------------------------------- this["tag 1"] = function(T) { var digit, digit_0, digit_1, i, j, n, u; u = ISL.new(); //......................................................................................................... ISL.add(u, { lo: 0x00, hi: 0x7f, name: 'ascii' }); for (n = i = 0; i <= 8; n = i += +2) { digit_0 = `${n}`; digit_1 = `${n + 1}`; ISL.add(u, { lo: digit_0, hi: digit_0, tag: ['ascii', 'digit', 'even'] }); ISL.add(u, { lo: digit_1, hi: digit_1, tag: ['ascii', 'digit', 'odd'] }); } ISL.add(u, { lo: '2', hi: '2', tag: ['prime'] }); ISL.add(u, { lo: '3', hi: '3', tag: ['prime'] }); ISL.add(u, { lo: '5', hi: '5', tag: ['prime'] }); ISL.add(u, { lo: '7', hi: '7', tag: ['prime'] }); //......................................................................................................... for (n = j = 0; j <= 9; n = ++j) { digit = `${n}`; help(digit, ISL.aggregate(u, digit, { fallback: 'skip', tag: 'tag' })); } //......................................................................................................... T.eq(ISL.aggregate(u, '3', { fallback: 'skip', tag: 'tag' }), { tag: ['ascii', 'digit', 'odd', 'prime'] }); //......................................................................................................... return null; }; //----------------------------------------------------------------------------------------------------------- this["tag 2"] = function(T) { var digit_0, digit_1, i, n, u; u = ISL.new(); //......................................................................................................... ISL.add(u, { lo: 0x00, hi: 0x7f, name: 'ascii' }); for (n = i = 0; i <= 8; n = i += +2) { digit_0 = `${n}`; digit_1 = `${n + 1}`; ISL.add(u, { lo: digit_0, hi: digit_0, tag: ['ascii', 'digit', 'even'] }); ISL.add(u, { lo: digit_1, hi: digit_1, tag: ['ascii', 'digit', 'odd'] }); } ISL.add(u, { lo: '2', hi: '2', tag: 'prime' }); ISL.add(u, { lo: '3', hi: '3', tag: 'prime' }); ISL.add(u, { lo: '5', hi: '5', tag: 'prime' }); ISL.add(u, { lo: '7', hi: '7', tag: 'prime' }); //......................................................................................................... T.eq(ISL.aggregate(u, '3'), { tag: ['ascii', 'digit', 'odd', 'prime'] }); //......................................................................................................... return null; }; //----------------------------------------------------------------------------------------------------------- this["tag 2a"] = function(T) { var digit_0, i, j, len, matcher, n, probe, probes_and_matchers, result, u; probes_and_matchers = [ [ '0', { tag: ['digit', 'even'] } ], [ '1', { tag: ['digit', 'odd'] } ], [ '2', { tag: ['digit', 'even'] } ], [ '3', { tag: ['digit', 'odd'] } ], [ '4', { tag: ['digit', 'even'] } ], [ '5', { tag: ['digit', 'odd'] } ], [ '6', { tag: ['digit', 'even'] } ], [ '7', { tag: ['digit', 'odd'] } ], [ '8', { tag: ['digit', 'even'] } ], [ '9', { tag: ['digit', 'odd'] } ] ]; //......................................................................................................... u = ISL.new(); //......................................................................................................... ISL.add(u, { lo: 0x00, hi: 0x7f, name: 'ascii' }); ISL.add(u, { lo: '0', hi: '9', tag: ['digit', 'even'] }); for (n = i = 1; i <= 9; n = i += +2) { digit_0 = `${n}`; ISL.add(u, { lo: digit_0, hi: digit_0, tag: ['-even', 'odd'] }); } //......................................................................................................... for (j = 0, len = probes_and_matchers.length; j < len; j++) { [probe, matcher] = probes_and_matchers[j]; result = ISL.aggregate(u, probe, { name: 'skip' }); // debug '0141', [ probe, result, ] T.eq(result, matcher); } //......................................................................................................... return null; }; //----------------------------------------------------------------------------------------------------------- this["tag 2b"] = function(T) { var digit_0, i, j, len, matcher, n, probe, probes_and_matchers, result, u; probes_and_matchers = [ [ '0', { tag: ['digit', 'even'] } ], [ '1', { tag: ['digit', 'odd'] } ], [ '2', { tag: ['digit', 'even'] } ], [ '3', { tag: ['digit', 'odd'] } ], [ '4', { tag: ['digit', 'even'] } ], [ '5', { tag: ['digit', 'odd'] } ], [ '6', { tag: ['digit', 'even'] } ], [ '7', { tag: ['digit', 'odd'] } ], [ '8', { tag: ['digit', 'even'] } ], [ '9', { tag: ['digit', 'odd'] } ] ]; //......................................................................................................... u = ISL.new(); //......................................................................................................... ISL.add(u, { lo: 0x00, hi: 0x7f, name: 'ascii' }); ISL.add(u, { lo: '0', hi: '9', tag: 'digit even' }); for (n = i = 1; i <= 9; n = i += +2) { digit_0 = `${n}`; ISL.add(u, { lo: digit_0, hi: digit_0, tag: '-even odd' }); } //......................................................................................................... for (j = 0, len = probes_and_matchers.length; j < len; j++) { [probe, matcher] = probes_and_matchers[j]; result = ISL.aggregate(u, probe, { name: 'skip' }); // debug '0141', [ probe, result, ] T.eq(result, matcher); } //......................................................................................................... return null; }; //----------------------------------------------------------------------------------------------------------- this["tag 3"] = function(T) { var digit_0, digit_1, i, n, u; u = ISL.new(); //......................................................................................................... ISL.add(u, { lo: 0x00, hi: 0x7f, tag: 'ascii' }); ISL.add(u, { lo: 0x00, hi: 0x7f, name: 'ascii-duplicate' }); for (n = i = 0; i <= 8; n = i += +2) { digit_0 = `${n}`; digit_1 = `${n + 1}`; ISL.add(u, { lo: digit_0, hi: digit_0, tag: ['ascii', 'digit', 'even'] }); ISL.add(u, { lo: digit_1, hi: digit_1, tag: ['ascii', 'digit', 'odd'] }); } ISL.add(u, { lo: '2', hi: '2', tag: 'prime' }); ISL.add(u, { lo: '3', hi: '3', tag: 'prime' }); ISL.add(u, { lo: '5', hi: '5', tag: 'prime' }); ISL.add(u, { lo: '7', hi: '7', tag: 'prime' }); //......................................................................................................... T.eq(ISL.aggregate(u, '3'), { tag: ['ascii', 'digit', 'odd', 'prime'] }); // debug '5531-6', s ISL.find_tags_with_all_points u, [ '3', '7', '2', ] // debug '5531-7', s ISL.find_tags_with_any_points u, [ '3', '7', '2', ] // T.eq ( ISL.find_tags u, '3' ), ["ascii","digit","odd","prime"] // T.eq ( ISL.find_tags_with_all_points u, [ '3', '7', '2', ] ), ["ascii","digit","prime"] // T.eq ( ISL.find_tags_with_any_points u, [ '3', '7', '2', ] ), ["even","ascii","digit","odd","prime"] //......................................................................................................... info(u); return null; }; //----------------------------------------------------------------------------------------------------------- this["negative tags"] = function(T) { var add, description, descriptions, i, j, len, len1, matcher, probe, probes_and_matchers, tag_reducer, u; //......................................................................................................... add = function(isl, description) { var hi, interval, lo, name, rsg, tag, tail, type; rsg = null; tag = null; [type, ...tail] = description; //....................................................................................................... switch (type) { case 'block': [name, rsg, lo, hi, tag] = tail; break; case 'plane': case 'area': [name, lo, hi, tag] = tail; break; case 'codepoints': [lo, hi, tag] = tail; break; default: throw new Error(`unknown entry type ${rpr(type)}`); } //....................................................................................................... interval = {lo, hi}; if (name != null) { interval[type] = name; } if (rsg != null) { interval['rsg'] = rsg; } if (tag != null) { interval['tag'] = tag.split(/[\s,]+/); } ISL.add(isl, interval); //....................................................................................................... return null; }; //......................................................................................................... descriptions = [ //....................................................................................................... // Planes ['plane', 'Basic Multilingual Plane (BMP)', 0x0000, 0xffff], ['plane', 'Supplementary Multilingual Plane (SMP)', 0x10000, 0x1ffff], ['plane', 'Supplementary Ideographic Plane (SIP)', 0x20000, 0x2ffff], //....................................................................................................... // Areas ['area', 'ASCII & Latin-1 Compatibility Area', 0x0000, 0x00ff], ['area', 'General Scripts Area', 0x0100, 0x058f], //....................................................................................................... // Blocks ['block', 'Basic Latin', 'u-latn', 0x0, 0x7f], ['block', 'Latin-1 Supplement', 'u-latn-1', 0x80, 0xff], ['block', 'Latin Extended-A', 'u-latn-a', 0x100, 0x17f], ['block', 'Latin Extended-B', 'u-latn-b', 0x180, 0x24f], ['block', 'IPA Extensions', 'u-ipa-x', 0x250, 0x2af], ['block', 'Armenian', null, 0x530, 0x58f], //....................................................................................................... ['block', 'CJK Unified Ideographs', 'u-cjk', 0x4e00, 0x9fff, 'cjk ideograph'], //....................................................................................................... ['block', 'CJK Unified Ideographs Extension A', 'u-cjk-xa', 0x3400, 0x4dbf, 'cjk ideograph'], ['block', 'CJK Unified Ideographs Extension B', 'u-cjk-xb', 0x20000, 0x2a6df, 'cjk ideograph'], ['block', 'CJK Unified Ideographs Extension C', 'u-cjk-xc', 0x2a700, 0x2b73f, 'cjk ideograph'], ['block', 'CJK Unified Ideographs Extension D', 'u-cjk-xd', 0x2b740, 0x2b81f, 'cjk ideograph'], ['block', 'CJK Unified Ideographs Extension E', 'u-cjk-xe', 0x2b820, 0x2ceaf, 'cjk ideograph'], ['block', 'CJK Unified Ideographs Extension F', 'u-cjk-xf', 0x2ceb0, 0x2ebef, 'cjk ideograph'], //....................................................................................................... ['block', 'Ideographic Description Characters', 'u-cjk-idc', 0x2ff0, 0x2fff, 'cjk idl'], ['block', 'CJK Symbols and Punctuation', 'u-cjk-sym', 0x3000, 0x303f, 'cjk punctuation'], ['block', 'CJK Strokes', 'u-cjk-strk', 0x31c0, 0x31ef, 'cjk stroke'], ['block', 'Enclosed CJK Letters and Months', 'u-cjk-enclett', 0x3200, 0x32ff, 'cjk'], //....................................................................................................... ['block', 'Kangxi Radicals', 'u-cjk-rad1', 0x2f00, 0x2fdf, 'cjk ideograph kxr'], ['block', 'CJK Radicals Supplement', 'u-cjk-rad2', 0x2e80, 0x2eff, 'cjk ideograph'], //....................................................................................................... ['block', 'Hiragana', 'u-cjk-hira', 0x3040, 0x309f, 'cjk japanese kana hiragana'], ['block', 'Katakana', 'u-cjk-kata', 0x30a0, 0x30ff, 'cjk japanese kana katakana'], ['block', 'Kanbun', 'u-cjk-kanbun', 0x3190, 0x319f, 'cjk japanese kanbun'], ['block', 'Katakana Phonetic Extensions', 'u-cjk-kata-x', 0x31f0, 0x31ff, 'cjk japanese kana katakana'], //....................................................................................................... ['block', 'Hangul Jamo', 'u-hang-jm', 0x1100, 0x11ff, 'cjk korean hangeul jamo'], ['block', 'Hangul Syllables', 'u-hang-syl', 0xac00, 0xd7af, 'cjk korean hangeul syllable'], ['block', 'Hangul Jamo Extended-A', null, 0xa960, 0xa97f, 'cjk korean hangeul jamo'], ['block', 'Hangul Jamo Extended-B', null, 0xd7b0, 0xd7ff, 'cjk korean hangeul jamo'], //....................................................................................................... ['block', 'Bopomofo', 'u-bopo', 0x3100, 0x312f, 'cjk bopomofo'], ['block', 'Bopomofo Extended', 'u-bopo-x', 0x31a0, 0x31bf, 'cjk bopomofo'], ['block', 'CJK Compatibility Forms', 'u-cjk-cmpf', 0xfe30, 0xfe4f, 'cjk vertical'], //....................................................................................................... ['codepoints', 0xfe45, 0xfe46, '-vertical'], ['codepoints', 0xfe49, 0xfe4f, '-vertical'], ['block', 'Vertical Forms', 'u-vertf', 0xfe10, 0xfe1f, 'cjk vertical'], //....................................................................................................... ['block', 'Miscellaneous Symbols', 'u-sym', 0x2600, 0x26ff], ['codepoints', 0x262f, 0x2637, 'cjk'], ['codepoints', 0x2630, 0x2637, 'cjk yijing trigram'], ['block', 'Yijing Hexagram Symbols', 'u-yijng', 0x4dc0, 0x4dff, 'cjk yijing hexagram'], ['block', 'Tai Xuan Jing Symbols', 'u-txj-sym', 0x1d300, 0x1d35f, 'cjk yijing taixuanjing tetragram'], ['codepoints', 0x1d357, 0x1d35f, '-* reserved'], //....................................................................................................... ['block', 'CJK Compatibility Ideographs', 'u-cjk-cmpi1', 0xf900, 0xfaff, 'cjk'], ['block', 'Hangul Compatibility Jamo', 'u-hang-comp-jm', 0x3130, 0x318f, 'cjk'], ['block', 'CJK Compatibility', 'u-cjk-cmp', 0x3300, 0x33ff, 'cjk'], ['block', 'CJK Co