Skip to content
Browse files

Addition of string types

  • Loading branch information...
1 parent a227084 commit 2b8e78bc41d8a2d7d53e3c1d03a557ca5d7e72a2 @Benvie committed Mar 30, 2012
Showing with 174 additions and 10 deletions.
  1. +3 −3 lib/array.js
  2. +1 −1 lib/buffer.js
  3. +8 −0 lib/genesis.js
  4. +16 −6 lib/index.js
  5. +12 −0 lib/inspect.js
  6. +1 −0 lib/numeric.js
  7. +133 −0 lib/string.js
View
6 lib/array.js
@@ -32,7 +32,7 @@ function ArrayType(name, MemberType, length) {
genesis.api(this, '_offset', offset || 0);
values && Object.keys(values).forEach(function(i){
- initIndex(this, MemberType, i).write(values[i]);
+ initIndex(this, this.constructor.memberType, i).write(values[i]);
}, this);
this.emit('construct');
}
@@ -102,7 +102,7 @@ genesis.Type(ArrayType, {
write: function write(value, index, offset){
if (value == null) throw new TypeError('Tried to write nothing');
- if (isFinite(index) && typeof offset === 'undefined') {
+ if (isFinite(index) && typeof offset === 'undefined' && !value.length) {
// writing to specific index
return this[index] = value;
}
@@ -113,7 +113,7 @@ genesis.Type(ArrayType, {
// reify if needed, direct buffer copying doesn't happen here
value = value.reify ? value.reify() : value;
- if (Array.isArray(value) || Object(value) === value && 'length' in value) {
+ if (value && value.length) {
// arrayish and offset + index are already good to go
for (var index; index < this.length && index+offset < value.length; index++) {
if (value[offset+index] === null) {
View
2 lib/buffer.js
@@ -64,7 +64,7 @@ DataBuffer.prototype = {
subarray: function(start, end){
start = toNum(start);
- end = toNumOrUndef(end - start);
+ end = toNumOrUndef(end);
return new DataBuffer(this.view, start, end);
},
View
8 lib/genesis.js
@@ -51,11 +51,18 @@ function lookupType(name, label){
var count = name.match(/(.*)\[(\d+)\]$/);
if (count) {
var ArrayType = require('./array');
+ var CharType = require('./string');
name = count[1];
count = +count[2];
+ if (name === 'Char') {
+ return new CharType(count);
+ }
if (typeof label === 'string') {
return new ArrayType(label, lookupType(name), count);
} else {
+ if (type === 'Char') {
+ return new CharType(count);
+ }
var type = lookupType(name);
if (type === name) {
return new ArrayType(name, count);
@@ -108,6 +115,7 @@ Array.apply(null, Array(20)).forEach(function(n, i){
});
function createInterface(type, name, ctor){
+ name = name.replace(/[^\w0-9_$]/g, '');
var iface = Function(name+'Constructor', 'return function '+name+'(data, offset, values){ return new '+name+'Constructor(data, offset, values) }')(ctor);
hidden.value = function rename(name){
View
22 lib/index.js
@@ -4,6 +4,7 @@ var NumericType = require('./numeric');
var StructType = require('./struct');
var ArrayType = require('./array');
var BitfieldType = require('./bitfield');
+var CharType = require('./string');
@@ -14,14 +15,21 @@ function reified(type, subject, size, values){
if (reified.prototype.isPrototypeOf(this)) {
return new type(subject, size, values);
} else {
- subject = genesis.lookupType(subject, type);
- if (!subject) return type;
- if (typeof type === 'string' && subject.Class === 'Type') {
- return subject.rename(type);
+ subject = genesis.lookupType(subject);
+ if (!subject) {
+ if (type && type.name === 'CharArrayT') {
+ }
+ return type
+ }
+ if (subject === 'Char') return new CharType(type);
+ if (typeof type === 'string') {
+ if (subject.Class === 'Type') return subject.rename(type);
}
if (typeof subject === 'string' || subject.Class === 'Type') {
return new reified.ArrayType(type, subject, size);
- } else if (Array.isArray(subject) || typeof subject === 'number' || size) {
+ } else if (typeof type === 'undefined') {
+ console.log(subject)
+ } else if (Array.isArray(subject) || typeof subject === 'number') {
return new reified.BitfieldType(type, subject, size);
} else {
if (typeof type !== 'string' && typeof subject === 'undefined') {
@@ -31,6 +39,7 @@ function reified(type, subject, size, values){
subject = Object.keys(subject).reduce(function(ret, key){
if (subject[key].Class !== 'Type') {
var fieldType = reified(subject[key]);
+ if (!fieldType) return ret;
if (typeof fieldType === 'string' || fieldType.Class !== 'Type') {
ret[key] = reified(key, subject[key]);
} else {
@@ -101,4 +110,5 @@ var OctetString = new ArrayType('EightByteOctetString', 'Uint8', 8);
function octets(){ return new OctetString(this._data, this._offset) }
NumericType.Uint64.prototype.octets = octets;
-NumericType.Int64.prototype.octets = octets;
+NumericType.Int64.prototype.octets = octets;
+
View
12 lib/inspect.js
@@ -67,6 +67,10 @@ var inspectors = {
if (Object.prototype.hasOwnProperty.call(object, 'Type')) return '[NumericType Prototype]';
return color.bmagenta(object.name, '‹›');
},
+ CharArrayType: function(object, showHidden, depth, useColor){
+ if (Object.prototype.hasOwnProperty.call(object, 'Type')) return '[CharArray Prototype]';
+ return color.bgreen('CharArray', '‹›') + color.bblue('('+object.bytes+'b)');
+ },
ArrayType: function(object, showHidden, depth, useColor){
if (Object.prototype.hasOwnProperty.call(object, 'Type')) return '[ArrayType Prototype]';
var label = color.byellow(object.name, '‹›') + color.bblue('('+object.bytes+'b)');
@@ -100,6 +104,7 @@ var inspectors = {
BitfieldType: function(object, showHidden, depth, useColor){
if (Object.prototype.hasOwnProperty.call(object, 'Type')) return '[BitfieldType Prototype]';
var label = color.bgreen(object.name || 'Bitfield', '‹›') + color.bblue('('+object.bytes*8+'bit)');
+ if (Object(object.flags) !== object.flags) return util.inspect(object.flags);
var flags = Object.keys(object.flags);
if (!flags.length) {
return label;
@@ -115,6 +120,13 @@ var inspectors = {
if (!object.reify) return color.bred('[NumericData Prototype]');
return color.magenta(object.Subtype, '<>')+' '+color.bmagenta(object.reify());
},
+ CharArrayType: function(object, showHidden, depth, useColor){
+ if (object.bytes === 1) {
+ return color.green('Char', '<>')+' '+color.bgreen("'"+object.reify()+"'").replace(/\0/g,' ');
+ } else {
+ return color.green('CharArray', '<>')+' '+color.bgreen("'"+object.reify().join('').replace(/\0/g,' ')+"'");
+ }
+ },
ArrayType: function(object, showHidden, depth, useColor){
if (!object.constructor.memberType) return color.bred('[ArrayData Prototype]');
var fields = util.inspect(object.map(function(item){ return item }), showHidden, depth-1, useColor);
View
1 lib/numeric.js
@@ -42,6 +42,7 @@ function checkType(type, val){
}
}
if (!val) val = 0;
+ if (typeof val === 'undefined') val = 0;
if (isFinite(val)) {
val = +val;
} else {
View
133 lib/string.js
@@ -0,0 +1,133 @@
+var genesis = require('./genesis');
+var DataBuffer = require('./buffer');
+var numeric = require('./numeric');
+var ArrayType = require('./array');
+var StringSubtype = genesis.Subtype.bind(CharArrayType);
+
+module.exports = CharArrayType;
+
+
+var char = String.fromCharCode;
+var code = Function.call.bind(''.charCodeAt);
+
+var ucs2 = function(){
+ var a = 0x3ff,
+ o = 0x10000,
+ x = o - 0x800,
+ y = o - 0x2400,
+ z = o - 0x2800;
+ return function ucs2(v) {
+ if (typeof v === 'string') {
+ var r = code(v, 0);
+ return r & x === z ? o + ((r & a) << 10) + (code(v, 1) & a) : r;
+ } else if (isFinite(v)) {
+ return v >= o ? char((v -= o) >>> 10 & a | z) + char(y | v & a) : char(v);
+ }
+ }
+}()
+
+
+var cache = [];
+
+function CharArrayType(data, offset, value){
+ var length;
+ if (typeof data === 'number') {
+ length = data;
+ data = null;
+ } else if (typeof data === 'string') {
+ length = data.length;
+ value = data;
+ data = null;
+ } else if (data.bytes || data.byteLength) {
+ length = data.bytes || data.byteLength;
+ }
+ var bytes = length;
+
+ if (!(bytes in cache)) {
+ var CharArray = StringSubtype('CharArray'+bytes, bytes, function CharArray(data, offset, value){
+ if (!data) data = new DataBuffer(this.bytes);
+ this.rebase(data);
+ genesis.api(this, '_offset', offset || 0);
+
+ value && this.write(value);
+ this.emit('construct');
+ });
+ CharArray.bytes = bytes;
+ CharArray.prototype.bytes = bytes;
+ cache[bytes] = CharArray;
+ } else {
+ var CharArray = cache[bytes];
+ }
+
+ if (data || value) {
+ if (!data) data = new DataBuffer(bytes || value);
+ return new CharArray(data, offset, value);
+ } else {
+ return CharArray;
+ }
+}
+
+genesis.Type(CharArrayType, {
+ DataType: 'string',
+ Subtype: 'CharArray',
+ fill: function fill(v){ this.write(0, v || 0) },
+ reify: function reify(){
+ return this._data.subarray(this._offset, this.bytes).map(function(str){
+ return ucs2(str);
+ });
+ },
+ write: function write(value, index){
+ var isString = typeof value === 'string';
+ if (isFinite(index)) {
+ if (isString) value = ucs2(value);
+ this._data.writeUint8(index, value);
+ } else if (typeof value === 'string' || value && 'length' in value) {
+ for (var i=0; i<value.length && i<this.bytes; i++) {
+ this._data.writeUint8(this._offset+i, ucs2(value[i]));
+ }
+ }
+ },
+});
+
+
+
+function Char(data, offset, value){
+ if (typeof data === 'string' || typeof data === 'number' || !data) {
+ value = data;
+ data = null;
+ }
+ this.rebase(data);
+ genesis.api(this, '_offset', +offset || 0);
+
+ if (value != null) {
+ this.write(value);
+ }
+ this.emit('construct');
+}
+Char.prototype = {
+ length: 1,
+ Subtype: 'CharArray',
+ bytes: 1,
+ write: function write(v, i){
+ this._data.writeUint8(this._offset, typeof v === 'string' ? ucs2(v[i || 0]) : v);
+ return this;
+ },
+ reify: function reify(deallocate){
+ var val = this.reified = ucs2(this._data.readUint8(this._offset, 1));
+ this.emit('reify', val);
+ val = this.reified;
+ delete this.reified;
+ return val;
+ },
+ toNumber: function toNumber(v){
+ return this._data.readUint8(this._offset);
+ }
+};
+
+Char.__proto__ = CharArrayType.prototype;
+Char.constructor = CharArrayType;
+Char.prototype.__proto__ = CharArrayType.prototype.prototype;
+Char.bytes = Char.prototype.bytes = Char.prototype.length = 1
+Char.prototype.constructor = Char;
+
+cache[1] = Char;

0 comments on commit 2b8e78b

Please sign in to comment.
Something went wrong with that request. Please try again.