Index: web/protocol/protocol.js =================================================================== --- web/protocol/protocol.js (revision 4744) +++ web/protocol/protocol.js (revision 4745) @@ -157,11 +157,12 @@ } else { this.list.elements.push(this.str); this.state = ARGUMENT; + --i; } break; case BINARY_LENGTH: - if (this.strLenSize >= 5) { + if (this.strLenSize > 5) { this.onError(i, "binary string length is too long"); this.state = COMMENT; --i; @@ -168,21 +169,21 @@ } else if (b >= 65 && b <= 90) { // A-Z this.strLenSize++; let code = b - 65; - this.strLen += code << 6; + this.strLen = (this.strLen << 6) + code; } else if (b >= 97 && b <= 122) { // a-z this.strLenSize++; let code = b - 97 + 26; - this.strLen += code << 6; + this.strLen = (this.strLen << 6) + code; } else if (b >= 48 && b <= 57) { // 0-9 this.strLenSize++; let code = b - 48 + 52; - this.strLen += code << 6; - } else if (b === 42) { // '+' + this.strLen = (this.strLen << 6) + code; + } else if (b === 43) { // '+' this.strLenSize++; - this.strLen += 62 << 6; + this.strLen = (this.strLen << 6) + 62; } else if (b === 47) { // '/' this.strLenSize++; - this.strLen += 63 << 6; + this.strLen = (this.strLen << 6) + 63; } else if (b === 61) { // '=' this.state = BINARY_STRING; } else { @@ -196,6 +197,7 @@ if (this.strLen <= 0) { this.list.elements.push(this.str); this.state = ARGUMENT; + --i; } else { this.str += String.fromCharCode(b); this.strLen--; @@ -241,7 +243,7 @@ let list = tree.elements; for (let i = 0; i < list.length; ++i) { let elem = list[i]; - if (Array.isArray(elem)) { + if (typeof elem === "object") { list[i] = Parser.compactTree(elem); } } Index: web/protocol/test/test.js =================================================================== --- web/protocol/test/test.js (revision 4744) +++ web/protocol/test/test.js (revision 4745) @@ -31,15 +31,156 @@ t.notOk(parse("a\n")); t.notOk(parse("a \n")); t.notOk(parse("a(\n")); + t.notOk(parse("a{\n")); t.notOk(parse("a(}\n")); t.notOk(parse("a{)\n")); - t.notOk(parse("a(((((((((\n")); - t.notOk(parse("a{{{{{{{{{\n")); + t.notOk(parse("a(((\n")); + t.notOk(parse("a{{{\n")); t.end(); }); +test("generic", (t) => { + t.deepEqual(parse("a()\n"), { + cmd: "a", + args: [] + }); + t.deepEqual(parse("a(b)\n"), { + cmd: "a", + args: ["b"] + }); + t.deepEqual(parse("a(abc)\n"), { + cmd: "a", + args: ["abc"] + }); + t.deepEqual(parse("a(azAZ09_+-.#)\n"), { + cmd: "a", + args: ["azAZ09_+-.#"] + }); + t.deepEqual(parse("a(abcdefghijklmnop)\n"), { + cmd: "a", + args: ["abcdefghijklmnop"] + }); + + t.notOk(parse("a(abcdefghijklmnopq)\n")); + + t.end(); +}); + + +test("generic-multiple", (t) => { + t.deepEqual(parse("a(abc def ghi)\n"), { + cmd: "a", + args: ["abc", "def", "ghi"] + }); + + t.end(); +}); + + +test("binary", (t) => { + t.deepEqual(parse("a{}\n"), { + cmd: "a", + args: [] + }); + t.deepEqual(parse("a{A=}\n"), { + cmd: "a", + args: [""] + }); + t.deepEqual(parse("a{B=b}\n"), { + cmd: "a", + args: ["b"] + }); + t.deepEqual(parse("a{E= \n})}\n"), { + cmd: "a", + args: [" \n})"] + }); + t.deepEqual(parse("a{a=" + " ".repeat(26) + "}\n"), { + cmd: "a", + args: [" ".repeat(26)] + }); + t.deepEqual(parse("a{0=" + " ".repeat(52) + "}\n"), { + cmd: "a", + args: [" ".repeat(52)] + }); + t.deepEqual(parse("a{+=" + " ".repeat(62) + "}\n"), { + cmd: "a", + args: [" ".repeat(62)] + }); + t.deepEqual(parse("a{/=" + " ".repeat(63) + "}\n"), { + cmd: "a", + args: [" ".repeat(63)] + }); + t.deepEqual(parse("a{BA=" + " ".repeat(64) + "}\n"), { + cmd: "a", + args: [" ".repeat(64)] + }); + + t.end(); +}); + + +test("binary-multiple", (t) => { + t.deepEqual(parse("a{D=abc D=def D=ghi}\n"), { + cmd: "a", + args: ["abc", "def", "ghi"] + }); + + t.end(); +}); + + +test("gen-gen", (t) => { + t.deepEqual(parse("a((()))\n"), { + cmd: "a", + args: [[[]]] + }); + t.deepEqual(parse("a(b1(c11)(c21 c22)b3)\n"), { + cmd: "a", + args: ["b1", ["c11"], ["c21", "c22"], "b3"] + }); + + t.end(); +}); + + +test("gen-bin", (t) => { + t.deepEqual(parse("a({{}})\n"), { + cmd: "a", + args: [[[]]] + }); + t.deepEqual(parse("a(b1(c11){D=c21 D=c22}b3)\n"), { + cmd: "a", + args: ["b1", ["c11"], ["c21", "c22"], "b3"] + }); + + t.end(); +}); + + +test("bin-bin", (t) => { + t.deepEqual(parse("a{{{}}}\n"), { + cmd: "a", + args: [[[]]] + }); + t.deepEqual(parse("a{C=b1{C=c1}{D=c21 D=c22}C=b3}\n"), { + cmd: "a", + args: ["b1", ["c1"], ["c21", "c22"], "b3"] + }); + + t.end(); +}); + + +test("bin-gen", (t) => { + t.notOk(parse("a{(())}\n")); + t.notOk(parse("a{C=b1(c1)C=b3}\n")); + + t.end(); +}); + + test("whitespace", (t) => { t.deepEqual(parse(" \t b \t { \t } \t \n"), { cmd: "b", @@ -59,7 +200,24 @@ }); +test("after-comment", (t) => { + t.deepEqual(parse("#\na()\n"), { + cmd: "a", + args: [] + }); + t.deepEqual(parse("#\n \t a()\n"), { + cmd: "a", + args: [] + }); + + t.end(); +}); + + test("unfinished", (t) => { + t.equal(parse(""), "pending"); + t.equal(parse("\n"), "pending"); + t.equal(parse("\n\t \n"), "pending"); t.equal(parse("a()"), "pending"); t.equal(parse(" \t b \t { "), "pending"); t.equal(parse("fdfds"), "pending"); @@ -80,7 +238,7 @@ args = _args; }; parser.onError = function (pos, _err) { - console.log(" msg[%d]: ", pos, _err); + console.log("# msg[%d]: ", pos, _err); err = _err; }; parser.parse(buffer);