Not yet wired to the complete doxygen extraction, though.
DELETED = 1 << 2
_TYPE = 0xf << 4
+ ALIAS = 0 << 4
NAMESPACE = 1 << 4
CLASS = 2 << 4
STRUCT = 3 << 4
# id + len | length | suffix | |
# 16b + 8b | 8b | | 8b |
#
+ # alias item (flags & 0xf0 == 0x00):
+ #
+ # alias | | alias
+ # id | ... | name
+ # 16b | |
+ #
offset_struct = struct.Struct('<I')
flags_struct = struct.Struct('<B')
prefix_struct = struct.Struct('<HB')
suffix_length_struct = struct.Struct('<B')
+ alias_struct = struct.Struct('<H')
def __init__(self):
self.entries = []
- def add(self, name, url, suffix_length=0, flags=ResultFlag(0)) -> int:
+ def add(self, name, url, alias=None, suffix_length=0, flags=ResultFlag(0)) -> int:
if suffix_length: flags |= ResultFlag.HAS_SUFFIX
+ if alias is not None:
+ assert flags & ResultFlag._TYPE == ResultFlag.ALIAS
entry = Empty()
entry.name = name
entry.url = url
entry.flags = flags
+ entry.alias = alias
entry.prefix = 0
entry.prefix_length = 0
entry.suffix_length = suffix_length
entry.name = e.name[len(self.entries[longest_prefix.results[0]].name):]
entry.url = e.url[max_prefix[1]:]
entry.flags = e.flags|ResultFlag.HAS_PREFIX
+ entry.alias = e.alias
entry.prefix = max_prefix[0]
entry.prefix_length = max_prefix[1]
entry.suffix_length = e.suffix_length
output += self.offset_struct.pack(offset)
self.flags_struct.pack_into(output, len(output) - 1, e.flags.value)
+ # The entry is an alias, extra field for alias index
+ if e.flags & ResultFlag._TYPE == ResultFlag.ALIAS:
+ offset += 2
+
# Extra field for prefix index and length
if e.flags & ResultFlag.HAS_PREFIX:
offset += 3
# Write the entries themselves
for e in self.entries:
+ if e.flags & ResultFlag._TYPE == ResultFlag.ALIAS:
+ assert not e.alias is None
+ assert not e.url
+ output += self.alias_struct.pack(e.alias)
if e.flags & ResultFlag.HAS_PREFIX:
output += self.prefix_struct.pack(e.prefix, e.prefix_length)
if e.flags & ResultFlag.HAS_SUFFIX:
let flags = this.map.getUint8(index*4 + 3);
let resultOffset = this.map.getUint32(index*4, true) & 0x00ffffff;
+ /* The result is an alias, parse the aliased prefix */
+ let aliasedIndex = null;
+ if((flags & 0xf0) == 0x00) {
+ aliasedIndex = this.map.getUint16(resultOffset, true);
+ resultOffset += 2;
+ }
+
/* The result has a prefix, parse that first, recursively */
let name = '';
let url = '';
name += String.fromCharCode(c); /* eheh. IS THIS FAST?! */
}
- /* Extract URL */
- let max = Math.min(j + maxUrlPrefix, nextResultOffset);
- for(; j != max; ++j) {
- url += String.fromCharCode(this.map.getUint8(j));
+ /* The result is an alias and we're not deep inside resolving a prefix,
+ extract the aliased name and URL */
+ /* TODO: this abuses 0xffffff to guess how the call stack is deep and
+ that's just wrong, fix! */
+ if(aliasedIndex != null && maxUrlPrefix == 0xffffff) {
+ let alias = this.gatherResult(aliasedIndex, 0 /* ignored */, 0xffffff); /* should be enough haha */
+ name += ': ' + alias.name;
+ url = alias.url;
+ flags = alias.flags;
+
+ /* Result suffix length: add the whole aliased name + the `: ` */
+ resultSuffixLength += 2 + alias.name.length;
+
+ /* Otherwise extract URL from here */
+ } else {
+ let max = Math.min(j + maxUrlPrefix, nextResultOffset);
+ for(; j != max; ++j) {
+ url += String.fromCharCode(this.map.getUint8(j));
+ }
}
/* Keeping in UTF-8, as we need that for proper slicing (and concatenating) */
-O+!-vL;(N*Dggih0RRC2009I504V?g2mk;m009mF0B!&Q6aWBe0RRI400AHX04V?gBme*?00Alh0B!&QFaQ8)00A}t0BryPJOBVX0RaL4LI8j|00Bq<0CE5UPyhgL00CA20CWHWTmS%L00CkE0A&FH1poj6ZU6u&00D9U04M+fcmM!y00Djg0BHaLga80-00D{s06GBy1OSi#fI0vHmH+@{00Eu=0A~OJqyPYJ00F810AT<F8UO%oXaE3qumAvZ00FiD06GBy006`QfI0vH$^Zap00Ghf0CWQY0RRI41poj6-T(k800HIz04M+f>;M3600P(m0Aca~0BHdL1^@s70s#PJ009O80A~OJ3;_UP009yK0B`^S7y$rc00ABW0CfNa_y7QHXaE3qumAvZBmn?(AOHXmHvj->PXGWaa{vHoi2wj7s{jCP!2kfj-2eapO<{Cs0B&JzWpi+0V`WWYbZ9PUbZu+^01^l~I&EogC~0nVEFfuabSVHMZE0=*0025VR%K&!Z*l-*Y+-YAO<{CsUol@XR%K&!Z*neZbZu+`02l^3I&EogC@COgZ*FsR03&T_ZU6uPIyzEeZf9ixV{Bn_b4_7%XkRg3F;Zb}XJsyEbZu+|02c;2I&EogC@COgZ*FsR03&T_Zct%oWgx=4AX9Z>aA9X<0CRO>aA9X<E@*UZYybcN
\ No newline at end of file
+O+!-viU9xsZ~*`S0RRC2009I504V?g2mk;m009mF0B!&Q6aWBe0RRI400AHX04V?gBme*?00Alh0B!&QFaQ8)00A}t0BryPJOBVX0RaL4LI8j|00Bq<0CE5UPyhgL00CA20CWHWTmS%L00CkE0A&FH1poj6ZU6u&00D9U04M+fcmM!y00Djg0BHaLga80-00D{s06GBy1OSi#fI0vHmH+@{00Eu=0A~OJqyPYJ00F810AT<F8UO%oXaE3qumAvZ00FiD06GBy006`QfI0vH$^Zap00Ghf0CWQY0RRI41poj6-T(k800HIz04M+f>;M3600P(m0Aca~0BHdL2LJ#80s#PJ009O80BisO3;_UV009yK0B!*Q2mk;99svL;00I~R0AV5l04M+fC;<R;00A-q0Am0GssI3CH~|1<0RRR700Bq=0A&CHOaTCA00B|~0AT<DSOEZV00CYB0Ac_EWB~wm00j5|0BvXh0CqkB0CH*p0COk+01!U_0BKhM04jR`0BMl`04TEn0By+t0Knw{008g+015s8002#4bZ7u>VQpn|aA9L*O<{CsE@*UZYybcf2s%1#X>KTKZgealX>N2W03&T_ZU6uPIyzQmV{~tF0Ap-nb8}5$bZB2OUolo?V{~tFE@*UZYyton20A)zX>KSfAY*TCb94YBZE0=*0025VQekdqWdLJrVRLg$VRUF;F<&uKVQyz-E@*UZYy<!o20A)zX>KSfAY*TCb94YBZE0>$VP|C^!n+_-bz*Q~XJr6$bz*Q~XJsyEbZu+|08(XRbYX61Y-I!h2LJ#9IyzEiV{|Af
\ No newline at end of file
trie.insert("math::vector::min()", index, lookahead_barriers=[4, 12])
trie.insert("vector::min()", index, lookahead_barriers=[6])
trie.insert("min()", index)
-index = map.add("Math::Range", "classMath_1_1Range.html", flags=ResultFlag.CLASS)
-trie.insert("math::range", index)
-trie.insert("range", index)
+range_index = map.add("Math::Range", "classMath_1_1Range.html", flags=ResultFlag.CLASS)
+trie.insert("math::range", range_index)
+trie.insert("range", range_index)
index = map.add("Math::Range::min() const", "classMath_1_1Range.html#min", suffix_length=6, flags=ResultFlag.FUNC|ResultFlag.DELETED)
trie.insert("math::range::min()", index, lookahead_barriers=[4, 11])
trie.insert("range::min()", index, lookahead_barriers=[5])
trie.insert("min()", index)
trie.insert("subpage", map.add("Page » Subpage", "subpage.html", flags=ResultFlag.PAGE))
+trie.insert("rectangle", map.add("Rectangle", "", alias=range_index))
+trie.insert("rect()", map.add("Rectangle::Rect()", "", suffix_length=2, alias=range_index))
+
with open(basedir/'searchdata.bin', 'wb') as f:
f.write(serialize_search_data(trie, map))
with open(basedir/'searchdata.b85', 'wb') as f:
/* Verify that base85-decoded file is equivalent to the binary */
{
let binary = fs.readFileSync(path.join(__dirname, "js-test-data/searchdata.bin"));
- assert.equal(binary.byteLength, 545);
+ assert.equal(binary.byteLength, 648);
let b85 = fs.readFileSync(path.join(__dirname, "js-test-data/searchdata.b85"), {encoding: 'utf-8'});
assert.deepEqual(new DataView(binary.buffer.slice(binary.byteOffset, binary.byteOffset + binary.byteLength)), new DataView(Search.base85decode(b85), 0, binary.byteLength));
}
{
let buffer = fs.readFileSync(path.join(__dirname, "js-test-data/searchdata.bin"));
assert.ok(Search.init(buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength)));
- assert.equal(Search.dataSize, 545);
- assert.equal(Search.symbolCount, 7);
+ assert.equal(Search.dataSize, 648);
+ assert.equal(Search.symbolCount, 9);
assert.equal(Search.maxResults, 100);
/* Blow up */
url: 'subpage.html',
flags: 192,
suffixLength: 5 }]);
+
+ /* Alias */
+ assert.deepEqual(Search.search('r'), [
+ { name: 'Math::Range',
+ url: 'classMath_1_1Range.html',
+ flags: 40,
+ suffixLength: 4 },
+ { name: 'Rectangle::Rect(): Math::Range',
+ url: 'classMath_1_1Range.html',
+ flags: 40,
+ suffixLength: 20 },
+ { name: 'Rectangle: Math::Range',
+ url: 'classMath_1_1Range.html',
+ flags: 40,
+ suffixLength: 21 }]);
}
/* Search, limiting the results to 3 */
{
let buffer = fs.readFileSync(path.join(__dirname, "js-test-data/searchdata.bin"));
assert.ok(Search.init(buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength), 3));
- assert.equal(Search.dataSize, 545);
- assert.equal(Search.symbolCount, 7);
+ assert.equal(Search.dataSize, 648);
+ assert.equal(Search.symbolCount, 9);
assert.equal(Search.maxResults, 3);
assert.deepEqual(Search.search('m'), [
{ name: 'Math',
{
let b85 = fs.readFileSync(path.join(__dirname, "js-test-data/searchdata.b85"), {encoding: 'utf-8'});
assert.ok(Search.load(b85));
- assert.equal(Search.dataSize, 548); /* some padding on the end, that's okay */
- assert.equal(Search.symbolCount, 7);
+ assert.equal(Search.dataSize, 648); /* some padding on the end, that's okay */
+ assert.equal(Search.symbolCount, 9);
assert.equal(Search.maxResults, 100);
assert.deepEqual(Search.search('min'), [
{ name: 'Math::min(int, int)',
if i: out += '\n'
flags = ResultFlag(ResultMap.flags_struct.unpack_from(serialized, i*4 + 3)[0])
extra = []
+ if flags & ResultFlag._TYPE == ResultFlag.ALIAS:
+ extra += ['alias={}'.format(ResultMap.alias_struct.unpack_from(serialized, offset)[0])]
+ offset += ResultMap.alias_struct.size
if flags & ResultFlag.HAS_PREFIX:
extra += ['prefix={}[:{}]'.format(*ResultMap.prefix_struct.unpack_from(serialized, offset))]
offset += ResultMap.prefix_struct.size
self.assertEqual(map.add("Math::Range", "classMath_1_1Range.html", flags=ResultFlag.CLASS), 2)
self.assertEqual(map.add("Math::min()", "namespaceMath.html#abcdef2875", flags=ResultFlag.FUNC), 3)
self.assertEqual(map.add("Math::max(int, int)", "namespaceMath.html#abcdef1234", suffix_length=8, flags=ResultFlag.FUNC|ResultFlag.DEPRECATED|ResultFlag.DELETED), 4)
+ self.assertEqual(map.add("Rectangle", "", alias=2), 5)
+ self.assertEqual(map.add("Rectangle::Rect()", "", suffix_length=2, alias=2), 6)
serialized = map.serialize()
self.compare(serialized, """
2: ::Range [prefix=0[:0], type=CLASS] -> classMath_1_1Range.html
3: ::min() [prefix=0[:18], type=FUNC] -> #abcdef2875
4: ::max(int, int) [prefix=0[:18], suffix_length=8, deprecated, deleted, type=FUNC] -> #abcdef1234
+5: Rectangle [alias=2] ->
+6: ::Rect() [alias=2, prefix=5[:0], suffix_length=2] ->
""")
- self.assertEqual(len(serialized), 170)
+ self.assertEqual(len(serialized), 203)
class Serialization(unittest.TestCase):
def __init__(self, *args, **kwargs):