diff options
Diffstat (limited to 'js/src/Ice/StreamHelpers.js')
-rw-r--r-- | js/src/Ice/StreamHelpers.js | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/js/src/Ice/StreamHelpers.js b/js/src/Ice/StreamHelpers.js new file mode 100644 index 00000000000..6fcce91a4d0 --- /dev/null +++ b/js/src/Ice/StreamHelpers.js @@ -0,0 +1,327 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +(function(global){ + require("Ice/Class"); + require("Ice/HashMap"); + require("Ice/OptionalFormat"); + + var Ice = global.Ice || {}; + + var Class = Ice.Class; + var defineProperty = Object.defineProperty; + + var HashMap = Ice.HashMap; + var OptionalFormat = Ice.OptionalFormat; + + var StreamHelpers = {}; + + StreamHelpers.FSizeOptHelper = function() + { + this.writeOpt = function(os, tag, v) + { + if(v !== undefined && os.writeOpt(tag, OptionalFormat.FSize)) + { + var pos = os.startSize(); + this.write(os, v); + os.endSize(pos); + } + }; + + this.readOpt = function(is, tag) + { + var v; + if(is.readOpt(tag, OptionalFormat.FSize)) + { + is.skip(4); + v = this.read(is); + } + return v; + }; + }; + + StreamHelpers.VSizeOptHelper = function() + { + this.writeOpt = function(os, tag, v) + { + if(v !== undefined && os.writeOpt(tag, OptionalFormat.VSize)) + { + os.writeSize(this.minWireSize); + this.write(os, v); + } + }; + + this.readOpt = function(is, tag) + { + var v; + if(is.readOpt(tag, OptionalFormat.VSize)) + { + is.skipSize(); + v = this.read(is); + } + return v; + }; + }; + + StreamHelpers.VSizeContainerOptHelper = function(elementSize) + { + this.writeOpt = function(os, tag, v) + { + if(v !== undefined && os.writeOpt(tag, OptionalFormat.VSize)) + { + var sz = this.size(v); + os.writeSize(sz > 254 ? sz * elementSize + 5 : sz * elementSize + 1); + this.write(os, v); + } + }; + + this.readOpt = function(is, tag) + { + var v; + if(is.readOpt(tag, OptionalFormat.VSize)) + { + is.skipSize(); + v = this.read(is); + } + return v; + }; + }; + + StreamHelpers.VSizeContainer1OptHelper = function() + { + this.writeOpt = function(os, tag, v) + { + if(v !== undefined && os.writeOpt(tag, OptionalFormat.VSize)) + { + this.write(os, v); + } + }; + + this.readOpt = function(is, tag) + { + var v; + if(is.readOpt(tag, OptionalFormat.VSize)) + { + v = this.read(is); + } + return v; + }; + }; + + // + // Sequence helper to write sequences + // + var SequenceHelper = Class({ + write: function(os, v) + { + if(v === null || v.length === 0) + { + os.writeSize(0); + } + else + { + var helper = this.elementHelper; + os.writeSize(v.length); + for(var i = 0; i < v.length; ++i) + { + helper.write(os, v[i]); + } + } + }, + read: function(is) + { + var helper = this.elementHelper; // Cache the element helper. + var sz = is.readAndCheckSeqSize(helper.minWireSize); + var v = []; + v.length = sz; + for(var i = 0; i < sz; ++i) + { + v[i] = helper.read(is); + } + return v; + }, + size: function(v) + { + return (v === null || v === undefined) ? 0 : v.length; + } + }); + + defineProperty(SequenceHelper.prototype, "minWireSize", { + get: function(){ return 1; } + }); + + // Speacialization optimized for ByteSeq + var byteSeqHelper = new SequenceHelper(); + byteSeqHelper.write = function(os, v) { return os.writeByteSeq(v); }; + byteSeqHelper.read = function(is) { return is.readByteSeq(); }; + defineProperty(byteSeqHelper, "elementHelper", { + get: function(){ return Ice.ByteHelper; } + }); + StreamHelpers.VSizeContainer1OptHelper.call(byteSeqHelper); + + // Read method for object sequences + var objectSequenceHelperRead = function(is) + { + var sz = is.readAndCheckSeqSize(1); + var v = []; + v.length = sz; + var elementType = this.elementType; + var readObjectAtIndex = function(idx) + { + is.readObject(function(obj) { v[idx] = obj; }, elementType); + }; + + for(var i = 0; i < sz; ++i) + { + readObjectAtIndex(i); + } + return v; + }; + + StreamHelpers.generateSeqHelper = function(elementHelper, fixed, elementType) + { + if(elementHelper === Ice.ByteHelper) + { + return byteSeqHelper; + } + + var helper = new SequenceHelper(); + if(fixed) + { + if(elementHelper.minWireSize === 1) + { + StreamHelpers.VSizeContainer1OptHelper.call(helper); + } + else + { + StreamHelpers.VSizeContainerOptHelper.call(helper, elementHelper.minWireSize); + } + } + else + { + StreamHelpers.FSizeOptHelper.call(helper); + } + + defineProperty(helper, "elementHelper", { + get: function(){ return elementHelper; } + }); + + if(elementHelper == Ice.ObjectHelper) + { + defineProperty(helper, "elementType", { + get: function(){ return elementType; } + }); + helper.read = objectSequenceHelperRead; + } + + return helper; + }; + + // + // Dictionary helper to write dictionaries + // + var DictionaryHelper = Class({ + write: function(os, v) + { + if(v === null || v.size === 0) + { + os.writeSize(0); + } + else + { + var keyHelper = this.keyHelper; + var valueHelper = this.valueHelper; + os.writeSize(v.size); + for(var e = v.entries; e !== null; e = e.next) + { + keyHelper.write(os, e.key); + valueHelper.write(os, e.value); + } + } + }, + read: function(is) + { + var mapType = this.mapType; + var v = new mapType(); + var sz = is.readSize(); + var keyHelper = this.keyHelper; + var valueHelper = this.valueHelper; + for(var i = 0; i < sz; ++i) + { + v.set(keyHelper.read(is), valueHelper.read(is)); + } + return v; + }, + size: function(v) + { + return (v === null || v === undefined) ? 0 : v.size; + } + }); + + Object.defineProperty(DictionaryHelper.prototype, "minWireSize", { + get: function(){ return 1; } + }); + + // Read method for dictionaries of objects + var objectDictionaryHelperRead = function(is) + { + var sz = is.readSize(); + var mapType = this.mapType; + var v = new mapType(); + var valueType = this.valueType; + + var readObjectForKey = function(key) + { + is.readObject(function(obj) { v.set(key, obj); }, valueType); + }; + + var keyHelper = this.keyHelper; + for(var i = 0; i < sz; ++i) + { + readObjectForKey(keyHelper.read(is)); + } + return v; + }; + + StreamHelpers.generateDictHelper = function(keyHelper, valueHelper, fixed, valueType, mapType) + { + var helper = new DictionaryHelper(); + if(fixed) + { + StreamHelpers.VSizeContainerOptHelper.call(helper, keyHelper.minWireSize + valueHelper.minWireSize); + } + else + { + StreamHelpers.FSizeOptHelper.call(helper); + } + defineProperty(helper, "mapType", { + get: function(){ return mapType; } + }); + defineProperty(helper, "keyHelper", { + get: function(){ return keyHelper; } + }); + defineProperty(helper, "valueHelper", { + get: function(){ return valueHelper; } + }); + + if(valueHelper == Ice.ObjectHelper) + { + defineProperty(helper, "valueType", { + get: function(){ return valueType; } + }); + helper.read = objectDictionaryHelperRead; + } + + return helper; + }; + + Ice.StreamHelpers = StreamHelpers; + + global.Ice = Ice; +}(typeof (global) === "undefined" ? window : global)); |