hrev43938 adds 2 changesets to branch 'master' old head: 25f1f961113e5b4b3eb92c56f43968214a62b4d8 new head: e1b41a1a8c351233bcc6b98b6aa53a085351cf25 ---------------------------------------------------------------------------- c001665: Add a packed argument to encode_base64. Reintroduced the '=' padding modulo 3 characters from the original code from the mail kit, and a packed option to avoid it. Broadway uses this packed scheme to save bytes when sending many separate values. TODO: merge this with the mail kit one somewhere? e1b41a1: Add base64 decoding helpers to read ints Some helper functions to read uint8, uint16 and uint32 (actually int32 it seems...). Note the value is effectively read as big-endian. [ François Revol <revol@xxxxxxx> ] ---------------------------------------------------------------------------- 4 files changed, 287 insertions(+), 24 deletions(-) src/servers/app/drawing/html5/base64.cpp | 6 +- src/servers/app/drawing/html5/base64.h | 3 +- src/servers/app/drawing/html5/haiku.js | 151 ++++++++++++++++++++++++-- src/servers/app/drawing/html5/haiku.js.h | 151 ++++++++++++++++++++++++-- ############################################################################ Commit: c001665a7cd67a89cc33ed482fc8e9f3b2f6812a URL: http://cgit.haiku-os.org/haiku/commit/?id=c001665 Author: François Revol <revol@xxxxxxx> Date: Sun Apr 1 22:30:27 2012 UTC Add a packed argument to encode_base64. Reintroduced the '=' padding modulo 3 characters from the original code from the mail kit, and a packed option to avoid it. Broadway uses this packed scheme to save bytes when sending many separate values. TODO: merge this with the mail kit one somewhere? ---------------------------------------------------------------------------- diff --git a/src/servers/app/drawing/html5/base64.cpp b/src/servers/app/drawing/html5/base64.cpp index 2afffe7..8081559 100644 --- a/src/servers/app/drawing/html5/base64.cpp +++ b/src/servers/app/drawing/html5/base64.cpp @@ -25,7 +25,7 @@ static const char kHexAlphabet[16] = {'0', '1', '2', '3', '4', '5', '6', '7', ssize_t -encode_base64(char *out, const char *in, off_t length) +encode_base64(char *out, const char *in, off_t length, bool packed) { uint32 concat; int i = 0; @@ -45,8 +45,12 @@ encode_base64(char *out, const char *in, off_t length) out[k++] = kBase64Alphabet[(concat >> 12) & 63]; if ((i+1) < length) out[k++] = kBase64Alphabet[(concat >> 6) & 63]; + else if (!packed) + out[k++] = '='; if ((i+2) < length) out[k++] = kBase64Alphabet[concat & 63]; + else if (!packed) + out[k++] = '='; } return k; diff --git a/src/servers/app/drawing/html5/base64.h b/src/servers/app/drawing/html5/base64.h index fa2d3f0..8d75312 100644 --- a/src/servers/app/drawing/html5/base64.h +++ b/src/servers/app/drawing/html5/base64.h @@ -8,7 +8,8 @@ #include <ctype.h> -extern ssize_t encode_base64(char *out, const char *in, off_t length); +extern ssize_t encode_base64(char *out, const char *in, off_t length, + bool packed=false); extern ssize_t decode_base64(char *out, const char *in, off_t length); ############################################################################ Revision: hrev43938 Commit: e1b41a1a8c351233bcc6b98b6aa53a085351cf25 URL: http://cgit.haiku-os.org/haiku/commit/?id=e1b41a1 Author: François Revol <revol@xxxxxxx> Date: Sun Apr 1 22:43:30 2012 UTC Add base64 decoding helpers to read ints Some helper functions to read uint8, uint16 and uint32 (actually int32 it seems...). Note the value is effectively read as big-endian. ---------------------------------------------------------------------------- diff --git a/src/servers/app/drawing/html5/haiku.js b/src/servers/app/drawing/html5/haiku.js index 8c7b808..bf272ae 100644 --- a/src/servers/app/drawing/html5/haiku.js +++ b/src/servers/app/drawing/html5/haiku.js @@ -12,6 +12,92 @@ var logDiv; var desktop; // the canvas +var b64Values = new Array( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, + -1, 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, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1); + +//DEBUG +var stream={s:"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==",i:0}; +var stream2={s:"YWJjZAYWIYQVQqgqlUVaoVaqqVQqlVVqg",i:0}; + + +function b64_get_u32_(t, i) +{ + var v = 0; + if (b64Values[t.charCodeAt(i)] < 0) return v; + v += b64Values[t.charCodeAt(i++)] << 26; + if (b64Values[t.charCodeAt(i)] < 0) return v; + v += b64Values[t.charCodeAt(i++)] << 20; + if (b64Values[t.charCodeAt(i)] < 0) return v; + v += b64Values[t.charCodeAt(i++)] << 14; + if (b64Values[t.charCodeAt(i)] < 0) return v; + v += b64Values[t.charCodeAt(i++)] << 8; + if (b64Values[t.charCodeAt(i)] < 0) return v; + v += b64Values[t.charCodeAt(i++)] << 2; + if (b64Values[t.charCodeAt(i)] < 0) return v; + v += b64Values[t.charCodeAt(i++)] >> 4; + if (b64Values[t.charCodeAt(i)] < 0) i++; + if (b64Values[t.charCodeAt(i)] < 0) i++; + dbg("u32:" + v + " 0x" + v.toString(16)); + return v; +} + + +function b64_get_u8(s) +{ + var v = 0; + if (b64Values[s.s.charCodeAt(s.i)] < 0) return v; + v += b64Values[s.s.charCodeAt(s.i++)] << 2; + if (b64Values[s.s.charCodeAt(s.i)] < 0) return v; + v += b64Values[s.s.charCodeAt(s.i++)] >> 4; + if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++; + if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++; + dbg(" u8:" + v + " 0x" + v.toString(16)); + return v; +} + +function b64_get_u16(s) +{ + var v = 0; + if (b64Values[s.s.charCodeAt(s.i)] < 0) return v; + v += b64Values[s.s.charCodeAt(s.i++)] << 10; + if (b64Values[s.s.charCodeAt(s.i)] < 0) return v; + v += b64Values[s.s.charCodeAt(s.i++)] << 4; + if (b64Values[s.s.charCodeAt(s.i)] < 0) return v; + v += b64Values[s.s.charCodeAt(s.i++)] >> 2; + if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++; + dbg("u16:" + v + " 0x" + v.toString(16)); + return v; +} + +function b64_get_u32(s) +{ + var v = 0; + if (b64Values[s.s.charCodeAt(s.i)] < 0) return v; + v += b64Values[s.s.charCodeAt(s.i++)] << 26; + if (b64Values[s.s.charCodeAt(s.i)] < 0) return v; + v += b64Values[s.s.charCodeAt(s.i++)] << 20; + if (b64Values[s.s.charCodeAt(s.i)] < 0) return v; + v += b64Values[s.s.charCodeAt(s.i++)] << 14; + if (b64Values[s.s.charCodeAt(s.i)] < 0) return v; + v += b64Values[s.s.charCodeAt(s.i++)] << 8; + if (b64Values[s.s.charCodeAt(s.i)] < 0) return v; + v += b64Values[s.s.charCodeAt(s.i++)] << 2; + if (b64Values[s.s.charCodeAt(s.i)] < 0) return v; + v += b64Values[s.s.charCodeAt(s.i++)] >> 4; + //v &= 0x0ffffffff; + if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++; + if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++; + dbg("u32:" + v + " 0x" + v.toString(16)); + return v; +} + function dbg(str) { var div = document.createElement("div"); @@ -45,9 +131,61 @@ window.popup("plop"); dbg(message.target.responseText); } +function decodeCanvasMessage(msg) +{ + dbg("decodeCanvasMessage()"); + var code = b64_get_u16(msg); + dbg("code: " + code); +/* switch (code) { + //case 1: + //break; + default: + dbg("unhandled code " + code); + return; + }*/ +} + +function onReadyStateChange() +{ + dbg("readystate changed: " + this.readyState); + if (this.readyState != 4) + return; + dbg("status: " + this.status); + dbg("resonseType: " + this.responseType); + dbg("response: " + this.responseText); + //dbg("headers: " + this.getAllResponseHeaders()); +//var stream={s:"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==",i:0}; + var msg = {s:(this.responseText),i:0}; + decodeCanvasMessage(msg); +} + +//DEBUG +function testB64(stream) +{ + var i = 0; + b64_get_u32(stream); + b64_get_u16(stream); + b64_get_u8(stream); + b64_get_u8(stream); + b64_get_u8(stream); + b64_get_u16(stream); + b64_get_u16(stream); + b64_get_u32(stream); + b64_get_u32(stream); + dbg("s.i:"+stream.i); +} + function initDesktop() { dbg("initDesktop()"); + + //testB64(stream); + //testB64(stream2); + +//var stream={s:"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==",i:0}; + var msg = {s:"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==",i:0}; + decodeCanvasMessage(stream); + desktop = document.getElementById("desktop"); var xhr = createXHR(); if (xhr) { @@ -65,20 +203,11 @@ function initDesktop() dbg("multipart: " + xhr.multipart); xhr.open("GET", "http://127.0.0.1:8080/output";, true); //xhr.onload = onMessage; - xhr.onreadystatechange = function() { - dbg("readystate changed: " + xhr.readyState); - if (xhr.readyState != 4) - return; - dbg("status: " + xhr.status); - dbg("resonseType: " + xhr.responseType); - dbg("response: " + xhr.responseText); - dbg("headers: " + xhr.getAllResponseHeaders()); - - } + xhr.onreadystatechange = onReadyStateChange; //xhr.responseType = "arraybuffer"; //dbg("xhr.onload:" + xhr.onload); //dbg("xhr.send:" + xhr.send); - xhr.overrideMimeType("multipart/x-mixed-replace;boundary=x"); + //xhr.overrideMimeType("multipart/x-mixed-replace;boundary=x"); xhr.send(null); //dbg("headers: " + xhr.getAllResponseHeaders()); } else diff --git a/src/servers/app/drawing/html5/haiku.js.h b/src/servers/app/drawing/html5/haiku.js.h index 18e8abf..3c720f0 100644 --- a/src/servers/app/drawing/html5/haiku.js.h +++ b/src/servers/app/drawing/html5/haiku.js.h @@ -13,6 +13,92 @@ static const char haiku_js[] = "var logDiv;\n" "var desktop; // the canvas\n" "\n" + "var b64Values = new Array(\n" + " -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n" + " -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n" + " -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,\n" + " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,\n" + " -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n" + " 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,\n" + " -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,\n" + " 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);\n" + "\n" + "//DEBUG\n" + "var stream={s:\"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==\",i:0};\n" + "var stream2={s:\"YWJjZAYWIYQVQqgqlUVaoVaqqVQqlVVqg\",i:0};\n" + "\n" + "\n" + "function b64_get_u32_(t, i)\n" + "{\n" + " var v = 0;\n" + " if (b64Values[t.charCodeAt(i)] < 0) return v;\n" + " v += b64Values[t.charCodeAt(i++)] << 26;\n" + " if (b64Values[t.charCodeAt(i)] < 0) return v;\n" + " v += b64Values[t.charCodeAt(i++)] << 20;\n" + " if (b64Values[t.charCodeAt(i)] < 0) return v;\n" + " v += b64Values[t.charCodeAt(i++)] << 14;\n" + " if (b64Values[t.charCodeAt(i)] < 0) return v;\n" + " v += b64Values[t.charCodeAt(i++)] << 8;\n" + " if (b64Values[t.charCodeAt(i)] < 0) return v;\n" + " v += b64Values[t.charCodeAt(i++)] << 2;\n" + " if (b64Values[t.charCodeAt(i)] < 0) return v;\n" + " v += b64Values[t.charCodeAt(i++)] >> 4;\n" + " if (b64Values[t.charCodeAt(i)] < 0) i++;\n" + " if (b64Values[t.charCodeAt(i)] < 0) i++;\n" + " dbg(\"u32:\" + v + \" 0x\" + v.toString(16));\n" + " return v;\n" + "}\n" + "\n" + "\n" + "function b64_get_u8(s)\n" + "{\n" + " var v = 0;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n" + " v += b64Values[s.s.charCodeAt(s.i++)] << 2;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n" + " v += b64Values[s.s.charCodeAt(s.i++)] >> 4;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;\n" + " dbg(\" u8:\" + v + \" 0x\" + v.toString(16));\n" + " return v;\n" + "}\n" + "\n" + "function b64_get_u16(s)\n" + "{\n" + " var v = 0;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n" + " v += b64Values[s.s.charCodeAt(s.i++)] << 10;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n" + " v += b64Values[s.s.charCodeAt(s.i++)] << 4;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n" + " v += b64Values[s.s.charCodeAt(s.i++)] >> 2;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;\n" + " dbg(\"u16:\" + v + \" 0x\" + v.toString(16));\n" + " return v;\n" + "}\n" + "\n" + "function b64_get_u32(s)\n" + "{\n" + " var v = 0;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n" + " v += b64Values[s.s.charCodeAt(s.i++)] << 26;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n" + " v += b64Values[s.s.charCodeAt(s.i++)] << 20;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n" + " v += b64Values[s.s.charCodeAt(s.i++)] << 14;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n" + " v += b64Values[s.s.charCodeAt(s.i++)] << 8;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n" + " v += b64Values[s.s.charCodeAt(s.i++)] << 2;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n" + " v += b64Values[s.s.charCodeAt(s.i++)] >> 4;\n" + " //v &= 0x0ffffffff;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;\n" + " if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;\n" + " dbg(\"u32:\" + v + \" 0x\" + v.toString(16));\n" + " return v;\n" + "}\n" + "\n" "function dbg(str)\n" "{\n" " var div = document.createElement(\"div\");\n" @@ -46,9 +132,61 @@ static const char haiku_js[] = " dbg(message.target.responseText);\n" "}\n" "\n" + "function decodeCanvasMessage(msg)\n" + "{\n" + " dbg(\"decodeCanvasMessage()\");\n" + " var code = b64_get_u16(msg);\n" + " dbg(\"code: \" + code);\n" + "/* switch (code) {\n" + " //case 1:\n" + " //break;\n" + " default:\n" + " dbg(\"unhandled code \" + code);\n" + " return;\n" + " }*/\n" + "}\n" + "\n" + "function onReadyStateChange()\n" + "{\n" + " dbg(\"readystate changed: \" + this.readyState);\n" + " if (this.readyState != 4)\n" + " return;\n" + " dbg(\"status: \" + this.status);\n" + " dbg(\"resonseType: \" + this.responseType);\n" + " dbg(\"response: \" + this.responseText);\n" + " //dbg(\"headers: \" + this.getAllResponseHeaders());\n" + "//var stream={s:\"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==\",i:0};\n" + " var msg = {s:(this.responseText),i:0};\n" + " decodeCanvasMessage(msg);\n" + "}\n" + "\n" + "//DEBUG\n" + "function testB64(stream)\n" + "{\n" + " var i = 0;\n" + " b64_get_u32(stream);\n" + " b64_get_u16(stream);\n" + " b64_get_u8(stream);\n" + " b64_get_u8(stream);\n" + " b64_get_u8(stream);\n" + " b64_get_u16(stream);\n" + " b64_get_u16(stream);\n" + " b64_get_u32(stream);\n" + " b64_get_u32(stream);\n" + " dbg(\"s.i:\"+stream.i);\n" + "}\n" + "\n" "function initDesktop()\n" "{\n" " dbg(\"initDesktop()\");\n" + "\n" + " //testB64(stream);\n" + " //testB64(stream2);\n" + "\n" + "//var stream={s:\"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==\",i:0};\n" + " var msg = {s:\"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==\",i:0};\n" + " decodeCanvasMessage(stream);\n" + "\n" " desktop = document.getElementById(\"desktop\");\n" " var xhr = createXHR();\n" " if (xhr) {\n" @@ -66,20 +204,11 @@ static const char haiku_js[] = " dbg(\"multipart: \" + xhr.multipart);\n" " xhr.open(\"GET\", \"http://127.0.0.1:8080/output\";, true);\n" " //xhr.onload = onMessage;\n" - " xhr.onreadystatechange = function() {\n" - " dbg(\"readystate changed: \" + xhr.readyState);\n" - " if (xhr.readyState != 4)\n" - " return;\n" - " dbg(\"status: \" + xhr.status);\n" - " dbg(\"resonseType: \" + xhr.responseType);\n" - " dbg(\"response: \" + xhr.responseText);\n" - " dbg(\"headers: \" + xhr.getAllResponseHeaders());\n" - "\n" - " }\n" + " xhr.onreadystatechange = onReadyStateChange;\n" " //xhr.responseType = \"arraybuffer\";\n" " //dbg(\"xhr.onload:\" + xhr.onload);\n" " //dbg(\"xhr.send:\" + xhr.send);\n" - " xhr.overrideMimeType(\"multipart/x-mixed-replace;boundary=x\");\n" + " //xhr.overrideMimeType(\"multipart/x-mixed-replace;boundary=x\");\n" " xhr.send(null);\n" " //dbg(\"headers: \" + xhr.getAllResponseHeaders());\n" " } else\n"