Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Anton Klarén
LabComm
Commits
72b71cd2
Commit
72b71cd2
authored
Mar 06, 2015
by
Anton Klarén
Browse files
Added tests and refactored/cleanup array decoding
parent
dd72ad92
Changes
3
Hide whitespace changes
Inline
Side-by-side
lib/js/index.html
View file @
72b71cd2
...
...
@@ -35,122 +35,7 @@ btn.onclick = function() {
decodeFromUrl
(
urlInp
.
value
);
};
decodeFromUrl
(
'
http://fair-2014-4.lab1.cs.lth.se:8080/logdata/clamping/experiments/e12c4b31-5b32-41c0-b6a3-a5ad045aa997/data
'
);
var
referenceObject
=
{
log_message
:
{
//struct
sequence
:
10
,
//int
message
:
'
Test
'
,
//string
data
:
{
//struct
f_value
:
1.6
,
//float
d_value
:
1000000.0
,
//double
l_value
:
145
,
//long
s_value
:
10
,
//short
b_value
:
0xA
,
//byte
theStack
:
{
//struct
level
:
2
,
//int
name
:
'
Robot.Move.toPos(10)
'
,
//string
fatal
:
true
//bool
}
},
xyz
:
[
1
,
2
,
3
],
//int[3]
vect
:
[
8
,
7
,
6
,
5
,
4
,
3
],
//int[_]
fix_mat
:
[[
1
,
2
,
3
,
4
],[
2
,
3
,
4
,
5
],[
3
,
4
,
5
,
6
]],
//int[3][_]
dyn_mat
:
[[
1
,
2
],[
3
,
4
]],
//int[_][2]
fix_mul
:
[[
1
,
2
,
3
,
4
],[
2
,
3
,
4
,
5
],[
3
,
4
,
5
,
6
]],
//int[_, 4]
dyn_mul
:
[[
1
,
2
],[
3
,
4
]],
//int[_, 2]
fix_mulmat
:
[[[
1
,
2
,
3
],[
4
,
5
,
6
]]],
//int[1, _][_]
fix_matmul
:
[[[
1
,
2
,
3
],[
4
,
5
,
6
]]],
//int[_][2, _]
dyn_mulmat
:
[[[
1
,
2
,
3
],[
4
,
5
,
6
]]],
//int[_, _][3]
dyn_matmul
:
[[[
1
,
2
,
3
],[
4
,
5
,
6
]]],
//int[1][_, 3]
points
:
[
{
x
:
4.6
,
y
:
2.3
},
{
x
:
7.1
,
y
:
1.0
},
{
x
:
6.2
,
y
:
5.9
}
]
//struct { float x; float y; } points[_]
}
};
function
testObject
(
obj
)
{
console
.
log
(
JSON
.
stringify
(
obj
));
console
.
log
(
compareObjects
(
referenceObject
,
obj
));
}
function
compareObjects
(
o
,
p
)
{
var
i
,
keysO
=
Object
.
keys
(
o
).
sort
(),
keysP
=
Object
.
keys
(
p
).
sort
();
if
(
keysO
.
length
!==
keysP
.
length
)
{
return
false
;
//not the same nr of keys
}
if
(
keysO
.
join
(
''
)
!==
keysP
.
join
(
''
))
{
return
false
;
//different keys
}
for
(
i
=
0
;
i
<
keysO
.
length
;
++
i
)
{
var
x
=
o
[
keysO
[
i
]],
y
=
p
[
keysO
[
i
]];
if
(
x
instanceof
Array
)
{
if
(
!
(
y
instanceof
Array
))
return
false
;
//if (compareObjects(o[keysO[i]], p[keysO[i]] === false) return false
//would work, too, and perhaps is a better fit, still, this is easy, too
if
(
p
[
keysO
[
i
]].
sort
().
join
(
''
)
!==
o
[
keysO
[
i
]].
sort
().
join
(
''
))
return
false
;
}
else
if
(
o
[
keysO
[
i
]]
instanceof
Date
)
{
if
(
!
(
p
[
keysO
[
i
]]
instanceof
Date
))
return
false
;
if
((
''
+
o
[
keysO
[
i
]])
!==
(
''
+
p
[
keysO
[
i
]]))
return
false
;
}
else
if
(
o
[
keysO
[
i
]]
instanceof
Function
)
{
if
(
!
(
p
[
keysO
[
i
]]
instanceof
Function
))
return
false
;
//ignore functions, or check them regardless?
}
if
(
x
instanceof
Object
)
{
if
(
!
(
y
instanceof
Object
))
return
false
;
if
(
x
===
o
)
{
//self reference?
if
(
y
!==
p
)
return
false
;
}
else
if
(
compareObjects
(
x
,
y
)
===
false
)
{
return
false
;
//WARNING: does not deal with circular refs other than ^^
}
}
else
if
(
Number
(
x
)
===
x
)
{
//number
if
((
x
|
0
)
===
x
)
{
//int
if
(
x
!==
y
)
{
return
false
;
}
}
else
{
//float point, allow deviation
var
diff
=
Math
.
abs
(
x
-
y
);
if
(
diff
>
1
e
-
6
)
{
return
false
;
}
}
}
else
if
(
x
!==
y
)
{
//change !== to != for loose comparison
console
.
log
(
'
missmatch
'
+
x
+
'
:
'
+
y
);
return
false
;
//not the same value
}
console
.
log
(
'
match
'
+
x
+
'
:
'
+
y
);
}
return
true
;
}
function
isInt
(
n
){
return
Number
(
n
)
===
n
&&
n
%
1
===
0
;
}
</script>
<script
src=
'tester.js'
></script>
</body>
</html>
lib/js/lc.js
View file @
72b71cd2
...
...
@@ -115,7 +115,7 @@ LabComm.Buffer.prototype.getString = function() {
/**
* Reads a boolean (8-bits) from the buffer.
* @return {
B
oolean} A boolean
* @return {
b
oolean} A boolean
*/
LabComm
.
Buffer
.
prototype
.
getBoolean
=
function
()
{
return
Boolean
(
this
.
data_
.
getUint8
(
this
.
offset_
++
));
...
...
@@ -235,13 +235,13 @@ LabComm.Decoder = function(callback) {
* @param {string} type The string representation of the type
* @param {string} parser The parsing function to be called when decoding current field
* @param {number} level The current nesting level
* @param {string=} opt_array
Var
The array variable to put the result in
* @param {string=} opt_
p
ar
entAr
ray The array variable to put the result in
* @return {string} The JSON part of the final structure
* @private
*/
LabComm
.
Decoder
.
prototype
.
buildDecoder_
=
function
(
name
,
json
,
fb
,
type
,
parser
,
level
,
opt_array
Var
)
{
if
(
opt_array
Var
)
{
fb
.
push
(
this
.
indent_
(
level
)
+
opt_array
Var
+
'
=
'
+
parser
+
'
; //
'
+
name
+
'
\n
'
);
LabComm
.
Decoder
.
prototype
.
buildDecoder_
=
function
(
name
,
json
,
fb
,
type
,
parser
,
level
,
opt_
p
ar
entAr
ray
)
{
if
(
opt_
p
ar
entAr
ray
)
{
fb
.
push
(
this
.
indent_
(
level
)
+
opt_
p
ar
entAr
ray
+
'
=
'
+
parser
+
'
; //
'
+
name
+
'
\n
'
);
return
type
;
}
...
...
@@ -251,10 +251,22 @@ LabComm.Decoder.prototype.buildDecoder_ = function(name, json, fb, type, parser,
return
'
"
'
+
name
+
'
":
'
+
'
"
'
+
type
+
'
"
'
;
};
/**
* Creates indentation
* @param {number} level The indentation level to match
* @return {string} A string with the given level of indentation
* @private
*/
LabComm
.
Decoder
.
prototype
.
indent_
=
function
(
level
)
{
return
new
Array
(
level
+
1
).
join
(
'
\t
'
);
};
/**
* Splits the variable name based on array literal
* e.g. int[3] => {type: "int", dim: "[3]"}
* @param {string} str The string representation of an array type
* @return {{type: string, dim: string}} An object consisting of the split string
*/
LabComm
.
Decoder
.
prototype
.
exctractArray_
=
function
(
str
)
{
var
index
=
str
.
indexOf
(
'
[
'
);
if
(
index
>
0
)
{
...
...
@@ -263,113 +275,102 @@ LabComm.Decoder.prototype.exctractArray_ = function(str) {
return
{
type
:
str
,
dim
:
''
};
}
/**
* Decodes a signature recursively
* @param {string} name The name of the current field
* @param {Array<string>} json The final json representation of the fields
* @param {Array<string>} fb The final function body of the decoder
* @param {number} level The current nestling level
* @param {string=} opt_array
Var
The array variable to put the result in
* @param {string=} opt_
p
ar
entAr
ray The array variable to put the result in
* @return {string} The JSON part of the sub structure
* @throws {string} If decoding could not be performed
* @private
*/
LabComm
.
Decoder
.
prototype
.
decodeSignature_
=
function
(
name
,
json
,
fb
,
level
,
opt_array
Var
)
{
LabComm
.
Decoder
.
prototype
.
decodeSignature_
=
function
(
name
,
json
,
fb
,
level
,
opt_
p
ar
entAr
ray
)
{
var
type
=
this
.
data
.
getVarint
();
switch
(
type
)
{
case
LabComm
.
Constants
.
ARRAY
:
var
arrayVariable
=
'
a
'
+
this
.
uid_
++
;
var
func
=
[];
func
.
push
(
'
"
'
+
name
+
'
":[
'
);
if
(
!
opt_arrayVar
)
{
//only add first array to final result
if
(
!
opt_parentArray
)
{
//only add top-most array to final result
json
.
push
(
'
"
'
+
name
+
'
":
'
+
arrayVariable
);
}
//read number of indecies
var
indecies
=
this
.
data
.
getVarint
();
if
(
indecies
===
0
)
{
throw
"
Array cant have 0 dimensions
"
;
}
//get dimensions of the indecies and build for loop header
var
dims
=
new
Array
(
indecies
);
var
dimStr
=
new
Array
(
indecies
);
var
dimVars
=
new
Array
(
indecies
);
for
(
var
i
=
0
;
i
<
indecies
;
i
++
)
{
dims
[
i
]
=
this
.
data
.
getVarint
();
}
//console.log(name + '[' + dims + ']');
var
dimStr
=
[];
if
(
indecies
==
1
)
{
var
dim
=
dims
[
0
];
var
dim
=
this
.
data
.
getVarint
();
dims
[
i
]
=
dim
;
dimStr
[
i
]
=
(
dim
===
0
)?
'
_
'
:
dim
;
// 0 means dynamic array
if
(
dim
===
0
)
{
dimStr
.
push
(
'
_
'
);
var
arrayDimVar
=
'
d
'
+
this
.
uid_
++
;
fb
.
push
(
this
.
indent_
(
level
)
+
'
var
'
+
arrayDimVar
+
'
= data.getVarint();
\n
'
);
dim
=
arrayDimVar
;
}
else
dimStr
.
push
(
dim
);
fb
.
push
(
this
.
indent_
(
level
)
+
'
var
'
+
arrayVariable
+
'
= new Array(
'
+
dim
+
'
);
\n
'
);
var
indexVar
=
'
i
'
+
this
.
uid_
++
;
fb
.
push
(
this
.
indent_
(
level
)
+
'
for(var
'
+
indexVar
+
'
= 0;
'
+
indexVar
+
'
<
'
+
dim
+
'
;
'
+
indexVar
+
'
++) {
\n
'
)
var
arrayType
=
this
.
decodeSignature_
(
name
,
json
,
fb
,
level
+
1
,
arrayVariable
+
'
[
'
+
indexVar
+
'
]
'
);
fb
.
push
(
this
.
indent_
(
level
)
+
'
}
\n
'
);
// array for loop
if
(
opt_arrayVar
)
{
fb
.
push
(
this
.
indent_
(
level
)
+
opt_arrayVar
+
'
=
'
+
arrayVariable
+
'
;
\n
'
);
}
dimVars
[
i
]
=
dim
;
}
else
{
var
dimVars
=
new
Array
(
indecies
);
for
(
var
i
=
0
;
i
<
indecies
;
i
++
)
{
var
dim
=
dims
[
i
];
if
(
dim
===
0
)
{
var
arrayDimVar
=
'
d
'
+
this
.
uid_
++
;
fb
.
push
(
this
.
indent_
(
level
)
+
'
var
'
+
arrayDimVar
+
'
= data.getVarint();
\n
'
);
dim
=
arrayDimVar
;
dimStr
.
push
(
'
_
'
);
}
else
dimStr
.
push
(
dim
);
dimVars
[
i
]
=
dim
;
}
var
endFor
=
[];
var
nextVar
,
indexVar
,
prevVar
,
firstVar
=
arrayVariable
;
for
(
var
i
=
0
;
i
<
indecies
;
i
++
)
{
indexVar
=
'
i
'
+
this
.
uid_
++
;
fb
.
push
(
this
.
indent_
(
level
+
i
)
+
'
var
'
+
arrayVariable
+
'
= new Array(
'
+
dimVars
[
i
]
+
'
);
\n
'
);
fb
.
push
(
this
.
indent_
(
level
+
i
)
+
'
for(var
'
+
indexVar
+
'
= 0;
'
+
indexVar
+
'
<
'
+
dimVars
[
i
]
+
'
;
'
+
indexVar
+
'
++) {
\n
'
)
var
nextVar
=
'
a
'
+
this
.
uid_
++
;
endFor
.
unshift
(
this
.
indent_
(
level
+
i
+
1
)
+
'
}
\n
'
+
this
.
indent_
(
level
+
i
+
1
)
+
arrayVariable
+
'
[
'
+
indexVar
+
'
] =
'
+
nextVar
+
'
;
\n
'
+
this
.
indent_
(
level
+
i
)
+
'
}
\n
'
);
prevVar
=
arrayVariable
;
arrayVariable
=
nextVar
;
}
var
arrayType
=
this
.
decodeSignature_
(
name
,
json
,
fb
,
level
+
indecies
,
prevVar
+
'
[
'
+
indexVar
+
'
]
'
);
endFor
.
shift
();
// remove last
fb
.
push
(
endFor
.
join
(
''
));
if
(
opt_arrayVar
)
{
fb
.
push
(
this
.
indent_
(
level
)
+
opt_arrayVar
+
'
=
'
+
firstVar
+
'
;
\n
'
);
}
//create for loop(s)
var
endFor
=
[],
nextVar
,
indexVar
,
prevVar
,
currentVar
=
arrayVariable
;
for
(
var
i
=
0
;
i
<
indecies
;
i
++
)
{
indexVar
=
'
i
'
+
this
.
uid_
++
;
fb
.
push
(
this
.
indent_
(
level
+
i
)
+
'
var
'
+
currentVar
+
'
= new Array(
'
+
dimVars
[
i
]
+
'
);
\n
'
);
fb
.
push
(
this
.
indent_
(
level
+
i
)
+
'
for(var
'
+
indexVar
+
'
= 0;
'
+
indexVar
+
'
<
'
+
dimVars
[
i
]
+
'
;
'
+
indexVar
+
'
++) {
\n
'
)
var
nextVar
=
'
a
'
+
this
.
uid_
++
;
endFor
.
unshift
(
this
.
indent_
(
level
+
i
+
1
)
+
'
}
\n
'
+
this
.
indent_
(
level
+
i
+
1
)
+
arrayVariable
+
'
[
'
+
indexVar
+
'
] =
'
+
nextVar
+
'
;
\n
'
+
this
.
indent_
(
level
+
i
)
+
'
}
\n
'
);
prevVar
=
currentVar
;
currentVar
=
nextVar
;
}
endFor
.
shift
();
// remove last
//propagate decoding
var
arrayType
=
this
.
decodeSignature_
(
name
,
json
,
fb
,
level
+
indecies
,
prevVar
+
'
[
'
+
indexVar
+
'
]
'
);
//if we only have one index we need to explicitly end the foor loop
if
(
indecies
==
1
)
{
endFor
.
unshift
(
this
.
indent_
(
level
)
+
'
}
\n
'
);
}
if
(
opt_arrayVar
)
{
//create for loop footer
fb
.
push
(
endFor
.
join
(
''
));
if
(
opt_parentArray
)
{
fb
.
push
(
this
.
indent_
(
level
)
+
opt_parentArray
+
'
=
'
+
arrayVariable
+
'
;
\n
'
);
}
//if we have a parent array just return the type
if
(
opt_parentArray
)
{
return
arrayType
+
'
[
'
+
dimStr
.
join
(
'
,
'
)
+
'
]
'
;
}
var
arrayParts
=
this
.
exctractArray_
(
arrayType
);
if
(
arrayParts
.
type
.
charAt
(
0
)
==
'
{
'
)
{
//we need to handle structs seperatly since they contains JSON object
if
(
arrayParts
.
type
.
charAt
(
0
)
==
'
{
'
)
{
return
'
"
'
+
name
+
'
[
'
+
dimStr
.
join
(
'
,
'
)
+
'
]
'
+
arrayParts
.
dim
+
'
":
'
+
arrayParts
.
type
;
}
return
'
"
'
+
name
+
'
[
'
+
dimStr
.
join
(
'
,
'
)
+
'
]
'
+
arrayParts
.
dim
+
'
":
'
+
'
"
'
+
arrayParts
.
type
+
'
"
'
;
break
;
case
LabComm
.
Constants
.
STRUCT
:
var
func
=
[];
var
subJson
=
[];
var
structVar
=
'
s
'
+
this
.
uid_
++
;
if
(
opt_array
Var
)
{
func
.
push
(
'
{
'
);
if
(
opt_
p
ar
entAr
ray
)
{
func
.
push
(
'
{
'
);
//we get the name from the parent array
}
else
{
func
.
push
(
'
"
'
+
name
+
'
":{
'
);
...
...
@@ -386,8 +387,8 @@ LabComm.Decoder.prototype.decodeSignature_ = function(name, json, fb, level, opt
}
func
.
push
(
"
}
"
);
if
(
opt_array
Var
)
{
fb
.
push
(
this
.
indent_
(
level
)
+
opt_array
Var
+
'
= {
'
+
subJson
.
join
(
''
)
+
'
};
\n
'
);
if
(
opt_
p
ar
entAr
ray
)
{
fb
.
push
(
this
.
indent_
(
level
)
+
opt_
p
ar
entAr
ray
+
'
= {
'
+
subJson
.
join
(
''
)
+
'
};
\n
'
);
}
else
{
fb
.
push
(
this
.
indent_
(
level
)
+
'
var
'
+
structVar
+
'
= {
'
+
subJson
.
join
(
''
)
+
'
};
\n
'
);
...
...
@@ -395,21 +396,21 @@ LabComm.Decoder.prototype.decodeSignature_ = function(name, json, fb, level, opt
}
return
func
.
join
(
''
);
case
LabComm
.
Constants
.
BOOLEAN
:
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
bool
"
,
"
data.getBoolean()
"
,
level
,
opt_array
Var
);
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
bool
"
,
"
data.getBoolean()
"
,
level
,
opt_
p
ar
entAr
ray
);
case
LabComm
.
Constants
.
BYTE
:
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
byte
"
,
"
data.getByte()
"
,
level
,
opt_array
Var
);
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
byte
"
,
"
data.getByte()
"
,
level
,
opt_
p
ar
entAr
ray
);
case
LabComm
.
Constants
.
SHORT
:
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
short
"
,
"
data.getShort()
"
,
level
,
opt_array
Var
);
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
short
"
,
"
data.getShort()
"
,
level
,
opt_
p
ar
entAr
ray
);
case
LabComm
.
Constants
.
INT
:
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
int
"
,
"
data.getInt()
"
,
level
,
opt_array
Var
);
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
int
"
,
"
data.getInt()
"
,
level
,
opt_
p
ar
entAr
ray
);
case
LabComm
.
Constants
.
LONG
:
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
long
"
,
"
data.getLong()
"
,
level
,
opt_array
Var
);
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
long
"
,
"
data.getLong()
"
,
level
,
opt_
p
ar
entAr
ray
);
case
LabComm
.
Constants
.
FLOAT
:
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
float
"
,
"
data.getFloat()
"
,
level
,
opt_array
Var
);
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
float
"
,
"
data.getFloat()
"
,
level
,
opt_
p
ar
entAr
ray
);
case
LabComm
.
Constants
.
DOUBLE
:
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
double
"
,
"
data.getDouble()
"
,
level
,
opt_array
Var
);
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
double
"
,
"
data.getDouble()
"
,
level
,
opt_
p
ar
entAr
ray
);
case
LabComm
.
Constants
.
STRING
:
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
string
"
,
"
data.getString()
"
,
level
,
opt_array
Var
);
return
this
.
buildDecoder_
(
name
,
json
,
fb
,
"
string
"
,
"
data.getString()
"
,
level
,
opt_
p
ar
entAr
ray
);
}
throw
"
Unknown type found in signature: 0x
"
+
type
.
toString
(
16
);
};
...
...
@@ -425,7 +426,7 @@ LabComm.Decoder.prototype.decodePackage = function(buffer) {
var
tag
=
this
.
data
.
getVarint
();
var
len
=
this
.
data
.
getVarint
();
console
.
log
(
'
0x
'
+
tag
.
toString
(
16
)
+
'
:
'
+
len
);
//
console.log('0x' + tag.toString(16) + ':' + len);
switch
(
tag
)
{
case
LabComm
.
Constants
.
VERSION
:
...
...
@@ -441,10 +442,7 @@ LabComm.Decoder.prototype.decodePackage = function(buffer) {
var
json
=
[],
fb
=
[];
var
tmp
=
this
.
decodeSignature_
(
name
,
json
,
fb
,
1
);
console
.
log
(
tmp
);
var
struct
=
JSON
.
parse
(
'
{
'
+
tmp
+
"
}
"
);
console
.
log
(
struct
);
var
struct
=
JSON
.
parse
(
'
{
'
+
this
.
decodeSignature_
(
name
,
json
,
fb
,
1
)
+
"
}
"
);
var
func
=
fb
.
join
(
''
)
+
'
\n\t
return {
'
+
json
.
join
(
''
)
+
'
};
'
;
...
...
@@ -470,7 +468,7 @@ LabComm.Decoder.prototype.decodePackage = function(buffer) {
this
.
callback_
(
decl
,
sample
);
break
;
break
;
}
}
};
...
...
lib/js/tester.js
View file @
72b71cd2
'
use strict
'
;
(
function
()
{
function
decodeFromUrl
(
url
)
{
var
oReq
=
new
XMLHttpRequest
();
oReq
.
open
(
"
GET
"
,
url
,
true
);
oReq
.
responseType
=
"
arraybuffer
"
;
oReq
.
onload
=
function
(
oEvent
)
{
var
arrayBuffer
=
oReq
.
response
;
if
(
arrayBuffer
)
{
var
buff
=
new
LabComm
.
Buffer
(
new
DataView
(
arrayBuffer
));
window
.
decoder
=
new
LabComm
.
Decoder
(
function
(
decl
,
data
)
{
testObject
(
decl
,
data
);
});
window
.
decoder
.
decodePackage
(
buff
);
}
};
oReq
.
send
(
null
);
}
decodeFromUrl
(
'
http://fair-2014-4.lab1.cs.lth.se:8080/logdata/clamping/experiments/e12c4b31-5b32-41c0-b6a3-a5ad045aa997/data
'
);
var
referenceStruct
=
{
"
log_message
"
:{
"
sequence
"
:
"
int
"
,
"
message
"
:
"
string
"
,
"
data
"
:{
"
f_value
"
:
"
float
"
,
"
d_value
"
:
"
double
"
,
"
l_value
"
:
"
long
"
,
"
s_value
"
:
"
short
"
,
"
b_value
"
:
"
byte
"
,
"
theStack
"
:{
"
level
"
:
"
int
"
,
"
name
"
:
"
string
"
,
"
fatal
"
:
"
bool
"
}
},
"
xyz[3]
"
:
"
int
"
,
"
vect[_]
"
:
"
int
"
,
"
fix_mat[3][_]
"
:
"
int
"
,
"
dyn_mat[_][2]
"
:
"
int
"
,
"
fix_mul[_, 4]
"
:
"
int
"
,
"
dyn_mul[_, 2]
"
:
"
int
"
,
"
fix_mulmat[1, _][_]
"
:
"
int
"
,
"
fix_matmul[_][2, _]
"
:
"
int
"
,
"
dyn_mulmat[_, _][3]
"
:
"
int
"
,
"
dyn_matmul[1][_, 3]
"
:
"
int
"
,
"
points[_]
"
:{
"
x
"
:
"
float
"
,
"
y
"
:
"
float
"
}
}
};
var
referenceObject
=
{
log_message
:
{
//struct
sequence
:
10
,
//int
message
:
'
Test
'
,
//string
data
:
{
//struct
f_value
:
1.6
,
//float
d_value
:
1000000.0
,
//double
l_value
:
145
,
//long
s_value
:
10
,
//short
b_value
:
0xA
,
//byte
theStack
:
{
//struct
level
:
2
,
//int
name
:
'
Robot.Move.toPos(10)
'
,
//string
fatal
:
true
//bool
}
},
xyz
:
[
1
,
2
,
3
],
//int[3]
vect
:
[
8
,
7
,
6
,
5
,
4
,
3
],
//int[_]
fix_mat
:
[[
1
,
2
,
3
,
4
],[
2
,
3
,
4
,
5
],[
3
,
4
,
5
,
6
]],
//int[3][_]
dyn_mat
:
[[
1
,
2
],[
3
,
4
]],
//int[_][2]
fix_mul
:
[[
1
,
2
,
3
,
4
],[
2
,
3
,
4
,
5
],[
3
,
4
,
5
,
6
]],
//int[_, 4]
dyn_mul
:
[[
1
,
2
],[
3
,
4
]],
//int[_, 2]
fix_mulmat
:
[[[
1
,
2
,
3
],[
4
,
5
,
6
]]],
//int[1, _][_]
fix_matmul
:
[[[
1
,
2
,
3
],[
4
,
5
,
6
]]],
//int[_][2, _]
dyn_mulmat
:
[[[
1
,
2
,
3
],[
4
,
5
,
6
]]],
//int[_, _][3]
dyn_matmul
:
[[[
1
,
2
,
3
],[
4
,
5
,
6
]]],
//int[1][_, 3]
points
:
[
{
x
:
4.6
,
y
:
2.3
},
{
x
:
7.1
,
y
:
1.0
},
{
x
:
6.2
,
y
:
5.9
}
]
//struct { float x; float y; } points[_]
}
};
function
testObject
(
decl
,
obj
)
{
var
i
=
0
;
console
.
log
(
'
-----Running tests-----
'
);
testCase
(
'
Decode Sample Decalaration
'
,
referenceStruct
,
decl
.
struct
)
&&
i
++
;
testCase
(
'
Decode Data Sample
'
,
referenceObject
,
obj
)
&&
i
++
;
console
.
log
(
'
----------
'
);
console
.
log
(
i
+
'
of 2 tests success
'
);
console
.
log
(
'
----------
'
);
}
function
testCase
(
msg
,
r
,
t
)
{
var
test
=
compareObjects
(
r
,
t
);
console
.
log
(
'
Test "
'
+
msg
+
'
":
'
+
(
test
?
'
Success
'
:
'
Fail
'
));
if
(
!
test
)
{
console
.
log
(
t
);
console
.
log
(
'
but expected:
'
);
console
.
log
(
r
);
}
return
test
;
}
function
compareObjects
(
o
,
p
)
{
var
i
,
keysO
=
Object
.
keys
(
o
).
sort
(),
keysP
=
Object
.
keys
(
p
).
sort
();
if
(
keysO
.
length
!==
keysP
.
length
)
if
(
keysO
.
length
!==
keysP
.
length
)
{
return
false
;
//not the same nr of keys
if
(
keysO
.
join
(
''
)
!==
keysP
.
join
(
''
))
}
if
(
keysO
.
join
(
''
)
!==
keysP
.
join
(
''
))
{
return
false
;
//different keys
}
for
(
i
=
0
;
i
<
keysO
.
length
;
++
i
)
{
if
(
o
[
keysO
[
i
]]
instanceof
Array
)
{
if
(
!
(
p
[
keysO
[
i
]]
instanceof
Array
))
var
x
=
o
[
keysO
[
i
]],
y
=
p
[
keysO
[
i
]];
if
(
x
instanceof
Array
)
{
if
(
!
(
y
instanceof
Array
))
return
false
;
//if (compareObjects(o[keysO[i]], p[keysO[i]] === false) return false
//would work, too, and perhaps is a better fit, still, this is easy, too
if
(
p
[
keysO
[
i
]].
sort
().
join
(
''
)
!==
o
[
keysO
[
i
]].
sort
()
.
join
(
''
))
if
(
y
.
join
(
''
)
!==
x
.
join
(
''
))
return
false
;
}
else
if
(
o
[
keysO
[
i
]]
instanceof
Date
)
{
if
(
!
(
p
[
keysO
[
i
]]
instanceof
Date
)
else
if
(
x
instanceof
Date
)
{
if
(
!
(
y
instanceof
Date
)
)
return
false
;
if
((
''
+
o
[
keysO
[
i
]])
!==
(
''
+
p
[
keysO
[
i
]]
))
if
((
''
+
x
)
!==
(
''
+
y
))
return
false
;
}
else
if
(
o
[
keysO
[
i
]]
instanceof
Function
)
{
if
(
!
(
p
[
keysO
[
i
]]
instanceof
Function
)
else
if
(
x
instanceof
Function
)
{
if
(
!
(
y
instanceof
Function
)
)
return
false
;
//ignore functions
, or check them regardless?
//ignore functions
}
else
if
(
o
[
keysO
[
i
]]
instanceof
Object
)
{
if
(
!
(
p
[
keysO
[
i
]]
instanceof
Object
)
if
(
x
instanceof
Object
)
{
if
(
!
(
y
instanceof
Object
)
)
return
false
;
if
(
o
[
keysO
[
i
]]
===
o
)
{
//self reference?
if
(
p
[
keysO
[
i
]]
!==
p
)
if
(
x
===
o
)
{
//self reference?
if
(
y
!==
p
)
return
false
;
}
else
if
(
compareObjects
(
o
[
keysO
[
i
]],
p
[
keysO
[
i
]]
)
===
false
)
else
if
(
compareObjects
(
x
,
y
)
===
false
)
{
return
false
;
//WARNING: does not deal with circular refs other than ^^
}
}
else
if
(
Number
(
x
)
===
x
)
{
//number
if
((
x
|
0
)
===
x
)
{
//int
if
(
x
!==
y
)
{
return
false
;
}
}
else
{
//float point, allow deviation
var
diff
=
Math
.
abs
(
x
-
y
);
if
(
diff
>
1
e
-
6
)
{
return
false
;
}
}