pluotsorbet/midp/codec.js

225 строки
5.6 KiB
JavaScript

/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
'use strict';
var DataType = {
BOOLEAN: 0,
CHAR: 1,
BYTE: 2,
WCHAR: 3,
SHORT: 4,
USHORT: 5,
LONG: 6,
ULONG: 7,
FLOAT: 8,
DOUBLE: 9,
STRING: 10,
WSTRING: 11,
URI: 12,
METHOD: 13,
STRUCT: 14,
LIST: 15,
ARRAY: 16,
};
var DataEncoder = function() {
this.data = [];
}
DataEncoder.START = 1;
DataEncoder.END = 2;
DataEncoder.prototype.putStart = function(tag, name) {
this.data.push({
type: DataEncoder.START,
tag: tag,
name: name,
});
}
DataEncoder.prototype.putEnd = function(tag, name) {
this.data.push({
type: DataEncoder.END,
tag: tag,
name: name,
})
}
DataEncoder.prototype.put = function(tag, name, value) {
this.data.push({
tag: tag,
name: name,
value: value,
});
}
DataEncoder.prototype.getData = function() {
return JSON.stringify(this.data);
}
var DataDecoder = function(data, offset, length) {
this.data = JSON.parse(util.decodeUtf8(new Uint8Array(data.buffer, offset, length)));
this.current = [];
}
DataDecoder.prototype.find = function(tag, type) {
var elem;
var i = 0;
while (elem = this.data[i++]) {
if ((!type || elem.type == type) && elem.tag == tag) {
this.data = this.data.slice(i);
return elem;
}
if (elem.type == DataEncoder.END) {
break;
}
}
}
DataDecoder.prototype.getStart = function(tag) {
var elem = this.find(tag, DataEncoder.START);
if (!elem) {
return false;
}
this.current.push(elem);
return true;
}
DataDecoder.prototype.getEnd = function(tag) {
var elem = this.find(tag, DataEncoder.END);
if (!elem) {
return false;
}
// If this happens, a father has ended before a child
if (elem.tag != this.current[this.current.length - 1].tag ||
elem.name != this.current[this.current.length - 1].name) {
return false;
}
this.current.pop();
return true;
}
DataDecoder.prototype.getValue = function(tag) {
var elem = this.find(tag);
return elem ? elem.value : undefined;
}
DataDecoder.prototype.getNextValue = function() {
var elem = this.data.shift();
return elem ? elem.value : undefined;
}
DataDecoder.prototype.getName = function() {
return this.data[0].name;
}
DataDecoder.prototype.getTag = function() {
return this.data[0].tag;
}
DataDecoder.prototype.getType = function() {
return this.data[0].type || -1;
}
Native.create("com/nokia/mid/s40/codec/DataEncoder.init.()V", function() {
this.encoder = new DataEncoder();
});
Native.create("com/nokia/mid/s40/codec/DataEncoder.putStart.(ILjava/lang/String;)V", function(tag, name) {
this.encoder.putStart(tag, util.fromJavaString(name));
});
Native.create("com/nokia/mid/s40/codec/DataEncoder.put.(ILjava/lang/String;Ljava/lang/String;)V", function(tag, name, value) {
this.encoder.put(tag, util.fromJavaString(name), util.fromJavaString(value));
});
Native.create("com/nokia/mid/s40/codec/DataEncoder.put.(ILjava/lang/String;J)V", function(tag, name, value, _) {
this.encoder.put(tag, util.fromJavaString(name), value.toNumber());
});
Native.create("com/nokia/mid/s40/codec/DataEncoder.put.(ILjava/lang/String;Z)V", function(tag, name, value) {
this.encoder.put(tag, util.fromJavaString(name), value);
});
Native.create("com/nokia/mid/s40/codec/DataEncoder.putEnd.(ILjava/lang/String;)V", function(tag, name) {
this.encoder.putEnd(tag, util.fromJavaString(name));
});
Native.create("com/nokia/mid/s40/codec/DataEncoder.getData.()[B", function() {
var data = this.encoder.getData();
var array = util.newPrimitiveArray("B", data.length);
for (var i = 0; i < data.length; i++) {
array[i] = data.charCodeAt(i);
}
return array;
});
Native.create("com/nokia/mid/s40/codec/DataDecoder.init.([BII)V", function(data, offset, length) {
this.decoder = new DataDecoder(data, offset, length);
});
Native.create("com/nokia/mid/s40/codec/DataDecoder.getStart.(I)V", function(tag) {
if (!this.decoder.getStart(tag)) {
throw new JavaException("java/io/IOException", "no start found " + tag);
}
});
Native.create("com/nokia/mid/s40/codec/DataDecoder.getEnd.(I)V", function(tag) {
if (!this.decoder.getEnd(tag)) {
throw new JavaException("java/io/IOException", "no end found " + tag);
}
});
Native.create("com/nokia/mid/s40/codec/DataDecoder.getString.(I)Ljava/lang/String;", function(tag) {
var str = this.decoder.getValue(tag);
if (str === undefined) {
throw new JavaException("java/io/IOException", "tag (" + tag + ") invalid");
}
return str;
});
Native.create("com/nokia/mid/s40/codec/DataDecoder.getInteger.(I)J", function(tag) {
var num = this.decoder.getValue(tag);
if (num === undefined) {
throw new JavaException("java/io/IOException", "tag (" + tag + ") invalid");
}
return Long.fromNumber(num);
});
Native.create("com/nokia/mid/s40/codec/DataDecoder.getBoolean.()Z", function() {
var val = this.decoder.getNextValue();
if (val === undefined) {
throw new JavaException("java/io/IOException");
}
return val === 1;
});
Native.create("com/nokia/mid/s40/codec/DataDecoder.getName.()Ljava/lang/String;", function() {
var name = this.decoder.getName();
if (name === undefined) {
throw new JavaException("java/io/IOException");
}
return name;
});
Native.create("com/nokia/mid/s40/codec/DataDecoder.getType.()I", function() {
var tag = this.decoder.getTag();
if (tag === undefined) {
throw new JavaException("java/io/IOException");
}
return tag;
});
Native.create("com/nokia/mid/s40/codec/DataDecoder.listHasMoreItems.()Z", function() {
return this.decoder.getType() != DataEncoder.END;
});