├── .npmignore ├── CHANGELOG ├── LICENSE ├── README ├── README.old ├── ctf.js ├── ctio.js ├── ctype.js ├── man └── man3ctype │ └── ctio.3ctype ├── package.json ├── tools ├── jsl.conf └── jsstyle └── tst ├── ctf ├── float.json ├── int.json ├── psinfo.json ├── struct.json ├── tst.fail.js ├── tst.float.js ├── tst.int.js ├── tst.psinfo.js ├── tst.struct.js ├── tst.typedef.js └── typedef.json ├── ctio ├── float │ ├── tst.rfloat.js │ └── tst.wfloat.js ├── int │ ├── tst.64.js │ ├── tst.rint.js │ ├── tst.wbounds.js │ └── tst.wint.js └── uint │ ├── tst.64.js │ ├── tst.roundtrip.js │ ├── tst.ruint.js │ └── tst.wuint.js └── ctype ├── tst.basicr.js ├── tst.basicw.js ├── tst.char.js ├── tst.endian.js ├── tst.oldwrite.js ├── tst.readSize.js ├── tst.structw.js └── tst.writeStruct.js /.npmignore: -------------------------------------------------------------------------------- 1 | tst/ 2 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | This contains tickets fixed in each version release in reverse chronological 2 | order. There is one ticket per line. Each commits message has the tickets fixed 3 | in it. The commit message also has the corresponding github issue. i.e. CTYPE-42 4 | would be issue 42. Each issue can be found at: 5 | https://github.com/rmustacc/node-ctype/issues/%d. 6 | 7 | v0.5.6 8 | node-ctype#64 Handle deferred CTF type definitions 9 | 10 | v0.5.5 11 | node-ctype#56 Correct SPDX identifier 12 | ctf2json#55 remove sys 13 | 14 | v0.5.4 15 | CTYPE-54 Release v0.5.4 16 | CTYPE-51 Add "licenses" to package.json 17 | 18 | v0.5.3 19 | CTYPE-50 Release 0.5.3 20 | Contributed by Nick Schonning: 21 | CTYPE-49 Add repository section to package.json 22 | Contributed by Jonathan Ong: 23 | CTYPE-48 Create .npmignore 24 | 25 | v0.5.2 26 | CTYPE-46 Release 0.5.2 27 | CTYPE-45 error in setEndian logic 28 | 29 | v0.5.1 30 | CTYPE-44 Release 0.5.1 31 | Contributed by Terin Stock: 32 | CTYPE-41 CTypeParser.writeStruct should return its offset 33 | Contributed by Terin Stock: 34 | CTYPE-42 int64_t returns wrong size 35 | 36 | v0.5.0 37 | CTYPE-40 Release 0.5.0 38 | CTYPE-39 want > 0.6 engine support 39 | 40 | v0.4.0 41 | CTYPE-37 Release v0.4.0 42 | CTYPE-6 want additional entry point for write 43 | CTYPE-20 Add 64-bit int support into core parser 44 | CTYPE-31 Fix bounds errors node/2129 45 | CTYPE-33 Update copyright holders 46 | CTYPE-34 ctf.js confuses sign bit. 47 | CTYPE-35 Make the README more useful for getting started 48 | CTYPE-36 want manual page on ctio functions 49 | 50 | v0.3.1 51 | CTYPE-29 Release 0.3.1 52 | CTYPE-28 Want v0.6 npm support 53 | 54 | v0.3.0 55 | CTYPE-27 Release v0.3.0 56 | CTYPE-26 Want alternate default char behavior 57 | 58 | v0.2.1 59 | CTYPE-25 Release v0.2.1 60 | CTYPE-24 Writing structs is busted 61 | 62 | v0.2.0: 63 | CTYPE-23 Release v0.2.0 64 | CTYPE-21 Add support for CTF JSON data 65 | CTYPE-22 Add Javascriptlint profile 66 | CTYPE-15 Pull in ctio updates from node/master 67 | 68 | v0.1.0: 69 | CTYPE-18 Bump version to v0.1.0 70 | CTYPE-17 Fix nested structures 71 | CTYPE-16 Remove extraneous logging 72 | CTYPE-14 toAbs64 and toApprox64 are not exported 73 | 74 | v0.0.3: 75 | CTYPE-12 Bump version to v0.0.3 76 | CTYPE-11 fix typo in wuint64 77 | CTYPE-10 Integrate jsstyle 78 | 79 | v0.0.2: 80 | CTYPE-8 dump npm version to v0.0.2 81 | CTYPE-9 want changelog 82 | CTYPE-7 fix typo in detypes. 83 | 84 | v0.0.1: 85 | CTYPE-5 Missing from NPM registry 86 | CTYPE-4 int16_t calls wrong read function 87 | CTYPE-3 API example types are missing quotes as strings 88 | CTYPE-2 doc missing 64-bit functions 89 | CTYPE-1 Need license 90 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The following license applies to all files unless the file is specified below. 2 | Each file specified below has its license information embedded in it: 3 | 4 | tools/jsstyle 5 | 6 | Copyright 2011, Robert Mustacchi. All rights reserved. 7 | Copyright 2011, Joyent, Inc. All rights reserved. 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to 11 | deal in the Software without restriction, including without limitation the 12 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 13 | sell copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in 17 | all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 25 | IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Node-CType is a way to read and write binary data in structured and easy to use 2 | format. Its name comes from the C header file. 3 | 4 | To get started, simply clone the repository or use npm to install it. Once it is 5 | there, simply require it. 6 | 7 | git clone git://github.com/rmustacc/node-ctype 8 | npm install ctype 9 | var mod_ctype = require('ctype') 10 | 11 | 12 | There are two APIs that you can use, depending on what abstraction you'd like. 13 | The low level API let's you read and write individual integers and floats from 14 | buffers. The higher level API let's you read and write structures of these. To 15 | illustrate this, let's looks look at how we would read and write a binary 16 | encoded x,y point. 17 | 18 | In C we would define this structure as follows: 19 | 20 | typedef struct point { 21 | uint16_t p_x; 22 | uint16_t p_y; 23 | } point_t; 24 | 25 | To read a binary encoded point from a Buffer, we first need to create a CType 26 | parser (where we specify the endian and other options) and add the typedef. 27 | 28 | var parser = new mod_ctype.Parser({ endian: 'big' }); 29 | parser.typedef('point_t', [ 30 | { x: { type: 'uint16_t' } }, 31 | { y: { type: 'uint16_t' } } 32 | ]); 33 | 34 | From here, given a buffer buf and an offset into it, we can read a point. 35 | 36 | var out = parser.readData([ { point: { type: 'point_t' } } ], buffer, 0); 37 | console.log(out); 38 | { point: { x: 23, y: 42 } } 39 | 40 | Another way to get the same information would be to use the low level methods. 41 | Note that these require you to manually deal with the offset. Here's how we'd 42 | get the same values of x and y from the buffer. 43 | 44 | var x = mod_ctype.ruint16(buf, 'big', 0); 45 | var y = mod_ctype.ruint16(buf, 'big', 2); 46 | console.log(x + ', ' + y); 47 | 23, 42 48 | 49 | The true power of this API comes from the ability to define and nest typedefs, 50 | just as you would in C. By default, the following types are defined by default. 51 | Note that they return a Number, unless indicated otherwise. 52 | 53 | * int8_t 54 | * int16_t 55 | * int32_t 56 | * int64_t (returns an array where val[0] << 32 + val[1] would be the value) 57 | * uint8_t 58 | * uint16_t 59 | * uint32_t 60 | * uint64_t (returns an array where val[0] << 32 + val[1] would be the value) 61 | * float 62 | * double 63 | * char (either returns a buffer with that character or a uint8_t) 64 | * char[] (returns an object with the buffer and the number of characters read which is either the total amount requested or until the first 0) 65 | 66 | 67 | ctf2json integration: 68 | 69 | Node-CType supports consuming the output of ctf2json. Once you read in a JSON file, 70 | all you have to do to add all the definitions it contains is: 71 | 72 | var data, parser; 73 | data = JSON.parse(parsedJSONData); 74 | parser = mod_ctype.parseCTF(data, { endian: 'big' }); 75 | 76 | For more documentation, see the file README.old. Full documentation is in the 77 | process of being rewritten as a series of manual pages which will be available 78 | in the repository and online for viewing. 79 | 80 | To read the ctio manual page simple run, from the root of the workspace: 81 | 82 | man -Mman -s 3ctype ctio 83 | -------------------------------------------------------------------------------- /README.old: -------------------------------------------------------------------------------- 1 | This library provides a way to read and write binary data. 2 | 3 | Node CType is a way to read and write binary data in structured and easy to use 4 | formats. It's name comes from the header file, though it does not share as much 5 | with it as it perhaps should. 6 | 7 | There are two levels of the API. One is the raw API which everything is built on 8 | top of, while the other provides a much nicer abstraction and is built entirely 9 | by using the lower level API. The hope is that the low level API is both clear 10 | and useful. The low level API gets it's names from stdint.h (a rather 11 | appropriate source). The lower level API is presented at the end of this 12 | document. 13 | 14 | Standard CType API 15 | 16 | The CType interface is presented as a parser object that controls the 17 | endianness combined with a series of methods to change that value, parse and 18 | write out buffers, and a way to provide typedefs. Standard Types 19 | 20 | The CType parser supports the following basic types which return Numbers except 21 | as indicated: 22 | 23 | * int8_t 24 | * int16_t 25 | * int32_t 26 | * int64_t (returns an array where val[0] << 32 + val[1] would be the value) 27 | * uint8_t 28 | * uint16_t 29 | * uint32_t 30 | * uint64_t (returns an array where val[0] << 32 + val[1] would be the value) 31 | * float 32 | * double 33 | * char (returns a buffer with just that single character) 34 | * char[] (returns an object with the buffer and the number of characters read which is either the total amount requested or until the first 0) 35 | 36 | Specifying Structs 37 | 38 | The CType parser also supports the notion of structs. A struct is an array of 39 | JSON objects that defines an order of keys which have types and values. One 40 | would build a struct to represent a point (x,y) as follows: 41 | 42 | [ 43 | { x: { type: 'int16_t' }}, 44 | { y: { type: 'int16_t' }} 45 | ] 46 | 47 | When this is passed into the read routine, it would read the first two bytes 48 | (as defined by int16_t) to determine the Number to use for X, and then it would 49 | read the next two bytes to determine the value of Y. When read this could 50 | return something like: 51 | 52 | { 53 | x: 42, 54 | y: -23 55 | } 56 | 57 | When someone wants to write values, we use the same format as above, but with 58 | additional value field: 59 | 60 | [ 61 | { x: { type: 'int16_t', value: 42 }}, 62 | { y: { type: 'int16_t', value: -23 }} 63 | ] 64 | 65 | Now, the structure above may be optionally annotated with offsets. This tells 66 | us to rather than read continuously we should read the given value at the 67 | specified offset. If an offset is provided, it is is effectively the equivalent 68 | of lseek(offset, SEEK_SET). Thus, subsequent values will be read from that 69 | offset and incremented by the appropriate value. As an example: 70 | 71 | [ 72 | { x: { type: 'int16_t' }}, 73 | { y: { type: 'int16_t', offset: 20 }}, 74 | { z: { type: 'int16_t' }} 75 | ] 76 | 77 | We would read x from the first starting offset given to us, for the sake of 78 | example, let's assume that's 0. After reading x, the next offset to read from 79 | would be 2; however, y specifies an offset, thus we jump directly to that 80 | offset and read y from byte 20. We would then read z from byte 22. 81 | 82 | The same offsets may be used when writing values. 83 | 84 | Typedef 85 | 86 | The basic set of types while covers the basics, is somewhat limiting. To make 87 | this richer, there is functionality to typedef something like in C. One can use 88 | typedef to add a new name to an existing type or to define a name to refer to a 89 | struct. Thus the following are all examples of a typedef: 90 | 91 | typedef('size_t', 'uint32_t'); 92 | typedef('ssize_t', 'int32_t'); 93 | typedef('point_t', [ 94 | { x: { type: 'int16_t' }}, 95 | { y: { type: 'int16_t' }} 96 | ]); 97 | 98 | Once something has been typedef'd it can be used in any of the definitions 99 | previously shown. 100 | 101 | One cannot remove a typedef once created, this is analogous to C. 102 | 103 | The set of defined types can be printed with lstypes. The format of this output 104 | is subject to change, but likely will look something like: 105 | 106 | > lstypes(); 107 | { 108 | size_t: 'uint32_t', 109 | ssize_t: 'int32_t', 110 | point_t: [ 111 | { x: { type: 'int16_t' }}, 112 | { y: { type: 'int16_t' }} 113 | ] 114 | } 115 | 116 | Specifying arrays 117 | 118 | Arrays can be specified by appending []s to a type. Arrays must have the size 119 | specified. The size must be specified and it can be done in one of two ways: 120 | 121 | * An explicit non-zero integer size 122 | * A name of a previously declared variable in the struct whose value is a 123 | number. 124 | 125 | Note, that when using the name of a variable, it should be the string name for 126 | the key. This is only valid inside structs and the value must be declared 127 | before the value with the array. The following are examples: 128 | 129 | [ 130 | { ip_addr4: { type: 'uint8_t[4]' }}, 131 | { len: { type: 'uint32_t' }}, 132 | { data: { type: 'uint8_t[len]' }} 133 | ] 134 | 135 | Arrays are permitted in typedefs; however, they must have a declared integer 136 | size. The following are examples of valid and invalid arrays: 137 | 138 | typedef('path', 'char[1024]'); /* Good */ 139 | typedef('path', 'char[len]'); /* Bad! */ 140 | 141 | 64 bit values: 142 | 143 | Unfortunately Javascript represents values with a double, so you lose precision 144 | and the ability to represent Integers roughly beyond 2^53. To alleviate this, I 145 | propose the following for returning 64 bit integers when read: 146 | 147 | value[2]: Each entry is a 32 bit number which can be reconstructed to the 148 | original by the following formula: 149 | 150 | value[0] << 32 + value[1] (Note this will not work in Javascript) 151 | 152 | CTF JSON data: 153 | 154 | node-ctype can also handle JSON data that mathces the format described in the 155 | documentation of the tool ctf2json. Given the JSON data which specifies type 156 | information, it will transform that into a parser that understands all of the 157 | types defined inside of it. This is useful for more complicated structures that 158 | have a lot of typedefs. 159 | 160 | Interface overview 161 | 162 | The following is the header-file like interface to the parser object: 163 | 164 | /* 165 | * Create a new instance of the parser. Each parser has its own store of 166 | * typedefs and endianness. Conf is an object with the following values: 167 | * 168 | * endian Either 'big' or 'little' do determine the endianness we 169 | * want to read from or write to. 170 | * 171 | */ 172 | function CTypeParser(conf); 173 | 174 | /* 175 | * Parses the CTF JSON data and creates a parser that understands all of those 176 | * types. 177 | * 178 | * data Parsed JSON data that maches that CTF JSON 179 | * specification. 180 | * 181 | * conf The configuration object to create a new CTypeParser 182 | * from. 183 | */ 184 | CTypeParser parseCTF(data, conf); 185 | 186 | /* 187 | * This is what we were born to do. We read the data from a buffer and return it 188 | * in an object whose keys match the values from the object. 189 | * 190 | * def The array definition of the data to read in 191 | * 192 | * buffer The buffer to read data from 193 | * 194 | * offset The offset to start writing to 195 | * 196 | * Returns an object where each key corresponds to an entry in def and the value 197 | * is the read value. 198 | */ 199 | Object CTypeParser.readData(, buffer, offset); 200 | 201 | /* 202 | * This is the second half of what we were born to do, write out the data 203 | * itself. 204 | * 205 | * def The array definition of the data to write out with 206 | * values 207 | * 208 | * buffer The buffer to write to 209 | * 210 | * offset The offset in the buffer to write to 211 | */ 212 | void CTypeParser.writeData(, buffer, offset); 213 | 214 | /* 215 | * A user has requested to add a type, let us honor their request. Yet, if their 216 | * request doth spurn us, send them unto the Hells which Dante describes. 217 | * 218 | * name The string for the type definition we're adding 219 | * 220 | * value Either a string that is a type/array name or an object 221 | * that describes a struct. 222 | */ 223 | void CTypeParser.prototype.typedef(name, value); 224 | 225 | Object CTypeParser.prototype.lstypes(); 226 | 227 | /* 228 | * Get the endian value for the current parser 229 | */ 230 | String CTypeParser.prototype.getEndian(); 231 | 232 | /* 233 | * Sets the current endian value for the Parser. If the value is not valid, 234 | * throws an Error. 235 | * 236 | * endian Either 'big' or 'little' do determine the endianness we 237 | * want to read from or write to. 238 | * 239 | */ 240 | void CTypeParser.protoype.setEndian(String); 241 | 242 | /* 243 | * Attempts to convert an array of two integers returned from rsint64 / ruint64 244 | * into an absolute 64 bit number. If however the value would exceed 2^52 this 245 | * will instead throw an error. The mantissa in a double is a 52 bit number and 246 | * rather than potentially give you a value that is an approximation this will 247 | * error. If you would rather an approximation, please see toApprox64. 248 | * 249 | * val An array of two 32-bit integers 250 | */ 251 | Number function toAbs64(val) 252 | 253 | /* 254 | * Will return the 64 bit value as returned in an array from rsint64 / ruint64 255 | * to a value as close as it can. Note that Javascript stores all numbers as a 256 | * double and the mantissa only has 52 bits. Thus this version may approximate 257 | * the value. 258 | * 259 | * val An array of two 32-bit integers 260 | */ 261 | Number function toApprox64(val) 262 | 263 | Low Level API 264 | 265 | The following function are provided at the low level: 266 | 267 | Read unsigned integers from a buffer: 268 | Number ruint8(buffer, endian, offset); 269 | Number ruint16(buffer, endian, offset); 270 | Number ruint32(buffer, endian, offset); 271 | Number[] ruint64(buffer, endian, offset); 272 | 273 | Read signed integers from a buffer: 274 | Number rsint8(buffer, endian, offset); 275 | Number rsint16(buffer, endian, offset); 276 | Number rsint32(buffer, endian, offset); 277 | Number[] rsint64(buffer, endian, offset); 278 | 279 | Read floating point numbers from a buffer: 280 | Number rfloat(buffer, endian, offset); /* IEEE-754 Single precision */ 281 | Number rdouble(buffer, endian, offset); /* IEEE-754 Double precision */ 282 | 283 | Write unsigned integers to a buffer: 284 | void wuint8(Number, endian, buffer, offset); 285 | void wuint16(Number, endian, buffer, offset); 286 | void wuint32(Number, endian, buffer, offset); 287 | void wuint64(Number[], endian, buffer, offset); 288 | 289 | Write signed integers from a buffer: 290 | void wsint8(Number, endian, buffer, offset); 291 | void wsint16(Number, endian, buffer, offset); 292 | void wsint32(Number, endian, buffer, offset); 293 | void wsint64(Number[], endian, buffer offset); 294 | 295 | Write floating point numbers from a buffer: 296 | void wfloat(Number, buffer, endian, offset); /* IEEE-754 Single precision */ 297 | void wdouble(Number, buffer, endian, offset); /* IEEE-754 Double precision */ 298 | 299 | -------------------------------------------------------------------------------- /ctf.js: -------------------------------------------------------------------------------- 1 | /* 2 | * ctf.js 3 | * 4 | * Understand and parse all of the different JSON formats of CTF data and 5 | * translate that into a series of node-ctype friendly pieces. The reason for 6 | * the abstraction is to handle different changes in the file format. 7 | * 8 | * We have to be careful here that we don't end up using a name that is already 9 | * a built in type. 10 | */ 11 | var mod_assert = require('assert'); 12 | var ASSERT = mod_assert.ok; 13 | 14 | var ctf_versions = [ '1.0' ]; 15 | var ctf_entries = [ 'integer', 'float', 'typedef', 'struct' ]; 16 | var ctf_deftypes = [ 'int8_t', 'uint8_t', 'int16_t', 'uint16_t', 'int32_t', 17 | 'uint32_t', 'float', 'double' ]; 18 | 19 | function ctfParseInteger(entry, ctype) 20 | { 21 | var name, sign, len, type; 22 | 23 | name = entry['name']; 24 | if (!('signed' in entry['integer'])) 25 | throw (new Error('Malformed CTF JSON: integer missing ' + 26 | 'signed value')); 27 | 28 | 29 | if (!('length' in entry['integer'])) 30 | throw (new Error('Malformed CTF JSON: integer missing ' + 31 | 'length value')); 32 | 33 | sign = entry['integer']['signed']; 34 | len = entry['integer']['length']; 35 | type = null; 36 | 37 | if (sign && len == 1) 38 | type = 'int8_t'; 39 | else if (len == 1) 40 | type = 'uint8_t'; 41 | else if (sign && len == 2) 42 | type = 'int16_t'; 43 | else if (len == 2) 44 | type = 'uint16_t'; 45 | else if (sign && len == 4) 46 | type = 'int32_t'; 47 | else if (len == 4) 48 | type = 'uint32_t'; 49 | else if (sign && len == 8) 50 | type = 'int64_t'; 51 | else if (len == 8) 52 | type = 'uint64_t'; 53 | 54 | if (type === null) 55 | throw (new Error('Malformed CTF JSON: integer has ' + 56 | 'unsupported length and sign - ' + len + '/' + sign)); 57 | 58 | /* 59 | * This means that this is the same as one of our built in types. If 60 | * that's the case defining it would be an error. So instead of trying 61 | * to typedef it, we'll return here. 62 | */ 63 | if (name == type) 64 | return; 65 | 66 | if (name == 'char') { 67 | ASSERT(type == 'int8_t'); 68 | return; 69 | } 70 | 71 | ctype.typedef(name, type); 72 | } 73 | 74 | function ctfParseFloat(entry, ctype) 75 | { 76 | var name, len; 77 | 78 | name = entry['name']; 79 | if (!('length' in entry['float'])) 80 | throw (new Error('Malformed CTF JSON: float missing ' + 81 | 'length value')); 82 | 83 | len = entry['float']['length']; 84 | if (len != 4 && len != 8) 85 | throw (new Error('Malformed CTF JSON: float has invalid ' + 86 | 'length value')); 87 | 88 | if (len == 4) { 89 | if (name == 'float') 90 | return; 91 | ctype.typedef(name, 'float'); 92 | } else if (len == 8) { 93 | if (name == 'double') 94 | return; 95 | ctype.typedef(name, 'double'); 96 | } 97 | } 98 | 99 | function ctfParseTypedef(entry, ctype) 100 | { 101 | var name, type, ii; 102 | 103 | name = entry['name']; 104 | if (typeof (entry['typedef']) != 'string') 105 | throw (new Error('Malformed CTF JSON: typedef value in not ' + 106 | 'a string')); 107 | 108 | type = entry['typedef']; 109 | 110 | /* 111 | * We need to ensure that we're not looking at type that's one of our 112 | * built in types. Traditionally in C a uint32_t would be a typedef to 113 | * some kind of integer. However, those size types are built ins. 114 | */ 115 | for (ii = 0; ii < ctf_deftypes.length; ii++) { 116 | if (name == ctf_deftypes[ii]) 117 | return; 118 | } 119 | 120 | ctype.typedef(name, type); 121 | } 122 | 123 | function ctfParseStruct(entry, ctype) 124 | { 125 | var name, type, ii, val, index, member, push; 126 | 127 | member = []; 128 | if (!Array.isArray(entry['struct'])) 129 | throw (new Error('Malformed CTF JSON: struct value is not ' + 130 | 'an array')); 131 | 132 | for (ii = 0; ii < entry['struct'].length; ii++) { 133 | val = entry['struct'][ii]; 134 | if (!('name' in val)) 135 | throw (new Error('Malformed CTF JSON: struct member ' + 136 | 'missing name')); 137 | 138 | if (!('type' in val)) 139 | throw (new Error('Malformed CTF JSON: struct member ' + 140 | 'missing type')); 141 | 142 | if (typeof (val['name']) != 'string') 143 | throw (new Error('Malformed CTF JSON: struct member ' + 144 | 'name isn\'t a string')); 145 | 146 | if (typeof (val['type']) != 'string') 147 | throw (new Error('Malformed CTF JSON: struct member ' + 148 | 'type isn\'t a string')); 149 | 150 | /* 151 | * CTF version 2 specifies array names as [] where 152 | * as node-ctype does this as []. 153 | */ 154 | name = val['name']; 155 | type = val['type']; 156 | index = type.indexOf(' ['); 157 | if (index != -1) { 158 | type = type.substring(0, index) + 159 | type.substring(index + 1, type.length); 160 | } 161 | push = {}; 162 | push[name] = { 'type': type }; 163 | member.push(push); 164 | } 165 | 166 | name = entry['name']; 167 | ctype.typedef(name, member); 168 | } 169 | 170 | function ctfParseEntry(entry, ctype) 171 | { 172 | var ii, found; 173 | 174 | if (!('name' in entry)) 175 | throw (new Error('Malformed CTF JSON: entry missing "name" ' + 176 | 'section')); 177 | 178 | for (ii = 0; ii < ctf_entries.length; ii++) { 179 | if (ctf_entries[ii] in entry) 180 | found++; 181 | } 182 | 183 | if (found === 0) 184 | throw (new Error('Malformed CTF JSON: found no entries')); 185 | 186 | if (found >= 2) 187 | throw (new Error('Malformed CTF JSON: found more than one ' + 188 | 'entry')); 189 | 190 | if ('integer' in entry) { 191 | ctfParseInteger(entry, ctype); 192 | return; 193 | } 194 | 195 | if ('float' in entry) { 196 | ctfParseFloat(entry, ctype); 197 | return; 198 | } 199 | 200 | if ('typedef' in entry) { 201 | ctfParseTypedef(entry, ctype); 202 | return; 203 | } 204 | 205 | if ('struct' in entry) { 206 | ctfParseStruct(entry, ctype); 207 | return; 208 | } 209 | 210 | ASSERT(false, 'shouldn\'t reach here'); 211 | } 212 | 213 | function ctfParseJson(json, ctype) 214 | { 215 | var version, ii; 216 | 217 | ASSERT(json); 218 | ASSERT(ctype); 219 | if (!('metadata' in json)) 220 | throw (new Error('Invalid CTF JSON: missing metadata section')); 221 | 222 | if (!('ctf2json_version' in json['metadata'])) 223 | throw (new Error('Invalid CTF JSON: missing ctf2json_version')); 224 | 225 | version = json['metadata']['ctf2json_version']; 226 | for (ii = 0; ii < ctf_versions.length; ii++) { 227 | if (ctf_versions[ii] == version) 228 | break; 229 | } 230 | 231 | if (ii == ctf_versions.length) 232 | throw (new Error('Unsuported ctf2json_version: ' + version)); 233 | 234 | if (!('data' in json)) 235 | throw (new Error('Invalid CTF JSON: missing data section')); 236 | 237 | if (!Array.isArray(json['data'])) 238 | throw (new Error('Malformed CTF JSON: data section is not ' + 239 | 'an array')); 240 | 241 | for (ii = 0; ii < json['data'].length; ii++) 242 | ctfParseEntry(json['data'][ii], ctype); 243 | 244 | ctype.checkDeferred(); 245 | } 246 | 247 | exports.ctfParseJson = ctfParseJson; 248 | -------------------------------------------------------------------------------- /ctype.js: -------------------------------------------------------------------------------- 1 | /* 2 | * rm - Feb 2011 3 | * ctype.js 4 | * 5 | * This module provides a simple abstraction towards reading and writing 6 | * different types of binary data. It is designed to use ctio.js and provide a 7 | * richer and more expressive API on top of it. 8 | * 9 | * By default we support the following as built in basic types: 10 | * int8_t 11 | * int16_t 12 | * int32_t 13 | * uint8_t 14 | * uint16_t 15 | * uint32_t 16 | * uint64_t 17 | * float 18 | * double 19 | * char 20 | * char[] 21 | * 22 | * Each type is returned as a Number, with the exception of char and char[] 23 | * which are returned as Node Buffers. A char is considered a uint8_t. 24 | * 25 | * Requests to read and write data are specified as an array of JSON objects. 26 | * This is also the same way that one declares structs. Even if just a single 27 | * value is requested, it must be done as a struct. The array order determines 28 | * the order that we try and read values. Each entry has the following format 29 | * with values marked with a * being optional. 30 | * 31 | * { key: { type: /type/, value*: /value/, offset*: /offset/ } 32 | * 33 | * If offset is defined, we lseek(offset, SEEK_SET) before reading the next 34 | * value. Value is defined when we're writing out data, otherwise it's ignored. 35 | * 36 | */ 37 | 38 | var mod_ctf = require('./ctf.js'); 39 | var mod_ctio = require('./ctio.js'); 40 | var mod_assert = require('assert'); 41 | 42 | /* 43 | * This is the set of basic types that we support. 44 | * 45 | * read The function to call to read in a value from a buffer 46 | * 47 | * write The function to call to write a value to a buffer 48 | * 49 | */ 50 | var deftypes = { 51 | 'uint8_t': { read: ctReadUint8, write: ctWriteUint8 }, 52 | 'uint16_t': { read: ctReadUint16, write: ctWriteUint16 }, 53 | 'uint32_t': { read: ctReadUint32, write: ctWriteUint32 }, 54 | 'uint64_t': { read: ctReadUint64, write: ctWriteUint64 }, 55 | 'int8_t': { read: ctReadSint8, write: ctWriteSint8 }, 56 | 'int16_t': { read: ctReadSint16, write: ctWriteSint16 }, 57 | 'int32_t': { read: ctReadSint32, write: ctWriteSint32 }, 58 | 'int64_t': { read: ctReadSint64, write: ctWriteSint64 }, 59 | 'float': { read: ctReadFloat, write: ctWriteFloat }, 60 | 'double': { read: ctReadDouble, write: ctWriteDouble }, 61 | 'char': { read: ctReadChar, write: ctWriteChar }, 62 | 'char[]': { read: ctReadCharArray, write: ctWriteCharArray } 63 | }; 64 | 65 | /* 66 | * The following are wrappers around the CType IO low level API. They encode 67 | * knowledge about the size and return something in the expected format. 68 | */ 69 | function ctReadUint8(endian, buffer, offset) 70 | { 71 | var val = mod_ctio.ruint8(buffer, endian, offset); 72 | return ({ value: val, size: 1 }); 73 | } 74 | 75 | function ctReadUint16(endian, buffer, offset) 76 | { 77 | var val = mod_ctio.ruint16(buffer, endian, offset); 78 | return ({ value: val, size: 2 }); 79 | } 80 | 81 | function ctReadUint32(endian, buffer, offset) 82 | { 83 | var val = mod_ctio.ruint32(buffer, endian, offset); 84 | return ({ value: val, size: 4 }); 85 | } 86 | 87 | function ctReadUint64(endian, buffer, offset) 88 | { 89 | var val = mod_ctio.ruint64(buffer, endian, offset); 90 | return ({ value: val, size: 8 }); 91 | } 92 | 93 | function ctReadSint8(endian, buffer, offset) 94 | { 95 | var val = mod_ctio.rsint8(buffer, endian, offset); 96 | return ({ value: val, size: 1 }); 97 | } 98 | 99 | function ctReadSint16(endian, buffer, offset) 100 | { 101 | var val = mod_ctio.rsint16(buffer, endian, offset); 102 | return ({ value: val, size: 2 }); 103 | } 104 | 105 | function ctReadSint32(endian, buffer, offset) 106 | { 107 | var val = mod_ctio.rsint32(buffer, endian, offset); 108 | return ({ value: val, size: 4 }); 109 | } 110 | 111 | function ctReadSint64(endian, buffer, offset) 112 | { 113 | var val = mod_ctio.rsint64(buffer, endian, offset); 114 | return ({ value: val, size: 8 }); 115 | } 116 | 117 | function ctReadFloat(endian, buffer, offset) 118 | { 119 | var val = mod_ctio.rfloat(buffer, endian, offset); 120 | return ({ value: val, size: 4 }); 121 | } 122 | 123 | function ctReadDouble(endian, buffer, offset) 124 | { 125 | var val = mod_ctio.rdouble(buffer, endian, offset); 126 | return ({ value: val, size: 8 }); 127 | } 128 | 129 | /* 130 | * Reads a single character into a node buffer 131 | */ 132 | function ctReadChar(endian, buffer, offset) 133 | { 134 | var res = new Buffer(1); 135 | res[0] = mod_ctio.ruint8(buffer, endian, offset); 136 | return ({ value: res, size: 1 }); 137 | } 138 | 139 | function ctReadCharArray(length, endian, buffer, offset) 140 | { 141 | var ii; 142 | var res = new Buffer(length); 143 | 144 | for (ii = 0; ii < length; ii++) 145 | res[ii] = mod_ctio.ruint8(buffer, endian, offset + ii); 146 | 147 | return ({ value: res, size: length }); 148 | } 149 | 150 | function ctWriteUint8(value, endian, buffer, offset) 151 | { 152 | mod_ctio.wuint8(value, endian, buffer, offset); 153 | return (1); 154 | } 155 | 156 | function ctWriteUint16(value, endian, buffer, offset) 157 | { 158 | mod_ctio.wuint16(value, endian, buffer, offset); 159 | return (2); 160 | } 161 | 162 | function ctWriteUint32(value, endian, buffer, offset) 163 | { 164 | mod_ctio.wuint32(value, endian, buffer, offset); 165 | return (4); 166 | } 167 | 168 | function ctWriteUint64(value, endian, buffer, offset) 169 | { 170 | mod_ctio.wuint64(value, endian, buffer, offset); 171 | return (8); 172 | } 173 | 174 | function ctWriteSint8(value, endian, buffer, offset) 175 | { 176 | mod_ctio.wsint8(value, endian, buffer, offset); 177 | return (1); 178 | } 179 | 180 | function ctWriteSint16(value, endian, buffer, offset) 181 | { 182 | mod_ctio.wsint16(value, endian, buffer, offset); 183 | return (2); 184 | } 185 | 186 | function ctWriteSint32(value, endian, buffer, offset) 187 | { 188 | mod_ctio.wsint32(value, endian, buffer, offset); 189 | return (4); 190 | } 191 | 192 | function ctWriteSint64(value, endian, buffer, offset) 193 | { 194 | mod_ctio.wsint64(value, endian, buffer, offset); 195 | return (8); 196 | } 197 | 198 | function ctWriteFloat(value, endian, buffer, offset) 199 | { 200 | mod_ctio.wfloat(value, endian, buffer, offset); 201 | return (4); 202 | } 203 | 204 | function ctWriteDouble(value, endian, buffer, offset) 205 | { 206 | mod_ctio.wdouble(value, endian, buffer, offset); 207 | return (8); 208 | } 209 | 210 | /* 211 | * Writes a single character into a node buffer 212 | */ 213 | function ctWriteChar(value, endian, buffer, offset) 214 | { 215 | if (!(value instanceof Buffer)) 216 | throw (new Error('Input must be a buffer')); 217 | 218 | mod_ctio.ruint8(value[0], endian, buffer, offset); 219 | return (1); 220 | } 221 | 222 | /* 223 | * We're going to write 0s into the buffer if the string is shorter than the 224 | * length of the array. 225 | */ 226 | function ctWriteCharArray(value, length, endian, buffer, offset) 227 | { 228 | var ii; 229 | 230 | if (!(value instanceof Buffer)) 231 | throw (new Error('Input must be a buffer')); 232 | 233 | if (value.length > length) 234 | throw (new Error('value length greater than array length')); 235 | 236 | for (ii = 0; ii < value.length && ii < length; ii++) 237 | mod_ctio.wuint8(value[ii], endian, buffer, offset + ii); 238 | 239 | for (; ii < length; ii++) 240 | mod_ctio.wuint8(0, endian, offset + ii); 241 | 242 | 243 | return (length); 244 | } 245 | 246 | /* 247 | * Each parser has their own set of types. We want to make sure that they each 248 | * get their own copy as they may need to modify it. 249 | */ 250 | function ctGetBasicTypes() 251 | { 252 | var ret = {}; 253 | var key; 254 | for (key in deftypes) 255 | ret[key] = deftypes[key]; 256 | 257 | return (ret); 258 | } 259 | 260 | /* 261 | * Given a string in the form of type[length] we want to split this into an 262 | * object that extracts that information. We want to note that we could possibly 263 | * have nested arrays so this should only check the furthest one. It may also be 264 | * the case that we have no [] pieces, in which case we just return the current 265 | * type. 266 | */ 267 | function ctParseType(str) 268 | { 269 | var begInd, endInd; 270 | var type, len; 271 | if (typeof (str) != 'string') 272 | throw (new Error('type must be a Javascript string')); 273 | 274 | endInd = str.lastIndexOf(']'); 275 | if (endInd == -1) { 276 | if (str.lastIndexOf('[') != -1) 277 | throw (new Error('found invalid type with \'[\' but ' + 278 | 'no corresponding \']\'')); 279 | 280 | return ({ type: str }); 281 | } 282 | 283 | begInd = str.lastIndexOf('['); 284 | if (begInd == -1) 285 | throw (new Error('found invalid type with \']\' but ' + 286 | 'no corresponding \'[\'')); 287 | 288 | if (begInd >= endInd) 289 | throw (new Error('malformed type, \']\' appears before \'[\'')); 290 | 291 | type = str.substring(0, begInd); 292 | len = str.substring(begInd + 1, endInd); 293 | 294 | return ({ type: type, len: len }); 295 | } 296 | 297 | /* 298 | * Given a request validate that all of the fields for it are valid and make 299 | * sense. This includes verifying the following notions: 300 | * - Each type requested is present in types 301 | * - Only allow a name for a field to be specified once 302 | * - If an array is specified, validate that the requested field exists and 303 | * comes before it. 304 | * - If fields is defined, check that each entry has the occurrence of field 305 | */ 306 | function ctCheckReq(def, types, fields) 307 | { 308 | var ii, jj; 309 | var req, keys, key; 310 | var found = {}; 311 | 312 | if (!(def instanceof Array)) 313 | throw (new Error('definition is not an array')); 314 | 315 | if (def.length === 0) 316 | throw (new Error('definition must have at least one element')); 317 | 318 | for (ii = 0; ii < def.length; ii++) { 319 | req = def[ii]; 320 | if (!(req instanceof Object)) 321 | throw (new Error('definition must be an array of' + 322 | 'objects')); 323 | 324 | keys = Object.keys(req); 325 | if (keys.length != 1) 326 | throw (new Error('definition entry must only have ' + 327 | 'one key')); 328 | 329 | if (keys[0] in found) 330 | throw (new Error('Specified name already ' + 331 | 'specified: ' + keys[0])); 332 | 333 | if (!('type' in req[keys[0]])) 334 | throw (new Error('missing required type definition')); 335 | 336 | key = ctParseType(req[keys[0]]['type']); 337 | 338 | /* 339 | * We may have nested arrays, we need to check the validity of 340 | * the types until the len field is undefined in key. However, 341 | * each time len is defined we need to verify it is either an 342 | * integer or corresponds to an already seen key. 343 | */ 344 | while (key['len'] !== undefined) { 345 | if (isNaN(parseInt(key['len'], 10))) { 346 | if (!(key['len'] in found)) 347 | throw (new Error('Given an array ' + 348 | 'length without a matching type')); 349 | 350 | } 351 | 352 | key = ctParseType(key['type']); 353 | } 354 | 355 | /* Now we can validate if the type is valid */ 356 | if (!(key['type'] in types)) 357 | throw (new Error('type not found or typdefed: ' + 358 | key['type'])); 359 | 360 | /* Check for any required fields */ 361 | if (fields !== undefined) { 362 | for (jj = 0; jj < fields.length; jj++) { 363 | if (!(fields[jj] in req[keys[0]])) 364 | throw (new Error('Missing required ' + 365 | 'field: ' + fields[jj])); 366 | } 367 | } 368 | 369 | found[keys[0]] = true; 370 | } 371 | } 372 | 373 | 374 | /* 375 | * Create a new instance of the parser. Each parser has its own store of 376 | * typedefs and endianness. Conf is an object with the following required 377 | * values: 378 | * 379 | * endian Either 'big' or 'little' do determine the endianness we 380 | * want to read from or write to. 381 | * 382 | * And the following optional values: 383 | * 384 | * char-type Valid options here are uint8 and int8. If uint8 is 385 | * specified this changes the default behavior of a single 386 | * char from being a buffer of a single character to being 387 | * a uint8_t. If int8, it becomes an int8_t instead. 388 | */ 389 | function CTypeParser(conf) 390 | { 391 | if (!conf) throw (new Error('missing required argument')); 392 | 393 | if (!('endian' in conf)) 394 | throw (new Error('missing required endian value')); 395 | 396 | if (conf['endian'] != 'big' && conf['endian'] != 'little') 397 | throw (new Error('Invalid endian type')); 398 | 399 | if ('char-type' in conf && (conf['char-type'] != 'uint8' && 400 | conf['char-type'] != 'int8')) 401 | throw (new Error('invalid option for char-type: ' + 402 | conf['char-type'])); 403 | 404 | this.endian = conf['endian']; 405 | this.types = ctGetBasicTypes(); 406 | this.deferredCheckReqTypes = []; 407 | 408 | /* 409 | * There may be a more graceful way to do this, but this will have to 410 | * serve. 411 | */ 412 | if ('char-type' in conf && conf['char-type'] == 'uint8') 413 | this.types['char'] = this.types['uint8_t']; 414 | 415 | if ('char-type' in conf && conf['char-type'] == 'int8') 416 | this.types['char'] = this.types['int8_t']; 417 | } 418 | 419 | /* 420 | * Sets the current endian value for the Parser. If the value is not valid, 421 | * throws an Error. 422 | * 423 | * endian Either 'big' or 'little' do determine the endianness we 424 | * want to read from or write to. 425 | * 426 | */ 427 | CTypeParser.prototype.setEndian = function (endian) 428 | { 429 | if (endian != 'big' && endian != 'little') 430 | throw (new Error('invalid endian type, must be big or ' + 431 | 'little')); 432 | 433 | this.endian = endian; 434 | }; 435 | 436 | /* 437 | * Returns the current value of the endian value for the parser. 438 | */ 439 | CTypeParser.prototype.getEndian = function () 440 | { 441 | return (this.endian); 442 | }; 443 | 444 | /* 445 | * A user has requested to add a type, let us honor their request. Yet, if their 446 | * request doth spurn us, send them unto the Hells which Dante describes. 447 | * 448 | * name The string for the type definition we're adding 449 | * 450 | * value Either a string that is a type/array name or an object 451 | * that describes a struct. 452 | */ 453 | CTypeParser.prototype.typedef = function (name, value) 454 | { 455 | var type; 456 | 457 | if (name === undefined) 458 | throw (new (Error('missing required typedef argument: name'))); 459 | 460 | if (value === undefined) 461 | throw (new (Error('missing required typedef argument: value'))); 462 | 463 | if (typeof (name) != 'string') 464 | throw (new (Error('the name of a type must be a string'))); 465 | 466 | type = ctParseType(name); 467 | 468 | if (type['len'] !== undefined) 469 | throw (new Error('Cannot have an array in the typedef name')); 470 | 471 | if (name in this.types) 472 | throw (new Error('typedef name already present: ' + name)); 473 | 474 | if (typeof (value) != 'string' && !(value instanceof Array)) 475 | throw (new Error('typedef value must either be a string or ' + 476 | 'struct')); 477 | 478 | if (typeof (value) == 'string') { 479 | type = ctParseType(value); 480 | if (type['len'] !== undefined) { 481 | if (isNaN(parseInt(type['len'], 10))) 482 | throw (new (Error('typedef value must use ' + 483 | 'fixed size array when outside of a ' + 484 | 'struct'))); 485 | } 486 | 487 | this.types[name] = value; 488 | } else { 489 | /* We have a struct, validate it */ 490 | try { 491 | ctCheckReq(value, this.types); 492 | } catch (ex) { 493 | var notFoundMsg = 'type not found or typdefed: '; 494 | if ((ex.message || '').substr(notFoundMsg.length) === notFoundMsg) { 495 | this.deferredCheckReqTypes.push(value); 496 | } 497 | } 498 | this.types[name] = value; 499 | } 500 | }; 501 | 502 | /* 503 | * Include all of the typedefs, but none of the built in types. This should be 504 | * treated as read-only. 505 | */ 506 | CTypeParser.prototype.lstypes = function () 507 | { 508 | var key; 509 | var ret = {}; 510 | 511 | for (key in this.types) { 512 | if (key in deftypes) 513 | continue; 514 | ret[key] = this.types[key]; 515 | } 516 | 517 | return (ret); 518 | }; 519 | 520 | /* 521 | * Given a type string that may have array types that aren't numbers, try and 522 | * fill them in from the values object. The object should be of the format where 523 | * indexing into it should return a number for that type. 524 | * 525 | * str The type string 526 | * 527 | * values An object that can be used to fulfill type information 528 | */ 529 | function ctResolveArray(str, values) 530 | { 531 | var ret = ''; 532 | var type = ctParseType(str); 533 | 534 | while (type['len'] !== undefined) { 535 | if (isNaN(parseInt(type['len'], 10))) { 536 | if (typeof (values[type['len']]) != 'number') 537 | throw (new Error('cannot sawp in non-number ' + 538 | 'for array value')); 539 | ret = '[' + values[type['len']] + ']' + ret; 540 | } else { 541 | ret = '[' + type['len'] + ']' + ret; 542 | } 543 | type = ctParseType(type['type']); 544 | } 545 | 546 | ret = type['type'] + ret; 547 | 548 | return (ret); 549 | } 550 | 551 | /* 552 | * [private] Either the typedef resolves to another type string or to a struct. 553 | * If it resolves to a struct, we just pass it off to read struct. If not, we 554 | * can just pass it off to read entry. 555 | */ 556 | CTypeParser.prototype.resolveTypedef = function (type, dispatch, buffer, 557 | offset, value) 558 | { 559 | var pt; 560 | 561 | mod_assert.ok(type in this.types); 562 | if (typeof (this.types[type]) == 'string') { 563 | pt = ctParseType(this.types[type]); 564 | if (dispatch == 'read') 565 | return (this.readEntry(pt, buffer, offset)); 566 | else if (dispatch == 'write') 567 | return (this.writeEntry(value, pt, buffer, offset)); 568 | else 569 | throw (new Error('invalid dispatch type to ' + 570 | 'resolveTypedef')); 571 | } else { 572 | if (dispatch == 'read') 573 | return (this.readStruct(this.types[type], buffer, 574 | offset)); 575 | else if (dispatch == 'write') 576 | return (this.writeStruct(value, this.types[type], 577 | buffer, offset)); 578 | else 579 | throw (new Error('invalid dispatch type to ' + 580 | 'resolveTypedef')); 581 | } 582 | 583 | }; 584 | 585 | /* 586 | * [private] Try and read in the specific entry. 587 | */ 588 | CTypeParser.prototype.readEntry = function (type, buffer, offset) 589 | { 590 | var parse, len; 591 | 592 | /* 593 | * Because we want to special case char[]s this is unfortunately 594 | * a bit uglier than it really should be. We want to special 595 | * case char[]s so that we return a node buffer, thus they are a 596 | * first class type where as all other arrays just call into a 597 | * generic array routine which calls their data-specific routine 598 | * the specified number of times. 599 | * 600 | * The valid dispatch options we have are: 601 | * - Array and char => char[] handler 602 | * - Generic array handler 603 | * - Generic typedef handler 604 | * - Basic type handler 605 | */ 606 | if (type['len'] !== undefined) { 607 | len = parseInt(type['len'], 10); 608 | if (isNaN(len)) 609 | throw (new Error('somehow got a non-numeric length')); 610 | 611 | if (type['type'] == 'char') 612 | parse = this.types['char[]']['read'](len, 613 | this.endian, buffer, offset); 614 | else 615 | parse = this.readArray(type['type'], 616 | len, buffer, offset); 617 | } else { 618 | if (type['type'] in deftypes) 619 | parse = this.types[type['type']]['read'](this.endian, 620 | buffer, offset); 621 | else 622 | parse = this.resolveTypedef(type['type'], 'read', 623 | buffer, offset); 624 | } 625 | 626 | return (parse); 627 | }; 628 | 629 | /* 630 | * [private] Read an array of data 631 | */ 632 | CTypeParser.prototype.readArray = function (type, length, buffer, offset) 633 | { 634 | var ii, ent, pt; 635 | var baseOffset = offset; 636 | var ret = new Array(length); 637 | pt = ctParseType(type); 638 | 639 | for (ii = 0; ii < length; ii++) { 640 | ent = this.readEntry(pt, buffer, offset); 641 | offset += ent['size']; 642 | ret[ii] = ent['value']; 643 | } 644 | 645 | return ({ value: ret, size: offset - baseOffset }); 646 | }; 647 | 648 | /* 649 | * [private] Read a single struct in. 650 | */ 651 | CTypeParser.prototype.readStruct = function (def, buffer, offset) 652 | { 653 | var parse, ii, type, entry, key; 654 | var baseOffset = offset; 655 | var ret = {}; 656 | 657 | /* Walk it and handle doing what's necessary */ 658 | for (ii = 0; ii < def.length; ii++) { 659 | key = Object.keys(def[ii])[0]; 660 | entry = def[ii][key]; 661 | 662 | /* Resolve all array values */ 663 | type = ctParseType(ctResolveArray(entry['type'], ret)); 664 | 665 | if ('offset' in entry) 666 | offset = baseOffset + entry['offset']; 667 | 668 | parse = this.readEntry(type, buffer, offset); 669 | 670 | offset += parse['size']; 671 | ret[key] = parse['value']; 672 | } 673 | 674 | return ({ value: ret, size: (offset-baseOffset)}); 675 | }; 676 | 677 | /* 678 | * This is what we were born to do. We read the data from a buffer and return it 679 | * in an object whose keys match the values from the object. 680 | * 681 | * def The array definition of the data to read in 682 | * 683 | * buffer The buffer to read data from 684 | * 685 | * offset The offset to start writing to 686 | * 687 | * Returns an object where each key corresponds to an entry in def and the value 688 | * is the read value. 689 | */ 690 | CTypeParser.prototype.readData = function (def, buffer, offset) 691 | { 692 | /* Sanity check for arguments */ 693 | if (def === undefined) 694 | throw (new Error('missing definition for what we should be' + 695 | 'parsing')); 696 | 697 | if (buffer === undefined) 698 | throw (new Error('missing buffer for what we should be ' + 699 | 'parsing')); 700 | 701 | if (offset === undefined) 702 | throw (new Error('missing offset for what we should be ' + 703 | 'parsing')); 704 | 705 | /* Sanity check the object definition */ 706 | ctCheckReq(def, this.types); 707 | 708 | return (this.readStruct(def, buffer, offset)['value']); 709 | }; 710 | 711 | /* 712 | * [private] Write out an array of data 713 | */ 714 | CTypeParser.prototype.writeArray = function (value, type, length, buffer, 715 | offset) 716 | { 717 | var ii, pt; 718 | var baseOffset = offset; 719 | if (!(value instanceof Array)) 720 | throw (new Error('asked to write an array, but value is not ' + 721 | 'an array')); 722 | 723 | if (value.length != length) 724 | throw (new Error('asked to write array of length ' + length + 725 | ' but that does not match value length: ' + value.length)); 726 | 727 | pt = ctParseType(type); 728 | for (ii = 0; ii < length; ii++) 729 | offset += this.writeEntry(value[ii], pt, buffer, offset); 730 | 731 | return (offset - baseOffset); 732 | }; 733 | 734 | /* 735 | * [private] Write the specific entry 736 | */ 737 | CTypeParser.prototype.writeEntry = function (value, type, buffer, offset) 738 | { 739 | var len, ret; 740 | 741 | if (type['len'] !== undefined) { 742 | len = parseInt(type['len'], 10); 743 | if (isNaN(len)) 744 | throw (new Error('somehow got a non-numeric length')); 745 | 746 | if (type['type'] == 'char') 747 | ret = this.types['char[]']['write'](value, len, 748 | this.endian, buffer, offset); 749 | else 750 | ret = this.writeArray(value, type['type'], 751 | len, buffer, offset); 752 | } else { 753 | if (type['type'] in deftypes) 754 | ret = this.types[type['type']]['write'](value, 755 | this.endian, buffer, offset); 756 | else 757 | ret = this.resolveTypedef(type['type'], 'write', 758 | buffer, offset, value); 759 | } 760 | 761 | return (ret); 762 | }; 763 | 764 | /* 765 | * [private] Write a single struct out. 766 | */ 767 | CTypeParser.prototype.writeStruct = function (value, def, buffer, offset) 768 | { 769 | var ii, entry, type, key; 770 | var baseOffset = offset; 771 | var vals = {}; 772 | 773 | for (ii = 0; ii < def.length; ii++) { 774 | key = Object.keys(def[ii])[0]; 775 | entry = def[ii][key]; 776 | 777 | type = ctParseType(ctResolveArray(entry['type'], vals)); 778 | 779 | if ('offset' in entry) 780 | offset = baseOffset + entry['offset']; 781 | 782 | offset += this.writeEntry(value[ii], type, buffer, offset); 783 | /* Now that we've written it out, we can use it for arrays */ 784 | vals[key] = value[ii]; 785 | } 786 | 787 | return (offset); 788 | }; 789 | 790 | /* 791 | * Unfortunately, we're stuck with the sins of an initial poor design. Because 792 | * of that, we are going to have to support the old way of writing data via 793 | * writeData. There we insert the values that you want to write into the 794 | * definition. A little baroque. Internally, we use the new model. So we need to 795 | * just get those values out of there. But to maintain the principle of least 796 | * surprise, we're not going to modify the input data. 797 | */ 798 | function getValues(def) 799 | { 800 | var ii, out, key; 801 | out = []; 802 | for (ii = 0; ii < def.length; ii++) { 803 | key = Object.keys(def[ii])[0]; 804 | mod_assert.ok('value' in def[ii][key]); 805 | out.push(def[ii][key]['value']); 806 | } 807 | 808 | return (out); 809 | } 810 | 811 | /* 812 | * This is the second half of what we were born to do, write out the data 813 | * itself. Historically this function required you to put your values in the 814 | * definition section. This was not the smartest thing to do and a bit of an 815 | * oversight to be honest. As such, this function now takes a values argument. 816 | * If values is non-null and non-undefined, it will be used to determine the 817 | * values. This means that the old method is still supported, but is no longer 818 | * acceptable. 819 | * 820 | * def The array definition of the data to write out with 821 | * values 822 | * 823 | * buffer The buffer to write to 824 | * 825 | * offset The offset in the buffer to write to 826 | * 827 | * values An array of values to write. 828 | */ 829 | CTypeParser.prototype.writeData = function (def, buffer, offset, values) 830 | { 831 | var hv; 832 | 833 | if (def === undefined) 834 | throw (new Error('missing definition for what we should be' + 835 | 'parsing')); 836 | 837 | if (buffer === undefined) 838 | throw (new Error('missing buffer for what we should be ' + 839 | 'parsing')); 840 | 841 | if (offset === undefined) 842 | throw (new Error('missing offset for what we should be ' + 843 | 'parsing')); 844 | 845 | hv = (values != null && values != undefined); 846 | if (hv) { 847 | if (!Array.isArray(values)) 848 | throw (new Error('missing values for writing')); 849 | ctCheckReq(def, this.types); 850 | } else { 851 | ctCheckReq(def, this.types, [ 'value' ]); 852 | } 853 | 854 | this.writeStruct(hv ? values : getValues(def), def, buffer, offset); 855 | }; 856 | 857 | CTypeParser.prototype.checkDeferred = function () 858 | { 859 | var ii; 860 | 861 | for (ii = 0; ii < this.deferredCheckReqTypes.length; ii++) { 862 | ctCheckReq(this.deferredCheckReqTypes[ii], this.types); 863 | } 864 | }; 865 | 866 | /* 867 | * Functions to go to and from 64 bit numbers in a way that is compatible with 868 | * Javascript limitations. There are two sets. One where the user is okay with 869 | * an approximation and one where they are definitely not okay with an 870 | * approximation. 871 | */ 872 | 873 | /* 874 | * Attempts to convert an array of two integers returned from rsint64 / ruint64 875 | * into an absolute 64 bit number. If however the value would exceed 2^52 this 876 | * will instead throw an error. The mantissa in a double is a 52 bit number and 877 | * rather than potentially give you a value that is an approximation this will 878 | * error. If you would rather an approximation, please see toApprox64. 879 | * 880 | * val An array of two 32-bit integers 881 | */ 882 | function toAbs64(val) 883 | { 884 | if (val === undefined) 885 | throw (new Error('missing required arg: value')); 886 | 887 | if (!Array.isArray(val)) 888 | throw (new Error('value must be an array')); 889 | 890 | if (val.length != 2) 891 | throw (new Error('value must be an array of length 2')); 892 | 893 | /* We have 20 bits worth of precision in this range */ 894 | if (val[0] >= 0x100000) 895 | throw (new Error('value would become approximated')); 896 | 897 | return (val[0] * Math.pow(2, 32) + val[1]); 898 | } 899 | 900 | /* 901 | * Will return the 64 bit value as returned in an array from rsint64 / ruint64 902 | * to a value as close as it can. Note that Javascript stores all numbers as a 903 | * double and the mantissa only has 52 bits. Thus this version may approximate 904 | * the value. 905 | * 906 | * val An array of two 32-bit integers 907 | */ 908 | function toApprox64(val) 909 | { 910 | if (val === undefined) 911 | throw (new Error('missing required arg: value')); 912 | 913 | if (!Array.isArray(val)) 914 | throw (new Error('value must be an array')); 915 | 916 | if (val.length != 2) 917 | throw (new Error('value must be an array of length 2')); 918 | 919 | return (Math.pow(2, 32) * val[0] + val[1]); 920 | } 921 | 922 | function parseCTF(json, conf) 923 | { 924 | var ctype = new CTypeParser(conf); 925 | mod_ctf.ctfParseJson(json, ctype); 926 | 927 | return (ctype); 928 | } 929 | 930 | /* 931 | * Export the few things we actually want to. Currently this is just the CType 932 | * Parser and ctio. 933 | */ 934 | exports.Parser = CTypeParser; 935 | exports.toAbs64 = toAbs64; 936 | exports.toApprox64 = toApprox64; 937 | 938 | exports.parseCTF = parseCTF; 939 | 940 | exports.ruint8 = mod_ctio.ruint8; 941 | exports.ruint16 = mod_ctio.ruint16; 942 | exports.ruint32 = mod_ctio.ruint32; 943 | exports.ruint64 = mod_ctio.ruint64; 944 | exports.wuint8 = mod_ctio.wuint8; 945 | exports.wuint16 = mod_ctio.wuint16; 946 | exports.wuint32 = mod_ctio.wuint32; 947 | exports.wuint64 = mod_ctio.wuint64; 948 | 949 | exports.rsint8 = mod_ctio.rsint8; 950 | exports.rsint16 = mod_ctio.rsint16; 951 | exports.rsint32 = mod_ctio.rsint32; 952 | exports.rsint64 = mod_ctio.rsint64; 953 | exports.wsint8 = mod_ctio.wsint8; 954 | exports.wsint16 = mod_ctio.wsint16; 955 | exports.wsint32 = mod_ctio.wsint32; 956 | exports.wsint64 = mod_ctio.wsint64; 957 | 958 | exports.rfloat = mod_ctio.rfloat; 959 | exports.rdouble = mod_ctio.rdouble; 960 | exports.wfloat = mod_ctio.wfloat; 961 | exports.wdouble = mod_ctio.wdouble; 962 | -------------------------------------------------------------------------------- /man/man3ctype/ctio.3ctype: -------------------------------------------------------------------------------- 1 | '\" te 2 | .\" Copyright (c) 2011, Robert Mustacchi. All Rights Reserved. 3 | .\" Copyright (c) 2011, Joyent, Inc. All Rights Reserved. 4 | .\" 5 | .\" Permission is hereby granted, free of charge, to any person obtaining a copy 6 | .\" of this software and associated documentation files (the "Software"), to 7 | .\" deal in the Software without restriction, including without limitation the 8 | .\" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 | .\" sell copies of the Software, and to permit persons to whom the Software is 10 | .\" furnished to do so, subject to the following conditions: 11 | .\" 12 | .\" The above copyright notice and this permission notice shall be included in 13 | .\" all copies or substantial portions of the Software. 14 | .\" 15 | .\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | .\" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | .\" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | .\" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | .\" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | .\" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | .\" IN THE SOFTWARE. 22 | .TH CTIO 3CTYPE "December 12, 2011" 23 | .SH NAME 24 | ctio, ruint8, ruint16, ruint32, ruint64, wuint8, wuint16, wuint32, wuint64, 25 | rsint8, rsint16, rsint32, rsint64, wsint8, wsint16, wsint32, wsint64, rfloat, 26 | rdouble, wfloat, wdouble \- integer and float operations 27 | .SH SYNOPSIS 28 | .LP 29 | .nf 30 | var mod_ctype = require('ctype'); 31 | 32 | \fBNumber\fR \fBmod_ctype.ruint8\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR); 33 | .fi 34 | 35 | .LP 36 | .nf 37 | \fBNumber\fR \fBmod_ctype.ruint16\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR); 38 | .fi 39 | 40 | .LP 41 | .nf 42 | \fBNumber\fR \fBmod_ctype.ruint32\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR); 43 | .fi 44 | 45 | .LP 46 | .nf 47 | \fBNumber[2]\fR \fBmod_ctype.ruint64\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR); 48 | .fi 49 | 50 | .LP 51 | .nf 52 | \fBNumber\fR \fBmod_ctype.rsint8\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR); 53 | .fi 54 | 55 | .LP 56 | .nf 57 | \fBNumber\fR \fBmod_ctype.rsint16\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR); 58 | .fi 59 | 60 | .LP 61 | .nf 62 | \fBNumber\fR \fBmod_ctype.rsint32\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR); 63 | .fi 64 | 65 | .LP 66 | .nf 67 | \fBNumber[2]\fR \fBmod_ctype.rsint64\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR); 68 | .fi 69 | 70 | .LP 71 | .nf 72 | \fBNumber\fR \fBmod_ctype.rfloat\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR); 73 | .fi 74 | 75 | .LP 76 | .nf 77 | \fBNumber\fR \fBmod_ctype.rdouble\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR); 78 | .fi 79 | 80 | .LP 81 | .nf 82 | \fBvoid\fR \fBmod_ctype.wuint8\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR); 83 | .fi 84 | 85 | .LP 86 | .nf 87 | \fBvoid\fR \fBmod_ctype.wuint16\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR); 88 | .fi 89 | 90 | .LP 91 | .nf 92 | \fBvoid\fR \fBmod_ctype.wuint32\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR); 93 | .fi 94 | 95 | .LP 96 | .nf 97 | \fBvoid\fR \fBmod_ctype.wuint64\fR(\fBNumber[2]\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR); 98 | .fi 99 | 100 | .LP 101 | .nf 102 | \fBvoid\fR \fBmod_ctype.wsint8\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR); 103 | .fi 104 | 105 | .LP 106 | .nf 107 | \fBvoid\fR \fBmod_ctype.wsint16\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR); 108 | .fi 109 | 110 | .LP 111 | .nf 112 | \fBvoid\fR \fBmod_ctype.wsint32\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR); 113 | .fi 114 | 115 | .LP 116 | .nf 117 | \fBvoid\fR \fBmod_ctype.wsint64\fR(\fBNumber[2]\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR); 118 | .fi 119 | 120 | .LP 121 | .nf 122 | \fBvoid\fR \fBmod_ctype.wfloat\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR); 123 | .fi 124 | 125 | .LP 126 | .nf 127 | \fBvoid\fR \fBmod_ctype.wdouble\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR); 128 | .fi 129 | 130 | .SH DESCRIPTION 131 | .sp 132 | .LP 133 | The argument \fIbuf\fR refers to a valid buffer (from calling new Buffer()). The 134 | argument \fIendian\fR is either the string 'big' or 'little' and controls 135 | whether the data in the buffer is interpreted as big or little endian. The argument 136 | \fIoffset\fR indicates the starting index into the buffer to read or write. All 137 | functions ensure that starting at \fIoffset\fR does not overflow the end of the 138 | buffer. The argument \fIvalue\fR is a Number that is the valid type for the 139 | specific function. All functions that take \fIvalue\fR as an argument, verify 140 | that the passed value is valid. 141 | 142 | .SS "\fBruint8()\fR, \fBruint16()\fR, \fBruint32()\fR" 143 | .sp 144 | .LP 145 | The \fBruint8()\fR, \fBruint16()\fR, and \fBruint32()\fR functions read an 8, 146 | 16, and 32-bit unsigned value from \fIbuf\fR and return it. The value read is 147 | influenced by the values of \fIoffset\fR and \fRendian\fI. 148 | 149 | 150 | .SS "\fBrsint8()\fR, \fBrsint16()\fR, \fBrsint32()\fR" 151 | .sp 152 | .LP 153 | The \fBruint8()\fR, \fBruint16()\fR, and \fBruint32()\fR functions work just as 154 | \fBruint8()\fR, \fBruint16()\fR, and \fBruint32()\fR, except they return signed 155 | integers. 156 | 157 | .SS "\fBruint64()\fR, \fBrsint64()\fR" 158 | .sp 159 | .LP 160 | The \fBruint64()\fR and \fBrsint64()\fR functions read unsigned and signed 64 161 | bit integers respectively from \fBbuf\fR. Due to the limitations of ECMAScript's 162 | \fBNumber\fR type, they cannot be stored as one value without a loss of 163 | precision. Instead of returning the values as a single \fBNumber\fR, the 164 | functions return an array of two numbers. The first entry always contains the 165 | upper 32-bits and the second value contains the lower 32-bits. The lossy 166 | transformation into a number would be \fIres[0]*Math.pow(2,32)+res[1]\fR. 167 | Note that, unless an entry is zero, both array entries are guaranteed to have 168 | the same sign. 169 | 170 | .SS "\fBwuint8()\fR, \fBwuint16()\fR, \fBwuint32()\fR" 171 | .sp 172 | .LP 173 | The functions \fBwuint8()\fR, \fBwuint16()\fR, and \fBwuint32()\fR modify the 174 | contents of \fBbuf\fR by writing an 8, 16, and 32-bit unsigned integer 175 | respectively to \fBbuf\fR. It is illegal to pass a number that is not an integer 176 | within the domain of the integer size, for example, for \fBwuint8()\fR the valid 177 | range is \fB[0, 255]\fR. The value will be written in either big or little 178 | endian format based upon the value of \fBendian\fR. 179 | 180 | 181 | .SS "\fBwsint8()\fR, \fBwsint16()\fR, \fBwsint32()\fR" 182 | .sp 183 | .LP 184 | The functions \fBwsint8()\fR, \fBwsint16()\fR, and \fBwsint32()\fR function 185 | identically to the functions \fBwuint8()\fR, \fBwuint16()\fR, and 186 | \fBwuint32()\fR except that they the valid domain for \fBvalue\fR is that of a 187 | signed number instead of an unsigned number. For example the \fBwsint8()\fR has 188 | a domain of \fB[-128, 127]\fR. 189 | 190 | .SS "\fBwuint64()\fR, \fBwsint64()\fR" 191 | .sp 192 | .LP 193 | The functions \fBwuint64()\fR and \fBswint64()\fR write out 64-bit unsigned and 194 | signed integers to \fBbuf\fR. The \fBvalue\fR argument must be in the same 195 | format as described in \fBruint64()\fR and \fBrsint64()\fR. 196 | 197 | .SS "\fBrfloat()\fR, \fBrdouble()\fR" 198 | .sp 199 | .LP 200 | The functions "\fBrfloat()\fR and \fBrdouble()\fR" work like the other read 201 | functions, except that they read a single precision and double precision 202 | IEEE-754 floating point value instead. 203 | 204 | .SS "\fBwfloat()\fR, \fBwdouble()\fR" 205 | .sp 206 | .LP 207 | The functions "\fBrfloat()\fR and \fBrdouble()\fR" work like the other write 208 | functions, except that the domain for a float is that of a single precision 4 209 | byte value. The domain for a double is any \fBNumber\fR in ECMAScript, which is 210 | defined to be represented by a double. 211 | 212 | .SH ATTRIBUTES 213 | .sp 214 | .LP 215 | See \fBattributes\fR(5) for descriptions of the following attributes: 216 | .sp 217 | 218 | .sp 219 | .TS 220 | box; 221 | c | c 222 | l | l . 223 | ATTRIBUTE TYPE ATTRIBUTE VALUE 224 | _ 225 | Interface Stability Committed 226 | _ 227 | MT-Level See below. 228 | _ 229 | Standard Not standardized. 230 | .TE 231 | 232 | .sp 233 | .LP 234 | 235 | All functions are MT-safe in so far as there aren't shared memory MT concerns in 236 | most node programs. If one where to concoct such an environment, these functions 237 | wouldn't be MT-safe. 238 | 239 | .SH SEE ALSO 240 | .sp 241 | .LP 242 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ctype", 3 | "version": "0.5.6", 4 | "description": "read and write binary structures and data types", 5 | "homepage": "https://github.com/rmustacc/node-ctype", 6 | "author": "Robert Mustacchi ", 7 | "engines": { "node": ">= 0.4" }, 8 | "main": "ctype.js", 9 | "licenses": [ { 10 | "type": "MIT", 11 | "url": "https://github.com/rmustacc/node-ctype/blob/master/LICENSE" 12 | } ], 13 | "license": "MIT", 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/rmustacc/node-ctype.git" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tools/jsl.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Configuration File for JavaScript Lint 0.3.0 3 | # Developed by Matthias Miller (http://www.JavaScriptLint.com) 4 | # 5 | # This configuration file can be used to lint a collection of scripts, or to enable 6 | # or disable warnings for scripts that are linted via the command line. 7 | # 8 | 9 | ### Warnings 10 | # Enable or disable warnings based on requirements. 11 | # Use "+WarningName" to display or "-WarningName" to suppress. 12 | # 13 | +no_return_value # function {0} does not always return a value 14 | +duplicate_formal # duplicate formal argument {0} 15 | +equal_as_assign # test for equality (==) mistyped as assignment (=)?{0} 16 | +var_hides_arg # variable {0} hides argument 17 | +redeclared_var # redeclaration of {0} {1} 18 | +anon_no_return_value # anonymous function does not always return a value 19 | +missing_semicolon # missing semicolon 20 | +meaningless_block # meaningless block; curly braces have no impact 21 | +comma_separated_stmts # multiple statements separated by commas (use semicolons?) 22 | +unreachable_code # unreachable code 23 | +missing_break # missing break statement 24 | +missing_break_for_last_case # missing break statement for last case in switch 25 | +comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==) 26 | -inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement 27 | +useless_void # use of the void type may be unnecessary (void is always undefined) 28 | -useless_quotes # quotation marks are unnecessary 29 | +multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs 30 | +use_of_label # use of label 31 | -block_without_braces # block statement without curly braces 32 | +leading_decimal_point # leading decimal point may indicate a number or an object member 33 | +trailing_decimal_point # trailing decimal point may indicate a number or an object member 34 | -octal_number # leading zeros make an octal number 35 | +nested_comment # nested comment 36 | +misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma 37 | +ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement 38 | +empty_statement # empty statement or extra semicolon 39 | -missing_option_explicit # the "option explicit" control comment is missing 40 | +partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag 41 | +dup_option_explicit # duplicate "option explicit" control comment 42 | +useless_assign # useless assignment 43 | +ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity 44 | +ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent) 45 | +missing_default_case # missing default case in switch statement 46 | +duplicate_case_in_switch # duplicate case in switch statements 47 | +default_not_at_end # the default case is not at the end of the switch statement 48 | +legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax 49 | +jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax 50 | +useless_comparison # useless comparison; comparing identical expressions 51 | +with_statement # with statement hides undeclared variables; use temporary variable instead 52 | +trailing_comma_in_array # extra comma is not recommended in array initializers 53 | +assign_to_function_call # assignment to a function call 54 | +parseint_missing_radix # parseInt missing radix parameter 55 | -unreferenced_argument # argument declared but never referenced: {name} 56 | 57 | ### Output format 58 | # Customize the format of the error message. 59 | # __FILE__ indicates current file path 60 | # __FILENAME__ indicates current file name 61 | # __LINE__ indicates current line 62 | # __ERROR__ indicates error message 63 | # 64 | # Visual Studio syntax (default): 65 | +output-format __FILE__(__LINE__): __ERROR__ 66 | # Alternative syntax: 67 | #+output-format __FILE__:__LINE__: __ERROR__ 68 | 69 | 70 | ### Context 71 | # Show the in-line position of the error. 72 | # Use "+context" to display or "-context" to suppress. 73 | # 74 | +context 75 | 76 | 77 | ### Semicolons 78 | # By default, assignments of an anonymous function to a variable or 79 | # property (such as a function prototype) must be followed by a semicolon. 80 | # 81 | #+lambda_assign_requires_semicolon # deprecated setting 82 | 83 | 84 | ### Control Comments 85 | # Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for 86 | # the /*@keyword@*/ control comments and JScript conditional comments. (The latter is 87 | # enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason, 88 | # although legacy control comments are enabled by default for backward compatibility. 89 | # 90 | +legacy_control_comments 91 | 92 | 93 | ### JScript Function Extensions 94 | # JScript allows member functions to be defined like this: 95 | # function MyObj() { /*constructor*/ } 96 | # function MyObj.prototype.go() { /*member function*/ } 97 | # 98 | # It also allows events to be attached like this: 99 | # function window::onload() { /*init page*/ } 100 | # 101 | # This is a Microsoft-only JavaScript extension. Enable this setting to allow them. 102 | # 103 | #-jscript_function_extensions # deprecated setting 104 | 105 | 106 | ### Defining identifiers 107 | # By default, "option explicit" is enabled on a per-file basis. 108 | # To enable this for all files, use "+always_use_option_explicit" 109 | -always_use_option_explicit 110 | 111 | # Define certain identifiers of which the lint is not aware. 112 | # (Use this in conjunction with the "undeclared identifier" warning.) 113 | # 114 | # Common uses for webpages might be: 115 | #+define window 116 | #+define document 117 | +define require 118 | +define exports 119 | +define console 120 | +define Buffer 121 | +define JSON 122 | 123 | ### Files 124 | # Specify which files to lint 125 | # Use "+recurse" to enable recursion (disabled by default). 126 | # To add a set of files, use "+process FileName", "+process Folder\Path\*.js", 127 | # or "+process Folder\Path\*.htm". 128 | # 129 | #+process jsl-test.js 130 | -------------------------------------------------------------------------------- /tools/jsstyle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # 3 | # CDDL HEADER START 4 | # 5 | # The contents of this file are subject to the terms of the 6 | # Common Development and Distribution License (the "License"). 7 | # You may not use this file except in compliance with the License. 8 | # 9 | # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 | # or http://www.opensolaris.org/os/licensing. 11 | # See the License for the specific language governing permissions 12 | # and limitations under the License. 13 | # 14 | # When distributing Covered Code, include this CDDL HEADER in each 15 | # file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 | # If applicable, add the following below this CDDL HEADER, with the 17 | # fields enclosed by brackets "[]" replaced with your own identifying 18 | # information: Portions Copyright [yyyy] [name of copyright owner] 19 | # 20 | # CDDL HEADER END 21 | # 22 | # 23 | # Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 | # Use is subject to license terms. 25 | # 26 | # Copyright 2011 Joyent, Inc. All rights reserved. 27 | # 28 | # jsstyle - check for some common stylistic errors. 29 | # 30 | # jsstyle is a sort of "lint" for Javascript coding style. This tool is 31 | # derived from the cstyle tool, used to check for the style used in the 32 | # Solaris kernel, sometimes known as "Bill Joy Normal Form". 33 | # 34 | # There's a lot this can't check for, like proper indentation of code 35 | # blocks. There's also a lot more this could check for. 36 | # 37 | # A note to the non perl literate: 38 | # 39 | # perl regular expressions are pretty much like egrep 40 | # regular expressions, with the following special symbols 41 | # 42 | # \s any space character 43 | # \S any non-space character 44 | # \w any "word" character [a-zA-Z0-9_] 45 | # \W any non-word character 46 | # \d a digit [0-9] 47 | # \D a non-digit 48 | # \b word boundary (between \w and \W) 49 | # \B non-word boundary 50 | # 51 | 52 | require 5.0; 53 | use IO::File; 54 | use Getopt::Std; 55 | use strict; 56 | 57 | my $usage = 58 | "usage: jsstyle [-chvC] [-o constructs] file ... 59 | -c check continuation indentation inside functions 60 | -h perform heuristic checks that are sometimes wrong 61 | -v verbose 62 | -C don't check anything in header block comments 63 | -o constructs 64 | allow a comma-seperated list of optional constructs: 65 | doxygen allow doxygen-style block comments (/** /*!) 66 | splint allow splint-style lint comments (/*@ ... @*/) 67 | "; 68 | 69 | my %opts; 70 | 71 | if (!getopts("cho:vC", \%opts)) { 72 | print $usage; 73 | exit 2; 74 | } 75 | 76 | my $check_continuation = $opts{'c'}; 77 | my $heuristic = $opts{'h'}; 78 | my $verbose = $opts{'v'}; 79 | my $ignore_hdr_comment = $opts{'C'}; 80 | 81 | my $doxygen_comments = 0; 82 | my $splint_comments = 0; 83 | 84 | if (defined($opts{'o'})) { 85 | for my $x (split /,/, $opts{'o'}) { 86 | if ($x eq "doxygen") { 87 | $doxygen_comments = 1; 88 | } elsif ($x eq "splint") { 89 | $splint_comments = 1; 90 | } else { 91 | print "jsstyle: unrecognized construct \"$x\"\n"; 92 | print $usage; 93 | exit 2; 94 | } 95 | } 96 | } 97 | 98 | my ($filename, $line, $prev); # shared globals 99 | 100 | my $fmt; 101 | my $hdr_comment_start; 102 | 103 | if ($verbose) { 104 | $fmt = "%s: %d: %s\n%s\n"; 105 | } else { 106 | $fmt = "%s: %d: %s\n"; 107 | } 108 | 109 | if ($doxygen_comments) { 110 | # doxygen comments look like "/*!" or "/**"; allow them. 111 | $hdr_comment_start = qr/^\s*\/\*[\!\*]?$/; 112 | } else { 113 | $hdr_comment_start = qr/^\s*\/\*$/; 114 | } 115 | 116 | # Note, following must be in single quotes so that \s and \w work right. 117 | my $lint_re = qr/\/\*(?: 118 | jsl:\w+?|ARGSUSED[0-9]*|NOTREACHED|LINTLIBRARY|VARARGS[0-9]*| 119 | CONSTCOND|CONSTANTCOND|CONSTANTCONDITION|EMPTY| 120 | FALLTHRU|FALLTHROUGH|LINTED.*?|PRINTFLIKE[0-9]*| 121 | PROTOLIB[0-9]*|SCANFLIKE[0-9]*|JSSTYLED.*? 122 | )\*\//x; 123 | 124 | my $splint_re = qr/\/\*@.*?@\*\//x; 125 | 126 | my $err_stat = 0; # exit status 127 | 128 | if ($#ARGV >= 0) { 129 | foreach my $arg (@ARGV) { 130 | my $fh = new IO::File $arg, "r"; 131 | if (!defined($fh)) { 132 | printf "%s: cannot open\n", $arg; 133 | } else { 134 | &jsstyle($arg, $fh); 135 | close $fh; 136 | } 137 | } 138 | } else { 139 | &jsstyle("", *STDIN); 140 | } 141 | exit $err_stat; 142 | 143 | my $no_errs = 0; # set for JSSTYLED-protected lines 144 | 145 | sub err($) { 146 | my ($error) = @_; 147 | unless ($no_errs) { 148 | printf $fmt, $filename, $., $error, $line; 149 | $err_stat = 1; 150 | } 151 | } 152 | 153 | sub err_prefix($$) { 154 | my ($prevline, $error) = @_; 155 | my $out = $prevline."\n".$line; 156 | unless ($no_errs) { 157 | printf $fmt, $filename, $., $error, $out; 158 | $err_stat = 1; 159 | } 160 | } 161 | 162 | sub err_prev($) { 163 | my ($error) = @_; 164 | unless ($no_errs) { 165 | printf $fmt, $filename, $. - 1, $error, $prev; 166 | $err_stat = 1; 167 | } 168 | } 169 | 170 | sub jsstyle($$) { 171 | 172 | my ($fn, $filehandle) = @_; 173 | $filename = $fn; # share it globally 174 | 175 | my $in_cpp = 0; 176 | my $next_in_cpp = 0; 177 | 178 | my $in_comment = 0; 179 | my $in_header_comment = 0; 180 | my $comment_done = 0; 181 | my $in_function = 0; 182 | my $in_function_header = 0; 183 | my $in_declaration = 0; 184 | my $note_level = 0; 185 | my $nextok = 0; 186 | my $nocheck = 0; 187 | 188 | my $in_string = 0; 189 | 190 | my ($okmsg, $comment_prefix); 191 | 192 | $line = ''; 193 | $prev = ''; 194 | reset_indent(); 195 | 196 | line: while (<$filehandle>) { 197 | s/\r?\n$//; # strip return and newline 198 | 199 | # save the original line, then remove all text from within 200 | # double or single quotes, we do not want to check such text. 201 | 202 | $line = $_; 203 | 204 | # 205 | # C allows strings to be continued with a backslash at the end of 206 | # the line. We translate that into a quoted string on the previous 207 | # line followed by an initial quote on the next line. 208 | # 209 | # (we assume that no-one will use backslash-continuation with character 210 | # constants) 211 | # 212 | $_ = '"' . $_ if ($in_string && !$nocheck && !$in_comment); 213 | 214 | # 215 | # normal strings and characters 216 | # 217 | s/'([^\\']|\\.)*'/\'\'/g; 218 | s/"([^\\"]|\\.)*"/\"\"/g; 219 | 220 | # 221 | # detect string continuation 222 | # 223 | if ($nocheck || $in_comment) { 224 | $in_string = 0; 225 | } else { 226 | # 227 | # Now that all full strings are replaced with "", we check 228 | # for unfinished strings continuing onto the next line. 229 | # 230 | $in_string = 231 | (s/([^"](?:"")*)"([^\\"]|\\.)*\\$/$1""/ || 232 | s/^("")*"([^\\"]|\\.)*\\$/""/); 233 | } 234 | 235 | # 236 | # figure out if we are in a cpp directive 237 | # 238 | $in_cpp = $next_in_cpp || /^\s*#/; # continued or started 239 | $next_in_cpp = $in_cpp && /\\$/; # only if continued 240 | 241 | # strip off trailing backslashes, which appear in long macros 242 | s/\s*\\$//; 243 | 244 | # an /* END JSSTYLED */ comment ends a no-check block. 245 | if ($nocheck) { 246 | if (/\/\* *END *JSSTYLED *\*\//) { 247 | $nocheck = 0; 248 | } else { 249 | reset_indent(); 250 | next line; 251 | } 252 | } 253 | 254 | # a /*JSSTYLED*/ comment indicates that the next line is ok. 255 | if ($nextok) { 256 | if ($okmsg) { 257 | err($okmsg); 258 | } 259 | $nextok = 0; 260 | $okmsg = 0; 261 | if (/\/\* *JSSTYLED.*\*\//) { 262 | /^.*\/\* *JSSTYLED *(.*) *\*\/.*$/; 263 | $okmsg = $1; 264 | $nextok = 1; 265 | } 266 | $no_errs = 1; 267 | } elsif ($no_errs) { 268 | $no_errs = 0; 269 | } 270 | 271 | # check length of line. 272 | # first, a quick check to see if there is any chance of being too long. 273 | if (($line =~ tr/\t/\t/) * 7 + length($line) > 80) { 274 | # yes, there is a chance. 275 | # replace tabs with spaces and check again. 276 | my $eline = $line; 277 | 1 while $eline =~ 278 | s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e; 279 | if (length($eline) > 80) { 280 | err("line > 80 characters"); 281 | } 282 | } 283 | 284 | # ignore NOTE(...) annotations (assumes NOTE is on lines by itself). 285 | if ($note_level || /\b_?NOTE\s*\(/) { # if in NOTE or this is NOTE 286 | s/[^()]//g; # eliminate all non-parens 287 | $note_level += s/\(//g - length; # update paren nest level 288 | next; 289 | } 290 | 291 | # a /* BEGIN JSSTYLED */ comment starts a no-check block. 292 | if (/\/\* *BEGIN *JSSTYLED *\*\//) { 293 | $nocheck = 1; 294 | } 295 | 296 | # a /*JSSTYLED*/ comment indicates that the next line is ok. 297 | if (/\/\* *JSSTYLED.*\*\//) { 298 | /^.*\/\* *JSSTYLED *(.*) *\*\/.*$/; 299 | $okmsg = $1; 300 | $nextok = 1; 301 | } 302 | if (/\/\/ *JSSTYLED/) { 303 | /^.*\/\/ *JSSTYLED *(.*)$/; 304 | $okmsg = $1; 305 | $nextok = 1; 306 | } 307 | 308 | # universal checks; apply to everything 309 | if (/\t +\t/) { 310 | err("spaces between tabs"); 311 | } 312 | if (/ \t+ /) { 313 | err("tabs between spaces"); 314 | } 315 | if (/\s$/) { 316 | err("space or tab at end of line"); 317 | } 318 | if (/[^ \t(]\/\*/ && !/\w\(\/\*.*\*\/\);/) { 319 | err("comment preceded by non-blank"); 320 | } 321 | 322 | # is this the beginning or ending of a function? 323 | # (not if "struct foo\n{\n") 324 | if (/^{$/ && $prev =~ /\)\s*(const\s*)?(\/\*.*\*\/\s*)?\\?$/) { 325 | $in_function = 1; 326 | $in_declaration = 1; 327 | $in_function_header = 0; 328 | $prev = $line; 329 | next line; 330 | } 331 | if (/^}\s*(\/\*.*\*\/\s*)*$/) { 332 | if ($prev =~ /^\s*return\s*;/) { 333 | err_prev("unneeded return at end of function"); 334 | } 335 | $in_function = 0; 336 | reset_indent(); # we don't check between functions 337 | $prev = $line; 338 | next line; 339 | } 340 | if (/^\w*\($/) { 341 | $in_function_header = 1; 342 | } 343 | 344 | # a blank line terminates the declarations within a function. 345 | # XXX - but still a problem in sub-blocks. 346 | if ($in_declaration && /^$/) { 347 | $in_declaration = 0; 348 | } 349 | 350 | if ($comment_done) { 351 | $in_comment = 0; 352 | $in_header_comment = 0; 353 | $comment_done = 0; 354 | } 355 | # does this looks like the start of a block comment? 356 | if (/$hdr_comment_start/) { 357 | if (!/^\t*\/\*/) { 358 | err("block comment not indented by tabs"); 359 | } 360 | $in_comment = 1; 361 | /^(\s*)\//; 362 | $comment_prefix = $1; 363 | if ($comment_prefix eq "") { 364 | $in_header_comment = 1; 365 | } 366 | $prev = $line; 367 | next line; 368 | } 369 | # are we still in the block comment? 370 | if ($in_comment) { 371 | if (/^$comment_prefix \*\/$/) { 372 | $comment_done = 1; 373 | } elsif (/\*\//) { 374 | $comment_done = 1; 375 | err("improper block comment close") 376 | unless ($ignore_hdr_comment && $in_header_comment); 377 | } elsif (!/^$comment_prefix \*[ \t]/ && 378 | !/^$comment_prefix \*$/) { 379 | err("improper block comment") 380 | unless ($ignore_hdr_comment && $in_header_comment); 381 | } 382 | } 383 | 384 | if ($in_header_comment && $ignore_hdr_comment) { 385 | $prev = $line; 386 | next line; 387 | } 388 | 389 | # check for errors that might occur in comments and in code. 390 | 391 | # allow spaces to be used to draw pictures in header comments. 392 | #if (/[^ ] / && !/".* .*"/ && !$in_header_comment) { 393 | # err("spaces instead of tabs"); 394 | #} 395 | #if (/^ / && !/^ \*[ \t\/]/ && !/^ \*$/ && 396 | # (!/^ \w/ || $in_function != 0)) { 397 | # err("indent by spaces instead of tabs"); 398 | #} 399 | if (/^ {2,}/ && !/^ [^ ]/) { 400 | err("indent by spaces instead of tabs"); 401 | } 402 | if (/^\t+ [^ \t\*]/ || /^\t+ \S/ || /^\t+ \S/) { 403 | err("continuation line not indented by 4 spaces"); 404 | } 405 | 406 | if (/^\s*\/\*./ && !/^\s*\/\*.*\*\// && !/$hdr_comment_start/) { 407 | err("improper first line of block comment"); 408 | } 409 | 410 | if ($in_comment) { # still in comment, don't do further checks 411 | $prev = $line; 412 | next line; 413 | } 414 | 415 | if ((/[^(]\/\*\S/ || /^\/\*\S/) && 416 | !(/$lint_re/ || ($splint_comments && /$splint_re/))) { 417 | err("missing blank after open comment"); 418 | } 419 | if (/\S\*\/[^)]|\S\*\/$/ && 420 | !(/$lint_re/ || ($splint_comments && /$splint_re/))) { 421 | err("missing blank before close comment"); 422 | } 423 | if (/\/\/\S/) { # C++ comments 424 | err("missing blank after start comment"); 425 | } 426 | # check for unterminated single line comments, but allow them when 427 | # they are used to comment out the argument list of a function 428 | # declaration. 429 | if (/\S.*\/\*/ && !/\S.*\/\*.*\*\// && !/\(\/\*/) { 430 | err("unterminated single line comment"); 431 | } 432 | 433 | if (/^(#else|#endif|#include)(.*)$/) { 434 | $prev = $line; 435 | next line; 436 | } 437 | 438 | # 439 | # delete any comments and check everything else. Note that 440 | # ".*?" is a non-greedy match, so that we don't get confused by 441 | # multiple comments on the same line. 442 | # 443 | s/\/\*.*?\*\///g; 444 | s/\/\/.*$//; # C++ comments 445 | 446 | # delete any trailing whitespace; we have already checked for that. 447 | s/\s*$//; 448 | 449 | # following checks do not apply to text in comments. 450 | if (/"/) { 451 | err("literal string using double-quote instead of single"); 452 | } 453 | 454 | if (/[^=!<>\s][!<>=]=/ || /[^<>!=][!<>=]==?[^\s,=]/ || 455 | (/[^->]>[^,=>\s]/ && !/[^->]>$/) || 456 | (/[^<]<[^,=<\s]/ && !/[^<]<$/) || 457 | /[^<\s]<[^<]/ || /[^->\s]>[^>]/) { 458 | err("missing space around relational operator"); 459 | } 460 | if (/\S>>=/ || /\S<<=/ || />>=\S/ || /<<=\S/ || /\S[-+*\/&|^%]=/ || 461 | (/[^-+*\/&|^%!<>=\s]=[^=]/ && !/[^-+*\/&|^%!<>=\s]=$/) || 462 | (/[^!<>=]=[^=\s]/ && !/[^!<>=]=$/)) { 463 | # XXX - should only check this for C++ code 464 | # XXX - there are probably other forms that should be allowed 465 | if (!/\soperator=/) { 466 | err("missing space around assignment operator"); 467 | } 468 | } 469 | if (/[,;]\S/ && !/\bfor \(;;\)/) { 470 | err("comma or semicolon followed by non-blank"); 471 | } 472 | # allow "for" statements to have empty "while" clauses 473 | if (/\s[,;]/ && !/^[\t]+;$/ && !/^\s*for \([^;]*; ;[^;]*\)/) { 474 | err("comma or semicolon preceded by blank"); 475 | } 476 | if (/^\s*(&&|\|\|)/) { 477 | err("improper boolean continuation"); 478 | } 479 | if (/\S *(&&|\|\|)/ || /(&&|\|\|) *\S/) { 480 | err("more than one space around boolean operator"); 481 | } 482 | if (/\b(delete|typeof|instanceOf|throw|with|catch|new|function|in|for|if|while|switch|return|case)\(/) { 483 | err("missing space between keyword and paren"); 484 | } 485 | if (/(\b(catch|for|if|with|while|switch|return)\b.*){2,}/) { 486 | # multiple "case" and "sizeof" allowed 487 | err("more than one keyword on line"); 488 | } 489 | if (/\b(delete|typeof|instanceOf|with|throw|catch|new|function|in|for|if|while|switch|return|case)\s\s+\(/ && 490 | !/^#if\s+\(/) { 491 | err("extra space between keyword and paren"); 492 | } 493 | # try to detect "func (x)" but not "if (x)" or 494 | # "#define foo (x)" or "int (*func)();" 495 | if (/\w\s\(/) { 496 | my $s = $_; 497 | # strip off all keywords on the line 498 | s/\b(delete|typeof|instanceOf|throw|with|catch|new|function|in|for|if|while|switch|return|case)\s\(/XXX(/g; 499 | s/#elif\s\(/XXX(/g; 500 | s/^#define\s+\w+\s+\(/XXX(/; 501 | # do not match things like "void (*f)();" 502 | # or "typedef void (func_t)();" 503 | s/\w\s\(+\*/XXX(*/g; 504 | s/\b(void)\s+\(+/XXX(/og; 505 | if (/\w\s\(/) { 506 | err("extra space between function name and left paren"); 507 | } 508 | $_ = $s; 509 | } 510 | 511 | if (/^\s*return\W[^;]*;/ && !/^\s*return\s*\(.*\);/) { 512 | err("unparenthesized return expression"); 513 | } 514 | if (/\btypeof\b/ && !/\btypeof\s*\(.*\)/) { 515 | err("unparenthesized typeof expression"); 516 | } 517 | if (/\(\s/) { 518 | err("whitespace after left paren"); 519 | } 520 | # allow "for" statements to have empty "continue" clauses 521 | if (/\s\)/ && !/^\s*for \([^;]*;[^;]*; \)/) { 522 | err("whitespace before right paren"); 523 | } 524 | if (/^\s*\(void\)[^ ]/) { 525 | err("missing space after (void) cast"); 526 | } 527 | if (/\S{/ && !/({|\(){/) { 528 | err("missing space before left brace"); 529 | } 530 | if ($in_function && /^\s+{/ && 531 | ($prev =~ /\)\s*$/ || $prev =~ /\bstruct\s+\w+$/)) { 532 | err("left brace starting a line"); 533 | } 534 | if (/}(else|while)/) { 535 | err("missing space after right brace"); 536 | } 537 | if (/}\s\s+(else|while)/) { 538 | err("extra space after right brace"); 539 | } 540 | if (/^\s+#/) { 541 | err("preprocessor statement not in column 1"); 542 | } 543 | if (/^#\s/) { 544 | err("blank after preprocessor #"); 545 | } 546 | 547 | # 548 | # We completely ignore, for purposes of indentation: 549 | # * lines outside of functions 550 | # * preprocessor lines 551 | # 552 | if ($check_continuation && $in_function && !$in_cpp) { 553 | process_indent($_); 554 | } 555 | 556 | if ($heuristic) { 557 | # cannot check this everywhere due to "struct {\n...\n} foo;" 558 | if ($in_function && !$in_declaration && 559 | /}./ && !/}\s+=/ && !/{.*}[;,]$/ && !/}(\s|)*$/ && 560 | !/} (else|while)/ && !/}}/) { 561 | err("possible bad text following right brace"); 562 | } 563 | # cannot check this because sub-blocks in 564 | # the middle of code are ok 565 | if ($in_function && /^\s+{/) { 566 | err("possible left brace starting a line"); 567 | } 568 | } 569 | if (/^\s*else\W/) { 570 | if ($prev =~ /^\s*}$/) { 571 | err_prefix($prev, 572 | "else and right brace should be on same line"); 573 | } 574 | } 575 | $prev = $line; 576 | } 577 | 578 | if ($prev eq "") { 579 | err("last line in file is blank"); 580 | } 581 | 582 | } 583 | 584 | # 585 | # Continuation-line checking 586 | # 587 | # The rest of this file contains the code for the continuation checking 588 | # engine. It's a pretty simple state machine which tracks the expression 589 | # depth (unmatched '('s and '['s). 590 | # 591 | # Keep in mind that the argument to process_indent() has already been heavily 592 | # processed; all comments have been replaced by control-A, and the contents of 593 | # strings and character constants have been elided. 594 | # 595 | 596 | my $cont_in; # currently inside of a continuation 597 | my $cont_off; # skipping an initializer or definition 598 | my $cont_noerr; # suppress cascading errors 599 | my $cont_start; # the line being continued 600 | my $cont_base; # the base indentation 601 | my $cont_first; # this is the first line of a statement 602 | my $cont_multiseg; # this continuation has multiple segments 603 | 604 | my $cont_special; # this is a C statement (if, for, etc.) 605 | my $cont_macro; # this is a macro 606 | my $cont_case; # this is a multi-line case 607 | 608 | my @cont_paren; # the stack of unmatched ( and [s we've seen 609 | 610 | sub 611 | reset_indent() 612 | { 613 | $cont_in = 0; 614 | $cont_off = 0; 615 | } 616 | 617 | sub 618 | delabel($) 619 | { 620 | # 621 | # replace labels with tabs. Note that there may be multiple 622 | # labels on a line. 623 | # 624 | local $_ = $_[0]; 625 | 626 | while (/^(\t*)( *(?:(?:\w+\s*)|(?:case\b[^:]*)): *)(.*)$/) { 627 | my ($pre_tabs, $label, $rest) = ($1, $2, $3); 628 | $_ = $pre_tabs; 629 | while ($label =~ s/^([^\t]*)(\t+)//) { 630 | $_ .= "\t" x (length($2) + length($1) / 8); 631 | } 632 | $_ .= ("\t" x (length($label) / 8)).$rest; 633 | } 634 | 635 | return ($_); 636 | } 637 | 638 | sub 639 | process_indent($) 640 | { 641 | require strict; 642 | local $_ = $_[0]; # preserve the global $_ 643 | 644 | s///g; # No comments 645 | s/\s+$//; # Strip trailing whitespace 646 | 647 | return if (/^$/); # skip empty lines 648 | 649 | # regexps used below; keywords taking (), macros, and continued cases 650 | my $special = '(?:(?:\}\s*)?else\s+)?(?:if|for|while|switch)\b'; 651 | my $macro = '[A-Z_][A-Z_0-9]*\('; 652 | my $case = 'case\b[^:]*$'; 653 | 654 | # skip over enumerations, array definitions, initializers, etc. 655 | if ($cont_off <= 0 && !/^\s*$special/ && 656 | (/(?:(?:\b(?:enum|struct|union)\s*[^\{]*)|(?:\s+=\s*)){/ || 657 | (/^\s*{/ && $prev =~ /=\s*(?:\/\*.*\*\/\s*)*$/))) { 658 | $cont_in = 0; 659 | $cont_off = tr/{/{/ - tr/}/}/; 660 | return; 661 | } 662 | if ($cont_off) { 663 | $cont_off += tr/{/{/ - tr/}/}/; 664 | return; 665 | } 666 | 667 | if (!$cont_in) { 668 | $cont_start = $line; 669 | 670 | if (/^\t* /) { 671 | err("non-continuation indented 4 spaces"); 672 | $cont_noerr = 1; # stop reporting 673 | } 674 | $_ = delabel($_); # replace labels with tabs 675 | 676 | # check if the statement is complete 677 | return if (/^\s*\}?$/); 678 | return if (/^\s*\}?\s*else\s*\{?$/); 679 | return if (/^\s*do\s*\{?$/); 680 | return if (/{$/); 681 | return if (/}[,;]?$/); 682 | 683 | # Allow macros on their own lines 684 | return if (/^\s*[A-Z_][A-Z_0-9]*$/); 685 | 686 | # cases we don't deal with, generally non-kosher 687 | if (/{/) { 688 | err("stuff after {"); 689 | return; 690 | } 691 | 692 | # Get the base line, and set up the state machine 693 | /^(\t*)/; 694 | $cont_base = $1; 695 | $cont_in = 1; 696 | @cont_paren = (); 697 | $cont_first = 1; 698 | $cont_multiseg = 0; 699 | 700 | # certain things need special processing 701 | $cont_special = /^\s*$special/? 1 : 0; 702 | $cont_macro = /^\s*$macro/? 1 : 0; 703 | $cont_case = /^\s*$case/? 1 : 0; 704 | } else { 705 | $cont_first = 0; 706 | 707 | # Strings may be pulled back to an earlier (half-)tabstop 708 | unless ($cont_noerr || /^$cont_base / || 709 | (/^\t*(?: )?(?:gettext\()?\"/ && !/^$cont_base\t/)) { 710 | err_prefix($cont_start, 711 | "continuation should be indented 4 spaces"); 712 | } 713 | } 714 | 715 | my $rest = $_; # keeps the remainder of the line 716 | 717 | # 718 | # The split matches 0 characters, so that each 'special' character 719 | # is processed separately. Parens and brackets are pushed and 720 | # popped off the @cont_paren stack. For normal processing, we wait 721 | # until a ; or { terminates the statement. "special" processing 722 | # (if/for/while/switch) is allowed to stop when the stack empties, 723 | # as is macro processing. Case statements are terminated with a : 724 | # and an empty paren stack. 725 | # 726 | foreach $_ (split /[^\(\)\[\]\{\}\;\:]*/) { 727 | next if (length($_) == 0); 728 | 729 | # rest contains the remainder of the line 730 | my $rxp = "[^\Q$_\E]*\Q$_\E"; 731 | $rest =~ s/^$rxp//; 732 | 733 | if (/\(/ || /\[/) { 734 | push @cont_paren, $_; 735 | } elsif (/\)/ || /\]/) { 736 | my $cur = $_; 737 | tr/\)\]/\(\[/; 738 | 739 | my $old = (pop @cont_paren); 740 | if (!defined($old)) { 741 | err("unexpected '$cur'"); 742 | $cont_in = 0; 743 | last; 744 | } elsif ($old ne $_) { 745 | err("'$cur' mismatched with '$old'"); 746 | $cont_in = 0; 747 | last; 748 | } 749 | 750 | # 751 | # If the stack is now empty, do special processing 752 | # for if/for/while/switch and macro statements. 753 | # 754 | next if (@cont_paren != 0); 755 | if ($cont_special) { 756 | if ($rest =~ /^\s*{?$/) { 757 | $cont_in = 0; 758 | last; 759 | } 760 | if ($rest =~ /^\s*;$/) { 761 | err("empty if/for/while body ". 762 | "not on its own line"); 763 | $cont_in = 0; 764 | last; 765 | } 766 | if (!$cont_first && $cont_multiseg == 1) { 767 | err_prefix($cont_start, 768 | "multiple statements continued ". 769 | "over multiple lines"); 770 | $cont_multiseg = 2; 771 | } elsif ($cont_multiseg == 0) { 772 | $cont_multiseg = 1; 773 | } 774 | # We've finished this section, start 775 | # processing the next. 776 | goto section_ended; 777 | } 778 | if ($cont_macro) { 779 | if ($rest =~ /^$/) { 780 | $cont_in = 0; 781 | last; 782 | } 783 | } 784 | } elsif (/\;/) { 785 | if ($cont_case) { 786 | err("unexpected ;"); 787 | } elsif (!$cont_special) { 788 | err("unexpected ;") if (@cont_paren != 0); 789 | if (!$cont_first && $cont_multiseg == 1) { 790 | err_prefix($cont_start, 791 | "multiple statements continued ". 792 | "over multiple lines"); 793 | $cont_multiseg = 2; 794 | } elsif ($cont_multiseg == 0) { 795 | $cont_multiseg = 1; 796 | } 797 | if ($rest =~ /^$/) { 798 | $cont_in = 0; 799 | last; 800 | } 801 | if ($rest =~ /^\s*special/) { 802 | err("if/for/while/switch not started ". 803 | "on its own line"); 804 | } 805 | goto section_ended; 806 | } 807 | } elsif (/\{/) { 808 | err("{ while in parens/brackets") if (@cont_paren != 0); 809 | err("stuff after {") if ($rest =~ /[^\s}]/); 810 | $cont_in = 0; 811 | last; 812 | } elsif (/\}/) { 813 | err("} while in parens/brackets") if (@cont_paren != 0); 814 | if (!$cont_special && $rest !~ /^\s*(while|else)\b/) { 815 | if ($rest =~ /^$/) { 816 | err("unexpected }"); 817 | } else { 818 | err("stuff after }"); 819 | } 820 | $cont_in = 0; 821 | last; 822 | } 823 | } elsif (/\:/ && $cont_case && @cont_paren == 0) { 824 | err("stuff after multi-line case") if ($rest !~ /$^/); 825 | $cont_in = 0; 826 | last; 827 | } 828 | next; 829 | section_ended: 830 | # End of a statement or if/while/for loop. Reset 831 | # cont_special and cont_macro based on the rest of the 832 | # line. 833 | $cont_special = ($rest =~ /^\s*$special/)? 1 : 0; 834 | $cont_macro = ($rest =~ /^\s*$macro/)? 1 : 0; 835 | $cont_case = 0; 836 | next; 837 | } 838 | $cont_noerr = 0 if (!$cont_in); 839 | } 840 | -------------------------------------------------------------------------------- /tst/ctf/float.json: -------------------------------------------------------------------------------- 1 | { "metadata": 2 | { 3 | "ctf2json_version": "1.0", 4 | "created_at": 1316563626, 5 | "derived_from": "/lib/libc.so", 6 | "ctf_version": 2, 7 | "requested_types": [ "float" ] 8 | }, 9 | "data": 10 | [ 11 | { "name": "float", "float": { "length": 4 } } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /tst/ctf/int.json: -------------------------------------------------------------------------------- 1 | { "metadata": 2 | { 3 | "ctf2json_version": "1.0", 4 | "created_at": 1316563631, 5 | "derived_from": "/lib/libc.so", 6 | "ctf_version": 2, 7 | "requested_types": [ "int" ] 8 | }, 9 | "data": 10 | [ 11 | { "name": "int", "integer": { "length": 4, "signed": true } } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /tst/ctf/psinfo.json: -------------------------------------------------------------------------------- 1 | { "metadata": 2 | { 3 | "ctf2json_version": "1.0", 4 | "created_at": 1316563573, 5 | "derived_from": "/lib/libc.so", 6 | "ctf_version": 2, 7 | "requested_types": [ "psinfo_t" ] 8 | }, 9 | "data": 10 | [ 11 | { "name": "int", "integer": { "length": 4, "signed": true } }, 12 | { "name": "char", "integer": { "length": 1, "signed": true } }, 13 | { "name": "unsigned short", "integer": { "length": 2, "signed": false } }, 14 | { "name": "long", "integer": { "length": 4, "signed": true } }, 15 | { "name": "unsigned", "integer": { "length": 4, "signed": false } }, 16 | { "name": "size_t", "typedef": "unsigned" }, 17 | { "name": "unsigned long", "integer": { "length": 4, "signed": false } }, 18 | { "name": "time_t", "typedef": "long" }, 19 | { "name": "struct timespec", "struct": [ 20 | { "name": "tv_sec", "type": "time_t" }, 21 | { "name": "tv_nsec", "type": "long" } 22 | ] }, 23 | { "name": "zoneid_t", "typedef": "long" }, 24 | { "name": "taskid_t", "typedef": "long" }, 25 | { "name": "dev_t", "typedef": "unsigned long" }, 26 | { "name": "uid_t", "typedef": "unsigned" }, 27 | { "name": "gid_t", "typedef": "unsigned" }, 28 | { "name": "timestruc_t", "typedef": "struct timespec" }, 29 | { "name": "short", "integer": { "length": 2, "signed": true } }, 30 | { "name": "projid_t", "typedef": "long" }, 31 | { "name": "ushort_t", "typedef": "unsigned short" }, 32 | { "name": "poolid_t", "typedef": "long" }, 33 | { "name": "uintptr_t", "typedef": "unsigned" }, 34 | { "name": "id_t", "typedef": "long" }, 35 | { "name": "pid_t", "typedef": "long" }, 36 | { "name": "processorid_t", "typedef": "int" }, 37 | { "name": "psetid_t", "typedef": "int" }, 38 | { "name": "struct lwpsinfo", "struct": [ 39 | { "name": "pr_flag", "type": "int" }, 40 | { "name": "pr_lwpid", "type": "id_t" }, 41 | { "name": "pr_addr", "type": "uintptr_t" }, 42 | { "name": "pr_wchan", "type": "uintptr_t" }, 43 | { "name": "pr_stype", "type": "char" }, 44 | { "name": "pr_state", "type": "char" }, 45 | { "name": "pr_sname", "type": "char" }, 46 | { "name": "pr_nice", "type": "char" }, 47 | { "name": "pr_syscall", "type": "short" }, 48 | { "name": "pr_oldpri", "type": "char" }, 49 | { "name": "pr_cpu", "type": "char" }, 50 | { "name": "pr_pri", "type": "int" }, 51 | { "name": "pr_pctcpu", "type": "ushort_t" }, 52 | { "name": "pr_pad", "type": "ushort_t" }, 53 | { "name": "pr_start", "type": "timestruc_t" }, 54 | { "name": "pr_time", "type": "timestruc_t" }, 55 | { "name": "pr_clname", "type": "char [8]" }, 56 | { "name": "pr_name", "type": "char [16]" }, 57 | { "name": "pr_onpro", "type": "processorid_t" }, 58 | { "name": "pr_bindpro", "type": "processorid_t" }, 59 | { "name": "pr_bindpset", "type": "psetid_t" }, 60 | { "name": "pr_lgrp", "type": "int" }, 61 | { "name": "pr_filler", "type": "int [4]" } 62 | ] }, 63 | { "name": "lwpsinfo_t", "typedef": "struct lwpsinfo" }, 64 | { "name": "struct psinfo", "struct": [ 65 | { "name": "pr_flag", "type": "int" }, 66 | { "name": "pr_nlwp", "type": "int" }, 67 | { "name": "pr_pid", "type": "pid_t" }, 68 | { "name": "pr_ppid", "type": "pid_t" }, 69 | { "name": "pr_pgid", "type": "pid_t" }, 70 | { "name": "pr_sid", "type": "pid_t" }, 71 | { "name": "pr_uid", "type": "uid_t" }, 72 | { "name": "pr_euid", "type": "uid_t" }, 73 | { "name": "pr_gid", "type": "gid_t" }, 74 | { "name": "pr_egid", "type": "gid_t" }, 75 | { "name": "pr_addr", "type": "uintptr_t" }, 76 | { "name": "pr_size", "type": "size_t" }, 77 | { "name": "pr_rssize", "type": "size_t" }, 78 | { "name": "pr_pad1", "type": "size_t" }, 79 | { "name": "pr_ttydev", "type": "dev_t" }, 80 | { "name": "pr_pctcpu", "type": "ushort_t" }, 81 | { "name": "pr_pctmem", "type": "ushort_t" }, 82 | { "name": "pr_start", "type": "timestruc_t" }, 83 | { "name": "pr_time", "type": "timestruc_t" }, 84 | { "name": "pr_ctime", "type": "timestruc_t" }, 85 | { "name": "pr_fname", "type": "char [16]" }, 86 | { "name": "pr_psargs", "type": "char [80]" }, 87 | { "name": "pr_wstat", "type": "int" }, 88 | { "name": "pr_argc", "type": "int" }, 89 | { "name": "pr_argv", "type": "uintptr_t" }, 90 | { "name": "pr_envp", "type": "uintptr_t" }, 91 | { "name": "pr_dmodel", "type": "char" }, 92 | { "name": "pr_pad2", "type": "char [3]" }, 93 | { "name": "pr_taskid", "type": "taskid_t" }, 94 | { "name": "pr_projid", "type": "projid_t" }, 95 | { "name": "pr_nzomb", "type": "int" }, 96 | { "name": "pr_poolid", "type": "poolid_t" }, 97 | { "name": "pr_zoneid", "type": "zoneid_t" }, 98 | { "name": "pr_contract", "type": "id_t" }, 99 | { "name": "pr_filler", "type": "int [1]" }, 100 | { "name": "pr_lwp", "type": "lwpsinfo_t" } 101 | ] }, 102 | { "name": "psinfo_t", "typedef": "struct psinfo" } 103 | ] 104 | } 105 | -------------------------------------------------------------------------------- /tst/ctf/struct.json: -------------------------------------------------------------------------------- 1 | { "metadata": 2 | { 3 | "ctf2json_version": "1.0", 4 | "created_at": 1316563648, 5 | "derived_from": "/lib/libc.so", 6 | "ctf_version": 2, 7 | "requested_types": [ "timestruc_t" ] 8 | }, 9 | "data": 10 | [ 11 | { "name": "long", "integer": { "length": 4, "signed": true } }, 12 | { "name": "time_t", "typedef": "long" }, 13 | { "name": "struct timespec", "struct": [ 14 | { "name": "tv_sec", "type": "time_t" }, 15 | { "name": "tv_nsec", "type": "long" }, 16 | { "name": "ctxoption", "type": "contextoption_t" } 17 | ] }, 18 | { "name": "timestruc_t", "typedef": "struct timespec" }, 19 | { "name": "struct contextoption", "struct": [ 20 | { "name": "options", "type": "long" } 21 | ] }, 22 | { "name": "contextoption_t", "typedef": "struct contextoption" } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /tst/ctf/tst.fail.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Test several conditions that should always cause us to throw. 3 | */ 4 | var mod_assert = require('assert'); 5 | var mod_ctype = require('../../ctype.js'); 6 | 7 | var cases = [ 8 | { json: { }, msg: 'Invalid CTF JSON: missing metadata section' }, 9 | { json: { metadata: {} }, msg: 'Invalid CTF JSON: missing ctf2json_version' }, 10 | { json: { metadata: { 'ctf2json_version': [] } }, 11 | msg: 'Unsuported ctf2json_version: ' }, 12 | { json: { metadata: { 'ctf2json_version': 2 } }, 13 | msg: 'Unsuported ctf2json_version: 2' }, 14 | { json: { metadata: { 'ctf2json_version': '100.20' } }, 15 | msg: 'Unsuported ctf2json_version: 100.20' }, 16 | { json: { metadata: { 'ctf2json_version': '1.0' } }, 17 | msg: 'Invalid CTF JSON: missing data section' }, 18 | { json: { metadata: { 'ctf2json_version': '1.0' }, data: 1 }, 19 | msg: 'Malformed CTF JSON: data section is not an array' }, 20 | { json: { metadata: { 'ctf2json_version': '1.0' }, data: 1.1 }, 21 | msg: 'Malformed CTF JSON: data section is not an array' }, 22 | { json: { metadata: { 'ctf2json_version': '1.0' }, data: '1.1' }, 23 | msg: 'Malformed CTF JSON: data section is not an array' }, 24 | { json: { metadata: { 'ctf2json_version': '1.0' }, data: {} }, 25 | msg: 'Malformed CTF JSON: data section is not an array' }, 26 | { json: { metadata: { 'ctf2json_version': '1.0' }, 27 | data: [ { 28 | 'name': 'struct DataHolder', 'struct': [ 29 | { 'name': 'unknown', 'type': 'missing_t' } 30 | ] } ] 31 | }, 32 | msg: 'type not found or typdefed: missing_t' } 33 | ]; 34 | 35 | function test() 36 | { 37 | var conf = { endian: 'little' }; 38 | var ii; 39 | 40 | for (ii = 0; ii < cases.length; ii++) { 41 | try { 42 | mod_ctype.parseCTF(cases[ii].json, conf); 43 | mod_assert.fail('expected test to fail: ' + cases[ii].json); 44 | } catch (ex) { 45 | mod_assert.equal(ex.message, cases[ii].msg); 46 | } 47 | } 48 | } 49 | 50 | test(); 51 | -------------------------------------------------------------------------------- /tst/ctf/tst.float.js: -------------------------------------------------------------------------------- 1 | var mod_fs = require('fs'); 2 | var mod_ctype = require('../../ctype.js'); 3 | var mod_assert = require('assert'); 4 | 5 | function test() 6 | { 7 | var data, parser; 8 | 9 | data = JSON.parse(mod_fs.readFileSync('./float.json').toString()); 10 | parser = mod_ctype.parseCTF(data, { endian: 'big' }); 11 | mod_assert.deepEqual(parser.lstypes(), {}); 12 | } 13 | 14 | test(); 15 | -------------------------------------------------------------------------------- /tst/ctf/tst.int.js: -------------------------------------------------------------------------------- 1 | var mod_fs = require('fs'); 2 | var mod_ctype = require('../../ctype.js'); 3 | var mod_assert = require('assert'); 4 | 5 | function test() 6 | { 7 | var data, parser; 8 | 9 | data = JSON.parse(mod_fs.readFileSync('./int.json').toString()); 10 | parser = mod_ctype.parseCTF(data, { endian: 'big' }); 11 | mod_assert.deepEqual(parser.lstypes(), { 'int': 'int32_t' }); 12 | } 13 | 14 | test(); 15 | -------------------------------------------------------------------------------- /tst/ctf/tst.psinfo.js: -------------------------------------------------------------------------------- 1 | var mod_fs = require('fs'); 2 | var mod_ctype = require('../../ctype.js'); 3 | var mod_assert = require('assert'); 4 | 5 | /* 6 | * This is too unwieldly to actually write out. Just make sure we can parse it 7 | * without errrors. 8 | */ 9 | function test() 10 | { 11 | var data; 12 | 13 | data = JSON.parse(mod_fs.readFileSync('./psinfo.json').toString()); 14 | mod_ctype.parseCTF(data, { endian: 'big' }); 15 | } 16 | 17 | test(); 18 | -------------------------------------------------------------------------------- /tst/ctf/tst.struct.js: -------------------------------------------------------------------------------- 1 | var mod_fs = require('fs'); 2 | var mod_ctype = require('../../ctype.js'); 3 | var mod_assert = require('assert'); 4 | 5 | function test() 6 | { 7 | var data, parser; 8 | 9 | data = JSON.parse(mod_fs.readFileSync('./struct.json').toString()); 10 | parser = mod_ctype.parseCTF(data, { endian: 'big' }); 11 | mod_assert.deepEqual(parser.lstypes(), { 'long': 'int32_t', 12 | 'time_t': 'long', 13 | 'struct timespec': [ { tv_sec: { type: 'time_t' } }, 14 | { tv_nsec: { type: 'long' } }, 15 | { ctxoption: { type: 'contextoption_t' } } ], 16 | 'timestruc_t': 'struct timespec', 17 | 'struct contextoption': [ { options: { type: 'long' } } ], 18 | 'contextoption_t': 'struct contextoption' 19 | }); 20 | } 21 | 22 | test(); 23 | -------------------------------------------------------------------------------- /tst/ctf/tst.typedef.js: -------------------------------------------------------------------------------- 1 | var mod_fs = require('fs'); 2 | var mod_ctype = require('../../ctype.js'); 3 | var mod_assert = require('assert'); 4 | 5 | function test() 6 | { 7 | var data, parser; 8 | 9 | data = JSON.parse(mod_fs.readFileSync('./typedef.json').toString()); 10 | parser = mod_ctype.parseCTF(data, { endian: 'big' }); 11 | mod_assert.deepEqual(parser.lstypes(), { 'bar_t': 'int', 12 | 'int': 'int32_t' }); 13 | } 14 | 15 | test(); 16 | -------------------------------------------------------------------------------- /tst/ctf/typedef.json: -------------------------------------------------------------------------------- 1 | { "metadata": 2 | { 3 | "ctf2json_version": "1.0", 4 | "created_at": 1316302348, 5 | "derived_from": "/lib/libc.so", 6 | "ctf_version": 2, 7 | "requested_types": [ "bar_t" ] 8 | }, 9 | "data": 10 | [ 11 | { "name": "int", "integer": { "length": 4, "signed": true } }, 12 | { "name": "bar_t", "typedef": "int" } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /tst/ctio/float/tst.rfloat.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Battery of tests to break our floating point implementation. Oh ho ho. 3 | * 4 | * There are a few useful ways to generate the expected output. The first is 5 | * just write a C program and write raw bytes out and inspect with xxd. Remember 6 | * to consider whether or not you're on a big endian or little endian machine. 7 | * Another useful site I found to help with some of this was: 8 | * 9 | * http://babbage.cs.qc.edu/IEEE-754/ 10 | */ 11 | 12 | var mod_ctype = require('../../../ctio.js'); 13 | var ASSERT = require('assert'); 14 | 15 | function testfloat() 16 | { 17 | var buffer = new Buffer(4); 18 | /* Start off with some of the easy ones: +zero */ 19 | buffer[0] = 0; 20 | buffer[1] = 0; 21 | buffer[2] = 0; 22 | buffer[3] = 0; 23 | 24 | ASSERT.equal(0, mod_ctype.rfloat(buffer, 'big', 0)); 25 | ASSERT.equal(0, mod_ctype.rfloat(buffer, 'little', 0)); 26 | 27 | /* Test -0 */ 28 | buffer[0] = 0x80; 29 | ASSERT.equal(0, mod_ctype.rfloat(buffer, 'big', 0)); 30 | buffer[3] = buffer[0]; 31 | buffer[0] = 0; 32 | ASSERT.equal(0, mod_ctype.rfloat(buffer, 'little', 0)); 33 | 34 | /* Catch +infin */ 35 | buffer[0] = 0x7f; 36 | buffer[1] = 0x80; 37 | buffer[2] = 0x00; 38 | buffer[3] = 0x00; 39 | ASSERT.equal(Number.POSITIVE_INFINITY, 40 | mod_ctype.rfloat(buffer, 'big', 0)); 41 | buffer[3] = 0x7f; 42 | buffer[2] = 0x80; 43 | buffer[1] = 0x00; 44 | buffer[0] = 0x00; 45 | ASSERT.equal(Number.POSITIVE_INFINITY, 46 | mod_ctype.rfloat(buffer, 'litle', 0)); 47 | 48 | /* Catch -infin */ 49 | buffer[0] = 0xff; 50 | buffer[1] = 0x80; 51 | buffer[2] = 0x00; 52 | buffer[3] = 0x00; 53 | ASSERT.equal(Number.NEGATIVE_INFINITY, 54 | mod_ctype.rfloat(buffer, 'big', 0)); 55 | buffer[3] = 0xff; 56 | buffer[2] = 0x80; 57 | buffer[1] = 0x00; 58 | buffer[0] = 0x00; 59 | ASSERT.equal(Number.NEGATIVE_INFINITY, 60 | mod_ctype.rfloat(buffer, 'litle', 0)); 61 | 62 | /* Catch NaN */ 63 | 64 | buffer[0] = 0x7f; 65 | buffer[1] = 0x80; 66 | buffer[2] = 0x00; 67 | buffer[3] = 0x23; 68 | ASSERT.ok(isNaN(mod_ctype.rfloat(buffer, 'big', 0))); 69 | buffer[3] = 0x7f; 70 | buffer[2] = 0x80; 71 | buffer[1] = 0x00; 72 | buffer[0] = 0x23; 73 | ASSERT.ok(isNaN(mod_ctype.rfloat(buffer, 'little', 0))); 74 | 75 | /* Catch -infin */ 76 | buffer[0] = 0xff; 77 | buffer[1] = 0x80; 78 | buffer[2] = 0x00; 79 | buffer[3] = 0x23; 80 | ASSERT.ok(isNaN(mod_ctype.rfloat(buffer, 'big', 0))); 81 | buffer[3] = 0xff; 82 | buffer[2] = 0x80; 83 | buffer[1] = 0x00; 84 | buffer[0] = 0x23; 85 | ASSERT.ok(isNaN(mod_ctype.rfloat(buffer, 'little', 0))); 86 | 87 | /* On to some basic tests */ 88 | /* 1.125 */ 89 | buffer[0] = 0x3f; 90 | buffer[1] = 0x90; 91 | buffer[2] = 0x00; 92 | buffer[3] = 0x00; 93 | ASSERT.equal(1.125, mod_ctype.rfloat(buffer, 'big', 0)); 94 | 95 | buffer[3] = 0x3f; 96 | buffer[2] = 0x90; 97 | buffer[1] = 0x00; 98 | buffer[0] = 0x00; 99 | ASSERT.equal(1.125, mod_ctype.rfloat(buffer, 'little', 0)); 100 | 101 | /* ff34a2b0 -2.4010576103645774e+38 */ 102 | buffer[0] = 0xff; 103 | buffer[1] = 0x34; 104 | buffer[2] = 0xa2; 105 | buffer[3] = 0xb0; 106 | ASSERT.equal(-2.4010576103645774e+38, 107 | mod_ctype.rfloat(buffer, 'big', 0)); 108 | 109 | buffer[3] = 0xff; 110 | buffer[2] = 0x34; 111 | buffer[1] = 0xa2; 112 | buffer[0] = 0xb0; 113 | ASSERT.equal(-2.4010576103645774e+38, 114 | mod_ctype.rfloat(buffer, 'little', 0)); 115 | 116 | /* Denormalized tests */ 117 | 118 | /* 0003f89a +/- 3.6468792534053364e-40 */ 119 | buffer[0] = 0x00; 120 | buffer[1] = 0x03; 121 | buffer[2] = 0xf8; 122 | buffer[3] = 0x9a; 123 | ASSERT.equal(3.6468792534053364e-40, 124 | mod_ctype.rfloat(buffer, 'big', 0)); 125 | 126 | buffer[3] = 0x00; 127 | buffer[2] = 0x03; 128 | buffer[1] = 0xf8; 129 | buffer[0] = 0x9a; 130 | ASSERT.equal(3.6468792534053364e-40, 131 | mod_ctype.rfloat(buffer, 'little', 0)); 132 | 133 | buffer[0] = 0x80; 134 | buffer[1] = 0x03; 135 | buffer[2] = 0xf8; 136 | buffer[3] = 0x9a; 137 | ASSERT.equal(-3.6468792534053364e-40, 138 | mod_ctype.rfloat(buffer, 'big', 0)); 139 | 140 | buffer[3] = 0x80; 141 | buffer[2] = 0x03; 142 | buffer[1] = 0xf8; 143 | buffer[0] = 0x9a; 144 | ASSERT.equal(-3.6468792534053364e-40, 145 | mod_ctype.rfloat(buffer, 'little', 0)); 146 | 147 | 148 | /* Maximum and minimum normalized and denormalized values */ 149 | 150 | /* Largest normalized number +/- 3.4028234663852886e+38 */ 151 | 152 | buffer[0] = 0x7f; 153 | buffer[1] = 0x7f; 154 | buffer[2] = 0xff; 155 | buffer[3] = 0xff; 156 | ASSERT.equal(3.4028234663852886e+38, 157 | mod_ctype.rfloat(buffer, 'big', 0)); 158 | 159 | buffer[3] = 0x7f; 160 | buffer[2] = 0x7f; 161 | buffer[1] = 0xff; 162 | buffer[0] = 0xff; 163 | ASSERT.equal(3.4028234663852886e+38, 164 | mod_ctype.rfloat(buffer, 'little', 0)); 165 | 166 | buffer[0] = 0xff; 167 | buffer[1] = 0x7f; 168 | buffer[2] = 0xff; 169 | buffer[3] = 0xff; 170 | ASSERT.equal(-3.4028234663852886e+38, 171 | mod_ctype.rfloat(buffer, 'big', 0)); 172 | 173 | buffer[3] = 0xff; 174 | buffer[2] = 0x7f; 175 | buffer[1] = 0xff; 176 | buffer[0] = 0xff; 177 | ASSERT.equal(-3.4028234663852886e+38, 178 | mod_ctype.rfloat(buffer, 'little', 0)); 179 | 180 | /* Smallest normalied number +/- 1.1754943508222875e-38 */ 181 | buffer[0] = 0x00; 182 | buffer[1] = 0x80; 183 | buffer[2] = 0x00; 184 | buffer[3] = 0x00; 185 | ASSERT.equal(1.1754943508222875e-38, 186 | mod_ctype.rfloat(buffer, 'big', 0)); 187 | 188 | buffer[3] = 0x00; 189 | buffer[2] = 0x80; 190 | buffer[1] = 0x00; 191 | buffer[0] = 0x00; 192 | ASSERT.equal(1.1754943508222875e-38, 193 | mod_ctype.rfloat(buffer, 'little', 0)); 194 | 195 | buffer[0] = 0x80; 196 | buffer[1] = 0x80; 197 | buffer[2] = 0x00; 198 | buffer[3] = 0x00; 199 | ASSERT.equal(-1.1754943508222875e-38, 200 | mod_ctype.rfloat(buffer, 'big', 0)); 201 | 202 | buffer[3] = 0x80; 203 | buffer[2] = 0x80; 204 | buffer[1] = 0x00; 205 | buffer[0] = 0x00; 206 | ASSERT.equal(-1.1754943508222875e-38, 207 | mod_ctype.rfloat(buffer, 'little', 0)); 208 | 209 | 210 | /* Smallest denormalized number 1.401298464324817e-45 */ 211 | buffer[0] = 0x00; 212 | buffer[1] = 0x00; 213 | buffer[2] = 0x00; 214 | buffer[3] = 0x01; 215 | ASSERT.equal(1.401298464324817e-45, 216 | mod_ctype.rfloat(buffer, 'big', 0)); 217 | 218 | buffer[3] = 0x00; 219 | buffer[2] = 0x00; 220 | buffer[1] = 0x00; 221 | buffer[0] = 0x01; 222 | ASSERT.equal(1.401298464324817e-45, 223 | mod_ctype.rfloat(buffer, 'little', 0)); 224 | 225 | buffer[0] = 0x80; 226 | buffer[1] = 0x00; 227 | buffer[2] = 0x00; 228 | buffer[3] = 0x01; 229 | ASSERT.equal(-1.401298464324817e-45, 230 | mod_ctype.rfloat(buffer, 'big', 0)); 231 | 232 | buffer[3] = 0x80; 233 | buffer[2] = 0x00; 234 | buffer[1] = 0x00; 235 | buffer[0] = 0x01; 236 | ASSERT.equal(-1.401298464324817e-45, 237 | mod_ctype.rfloat(buffer, 'little', 0)); 238 | 239 | /* Largest denormalized value +/- 1.1754942106924411e-38 */ 240 | buffer[0] = 0x00; 241 | buffer[1] = 0x7f; 242 | buffer[2] = 0xff; 243 | buffer[3] = 0xff; 244 | ASSERT.equal(1.1754942106924411e-38, 245 | mod_ctype.rfloat(buffer, 'big', 0)); 246 | 247 | buffer[3] = 0x00; 248 | buffer[2] = 0x7f; 249 | buffer[1] = 0xff; 250 | buffer[0] = 0xff; 251 | ASSERT.equal(1.1754942106924411e-38, 252 | mod_ctype.rfloat(buffer, 'little', 0)); 253 | 254 | buffer[0] = 0x80; 255 | buffer[1] = 0x7f; 256 | buffer[2] = 0xff; 257 | buffer[3] = 0xff; 258 | ASSERT.equal(-1.1754942106924411e-38, 259 | mod_ctype.rfloat(buffer, 'big', 0)); 260 | 261 | buffer[3] = 0x80; 262 | buffer[2] = 0x7f; 263 | buffer[1] = 0xff; 264 | buffer[0] = 0xff; 265 | ASSERT.equal(-1.1754942106924411e-38, 266 | mod_ctype.rfloat(buffer, 'little', 0)); 267 | 268 | /* Do some quick offset testing */ 269 | buffer = new Buffer(6); 270 | buffer[0] = 0x7f; 271 | buffer[1] = 0x4e; 272 | buffer[2] = 0x8a; 273 | buffer[3] = 0x79; 274 | buffer[4] = 0xcd; 275 | buffer[5] = 0x3f; 276 | 277 | ASSERT.equal(2.745399582697325e+38, 278 | mod_ctype.rfloat(buffer, 'big', 0)); 279 | ASSERT.equal(1161619072, 280 | mod_ctype.rfloat(buffer, 'big', 1)); 281 | ASSERT.equal(-1.2027516403607578e-32, 282 | mod_ctype.rfloat(buffer, 'big', 2)); 283 | 284 | ASSERT.equal(8.97661320504413e+34, 285 | mod_ctype.rfloat(buffer, 'little', 0)); 286 | ASSERT.equal(-261661920, 287 | mod_ctype.rfloat(buffer, 'little', 1)); 288 | ASSERT.equal(1.605271577835083, 289 | mod_ctype.rfloat(buffer, 'little', 2)); 290 | 291 | } 292 | 293 | function testdouble() 294 | { 295 | var buffer = new Buffer(10); 296 | 297 | /* Check 0 */ 298 | buffer[0] = 0; 299 | buffer[1] = 0; 300 | buffer[2] = 0; 301 | buffer[3] = 0; 302 | buffer[4] = 0; 303 | buffer[5] = 0; 304 | buffer[6] = 0; 305 | buffer[7] = 0; 306 | ASSERT.equal(0, 307 | mod_ctype.rdouble(buffer, 'big', 0)); 308 | ASSERT.equal(0, 309 | mod_ctype.rdouble(buffer, 'little', 0)); 310 | 311 | buffer[0] = 0x80; 312 | buffer[1] = 0; 313 | buffer[2] = 0; 314 | buffer[3] = 0; 315 | buffer[4] = 0; 316 | buffer[5] = 0; 317 | buffer[6] = 0; 318 | buffer[7] = 0; 319 | ASSERT.equal(0, 320 | mod_ctype.rdouble(buffer, 'big', 0)); 321 | buffer[7] = 0x80; 322 | buffer[6] = 0; 323 | buffer[5] = 0; 324 | buffer[4] = 0; 325 | buffer[3] = 0; 326 | buffer[2] = 0; 327 | buffer[1] = 0; 328 | buffer[0] = 0; 329 | ASSERT.equal(0, 330 | mod_ctype.rdouble(buffer, 'little', 0)); 331 | 332 | /* Check NaN */ 333 | buffer[0] = 0x7f; 334 | buffer[1] = 0xf0; 335 | buffer[2] = 0; 336 | buffer[3] = 0; 337 | buffer[4] = 0; 338 | buffer[5] = 0; 339 | buffer[6] = 0; 340 | buffer[7] = 23; 341 | ASSERT.ok(isNaN(mod_ctype.rdouble(buffer, 'big', 0))); 342 | 343 | buffer[7] = 0x7f; 344 | buffer[6] = 0xf0; 345 | buffer[5] = 0; 346 | buffer[4] = 0; 347 | buffer[3] = 0; 348 | buffer[2] = 0; 349 | buffer[1] = 0; 350 | buffer[0] = 23; 351 | ASSERT.ok(isNaN(mod_ctype.rdouble(buffer, 'little', 0))); 352 | 353 | buffer[0] = 0xff; 354 | buffer[1] = 0xf0; 355 | buffer[2] = 0; 356 | buffer[3] = 0; 357 | buffer[4] = 0; 358 | buffer[5] = 0; 359 | buffer[6] = 0; 360 | buffer[7] = 23; 361 | ASSERT.ok(isNaN(mod_ctype.rdouble(buffer, 'big', 0))); 362 | 363 | buffer[7] = 0xff; 364 | buffer[6] = 0xf0; 365 | buffer[5] = 0; 366 | buffer[4] = 0; 367 | buffer[3] = 0; 368 | buffer[2] = 0; 369 | buffer[1] = 0; 370 | buffer[0] = 23; 371 | ASSERT.ok(isNaN(mod_ctype.rdouble(buffer, 'little', 0))); 372 | 373 | /* pos inf */ 374 | buffer[0] = 0x7f; 375 | buffer[1] = 0xf0; 376 | buffer[2] = 0; 377 | buffer[3] = 0; 378 | buffer[4] = 0; 379 | buffer[5] = 0; 380 | buffer[6] = 0; 381 | buffer[7] = 0; 382 | ASSERT.equal(Number.POSITIVE_INFINITY, 383 | mod_ctype.rdouble(buffer, 'big', 0)); 384 | 385 | buffer[7] = 0x7f; 386 | buffer[6] = 0xf0; 387 | buffer[5] = 0; 388 | buffer[4] = 0; 389 | buffer[3] = 0; 390 | buffer[2] = 0; 391 | buffer[1] = 0; 392 | buffer[0] = 0; 393 | ASSERT.equal(Number.POSITIVE_INFINITY, 394 | mod_ctype.rdouble(buffer, 'little', 0)); 395 | 396 | /* neg inf */ 397 | buffer[0] = 0xff; 398 | buffer[1] = 0xf0; 399 | buffer[2] = 0; 400 | buffer[3] = 0; 401 | buffer[4] = 0; 402 | buffer[5] = 0; 403 | buffer[6] = 0; 404 | buffer[7] = 0; 405 | ASSERT.equal(Number.NEGATIVE_INFINITY, 406 | mod_ctype.rdouble(buffer, 'big', 0)); 407 | 408 | buffer[7] = 0xff; 409 | buffer[6] = 0xf0; 410 | buffer[5] = 0; 411 | buffer[4] = 0; 412 | buffer[3] = 0; 413 | buffer[2] = 0; 414 | buffer[1] = 0; 415 | buffer[0] = 0; 416 | ASSERT.equal(Number.NEGATIVE_INFINITY, 417 | mod_ctype.rdouble(buffer, 'little', 0)); 418 | 419 | /* Simple normalized values */ 420 | 421 | /* +/- 1.125 */ 422 | buffer[0] = 0x3f; 423 | buffer[1] = 0xf2; 424 | buffer[2] = 0; 425 | buffer[3] = 0; 426 | buffer[4] = 0; 427 | buffer[5] = 0; 428 | buffer[6] = 0; 429 | buffer[7] = 0; 430 | ASSERT.equal(1.125, 431 | mod_ctype.rdouble(buffer, 'big', 0)); 432 | 433 | buffer[7] = 0x3f; 434 | buffer[6] = 0xf2; 435 | buffer[5] = 0; 436 | buffer[4] = 0; 437 | buffer[3] = 0; 438 | buffer[2] = 0; 439 | buffer[1] = 0; 440 | buffer[0] = 0; 441 | ASSERT.equal(1.125, 442 | mod_ctype.rdouble(buffer, 'little', 0)); 443 | 444 | buffer[0] = 0xbf; 445 | buffer[1] = 0xf2; 446 | buffer[2] = 0; 447 | buffer[3] = 0; 448 | buffer[4] = 0; 449 | buffer[5] = 0; 450 | buffer[6] = 0; 451 | buffer[7] = 0; 452 | ASSERT.equal(-1.125, 453 | mod_ctype.rdouble(buffer, 'big', 0)); 454 | 455 | buffer[7] = 0xbf; 456 | buffer[6] = 0xf2; 457 | buffer[5] = 0; 458 | buffer[4] = 0; 459 | buffer[3] = 0; 460 | buffer[2] = 0; 461 | buffer[1] = 0; 462 | buffer[0] = 0; 463 | ASSERT.equal(-1.125, 464 | mod_ctype.rdouble(buffer, 'little', 0)); 465 | 466 | /* +/- 1.4397318913736026e+283 */ 467 | buffer[0] = 0x7a; 468 | buffer[1] = 0xb8; 469 | buffer[2] = 0xc9; 470 | buffer[3] = 0x34; 471 | buffer[4] = 0x72; 472 | buffer[5] = 0x16; 473 | buffer[6] = 0xf9; 474 | buffer[7] = 0x0e; 475 | ASSERT.equal(1.4397318913736026e+283, 476 | mod_ctype.rdouble(buffer, 'big', 0)); 477 | 478 | buffer[7] = 0x7a; 479 | buffer[6] = 0xb8; 480 | buffer[5] = 0xc9; 481 | buffer[4] = 0x34; 482 | buffer[3] = 0x72; 483 | buffer[2] = 0x16; 484 | buffer[1] = 0xf9; 485 | buffer[0] = 0x0e; 486 | ASSERT.equal(1.4397318913736026e+283, 487 | mod_ctype.rdouble(buffer, 'little', 0)); 488 | 489 | buffer[0] = 0xfa; 490 | buffer[1] = 0xb8; 491 | buffer[2] = 0xc9; 492 | buffer[3] = 0x34; 493 | buffer[4] = 0x72; 494 | buffer[5] = 0x16; 495 | buffer[6] = 0xf9; 496 | buffer[7] = 0x0e; 497 | ASSERT.equal(-1.4397318913736026e+283, 498 | mod_ctype.rdouble(buffer, 'big', 0)); 499 | 500 | buffer[7] = 0xfa; 501 | buffer[6] = 0xb8; 502 | buffer[5] = 0xc9; 503 | buffer[4] = 0x34; 504 | buffer[3] = 0x72; 505 | buffer[2] = 0x16; 506 | buffer[1] = 0xf9; 507 | buffer[0] = 0x0e; 508 | ASSERT.equal(-1.4397318913736026e+283, 509 | mod_ctype.rdouble(buffer, 'little', 0)); 510 | 511 | /* Denormalized values */ 512 | /* +/- 8.82521232268344e-309 */ 513 | buffer[0] = 0x00; 514 | buffer[1] = 0x06; 515 | buffer[2] = 0x58; 516 | buffer[3] = 0x94; 517 | buffer[4] = 0x13; 518 | buffer[5] = 0x27; 519 | buffer[6] = 0x8a; 520 | buffer[7] = 0xcd; 521 | ASSERT.equal(8.82521232268344e-309, 522 | mod_ctype.rdouble(buffer, 'big', 0)); 523 | 524 | buffer[7] = 0x00; 525 | buffer[6] = 0x06; 526 | buffer[5] = 0x58; 527 | buffer[4] = 0x94; 528 | buffer[3] = 0x13; 529 | buffer[2] = 0x27; 530 | buffer[1] = 0x8a; 531 | buffer[0] = 0xcd; 532 | ASSERT.equal(8.82521232268344e-309, 533 | mod_ctype.rdouble(buffer, 'little', 0)); 534 | 535 | buffer[0] = 0x80; 536 | buffer[1] = 0x06; 537 | buffer[2] = 0x58; 538 | buffer[3] = 0x94; 539 | buffer[4] = 0x13; 540 | buffer[5] = 0x27; 541 | buffer[6] = 0x8a; 542 | buffer[7] = 0xcd; 543 | ASSERT.equal(-8.82521232268344e-309, 544 | mod_ctype.rdouble(buffer, 'big', 0)); 545 | 546 | buffer[7] = 0x80; 547 | buffer[6] = 0x06; 548 | buffer[5] = 0x58; 549 | buffer[4] = 0x94; 550 | buffer[3] = 0x13; 551 | buffer[2] = 0x27; 552 | buffer[1] = 0x8a; 553 | buffer[0] = 0xcd; 554 | ASSERT.equal(-8.82521232268344e-309, 555 | mod_ctype.rdouble(buffer, 'little', 0)); 556 | 557 | /* Edge cases, maximum and minimum values */ 558 | 559 | /* Smallest denormalized value 5e-324 */ 560 | buffer[0] = 0x00; 561 | buffer[1] = 0x00; 562 | buffer[2] = 0x00; 563 | buffer[3] = 0x00; 564 | buffer[4] = 0x00; 565 | buffer[5] = 0x00; 566 | buffer[6] = 0x00; 567 | buffer[7] = 0x01; 568 | ASSERT.equal(5e-324, 569 | mod_ctype.rdouble(buffer, 'big', 0)); 570 | 571 | buffer[7] = 0x00; 572 | buffer[6] = 0x00; 573 | buffer[5] = 0x00; 574 | buffer[4] = 0x00; 575 | buffer[3] = 0x00; 576 | buffer[2] = 0x00; 577 | buffer[1] = 0x00; 578 | buffer[0] = 0x01; 579 | ASSERT.equal(5e-324, 580 | mod_ctype.rdouble(buffer, 'little', 0)); 581 | 582 | buffer[0] = 0x80; 583 | buffer[1] = 0x00; 584 | buffer[2] = 0x00; 585 | buffer[3] = 0x00; 586 | buffer[4] = 0x00; 587 | buffer[5] = 0x00; 588 | buffer[6] = 0x00; 589 | buffer[7] = 0x01; 590 | ASSERT.equal(-5e-324, 591 | mod_ctype.rdouble(buffer, 'big', 0)); 592 | 593 | buffer[7] = 0x80; 594 | buffer[6] = 0x00; 595 | buffer[5] = 0x00; 596 | buffer[4] = 0x00; 597 | buffer[3] = 0x00; 598 | buffer[2] = 0x00; 599 | buffer[1] = 0x00; 600 | buffer[0] = 0x01; 601 | ASSERT.equal(-5e-324, 602 | mod_ctype.rdouble(buffer, 'little', 0)); 603 | 604 | /* Largest denormalized value 2.225073858507201e-308 */ 605 | buffer[0] = 0x00; 606 | buffer[1] = 0x0f; 607 | buffer[2] = 0xff; 608 | buffer[3] = 0xff; 609 | buffer[4] = 0xff; 610 | buffer[5] = 0xff; 611 | buffer[6] = 0xff; 612 | buffer[7] = 0xff; 613 | ASSERT.equal(2.225073858507201e-308, 614 | mod_ctype.rdouble(buffer, 'big', 0)); 615 | 616 | buffer[7] = 0x00; 617 | buffer[6] = 0x0f; 618 | buffer[5] = 0xff; 619 | buffer[4] = 0xff; 620 | buffer[3] = 0xff; 621 | buffer[2] = 0xff; 622 | buffer[1] = 0xff; 623 | buffer[0] = 0xff; 624 | ASSERT.equal(2.225073858507201e-308, 625 | mod_ctype.rdouble(buffer, 'little', 0)); 626 | 627 | buffer[0] = 0x80; 628 | buffer[1] = 0x0f; 629 | buffer[2] = 0xff; 630 | buffer[3] = 0xff; 631 | buffer[4] = 0xff; 632 | buffer[5] = 0xff; 633 | buffer[6] = 0xff; 634 | buffer[7] = 0xff; 635 | ASSERT.equal(-2.225073858507201e-308, 636 | mod_ctype.rdouble(buffer, 'big', 0)); 637 | 638 | buffer[7] = 0x80; 639 | buffer[6] = 0x0f; 640 | buffer[5] = 0xff; 641 | buffer[4] = 0xff; 642 | buffer[3] = 0xff; 643 | buffer[2] = 0xff; 644 | buffer[1] = 0xff; 645 | buffer[0] = 0xff; 646 | ASSERT.equal(-2.225073858507201e-308, 647 | mod_ctype.rdouble(buffer, 'little', 0)); 648 | 649 | /* Smallest normalized value 2.2250738585072014e-308 */ 650 | buffer[0] = 0x00; 651 | buffer[1] = 0x10; 652 | buffer[2] = 0x00; 653 | buffer[3] = 0x00; 654 | buffer[4] = 0x00; 655 | buffer[5] = 0x00; 656 | buffer[6] = 0x00; 657 | buffer[7] = 0x00; 658 | ASSERT.equal(2.2250738585072014e-308, 659 | mod_ctype.rdouble(buffer, 'big', 0)); 660 | 661 | buffer[7] = 0x00; 662 | buffer[6] = 0x10; 663 | buffer[5] = 0x00; 664 | buffer[4] = 0x00; 665 | buffer[3] = 0x00; 666 | buffer[2] = 0x00; 667 | buffer[1] = 0x00; 668 | buffer[0] = 0x00; 669 | ASSERT.equal(2.2250738585072014e-308, 670 | mod_ctype.rdouble(buffer, 'little', 0)); 671 | 672 | buffer[0] = 0x80; 673 | buffer[1] = 0x10; 674 | buffer[2] = 0x00; 675 | buffer[3] = 0x00; 676 | buffer[4] = 0x00; 677 | buffer[5] = 0x00; 678 | buffer[6] = 0x00; 679 | buffer[7] = 0x00; 680 | ASSERT.equal(-2.2250738585072014e-308, 681 | mod_ctype.rdouble(buffer, 'big', 0)); 682 | 683 | buffer[7] = 0x80; 684 | buffer[6] = 0x10; 685 | buffer[5] = 0x00; 686 | buffer[4] = 0x00; 687 | buffer[3] = 0x00; 688 | buffer[2] = 0x00; 689 | buffer[1] = 0x00; 690 | buffer[0] = 0x00; 691 | ASSERT.equal(-2.2250738585072014e-308, 692 | mod_ctype.rdouble(buffer, 'little', 0)); 693 | 694 | /* Largest normalized value 1.7976931348623157e+308 */ 695 | buffer[0] = 0x7f; 696 | buffer[1] = 0xef; 697 | buffer[2] = 0xff; 698 | buffer[3] = 0xff; 699 | buffer[4] = 0xff; 700 | buffer[5] = 0xff; 701 | buffer[6] = 0xff; 702 | buffer[7] = 0xff; 703 | ASSERT.equal(1.7976931348623157e+308, 704 | mod_ctype.rdouble(buffer, 'big', 0)); 705 | 706 | buffer[7] = 0x7f; 707 | buffer[6] = 0xef; 708 | buffer[5] = 0xff; 709 | buffer[4] = 0xff; 710 | buffer[3] = 0xff; 711 | buffer[2] = 0xff; 712 | buffer[1] = 0xff; 713 | buffer[0] = 0xff; 714 | ASSERT.equal(1.7976931348623157e+308, 715 | mod_ctype.rdouble(buffer, 'little', 0)); 716 | 717 | buffer[0] = 0xff; 718 | buffer[1] = 0xef; 719 | buffer[2] = 0xff; 720 | buffer[3] = 0xff; 721 | buffer[4] = 0xff; 722 | buffer[5] = 0xff; 723 | buffer[6] = 0xff; 724 | buffer[7] = 0xff; 725 | ASSERT.equal(-1.7976931348623157e+308, 726 | mod_ctype.rdouble(buffer, 'big', 0)); 727 | 728 | buffer[7] = 0xff; 729 | buffer[6] = 0xef; 730 | buffer[5] = 0xff; 731 | buffer[4] = 0xff; 732 | buffer[3] = 0xff; 733 | buffer[2] = 0xff; 734 | buffer[1] = 0xff; 735 | buffer[0] = 0xff; 736 | ASSERT.equal(-1.7976931348623157e+308, 737 | mod_ctype.rdouble(buffer, 'little', 0)); 738 | 739 | /* Try offsets */ 740 | buffer[0] = 0xde; 741 | buffer[1] = 0xad; 742 | buffer[2] = 0xbe; 743 | buffer[3] = 0xef; 744 | buffer[4] = 0xba; 745 | buffer[5] = 0xdd; 746 | buffer[6] = 0xca; 747 | buffer[7] = 0xfe; 748 | buffer[8] = 0x16; 749 | buffer[9] = 0x79; 750 | 751 | ASSERT.equal(-1.1885958404126936e+148, 752 | mod_ctype.rdouble(buffer, 'big', 0)); 753 | ASSERT.equal(-2.4299184080448593e-88, 754 | mod_ctype.rdouble(buffer, 'big', 1)); 755 | ASSERT.equal(-0.000015130017658081283, 756 | mod_ctype.rdouble(buffer, 'big', 2)); 757 | 758 | ASSERT.equal(-5.757458694845505e+302, 759 | mod_ctype.rdouble(buffer, 'little', 0)); 760 | ASSERT.equal(6.436459604192476e-198, 761 | mod_ctype.rdouble(buffer, 'little', 1)); 762 | ASSERT.equal(1.9903745632417286e+275, 763 | mod_ctype.rdouble(buffer, 'little', 2)); 764 | } 765 | 766 | testfloat(); 767 | testdouble(); 768 | -------------------------------------------------------------------------------- /tst/ctio/float/tst.wfloat.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Another place to find bugs that may yet plague us. This time with writing out 3 | * floats to arrays. We are lazy and did basically just take the opposite of our 4 | * test code to read in values. 5 | */ 6 | 7 | var mod_ctype = require('../../../ctio.js'); 8 | var ASSERT = require('assert'); 9 | 10 | 11 | /* 12 | * A useful thing to keep around for debugging 13 | * console.log('buffer[0]: ' + buffer[0].toString(16)); 14 | * console.log('buffer[1]: ' + buffer[1].toString(16)); 15 | * console.log('buffer[2]: ' + buffer[2].toString(16)); 16 | * console.log('buffer[3]: ' + buffer[3].toString(16)); 17 | * console.log('buffer[4]: ' + buffer[4].toString(16)); 18 | * console.log('buffer[5]: ' + buffer[5].toString(16)); 19 | * console.log('buffer[6]: ' + buffer[6].toString(16)); 20 | * console.log('buffer[7]: ' + buffer[7].toString(16)); 21 | */ 22 | 23 | function testfloat() 24 | { 25 | var buffer = new Buffer(4); 26 | mod_ctype.wfloat(0, 'big', buffer, 0); 27 | /* Start off with some of the easy ones: +zero */ 28 | ASSERT.equal(0, buffer[0]); 29 | ASSERT.equal(0, buffer[1]); 30 | ASSERT.equal(0, buffer[2]); 31 | ASSERT.equal(0, buffer[3]); 32 | mod_ctype.wfloat(0, 'little', buffer, 0); 33 | ASSERT.equal(0, buffer[0]); 34 | ASSERT.equal(0, buffer[1]); 35 | ASSERT.equal(0, buffer[2]); 36 | ASSERT.equal(0, buffer[3]); 37 | 38 | /* Catch +infin */ 39 | mod_ctype.wfloat(Number.POSITIVE_INFINITY, 'big', buffer, 0); 40 | ASSERT.equal(0x7f, buffer[0]); 41 | ASSERT.equal(0x80, buffer[1]); 42 | ASSERT.equal(0x00, buffer[2]); 43 | ASSERT.equal(0x00, buffer[3]); 44 | mod_ctype.wfloat(Number.POSITIVE_INFINITY, 'little', buffer, 0); 45 | ASSERT.equal(0x7f, buffer[3]); 46 | ASSERT.equal(0x80, buffer[2]); 47 | ASSERT.equal(0x00, buffer[1]); 48 | ASSERT.equal(0x00, buffer[0]); 49 | 50 | /* Catch -infin */ 51 | mod_ctype.wfloat(Number.NEGATIVE_INFINITY, 'big', buffer, 0); 52 | ASSERT.equal(0xff, buffer[0]); 53 | ASSERT.equal(0x80, buffer[1]); 54 | ASSERT.equal(0x00, buffer[2]); 55 | ASSERT.equal(0x00, buffer[3]); 56 | mod_ctype.wfloat(Number.NEGATIVE_INFINITY, 'little', buffer, 0); 57 | ASSERT.equal(0xff, buffer[3]); 58 | ASSERT.equal(0x80, buffer[2]); 59 | ASSERT.equal(0x00, buffer[1]); 60 | ASSERT.equal(0x00, buffer[0]); 61 | 62 | /* Catch NaN */ 63 | 64 | /* 65 | * NaN Is a litle weird in its requirements, so we're going to encode a 66 | * bit of how we actually implement it into this test. Probably not the 67 | * best, since technically the sign is a don't care and the mantissa 68 | * needs to just be non-zero. 69 | */ 70 | mod_ctype.wfloat(NaN, 'big', buffer, 0); 71 | ASSERT.equal(0x7f, buffer[0]); 72 | ASSERT.equal(0x80, buffer[1]); 73 | ASSERT.equal(0x00, buffer[2]); 74 | ASSERT.equal(0x17, buffer[3]); 75 | mod_ctype.wfloat(NaN, 'little', buffer, 0); 76 | ASSERT.equal(0x7f, buffer[3]); 77 | ASSERT.equal(0x80, buffer[2]); 78 | ASSERT.equal(0x00, buffer[1]); 79 | ASSERT.equal(0x17, buffer[0]); 80 | 81 | /* On to some basic tests */ 82 | /* 1.125 */ 83 | mod_ctype.wfloat(1.125, 'big', buffer, 0); 84 | ASSERT.equal(0x3f, buffer[0]); 85 | ASSERT.equal(0x90, buffer[1]); 86 | ASSERT.equal(0x00, buffer[2]); 87 | ASSERT.equal(0x00, buffer[3]); 88 | mod_ctype.wfloat(1.125, 'little', buffer, 0); 89 | ASSERT.equal(0x3f, buffer[3]); 90 | ASSERT.equal(0x90, buffer[2]); 91 | ASSERT.equal(0x00, buffer[1]); 92 | ASSERT.equal(0x00, buffer[0]); 93 | 94 | mod_ctype.wfloat(1.0000001192092896, 'big', buffer, 0); 95 | ASSERT.equal(0x3f, buffer[0]); 96 | ASSERT.equal(0x80, buffer[1]); 97 | ASSERT.equal(0x00, buffer[2]); 98 | ASSERT.equal(0x01, buffer[3]); 99 | mod_ctype.wfloat(1.0000001192092896, 'little', buffer, 0); 100 | ASSERT.equal(0x3f, buffer[3]); 101 | ASSERT.equal(0x80, buffer[2]); 102 | ASSERT.equal(0x00, buffer[1]); 103 | ASSERT.equal(0x01, buffer[0]); 104 | 105 | mod_ctype.wfloat(1.0000001192092896, 'big', buffer, 0); 106 | ASSERT.equal(0x3f, buffer[0]); 107 | ASSERT.equal(0x80, buffer[1]); 108 | ASSERT.equal(0x00, buffer[2]); 109 | ASSERT.equal(0x01, buffer[3]); 110 | mod_ctype.wfloat(1.0000001192092896, 'little', buffer, 0); 111 | ASSERT.equal(0x3f, buffer[3]); 112 | ASSERT.equal(0x80, buffer[2]); 113 | ASSERT.equal(0x00, buffer[1]); 114 | ASSERT.equal(0x01, buffer[0]); 115 | 116 | mod_ctype.wfloat(2.3283067140944524e-10, 'big', buffer, 0); 117 | ASSERT.equal(0x2f, buffer[0]); 118 | ASSERT.equal(0x80, buffer[1]); 119 | ASSERT.equal(0x00, buffer[2]); 120 | ASSERT.equal(0x01, buffer[3]); 121 | mod_ctype.wfloat(2.3283067140944524e-10, 'little', buffer, 0); 122 | ASSERT.equal(0x2f, buffer[3]); 123 | ASSERT.equal(0x80, buffer[2]); 124 | ASSERT.equal(0x00, buffer[1]); 125 | ASSERT.equal(0x01, buffer[0]); 126 | 127 | /* ff34a2b0 -2.4010576103645774e+38 */ 128 | mod_ctype.wfloat(-2.4010576103645774e+38, 129 | 'big', buffer, 0); 130 | ASSERT.equal(0xff, buffer[0]); 131 | ASSERT.equal(0x34, buffer[1]); 132 | ASSERT.equal(0xa2, buffer[2]); 133 | ASSERT.equal(0xb0, buffer[3]); 134 | mod_ctype.wfloat(-2.4010576103645774e+38, 135 | 'little', buffer, 0); 136 | ASSERT.equal(0xff, buffer[3]); 137 | ASSERT.equal(0x34, buffer[2]); 138 | ASSERT.equal(0xa2, buffer[1]); 139 | ASSERT.equal(0xb0, buffer[0]); 140 | 141 | /* Denormalized tests */ 142 | 143 | /* 0003f89a +/- 3.6468792534053364e-40 */ 144 | mod_ctype.wfloat(3.6468792534053364e-40, 145 | 'big', buffer, 0); 146 | ASSERT.equal(0x00, buffer[0]); 147 | ASSERT.equal(0x03, buffer[1]); 148 | ASSERT.equal(0xf8, buffer[2]); 149 | ASSERT.equal(0x9a, buffer[3]); 150 | mod_ctype.wfloat(3.6468792534053364e-40, 151 | 'little', buffer, 0); 152 | ASSERT.equal(0x00, buffer[3]); 153 | ASSERT.equal(0x03, buffer[2]); 154 | ASSERT.equal(0xf8, buffer[1]); 155 | ASSERT.equal(0x9a, buffer[0]); 156 | 157 | mod_ctype.wfloat(-3.6468792534053364e-40, 158 | 'big', buffer, 0); 159 | ASSERT.equal(0x80, buffer[0]); 160 | ASSERT.equal(0x03, buffer[1]); 161 | ASSERT.equal(0xf8, buffer[2]); 162 | ASSERT.equal(0x9a, buffer[3]); 163 | mod_ctype.wfloat(-3.6468792534053364e-40, 164 | 'little', buffer, 0); 165 | ASSERT.equal(0x80, buffer[3]); 166 | ASSERT.equal(0x03, buffer[2]); 167 | ASSERT.equal(0xf8, buffer[1]); 168 | ASSERT.equal(0x9a, buffer[0]); 169 | 170 | /* Maximum and minimum normalized and denormalized values */ 171 | 172 | /* Largest normalized number +/- 3.4028234663852886e+38 */ 173 | 174 | mod_ctype.wfloat(3.4028234663852886e+38, 175 | 'big', buffer, 0); 176 | ASSERT.equal(0x7f, buffer[0]); 177 | ASSERT.equal(0x7f, buffer[1]); 178 | ASSERT.equal(0xff, buffer[2]); 179 | ASSERT.equal(0xff, buffer[3]); 180 | mod_ctype.wfloat(3.4028234663852886e+38, 181 | 'little', buffer, 0); 182 | ASSERT.equal(0x7f, buffer[3]); 183 | ASSERT.equal(0x7f, buffer[2]); 184 | ASSERT.equal(0xff, buffer[1]); 185 | ASSERT.equal(0xff, buffer[0]); 186 | 187 | mod_ctype.wfloat(-3.4028234663852886e+38, 188 | 'big', buffer, 0); 189 | ASSERT.equal(0xff, buffer[0]); 190 | ASSERT.equal(0x7f, buffer[1]); 191 | ASSERT.equal(0xff, buffer[2]); 192 | ASSERT.equal(0xff, buffer[3]); 193 | mod_ctype.wfloat(-3.4028234663852886e+38, 194 | 'little', buffer, 0); 195 | ASSERT.equal(0xff, buffer[3]); 196 | ASSERT.equal(0x7f, buffer[2]); 197 | ASSERT.equal(0xff, buffer[1]); 198 | ASSERT.equal(0xff, buffer[0]); 199 | 200 | /* Smallest normalied number +/- 1.1754943508222875e-38 */ 201 | 202 | mod_ctype.wfloat(1.1754943508222875e-38, 203 | 'big', buffer, 0); 204 | ASSERT.equal(0x00, buffer[0]); 205 | ASSERT.equal(0x80, buffer[1]); 206 | ASSERT.equal(0x00, buffer[2]); 207 | ASSERT.equal(0x00, buffer[3]); 208 | mod_ctype.wfloat(1.1754943508222875e-38, 209 | 'little', buffer, 0); 210 | ASSERT.equal(0x00, buffer[3]); 211 | ASSERT.equal(0x80, buffer[2]); 212 | ASSERT.equal(0x00, buffer[1]); 213 | ASSERT.equal(0x00, buffer[0]); 214 | 215 | mod_ctype.wfloat(-1.1754943508222875e-38, 216 | 'big', buffer, 0); 217 | ASSERT.equal(0x80, buffer[0]); 218 | ASSERT.equal(0x80, buffer[1]); 219 | ASSERT.equal(0x00, buffer[2]); 220 | ASSERT.equal(0x00, buffer[3]); 221 | mod_ctype.wfloat(-1.1754943508222875e-38, 222 | 'little', buffer, 0); 223 | ASSERT.equal(0x80, buffer[3]); 224 | ASSERT.equal(0x80, buffer[2]); 225 | ASSERT.equal(0x00, buffer[1]); 226 | ASSERT.equal(0x00, buffer[0]); 227 | 228 | /* Smallest denormalized number 1.401298464324817e-45 */ 229 | mod_ctype.wfloat(1.401298464324817e-45, 230 | 'big', buffer, 0); 231 | ASSERT.equal(0x00, buffer[0]); 232 | ASSERT.equal(0x00, buffer[1]); 233 | ASSERT.equal(0x00, buffer[2]); 234 | ASSERT.equal(0x01, buffer[3]); 235 | mod_ctype.wfloat(1.401298464324817e-45, 236 | 'little', buffer, 0); 237 | ASSERT.equal(0x00, buffer[3]); 238 | ASSERT.equal(0x00, buffer[2]); 239 | ASSERT.equal(0x00, buffer[1]); 240 | ASSERT.equal(0x01, buffer[0]); 241 | 242 | mod_ctype.wfloat(-1.401298464324817e-45, 243 | 'big', buffer, 0); 244 | ASSERT.equal(0x80, buffer[0]); 245 | ASSERT.equal(0x00, buffer[1]); 246 | ASSERT.equal(0x00, buffer[2]); 247 | ASSERT.equal(0x01, buffer[3]); 248 | mod_ctype.wfloat(-1.401298464324817e-45, 249 | 'little', buffer, 0); 250 | ASSERT.equal(0x80, buffer[3]); 251 | ASSERT.equal(0x00, buffer[2]); 252 | ASSERT.equal(0x00, buffer[1]); 253 | ASSERT.equal(0x01, buffer[0]); 254 | 255 | /* Largest denormalized value +/- 1.1754942106924411e-38 */ 256 | 257 | mod_ctype.wfloat(1.1754942106924411e-38, 258 | 'big', buffer, 0); 259 | ASSERT.equal(0x00, buffer[0]); 260 | ASSERT.equal(0x7f, buffer[1]); 261 | ASSERT.equal(0xff, buffer[2]); 262 | ASSERT.equal(0xff, buffer[3]); 263 | mod_ctype.wfloat(1.1754942106924411e-38, 264 | 'little', buffer, 0); 265 | ASSERT.equal(0x00, buffer[3]); 266 | ASSERT.equal(0x7f, buffer[2]); 267 | ASSERT.equal(0xff, buffer[1]); 268 | ASSERT.equal(0xff, buffer[0]); 269 | 270 | mod_ctype.wfloat(-1.1754942106924411e-38, 271 | 'big', buffer, 0); 272 | ASSERT.equal(0x80, buffer[0]); 273 | ASSERT.equal(0x7f, buffer[1]); 274 | ASSERT.equal(0xff, buffer[2]); 275 | ASSERT.equal(0xff, buffer[3]); 276 | mod_ctype.wfloat(-1.1754942106924411e-38, 277 | 'little', buffer, 0); 278 | ASSERT.equal(0x80, buffer[3]); 279 | ASSERT.equal(0x7f, buffer[2]); 280 | ASSERT.equal(0xff, buffer[1]); 281 | ASSERT.equal(0xff, buffer[0]); 282 | 283 | /* Do some quick offset testing */ 284 | buffer = new Buffer(6); 285 | mod_ctype.wfloat(-1.2027516403607578e-32, 286 | 'big', buffer, 2); 287 | ASSERT.equal(0x8a, buffer[2]); 288 | ASSERT.equal(0x79, buffer[3]); 289 | ASSERT.equal(0xcd, buffer[4]); 290 | ASSERT.equal(0x3f, buffer[5]); 291 | 292 | mod_ctype.wfloat(-1.2027516403607578e-32, 293 | 'little', buffer, 2); 294 | ASSERT.equal(0x8a, buffer[5]); 295 | ASSERT.equal(0x79, buffer[4]); 296 | ASSERT.equal(0xcd, buffer[3]); 297 | ASSERT.equal(0x3f, buffer[2]); 298 | 299 | } 300 | 301 | function testdouble() 302 | { 303 | var buffer = new Buffer(10); 304 | 305 | /* Check 0 */ 306 | mod_ctype.wdouble(0, 'big', buffer, 0); 307 | ASSERT.equal(0x00, buffer[0]); 308 | ASSERT.equal(0x00, buffer[1]); 309 | ASSERT.equal(0x00, buffer[2]); 310 | ASSERT.equal(0x00, buffer[3]); 311 | ASSERT.equal(0x00, buffer[4]); 312 | ASSERT.equal(0x00, buffer[5]); 313 | ASSERT.equal(0x00, buffer[6]); 314 | ASSERT.equal(0x00, buffer[7]); 315 | mod_ctype.wdouble(0, 'little', buffer, 0); 316 | ASSERT.equal(0x00, buffer[7]); 317 | ASSERT.equal(0x00, buffer[6]); 318 | ASSERT.equal(0x00, buffer[5]); 319 | ASSERT.equal(0x00, buffer[4]); 320 | ASSERT.equal(0x00, buffer[3]); 321 | ASSERT.equal(0x00, buffer[2]); 322 | ASSERT.equal(0x00, buffer[1]); 323 | ASSERT.equal(0x00, buffer[0]); 324 | 325 | /* Check NaN */ 326 | /* Similar to floats we are only generating a subset of values */ 327 | mod_ctype.wdouble(NaN, 'big', buffer, 0); 328 | ASSERT.equal(0x7f, buffer[0]); 329 | ASSERT.equal(0xf0, buffer[1]); 330 | ASSERT.equal(0x00, buffer[2]); 331 | ASSERT.equal(0x00, buffer[3]); 332 | ASSERT.equal(0x00, buffer[4]); 333 | ASSERT.equal(0x00, buffer[5]); 334 | ASSERT.equal(0x00, buffer[6]); 335 | ASSERT.equal(0x17, buffer[7]); 336 | mod_ctype.wdouble(NaN, 'little', buffer, 0); 337 | ASSERT.equal(0x7f, buffer[7]); 338 | ASSERT.equal(0xf0, buffer[6]); 339 | ASSERT.equal(0x00, buffer[5]); 340 | ASSERT.equal(0x00, buffer[4]); 341 | ASSERT.equal(0x00, buffer[3]); 342 | ASSERT.equal(0x00, buffer[2]); 343 | ASSERT.equal(0x00, buffer[1]); 344 | ASSERT.equal(0x17, buffer[0]); 345 | 346 | /* pos inf */ 347 | mod_ctype.wdouble(Number.POSITIVE_INFINITY, 348 | 'big', buffer, 0); 349 | ASSERT.equal(0x7f, buffer[0]); 350 | ASSERT.equal(0xf0, buffer[1]); 351 | ASSERT.equal(0x00, buffer[2]); 352 | ASSERT.equal(0x00, buffer[3]); 353 | ASSERT.equal(0x00, buffer[4]); 354 | ASSERT.equal(0x00, buffer[5]); 355 | ASSERT.equal(0x00, buffer[6]); 356 | ASSERT.equal(0x00, buffer[7]); 357 | mod_ctype.wdouble(Number.POSITIVE_INFINITY, 358 | 'little', buffer, 0); 359 | ASSERT.equal(0x7f, buffer[7]); 360 | ASSERT.equal(0xf0, buffer[6]); 361 | ASSERT.equal(0x00, buffer[5]); 362 | ASSERT.equal(0x00, buffer[4]); 363 | ASSERT.equal(0x00, buffer[3]); 364 | ASSERT.equal(0x00, buffer[2]); 365 | ASSERT.equal(0x00, buffer[1]); 366 | ASSERT.equal(0x00, buffer[0]); 367 | 368 | /* neg inf */ 369 | mod_ctype.wdouble(Number.NEGATIVE_INFINITY, 370 | 'big', buffer, 0); 371 | ASSERT.equal(0xff, buffer[0]); 372 | ASSERT.equal(0xf0, buffer[1]); 373 | ASSERT.equal(0x00, buffer[2]); 374 | ASSERT.equal(0x00, buffer[3]); 375 | ASSERT.equal(0x00, buffer[4]); 376 | ASSERT.equal(0x00, buffer[5]); 377 | ASSERT.equal(0x00, buffer[6]); 378 | ASSERT.equal(0x00, buffer[7]); 379 | mod_ctype.wdouble(Number.NEGATIVE_INFINITY, 380 | 'little', buffer, 0); 381 | ASSERT.equal(0xff, buffer[7]); 382 | ASSERT.equal(0xf0, buffer[6]); 383 | ASSERT.equal(0x00, buffer[5]); 384 | ASSERT.equal(0x00, buffer[4]); 385 | ASSERT.equal(0x00, buffer[3]); 386 | ASSERT.equal(0x00, buffer[2]); 387 | ASSERT.equal(0x00, buffer[1]); 388 | ASSERT.equal(0x00, buffer[0]); 389 | 390 | /* Simple normalized values */ 391 | 392 | /* +/- 1.125 */ 393 | mod_ctype.wdouble(1.125, 394 | 'big', buffer, 0); 395 | ASSERT.equal(0x3f, buffer[0]); 396 | ASSERT.equal(0xf2, buffer[1]); 397 | ASSERT.equal(0x00, buffer[2]); 398 | ASSERT.equal(0x00, buffer[3]); 399 | ASSERT.equal(0x00, buffer[4]); 400 | ASSERT.equal(0x00, buffer[5]); 401 | ASSERT.equal(0x00, buffer[6]); 402 | ASSERT.equal(0x00, buffer[7]); 403 | 404 | mod_ctype.wdouble(1.125, 405 | 'little', buffer, 0); 406 | ASSERT.equal(0x3f, buffer[7]); 407 | ASSERT.equal(0xf2, buffer[6]); 408 | ASSERT.equal(0x00, buffer[5]); 409 | ASSERT.equal(0x00, buffer[4]); 410 | ASSERT.equal(0x00, buffer[3]); 411 | ASSERT.equal(0x00, buffer[2]); 412 | ASSERT.equal(0x00, buffer[1]); 413 | ASSERT.equal(0x00, buffer[0]); 414 | 415 | mod_ctype.wdouble(-1.125, 416 | 'big', buffer, 0); 417 | ASSERT.equal(0xbf, buffer[0]); 418 | ASSERT.equal(0xf2, buffer[1]); 419 | ASSERT.equal(0x00, buffer[2]); 420 | ASSERT.equal(0x00, buffer[3]); 421 | ASSERT.equal(0x00, buffer[4]); 422 | ASSERT.equal(0x00, buffer[5]); 423 | ASSERT.equal(0x00, buffer[6]); 424 | ASSERT.equal(0x00, buffer[7]); 425 | 426 | mod_ctype.wdouble(-1.125, 427 | 'little', buffer, 0); 428 | ASSERT.equal(0xbf, buffer[7]); 429 | ASSERT.equal(0xf2, buffer[6]); 430 | ASSERT.equal(0x00, buffer[5]); 431 | ASSERT.equal(0x00, buffer[4]); 432 | ASSERT.equal(0x00, buffer[3]); 433 | ASSERT.equal(0x00, buffer[2]); 434 | ASSERT.equal(0x00, buffer[1]); 435 | ASSERT.equal(0x00, buffer[0]); 436 | 437 | 438 | /* +/- 1.4397318913736026e+283 */ 439 | mod_ctype.wdouble(1.4397318913736026e+283, 440 | 'big', buffer, 0); 441 | ASSERT.equal(0x7a, buffer[0]); 442 | ASSERT.equal(0xb8, buffer[1]); 443 | ASSERT.equal(0xc9, buffer[2]); 444 | ASSERT.equal(0x34, buffer[3]); 445 | ASSERT.equal(0x72, buffer[4]); 446 | ASSERT.equal(0x16, buffer[5]); 447 | ASSERT.equal(0xf9, buffer[6]); 448 | ASSERT.equal(0x0e, buffer[7]); 449 | 450 | mod_ctype.wdouble(1.4397318913736026e+283, 451 | 'little', buffer, 0); 452 | ASSERT.equal(0x7a, buffer[7]); 453 | ASSERT.equal(0xb8, buffer[6]); 454 | ASSERT.equal(0xc9, buffer[5]); 455 | ASSERT.equal(0x34, buffer[4]); 456 | ASSERT.equal(0x72, buffer[3]); 457 | ASSERT.equal(0x16, buffer[2]); 458 | ASSERT.equal(0xf9, buffer[1]); 459 | ASSERT.equal(0x0e, buffer[0]); 460 | 461 | mod_ctype.wdouble(-1.4397318913736026e+283, 462 | 'big', buffer, 0); 463 | ASSERT.equal(0xfa, buffer[0]); 464 | ASSERT.equal(0xb8, buffer[1]); 465 | ASSERT.equal(0xc9, buffer[2]); 466 | ASSERT.equal(0x34, buffer[3]); 467 | ASSERT.equal(0x72, buffer[4]); 468 | ASSERT.equal(0x16, buffer[5]); 469 | ASSERT.equal(0xf9, buffer[6]); 470 | ASSERT.equal(0x0e, buffer[7]); 471 | 472 | mod_ctype.wdouble(-1.4397318913736026e+283, 473 | 'little', buffer, 0); 474 | ASSERT.equal(0xfa, buffer[7]); 475 | ASSERT.equal(0xb8, buffer[6]); 476 | ASSERT.equal(0xc9, buffer[5]); 477 | ASSERT.equal(0x34, buffer[4]); 478 | ASSERT.equal(0x72, buffer[3]); 479 | ASSERT.equal(0x16, buffer[2]); 480 | ASSERT.equal(0xf9, buffer[1]); 481 | ASSERT.equal(0x0e, buffer[0]); 482 | 483 | /* Denormalized values */ 484 | /* +/- 8.82521232268344e-309 */ 485 | mod_ctype.wdouble(8.82521232268344e-309, 486 | 'big', buffer, 0); 487 | ASSERT.equal(0x00, buffer[0]); 488 | ASSERT.equal(0x06, buffer[1]); 489 | ASSERT.equal(0x58, buffer[2]); 490 | ASSERT.equal(0x94, buffer[3]); 491 | ASSERT.equal(0x13, buffer[4]); 492 | ASSERT.equal(0x27, buffer[5]); 493 | ASSERT.equal(0x8a, buffer[6]); 494 | ASSERT.equal(0xcd, buffer[7]); 495 | 496 | mod_ctype.wdouble(8.82521232268344e-309, 497 | 'little', buffer, 0); 498 | ASSERT.equal(0x00, buffer[7]); 499 | ASSERT.equal(0x06, buffer[6]); 500 | ASSERT.equal(0x58, buffer[5]); 501 | ASSERT.equal(0x94, buffer[4]); 502 | ASSERT.equal(0x13, buffer[3]); 503 | ASSERT.equal(0x27, buffer[2]); 504 | ASSERT.equal(0x8a, buffer[1]); 505 | ASSERT.equal(0xcd, buffer[0]); 506 | 507 | mod_ctype.wdouble(-8.82521232268344e-309, 508 | 'big', buffer, 0); 509 | ASSERT.equal(0x80, buffer[0]); 510 | ASSERT.equal(0x06, buffer[1]); 511 | ASSERT.equal(0x58, buffer[2]); 512 | ASSERT.equal(0x94, buffer[3]); 513 | ASSERT.equal(0x13, buffer[4]); 514 | ASSERT.equal(0x27, buffer[5]); 515 | ASSERT.equal(0x8a, buffer[6]); 516 | ASSERT.equal(0xcd, buffer[7]); 517 | 518 | mod_ctype.wdouble(-8.82521232268344e-309, 519 | 'little', buffer, 0); 520 | ASSERT.equal(0x80, buffer[7]); 521 | ASSERT.equal(0x06, buffer[6]); 522 | ASSERT.equal(0x58, buffer[5]); 523 | ASSERT.equal(0x94, buffer[4]); 524 | ASSERT.equal(0x13, buffer[3]); 525 | ASSERT.equal(0x27, buffer[2]); 526 | ASSERT.equal(0x8a, buffer[1]); 527 | ASSERT.equal(0xcd, buffer[0]); 528 | 529 | 530 | /* Edge cases, maximum and minimum values */ 531 | 532 | /* Smallest denormalized value 5e-324 */ 533 | mod_ctype.wdouble(5e-324, 534 | 'big', buffer, 0); 535 | ASSERT.equal(0x00, buffer[0]); 536 | ASSERT.equal(0x00, buffer[1]); 537 | ASSERT.equal(0x00, buffer[2]); 538 | ASSERT.equal(0x00, buffer[3]); 539 | ASSERT.equal(0x00, buffer[4]); 540 | ASSERT.equal(0x00, buffer[5]); 541 | ASSERT.equal(0x00, buffer[6]); 542 | ASSERT.equal(0x01, buffer[7]); 543 | 544 | mod_ctype.wdouble(5e-324, 545 | 'little', buffer, 0); 546 | ASSERT.equal(0x00, buffer[7]); 547 | ASSERT.equal(0x00, buffer[6]); 548 | ASSERT.equal(0x00, buffer[5]); 549 | ASSERT.equal(0x00, buffer[4]); 550 | ASSERT.equal(0x00, buffer[3]); 551 | ASSERT.equal(0x00, buffer[2]); 552 | ASSERT.equal(0x00, buffer[1]); 553 | ASSERT.equal(0x01, buffer[0]); 554 | 555 | mod_ctype.wdouble(-5e-324, 556 | 'big', buffer, 0); 557 | ASSERT.equal(0x80, buffer[0]); 558 | ASSERT.equal(0x00, buffer[1]); 559 | ASSERT.equal(0x00, buffer[2]); 560 | ASSERT.equal(0x00, buffer[3]); 561 | ASSERT.equal(0x00, buffer[4]); 562 | ASSERT.equal(0x00, buffer[5]); 563 | ASSERT.equal(0x00, buffer[6]); 564 | ASSERT.equal(0x01, buffer[7]); 565 | 566 | mod_ctype.wdouble(-5e-324, 567 | 'little', buffer, 0); 568 | ASSERT.equal(0x80, buffer[7]); 569 | ASSERT.equal(0x00, buffer[6]); 570 | ASSERT.equal(0x00, buffer[5]); 571 | ASSERT.equal(0x00, buffer[4]); 572 | ASSERT.equal(0x00, buffer[3]); 573 | ASSERT.equal(0x00, buffer[2]); 574 | ASSERT.equal(0x00, buffer[1]); 575 | ASSERT.equal(0x01, buffer[0]); 576 | 577 | 578 | 579 | /* Largest denormalized value 2.225073858507201e-308 */ 580 | mod_ctype.wdouble(2.225073858507201e-308, 581 | 'big', buffer, 0); 582 | ASSERT.equal(0x00, buffer[0]); 583 | ASSERT.equal(0x0f, buffer[1]); 584 | ASSERT.equal(0xff, buffer[2]); 585 | ASSERT.equal(0xff, buffer[3]); 586 | ASSERT.equal(0xff, buffer[4]); 587 | ASSERT.equal(0xff, buffer[5]); 588 | ASSERT.equal(0xff, buffer[6]); 589 | ASSERT.equal(0xff, buffer[7]); 590 | 591 | mod_ctype.wdouble(2.225073858507201e-308, 592 | 'little', buffer, 0); 593 | ASSERT.equal(0x00, buffer[7]); 594 | ASSERT.equal(0x0f, buffer[6]); 595 | ASSERT.equal(0xff, buffer[5]); 596 | ASSERT.equal(0xff, buffer[4]); 597 | ASSERT.equal(0xff, buffer[3]); 598 | ASSERT.equal(0xff, buffer[2]); 599 | ASSERT.equal(0xff, buffer[1]); 600 | ASSERT.equal(0xff, buffer[0]); 601 | 602 | mod_ctype.wdouble(-2.225073858507201e-308, 603 | 'big', buffer, 0); 604 | ASSERT.equal(0x80, buffer[0]); 605 | ASSERT.equal(0x0f, buffer[1]); 606 | ASSERT.equal(0xff, buffer[2]); 607 | ASSERT.equal(0xff, buffer[3]); 608 | ASSERT.equal(0xff, buffer[4]); 609 | ASSERT.equal(0xff, buffer[5]); 610 | ASSERT.equal(0xff, buffer[6]); 611 | ASSERT.equal(0xff, buffer[7]); 612 | 613 | mod_ctype.wdouble(-2.225073858507201e-308, 614 | 'little', buffer, 0); 615 | ASSERT.equal(0x80, buffer[7]); 616 | ASSERT.equal(0x0f, buffer[6]); 617 | ASSERT.equal(0xff, buffer[5]); 618 | ASSERT.equal(0xff, buffer[4]); 619 | ASSERT.equal(0xff, buffer[3]); 620 | ASSERT.equal(0xff, buffer[2]); 621 | ASSERT.equal(0xff, buffer[1]); 622 | ASSERT.equal(0xff, buffer[0]); 623 | 624 | 625 | /* Smallest normalized value 2.2250738585072014e-308 */ 626 | mod_ctype.wdouble(2.2250738585072014e-308, 627 | 'big', buffer, 0); 628 | ASSERT.equal(0x00, buffer[0]); 629 | ASSERT.equal(0x10, buffer[1]); 630 | ASSERT.equal(0x00, buffer[2]); 631 | ASSERT.equal(0x00, buffer[3]); 632 | ASSERT.equal(0x00, buffer[4]); 633 | ASSERT.equal(0x00, buffer[5]); 634 | ASSERT.equal(0x00, buffer[6]); 635 | ASSERT.equal(0x00, buffer[7]); 636 | 637 | mod_ctype.wdouble(2.2250738585072014e-308, 638 | 'little', buffer, 0); 639 | ASSERT.equal(0x00, buffer[7]); 640 | ASSERT.equal(0x10, buffer[6]); 641 | ASSERT.equal(0x00, buffer[5]); 642 | ASSERT.equal(0x00, buffer[4]); 643 | ASSERT.equal(0x00, buffer[3]); 644 | ASSERT.equal(0x00, buffer[2]); 645 | ASSERT.equal(0x00, buffer[1]); 646 | ASSERT.equal(0x00, buffer[0]); 647 | 648 | mod_ctype.wdouble(-2.2250738585072014e-308, 649 | 'big', buffer, 0); 650 | ASSERT.equal(0x80, buffer[0]); 651 | ASSERT.equal(0x10, buffer[1]); 652 | ASSERT.equal(0x00, buffer[2]); 653 | ASSERT.equal(0x00, buffer[3]); 654 | ASSERT.equal(0x00, buffer[4]); 655 | ASSERT.equal(0x00, buffer[5]); 656 | ASSERT.equal(0x00, buffer[6]); 657 | ASSERT.equal(0x00, buffer[7]); 658 | 659 | mod_ctype.wdouble(-2.2250738585072014e-308, 660 | 'little', buffer, 0); 661 | ASSERT.equal(0x80, buffer[7]); 662 | ASSERT.equal(0x10, buffer[6]); 663 | ASSERT.equal(0x00, buffer[5]); 664 | ASSERT.equal(0x00, buffer[4]); 665 | ASSERT.equal(0x00, buffer[3]); 666 | ASSERT.equal(0x00, buffer[2]); 667 | ASSERT.equal(0x00, buffer[1]); 668 | ASSERT.equal(0x00, buffer[0]); 669 | 670 | 671 | /* Largest normalized value 1.7976931348623157e+308 */ 672 | mod_ctype.wdouble(1.7976931348623157e+308, 673 | 'big', buffer, 0); 674 | ASSERT.equal(0x7f, buffer[0]); 675 | ASSERT.equal(0xef, buffer[1]); 676 | ASSERT.equal(0xff, buffer[2]); 677 | ASSERT.equal(0xff, buffer[3]); 678 | ASSERT.equal(0xff, buffer[4]); 679 | ASSERT.equal(0xff, buffer[5]); 680 | ASSERT.equal(0xff, buffer[6]); 681 | ASSERT.equal(0xff, buffer[7]); 682 | 683 | mod_ctype.wdouble(1.7976931348623157e+308, 684 | 'little', buffer, 0); 685 | ASSERT.equal(0x7f, buffer[7]); 686 | ASSERT.equal(0xef, buffer[6]); 687 | ASSERT.equal(0xff, buffer[5]); 688 | ASSERT.equal(0xff, buffer[4]); 689 | ASSERT.equal(0xff, buffer[3]); 690 | ASSERT.equal(0xff, buffer[2]); 691 | ASSERT.equal(0xff, buffer[1]); 692 | ASSERT.equal(0xff, buffer[0]); 693 | 694 | mod_ctype.wdouble(-1.7976931348623157e+308, 695 | 'big', buffer, 0); 696 | ASSERT.equal(0xff, buffer[0]); 697 | ASSERT.equal(0xef, buffer[1]); 698 | ASSERT.equal(0xff, buffer[2]); 699 | ASSERT.equal(0xff, buffer[3]); 700 | ASSERT.equal(0xff, buffer[4]); 701 | ASSERT.equal(0xff, buffer[5]); 702 | ASSERT.equal(0xff, buffer[6]); 703 | ASSERT.equal(0xff, buffer[7]); 704 | 705 | mod_ctype.wdouble(-1.7976931348623157e+308, 706 | 'little', buffer, 0); 707 | ASSERT.equal(0xff, buffer[7]); 708 | ASSERT.equal(0xef, buffer[6]); 709 | ASSERT.equal(0xff, buffer[5]); 710 | ASSERT.equal(0xff, buffer[4]); 711 | ASSERT.equal(0xff, buffer[3]); 712 | ASSERT.equal(0xff, buffer[2]); 713 | ASSERT.equal(0xff, buffer[1]); 714 | ASSERT.equal(0xff, buffer[0]); 715 | 716 | 717 | /* Try offsets */ 718 | buffer[0] = 0xde; 719 | buffer[1] = 0xad; 720 | buffer[2] = 0xbe; 721 | buffer[3] = 0xef; 722 | buffer[4] = 0xba; 723 | buffer[5] = 0xdd; 724 | buffer[6] = 0xca; 725 | buffer[7] = 0xfe; 726 | buffer[8] = 0x16; 727 | buffer[9] = 0x79; 728 | 729 | mod_ctype.wdouble(-0.000015130017658081283, 730 | 'big', buffer, 2); 731 | ASSERT.equal(0xbe, buffer[2]); 732 | ASSERT.equal(0xef, buffer[3]); 733 | ASSERT.equal(0xba, buffer[4]); 734 | ASSERT.equal(0xdd, buffer[5]); 735 | ASSERT.equal(0xca, buffer[6]); 736 | ASSERT.equal(0xfe, buffer[7]); 737 | ASSERT.equal(0x16, buffer[8]); 738 | ASSERT.equal(0x79, buffer[9]); 739 | 740 | mod_ctype.wdouble(-0.000015130017658081283, 741 | 'little', buffer, 2); 742 | ASSERT.equal(0xbe, buffer[9]); 743 | ASSERT.equal(0xef, buffer[8]); 744 | ASSERT.equal(0xba, buffer[7]); 745 | ASSERT.equal(0xdd, buffer[6]); 746 | ASSERT.equal(0xca, buffer[5]); 747 | ASSERT.equal(0xfe, buffer[4]); 748 | ASSERT.equal(0x16, buffer[3]); 749 | ASSERT.equal(0x79, buffer[2]); 750 | } 751 | 752 | testfloat(); 753 | testdouble(); 754 | -------------------------------------------------------------------------------- /tst/ctio/int/tst.64.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Test our ability to read and write signed 64-bit integers. 3 | */ 4 | 5 | var mod_ctype = require('../../../ctio.js'); 6 | var ASSERT = require('assert'); 7 | 8 | function testRead() 9 | { 10 | var res, data; 11 | data = new Buffer(10); 12 | 13 | data[0] = 0x32; 14 | data[1] = 0x65; 15 | data[2] = 0x42; 16 | data[3] = 0x56; 17 | data[4] = 0x23; 18 | data[5] = 0xff; 19 | data[6] = 0xff; 20 | data[7] = 0xff; 21 | data[8] = 0x89; 22 | data[9] = 0x11; 23 | res = mod_ctype.rsint64(data, 'big', 0); 24 | ASSERT.equal(0x32654256, res[0]); 25 | ASSERT.equal(0x23ffffff, res[1]); 26 | res = mod_ctype.rsint64(data, 'big', 1); 27 | ASSERT.equal(0x65425623, res[0]); 28 | ASSERT.equal(0xffffff89, res[1]); 29 | res = mod_ctype.rsint64(data, 'big', 2); 30 | ASSERT.equal(0x425623ff, res[0]); 31 | ASSERT.equal(0xffff8911, res[1]); 32 | res = mod_ctype.rsint64(data, 'little', 0); 33 | ASSERT.equal(-0x000000dc, res[0]); 34 | ASSERT.equal(-0xa9bd9ace, res[1]); 35 | res = mod_ctype.rsint64(data, 'little', 1); 36 | ASSERT.equal(-0x76000000, res[0]); 37 | ASSERT.equal(-0xdca9bd9b, res[1]); 38 | res = mod_ctype.rsint64(data, 'little', 2); 39 | ASSERT.equal(0x1189ffff, res[0]); 40 | ASSERT.equal(0xff235642, res[1]); 41 | 42 | data.fill(0x00); 43 | res = mod_ctype.rsint64(data, 'big', 0); 44 | ASSERT.equal(0x00000000, res[0]); 45 | ASSERT.equal(0x00000000, res[1]); 46 | res = mod_ctype.rsint64(data, 'big', 1); 47 | ASSERT.equal(0x00000000, res[0]); 48 | ASSERT.equal(0x00000000, res[1]); 49 | res = mod_ctype.rsint64(data, 'big', 2); 50 | ASSERT.equal(0x00000000, res[0]); 51 | ASSERT.equal(0x00000000, res[1]); 52 | res = mod_ctype.rsint64(data, 'little', 0); 53 | ASSERT.equal(0x00000000, res[0]); 54 | ASSERT.equal(0x00000000, res[1]); 55 | res = mod_ctype.rsint64(data, 'little', 1); 56 | ASSERT.equal(0x00000000, res[0]); 57 | ASSERT.equal(0x00000000, res[1]); 58 | res = mod_ctype.rsint64(data, 'little', 2); 59 | ASSERT.equal(0x00000000, res[0]); 60 | ASSERT.equal(0x00000000, res[1]); 61 | 62 | data.fill(0xff); 63 | res = mod_ctype.rsint64(data, 'big', 0); 64 | ASSERT.equal(0x00000000, res[0]); 65 | ASSERT.equal(-1, res[1]); 66 | res = mod_ctype.rsint64(data, 'big', 1); 67 | ASSERT.equal(0x00000000, res[0]); 68 | ASSERT.equal(-1, res[1]); 69 | res = mod_ctype.rsint64(data, 'big', 2); 70 | ASSERT.equal(0x00000000, res[0]); 71 | ASSERT.equal(-1, res[1]); 72 | res = mod_ctype.rsint64(data, 'little', 0); 73 | ASSERT.equal(0x00000000, res[0]); 74 | ASSERT.equal(-1, res[1]); 75 | res = mod_ctype.rsint64(data, 'little', 1); 76 | ASSERT.equal(0x00000000, res[0]); 77 | ASSERT.equal(-1, res[1]); 78 | res = mod_ctype.rsint64(data, 'little', 2); 79 | ASSERT.equal(0x00000000, res[0]); 80 | ASSERT.equal(-1, res[1]); 81 | 82 | data[0] = 0x80; 83 | data[1] = 0x00; 84 | data[2] = 0x00; 85 | data[3] = 0x00; 86 | data[4] = 0x00; 87 | data[5] = 0x00; 88 | data[6] = 0x00; 89 | data[7] = 0x00; 90 | res = mod_ctype.rsint64(data, 'big', 0); 91 | ASSERT.equal(-0x80000000, res[0]); 92 | ASSERT.equal(0, res[1]); 93 | 94 | 95 | data[7] = 0x80; 96 | data[6] = 0x00; 97 | data[5] = 0x00; 98 | data[4] = 0x00; 99 | data[3] = 0x00; 100 | data[2] = 0x00; 101 | data[1] = 0x00; 102 | data[0] = 0x00; 103 | res = mod_ctype.rsint64(data, 'little', 0); 104 | ASSERT.equal(-0x80000000, res[0]); 105 | ASSERT.equal(0, res[1]); 106 | 107 | data[0] = 0x80; 108 | data[1] = 0x00; 109 | data[2] = 0x00; 110 | data[3] = 0x00; 111 | data[4] = 0x00; 112 | data[5] = 0x00; 113 | data[6] = 0x00; 114 | data[7] = 0x01; 115 | res = mod_ctype.rsint64(data, 'big', 0); 116 | ASSERT.equal(-0x7fffffff, res[0]); 117 | ASSERT.equal(-0xffffffff, res[1]); 118 | 119 | 120 | } 121 | 122 | function testWriteZero() 123 | { 124 | var data, buf; 125 | buf = new Buffer(10); 126 | 127 | buf.fill(0x66); 128 | data = [0, 0]; 129 | mod_ctype.wsint64(data, 'big', buf, 0); 130 | ASSERT.equal(0, buf[0]); 131 | ASSERT.equal(0, buf[1]); 132 | ASSERT.equal(0, buf[2]); 133 | ASSERT.equal(0, buf[3]); 134 | ASSERT.equal(0, buf[4]); 135 | ASSERT.equal(0, buf[5]); 136 | ASSERT.equal(0, buf[6]); 137 | ASSERT.equal(0, buf[7]); 138 | ASSERT.equal(0x66, buf[8]); 139 | ASSERT.equal(0x66, buf[9]); 140 | 141 | buf.fill(0x66); 142 | data = [0, 0]; 143 | mod_ctype.wsint64(data, 'big', buf, 1); 144 | ASSERT.equal(0x66, buf[0]); 145 | ASSERT.equal(0, buf[1]); 146 | ASSERT.equal(0, buf[2]); 147 | ASSERT.equal(0, buf[3]); 148 | ASSERT.equal(0, buf[4]); 149 | ASSERT.equal(0, buf[5]); 150 | ASSERT.equal(0, buf[6]); 151 | ASSERT.equal(0, buf[7]); 152 | ASSERT.equal(0, buf[8]); 153 | ASSERT.equal(0x66, buf[9]); 154 | 155 | buf.fill(0x66); 156 | data = [0, 0]; 157 | mod_ctype.wsint64(data, 'big', buf, 2); 158 | ASSERT.equal(0x66, buf[0]); 159 | ASSERT.equal(0x66, buf[1]); 160 | ASSERT.equal(0, buf[2]); 161 | ASSERT.equal(0, buf[3]); 162 | ASSERT.equal(0, buf[4]); 163 | ASSERT.equal(0, buf[5]); 164 | ASSERT.equal(0, buf[6]); 165 | ASSERT.equal(0, buf[7]); 166 | ASSERT.equal(0, buf[8]); 167 | ASSERT.equal(0, buf[9]); 168 | 169 | 170 | buf.fill(0x66); 171 | data = [0, 0]; 172 | mod_ctype.wsint64(data, 'little', buf, 0); 173 | ASSERT.equal(0, buf[0]); 174 | ASSERT.equal(0, buf[1]); 175 | ASSERT.equal(0, buf[2]); 176 | ASSERT.equal(0, buf[3]); 177 | ASSERT.equal(0, buf[4]); 178 | ASSERT.equal(0, buf[5]); 179 | ASSERT.equal(0, buf[6]); 180 | ASSERT.equal(0, buf[7]); 181 | ASSERT.equal(0x66, buf[8]); 182 | ASSERT.equal(0x66, buf[9]); 183 | 184 | buf.fill(0x66); 185 | data = [0, 0]; 186 | mod_ctype.wsint64(data, 'little', buf, 1); 187 | ASSERT.equal(0x66, buf[0]); 188 | ASSERT.equal(0, buf[1]); 189 | ASSERT.equal(0, buf[2]); 190 | ASSERT.equal(0, buf[3]); 191 | ASSERT.equal(0, buf[4]); 192 | ASSERT.equal(0, buf[5]); 193 | ASSERT.equal(0, buf[6]); 194 | ASSERT.equal(0, buf[7]); 195 | ASSERT.equal(0, buf[8]); 196 | ASSERT.equal(0x66, buf[9]); 197 | 198 | buf.fill(0x66); 199 | data = [0, 0]; 200 | mod_ctype.wsint64(data, 'little', buf, 2); 201 | ASSERT.equal(0x66, buf[0]); 202 | ASSERT.equal(0x66, buf[1]); 203 | ASSERT.equal(0, buf[2]); 204 | ASSERT.equal(0, buf[3]); 205 | ASSERT.equal(0, buf[4]); 206 | ASSERT.equal(0, buf[5]); 207 | ASSERT.equal(0, buf[6]); 208 | ASSERT.equal(0, buf[7]); 209 | ASSERT.equal(0, buf[8]); 210 | ASSERT.equal(0, buf[9]); 211 | } 212 | 213 | /* 214 | * Also include tests that are going to force us to go into a negative value and 215 | * insure that it's written correctly. 216 | */ 217 | function testWrite() 218 | { 219 | var data, buf; 220 | 221 | buf = new Buffer(10); 222 | data = [ 0x234456, 0x87 ]; 223 | buf.fill(0x66); 224 | mod_ctype.wsint64(data, 'big', buf, 0); 225 | ASSERT.equal(0x00, buf[0]); 226 | ASSERT.equal(0x23, buf[1]); 227 | ASSERT.equal(0x44, buf[2]); 228 | ASSERT.equal(0x56, buf[3]); 229 | ASSERT.equal(0x00, buf[4]); 230 | ASSERT.equal(0x00, buf[5]); 231 | ASSERT.equal(0x00, buf[6]); 232 | ASSERT.equal(0x87, buf[7]); 233 | ASSERT.equal(0x66, buf[8]); 234 | ASSERT.equal(0x66, buf[9]); 235 | 236 | buf.fill(0x66); 237 | mod_ctype.wsint64(data, 'big', buf, 1); 238 | ASSERT.equal(0x66, buf[0]); 239 | ASSERT.equal(0x00, buf[1]); 240 | ASSERT.equal(0x23, buf[2]); 241 | ASSERT.equal(0x44, buf[3]); 242 | ASSERT.equal(0x56, buf[4]); 243 | ASSERT.equal(0x00, buf[5]); 244 | ASSERT.equal(0x00, buf[6]); 245 | ASSERT.equal(0x00, buf[7]); 246 | ASSERT.equal(0x87, buf[8]); 247 | ASSERT.equal(0x66, buf[9]); 248 | 249 | buf.fill(0x66); 250 | mod_ctype.wsint64(data, 'big', buf, 2); 251 | ASSERT.equal(0x66, buf[0]); 252 | ASSERT.equal(0x66, buf[1]); 253 | ASSERT.equal(0x00, buf[2]); 254 | ASSERT.equal(0x23, buf[3]); 255 | ASSERT.equal(0x44, buf[4]); 256 | ASSERT.equal(0x56, buf[5]); 257 | ASSERT.equal(0x00, buf[6]); 258 | ASSERT.equal(0x00, buf[7]); 259 | ASSERT.equal(0x00, buf[8]); 260 | ASSERT.equal(0x87, buf[9]); 261 | 262 | buf.fill(0x66); 263 | mod_ctype.wsint64(data, 'little', buf, 0); 264 | ASSERT.equal(0x87, buf[0]); 265 | ASSERT.equal(0x00, buf[1]); 266 | ASSERT.equal(0x00, buf[2]); 267 | ASSERT.equal(0x00, buf[3]); 268 | ASSERT.equal(0x56, buf[4]); 269 | ASSERT.equal(0x44, buf[5]); 270 | ASSERT.equal(0x23, buf[6]); 271 | ASSERT.equal(0x00, buf[7]); 272 | ASSERT.equal(0x66, buf[8]); 273 | ASSERT.equal(0x66, buf[9]); 274 | 275 | buf.fill(0x66); 276 | mod_ctype.wsint64(data, 'little', buf, 1); 277 | ASSERT.equal(0x66, buf[0]); 278 | ASSERT.equal(0x87, buf[1]); 279 | ASSERT.equal(0x00, buf[2]); 280 | ASSERT.equal(0x00, buf[3]); 281 | ASSERT.equal(0x00, buf[4]); 282 | ASSERT.equal(0x56, buf[5]); 283 | ASSERT.equal(0x44, buf[6]); 284 | ASSERT.equal(0x23, buf[7]); 285 | ASSERT.equal(0x00, buf[8]); 286 | ASSERT.equal(0x66, buf[9]); 287 | 288 | 289 | buf.fill(0x66); 290 | mod_ctype.wsint64(data, 'little', buf, 2); 291 | ASSERT.equal(0x66, buf[0]); 292 | ASSERT.equal(0x66, buf[1]); 293 | ASSERT.equal(0x87, buf[2]); 294 | ASSERT.equal(0x00, buf[3]); 295 | ASSERT.equal(0x00, buf[4]); 296 | ASSERT.equal(0x00, buf[5]); 297 | ASSERT.equal(0x56, buf[6]); 298 | ASSERT.equal(0x44, buf[7]); 299 | ASSERT.equal(0x23, buf[8]); 300 | ASSERT.equal(0x00, buf[9]); 301 | 302 | data = [0x3421, 0x34abcdba]; 303 | buf.fill(0x66); 304 | mod_ctype.wsint64(data, 'big', buf, 0); 305 | ASSERT.equal(0x00, buf[0]); 306 | ASSERT.equal(0x00, buf[1]); 307 | ASSERT.equal(0x34, buf[2]); 308 | ASSERT.equal(0x21, buf[3]); 309 | ASSERT.equal(0x34, buf[4]); 310 | ASSERT.equal(0xab, buf[5]); 311 | ASSERT.equal(0xcd, buf[6]); 312 | ASSERT.equal(0xba, buf[7]); 313 | ASSERT.equal(0x66, buf[8]); 314 | ASSERT.equal(0x66, buf[9]); 315 | 316 | buf.fill(0x66); 317 | mod_ctype.wsint64(data, 'big', buf, 1); 318 | ASSERT.equal(0x66, buf[0]); 319 | ASSERT.equal(0x00, buf[1]); 320 | ASSERT.equal(0x00, buf[2]); 321 | ASSERT.equal(0x34, buf[3]); 322 | ASSERT.equal(0x21, buf[4]); 323 | ASSERT.equal(0x34, buf[5]); 324 | ASSERT.equal(0xab, buf[6]); 325 | ASSERT.equal(0xcd, buf[7]); 326 | ASSERT.equal(0xba, buf[8]); 327 | ASSERT.equal(0x66, buf[9]); 328 | 329 | buf.fill(0x66); 330 | mod_ctype.wsint64(data, 'big', buf, 2); 331 | ASSERT.equal(0x66, buf[0]); 332 | ASSERT.equal(0x66, buf[1]); 333 | ASSERT.equal(0x00, buf[2]); 334 | ASSERT.equal(0x00, buf[3]); 335 | ASSERT.equal(0x34, buf[4]); 336 | ASSERT.equal(0x21, buf[5]); 337 | ASSERT.equal(0x34, buf[6]); 338 | ASSERT.equal(0xab, buf[7]); 339 | ASSERT.equal(0xcd, buf[8]); 340 | ASSERT.equal(0xba, buf[9]); 341 | 342 | buf.fill(0x66); 343 | mod_ctype.wsint64(data, 'little', buf, 0); 344 | ASSERT.equal(0xba, buf[0]); 345 | ASSERT.equal(0xcd, buf[1]); 346 | ASSERT.equal(0xab, buf[2]); 347 | ASSERT.equal(0x34, buf[3]); 348 | ASSERT.equal(0x21, buf[4]); 349 | ASSERT.equal(0x34, buf[5]); 350 | ASSERT.equal(0x00, buf[6]); 351 | ASSERT.equal(0x00, buf[7]); 352 | ASSERT.equal(0x66, buf[8]); 353 | ASSERT.equal(0x66, buf[9]); 354 | 355 | buf.fill(0x66); 356 | mod_ctype.wsint64(data, 'little', buf, 1); 357 | ASSERT.equal(0x66, buf[0]); 358 | ASSERT.equal(0xba, buf[1]); 359 | ASSERT.equal(0xcd, buf[2]); 360 | ASSERT.equal(0xab, buf[3]); 361 | ASSERT.equal(0x34, buf[4]); 362 | ASSERT.equal(0x21, buf[5]); 363 | ASSERT.equal(0x34, buf[6]); 364 | ASSERT.equal(0x00, buf[7]); 365 | ASSERT.equal(0x00, buf[8]); 366 | ASSERT.equal(0x66, buf[9]); 367 | 368 | buf.fill(0x66); 369 | mod_ctype.wsint64(data, 'little', buf, 2); 370 | ASSERT.equal(0x66, buf[0]); 371 | ASSERT.equal(0x66, buf[1]); 372 | ASSERT.equal(0xba, buf[2]); 373 | ASSERT.equal(0xcd, buf[3]); 374 | ASSERT.equal(0xab, buf[4]); 375 | ASSERT.equal(0x34, buf[5]); 376 | ASSERT.equal(0x21, buf[6]); 377 | ASSERT.equal(0x34, buf[7]); 378 | ASSERT.equal(0x00, buf[8]); 379 | ASSERT.equal(0x00, buf[9]); 380 | 381 | 382 | data = [ -0x80000000, 0 ]; 383 | buf.fill(0x66); 384 | mod_ctype.wsint64(data, 'big', buf, 0); 385 | ASSERT.equal(0x80, buf[0]); 386 | ASSERT.equal(0x00, buf[1]); 387 | ASSERT.equal(0x00, buf[2]); 388 | ASSERT.equal(0x00, buf[3]); 389 | ASSERT.equal(0x00, buf[4]); 390 | ASSERT.equal(0x00, buf[5]); 391 | ASSERT.equal(0x00, buf[6]); 392 | ASSERT.equal(0x00, buf[7]); 393 | ASSERT.equal(0x66, buf[8]); 394 | ASSERT.equal(0x66, buf[9]); 395 | 396 | buf.fill(0x66); 397 | mod_ctype.wsint64(data, 'little', buf, 0); 398 | ASSERT.equal(0x00, buf[0]); 399 | ASSERT.equal(0x00, buf[1]); 400 | ASSERT.equal(0x00, buf[2]); 401 | ASSERT.equal(0x00, buf[3]); 402 | ASSERT.equal(0x00, buf[4]); 403 | ASSERT.equal(0x00, buf[5]); 404 | ASSERT.equal(0x00, buf[6]); 405 | ASSERT.equal(0x80, buf[7]); 406 | ASSERT.equal(0x66, buf[8]); 407 | ASSERT.equal(0x66, buf[9]); 408 | 409 | data = [ -0x7fffffff, -0xffffffff ]; 410 | buf.fill(0x66); 411 | mod_ctype.wsint64(data, 'big', buf, 0); 412 | ASSERT.equal(0x80, buf[0]); 413 | ASSERT.equal(0x00, buf[1]); 414 | ASSERT.equal(0x00, buf[2]); 415 | ASSERT.equal(0x00, buf[3]); 416 | ASSERT.equal(0x00, buf[4]); 417 | ASSERT.equal(0x00, buf[5]); 418 | ASSERT.equal(0x00, buf[6]); 419 | ASSERT.equal(0x01, buf[7]); 420 | ASSERT.equal(0x66, buf[8]); 421 | ASSERT.equal(0x66, buf[9]); 422 | 423 | buf.fill(0x66); 424 | mod_ctype.wsint64(data, 'little', buf, 0); 425 | ASSERT.equal(0x01, buf[0]); 426 | ASSERT.equal(0x00, buf[1]); 427 | ASSERT.equal(0x00, buf[2]); 428 | ASSERT.equal(0x00, buf[3]); 429 | ASSERT.equal(0x00, buf[4]); 430 | ASSERT.equal(0x00, buf[5]); 431 | ASSERT.equal(0x00, buf[6]); 432 | ASSERT.equal(0x80, buf[7]); 433 | ASSERT.equal(0x66, buf[8]); 434 | ASSERT.equal(0x66, buf[9]); 435 | 436 | data = [ 0x0, -0x1]; 437 | buf.fill(0x66); 438 | mod_ctype.wsint64(data, 'big', buf, 0); 439 | ASSERT.equal(0xff, buf[0]); 440 | ASSERT.equal(0xff, buf[1]); 441 | ASSERT.equal(0xff, buf[2]); 442 | ASSERT.equal(0xff, buf[3]); 443 | ASSERT.equal(0xff, buf[4]); 444 | ASSERT.equal(0xff, buf[5]); 445 | ASSERT.equal(0xff, buf[6]); 446 | ASSERT.equal(0xff, buf[7]); 447 | ASSERT.equal(0x66, buf[8]); 448 | ASSERT.equal(0x66, buf[9]); 449 | 450 | buf.fill(0x66); 451 | mod_ctype.wsint64(data, 'little', buf, 0); 452 | ASSERT.equal(0xff, buf[0]); 453 | ASSERT.equal(0xff, buf[1]); 454 | ASSERT.equal(0xff, buf[2]); 455 | ASSERT.equal(0xff, buf[3]); 456 | ASSERT.equal(0xff, buf[4]); 457 | ASSERT.equal(0xff, buf[5]); 458 | ASSERT.equal(0xff, buf[6]); 459 | ASSERT.equal(0xff, buf[7]); 460 | ASSERT.equal(0x66, buf[8]); 461 | ASSERT.equal(0x66, buf[9]); 462 | } 463 | 464 | /* 465 | * Make sure we catch invalid writes. 466 | */ 467 | function testWriteInvalid() 468 | { 469 | var data, buf; 470 | 471 | /* Buffer too small */ 472 | buf = new Buffer(4); 473 | data = [ 0, 0]; 474 | ASSERT.throws(function () { 475 | mod_ctype.wsint64(data, 'big', buf, 0); 476 | }, Error, 'buffer too small'); 477 | ASSERT.throws(function () { 478 | mod_ctype.wsint64(data, 'little', buf, 0); 479 | }, Error, 'buffer too small'); 480 | 481 | /* Beyond the end of the buffer */ 482 | buf = new Buffer(12); 483 | data = [ 0, 0]; 484 | ASSERT.throws(function () { 485 | mod_ctype.wsint64(data, 'little', buf, 11); 486 | }, Error, 'write beyond end of buffer'); 487 | ASSERT.throws(function () { 488 | mod_ctype.wsint64(data, 'big', buf, 11); 489 | }, Error, 'write beyond end of buffer'); 490 | 491 | /* Write fractional values */ 492 | buf = new Buffer(12); 493 | data = [ 3.33, 0 ]; 494 | ASSERT.throws(function () { 495 | mod_ctype.wsint64(data, 'big', buf, 1); 496 | }, Error, 'write fractions'); 497 | ASSERT.throws(function () { 498 | mod_ctype.wsint64(data, 'little', buf, 1); 499 | }, Error, 'write fractions'); 500 | 501 | data = [ 0, 3.3 ]; 502 | ASSERT.throws(function () { 503 | mod_ctype.wsint64(data, 'big', buf, 1); 504 | }, Error, 'write fractions'); 505 | ASSERT.throws(function () { 506 | mod_ctype.wsint64(data, 'little', buf, 1); 507 | }, Error, 'write fractions'); 508 | 509 | data = [ -3.33, 0 ]; 510 | ASSERT.throws(function () { 511 | mod_ctype.wsint64(data, 'big', buf, 1); 512 | }, Error, 'write fractions'); 513 | ASSERT.throws(function () { 514 | mod_ctype.wsint64(data, 'little', buf, 1); 515 | }, Error, 'write fractions'); 516 | 517 | data = [ 0, -3.3 ]; 518 | ASSERT.throws(function () { 519 | mod_ctype.wsint64(data, 'big', buf, 1); 520 | }, Error, 'write fractions'); 521 | ASSERT.throws(function () { 522 | mod_ctype.wsint64(data, 'little', buf, 1); 523 | }, Error, 'write fractions'); 524 | 525 | data = [ 3.33, 2.42 ]; 526 | ASSERT.throws(function () { 527 | mod_ctype.wsint64(data, 'big', buf, 1); 528 | }, Error, 'write fractions'); 529 | ASSERT.throws(function () { 530 | mod_ctype.wsint64(data, 'little', buf, 1); 531 | }, Error, 'write fractions'); 532 | 533 | data = [ 3.33, -2.42 ]; 534 | ASSERT.throws(function () { 535 | mod_ctype.wsint64(data, 'big', buf, 1); 536 | }, Error, 'write fractions'); 537 | ASSERT.throws(function () { 538 | mod_ctype.wsint64(data, 'little', buf, 1); 539 | }, Error, 'write fractions'); 540 | 541 | data = [ -3.33, -2.42 ]; 542 | ASSERT.throws(function () { 543 | mod_ctype.wsint64(data, 'big', buf, 1); 544 | }, Error, 'write fractions'); 545 | ASSERT.throws(function () { 546 | mod_ctype.wsint64(data, 'little', buf, 1); 547 | }, Error, 'write fractions'); 548 | 549 | data = [ -3.33, 2.42 ]; 550 | ASSERT.throws(function () { 551 | mod_ctype.wsint64(data, 'big', buf, 1); 552 | }, Error, 'write fractions'); 553 | ASSERT.throws(function () { 554 | mod_ctype.wsint64(data, 'little', buf, 1); 555 | }, Error, 'write fractions'); 556 | 557 | /* Signs don't match */ 558 | buf = new Buffer(12); 559 | data = [ 0x800000, -0x32 ]; 560 | ASSERT.throws(function () { 561 | mod_ctype.wsint64(data, 'big', buf, 1); 562 | }, Error, 'write too large'); 563 | ASSERT.throws(function () { 564 | mod_ctype.wsint64(data, 'little', buf, 1); 565 | }, Error, 'write too large'); 566 | 567 | data = [ -0x800000, 0x32 ]; 568 | ASSERT.throws(function () { 569 | mod_ctype.wsint64(data, 'big', buf, 1); 570 | }, Error, 'write too large'); 571 | ASSERT.throws(function () { 572 | mod_ctype.wsint64(data, 'little', buf, 1); 573 | }, Error, 'write too large'); 574 | 575 | /* Write values that are too large */ 576 | buf = new Buffer(12); 577 | data = [ 0x80000000, 0 ]; 578 | ASSERT.throws(function () { 579 | mod_ctype.wsint64(data, 'big', buf, 1); 580 | }, Error, 'write too large'); 581 | ASSERT.throws(function () { 582 | mod_ctype.wsint64(data, 'little', buf, 1); 583 | }, Error, 'write too large'); 584 | 585 | data = [ 0x7fffffff, 0x100000000 ]; 586 | ASSERT.throws(function () { 587 | mod_ctype.wsint64(data, 'big', buf, 1); 588 | }, Error, 'write too large'); 589 | ASSERT.throws(function () { 590 | mod_ctype.wsint64(data, 'little', buf, 1); 591 | }, Error, 'write too large'); 592 | 593 | data = [ 0x00, 0x800000000 ]; 594 | ASSERT.throws(function () { 595 | mod_ctype.wsint64(data, 'big', buf, 1); 596 | }, Error, 'write too large'); 597 | ASSERT.throws(function () { 598 | mod_ctype.wsint64(data, 'little', buf, 1); 599 | }, Error, 'write too large'); 600 | 601 | data = [ 0xffffffffff, 0xffffff238 ]; 602 | ASSERT.throws(function () { 603 | mod_ctype.wsint64(data, 'big', buf, 1); 604 | }, Error, 'write too large'); 605 | ASSERT.throws(function () { 606 | mod_ctype.wsint64(data, 'little', buf, 1); 607 | }, Error, 'write too large'); 608 | 609 | data = [ 0x23, 0xffffff238 ]; 610 | ASSERT.throws(function () { 611 | mod_ctype.wsint64(data, 'big', buf, 1); 612 | }, Error, 'write too large'); 613 | ASSERT.throws(function () { 614 | mod_ctype.wsint64(data, 'little', buf, 1); 615 | }, Error, 'write too large'); 616 | 617 | data = [ -0x80000000, -0xfff238 ]; 618 | ASSERT.throws(function () { 619 | mod_ctype.wsint64(data, 'big', buf, 1); 620 | }, Error, 'write too large'); 621 | ASSERT.throws(function () { 622 | mod_ctype.wsint64(data, 'little', buf, 1); 623 | }, Error, 'write too large'); 624 | 625 | data = [ -0x80000004, -0xfff238 ]; 626 | ASSERT.throws(function () { 627 | mod_ctype.wsint64(data, 'big', buf, 1); 628 | }, Error, 'write too large'); 629 | ASSERT.throws(function () { 630 | mod_ctype.wsint64(data, 'little', buf, 1); 631 | }, Error, 'write too large'); 632 | } 633 | 634 | 635 | testRead(); 636 | testWrite(); 637 | testWriteZero(); 638 | testWriteInvalid(); 639 | -------------------------------------------------------------------------------- /tst/ctio/int/tst.rint.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Tests to verify we're reading in signed integers correctly 3 | */ 4 | var mod_ctype = require('../../../ctio.js'); 5 | var ASSERT = require('assert'); 6 | 7 | /* 8 | * Test 8 bit signed integers 9 | */ 10 | function test8() 11 | { 12 | var data = new Buffer(4); 13 | 14 | data[0] = 0x23; 15 | ASSERT.equal(0x23, mod_ctype.rsint8(data, 'big', 0)); 16 | ASSERT.equal(0x23, mod_ctype.rsint8(data, 'little', 0)); 17 | 18 | data[0] = 0xff; 19 | ASSERT.equal(-1, mod_ctype.rsint8(data, 'big', 0)); 20 | ASSERT.equal(-1, mod_ctype.rsint8(data, 'little', 0)); 21 | 22 | data[0] = 0x87; 23 | data[1] = 0xab; 24 | data[2] = 0x7c; 25 | data[3] = 0xef; 26 | ASSERT.equal(-121, mod_ctype.rsint8(data, 'big', 0)); 27 | ASSERT.equal(-85, mod_ctype.rsint8(data, 'big', 1)); 28 | ASSERT.equal(124, mod_ctype.rsint8(data, 'big', 2)); 29 | ASSERT.equal(-17, mod_ctype.rsint8(data, 'big', 3)); 30 | ASSERT.equal(-121, mod_ctype.rsint8(data, 'little', 0)); 31 | ASSERT.equal(-85, mod_ctype.rsint8(data, 'little', 1)); 32 | ASSERT.equal(124, mod_ctype.rsint8(data, 'little', 2)); 33 | ASSERT.equal(-17, mod_ctype.rsint8(data, 'little', 3)); 34 | } 35 | 36 | function test16() 37 | { 38 | var buffer = new Buffer(6); 39 | buffer[0] = 0x16; 40 | buffer[1] = 0x79; 41 | ASSERT.equal(0x1679, mod_ctype.rsint16(buffer, 'big', 0)); 42 | ASSERT.equal(0x7916, mod_ctype.rsint16(buffer, 'little', 0)); 43 | 44 | buffer[0] = 0xff; 45 | buffer[1] = 0x80; 46 | ASSERT.equal(-128, mod_ctype.rsint16(buffer, 'big', 0)); 47 | ASSERT.equal(-32513, mod_ctype.rsint16(buffer, 'little', 0)); 48 | 49 | /* test offset with weenix */ 50 | buffer[0] = 0x77; 51 | buffer[1] = 0x65; 52 | buffer[2] = 0x65; 53 | buffer[3] = 0x6e; 54 | buffer[4] = 0x69; 55 | buffer[5] = 0x78; 56 | ASSERT.equal(0x7765, mod_ctype.rsint16(buffer, 'big', 0)); 57 | ASSERT.equal(0x6565, mod_ctype.rsint16(buffer, 'big', 1)); 58 | ASSERT.equal(0x656e, mod_ctype.rsint16(buffer, 'big', 2)); 59 | ASSERT.equal(0x6e69, mod_ctype.rsint16(buffer, 'big', 3)); 60 | ASSERT.equal(0x6978, mod_ctype.rsint16(buffer, 'big', 4)); 61 | ASSERT.equal(0x6577, mod_ctype.rsint16(buffer, 'little', 0)); 62 | ASSERT.equal(0x6565, mod_ctype.rsint16(buffer, 'little', 1)); 63 | ASSERT.equal(0x6e65, mod_ctype.rsint16(buffer, 'little', 2)); 64 | ASSERT.equal(0x696e, mod_ctype.rsint16(buffer, 'little', 3)); 65 | ASSERT.equal(0x7869, mod_ctype.rsint16(buffer, 'little', 4)); 66 | } 67 | 68 | function test32() 69 | { 70 | var buffer = new Buffer(6); 71 | buffer[0] = 0x43; 72 | buffer[1] = 0x53; 73 | buffer[2] = 0x16; 74 | buffer[3] = 0x79; 75 | ASSERT.equal(0x43531679, mod_ctype.rsint32(buffer, 'big', 0)); 76 | ASSERT.equal(0x79165343, mod_ctype.rsint32(buffer, 'little', 0)); 77 | 78 | buffer[0] = 0xff; 79 | buffer[1] = 0xfe; 80 | buffer[2] = 0xef; 81 | buffer[3] = 0xfa; 82 | ASSERT.equal(-69638, mod_ctype.rsint32(buffer, 'big', 0)); 83 | ASSERT.equal(-84934913, mod_ctype.rsint32(buffer, 'little', 0)); 84 | 85 | buffer[0] = 0x42; 86 | buffer[1] = 0xc3; 87 | buffer[2] = 0x95; 88 | buffer[3] = 0xa9; 89 | buffer[4] = 0x36; 90 | buffer[5] = 0x17; 91 | ASSERT.equal(0x42c395a9, mod_ctype.rsint32(buffer, 'big', 0)); 92 | ASSERT.equal(-1013601994, mod_ctype.rsint32(buffer, 'big', 1)); 93 | ASSERT.equal(-1784072681, mod_ctype.rsint32(buffer, 'big', 2)); 94 | ASSERT.equal(-1449802942, mod_ctype.rsint32(buffer, 'little', 0)); 95 | ASSERT.equal(917083587, mod_ctype.rsint32(buffer, 'little', 1)); 96 | ASSERT.equal(389458325, mod_ctype.rsint32(buffer, 'little', 2)); 97 | } 98 | 99 | test8(); 100 | test16(); 101 | test32(); 102 | -------------------------------------------------------------------------------- /tst/ctio/int/tst.wbounds.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Test to make sure that we properly are erroring whenever we try to write 3 | * beyond the size of the integer. 4 | */ 5 | 6 | var mod_ctio = require('../../../ctio.js'); 7 | var mod_assert = require('assert'); 8 | var tb = new Buffer(16); /* Largest buffer we'll need */ 9 | 10 | var cases = [ 11 | { func: 12 | function () { 13 | mod_ctio.wsint8(0x80, 'big', tb, 0); 14 | }, test: '+int8_t' }, 15 | { func: 16 | function () { 17 | mod_ctio.wsint8(-0x81, 'big', tb, 0); 18 | }, test: '-int8_t' }, 19 | 20 | { func: 21 | function () { 22 | mod_ctio.wsint16(0x8000, 'big', tb, 0); 23 | }, test: '+int16_t' }, 24 | { func: 25 | function () { 26 | mod_ctio.wsint16(-0x8001, 'big', tb, 0); 27 | }, test: '-int16_t' }, 28 | { func: 29 | function () { 30 | mod_ctio.wsint32(0x80000000, 'big', tb, 0); 31 | }, test: '+int32_t' }, 32 | { func: 33 | function () { 34 | mod_ctio.wsint32(-0x80000001, 'big', tb, 0); 35 | }, test: '-int32_t' }, 36 | { func: 37 | function () { 38 | mod_ctio.wsint64([ 0x80000000, 0 ], 'big', tb, 0); 39 | }, test: '+int64_t' }, 40 | { func: 41 | function () { 42 | mod_ctio.wsint64([ -0x80000000, -1 ], 'big', tb, 0); 43 | }, test: '-int64_t' } 44 | ]; 45 | 46 | function test() 47 | { 48 | var ii; 49 | for (ii = 0; ii < cases.length; ii++) 50 | mod_assert.throws(cases[ii]['func'], Error, cases[ii]['test']); 51 | } 52 | 53 | test(); 54 | -------------------------------------------------------------------------------- /tst/ctio/int/tst.wint.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Tests to verify we're writing signed integers correctly 3 | */ 4 | var mod_ctype = require('../../../ctio.js'); 5 | var ASSERT = require('assert'); 6 | 7 | function test8() 8 | { 9 | var buffer = new Buffer(4); 10 | mod_ctype.wsint8(0x23, 'big', buffer, 0); 11 | mod_ctype.wsint8(0x23, 'little', buffer, 1); 12 | mod_ctype.wsint8(-5, 'big', buffer, 2); 13 | mod_ctype.wsint8(-5, 'little', buffer, 3); 14 | 15 | ASSERT.equal(0x23, buffer[0]); 16 | ASSERT.equal(0x23, buffer[1]); 17 | ASSERT.equal(0xfb, buffer[2]); 18 | ASSERT.equal(0xfb, buffer[3]); 19 | 20 | /* Make sure we handle truncation correctly */ 21 | ASSERT.throws(function () { 22 | mod_ctype.wsint8(0xabc, 'big', buffer, 0); 23 | }); 24 | ASSERT.throws(function () { 25 | mod_ctype.wsint8(0xabc, 'little', buffer, 0); 26 | }); 27 | } 28 | 29 | function test16() 30 | { 31 | var buffer = new Buffer(6); 32 | mod_ctype.wsint16(0x0023, 'big', buffer, 0); 33 | mod_ctype.wsint16(0x0023, 'little', buffer, 2); 34 | ASSERT.equal(0x00, buffer[0]); 35 | ASSERT.equal(0x23, buffer[1]); 36 | ASSERT.equal(0x23, buffer[2]); 37 | ASSERT.equal(0x00, buffer[3]); 38 | mod_ctype.wsint16(-5, 'big', buffer, 0); 39 | mod_ctype.wsint16(-5, 'little', buffer, 2); 40 | ASSERT.equal(0xff, buffer[0]); 41 | ASSERT.equal(0xfb, buffer[1]); 42 | ASSERT.equal(0xfb, buffer[2]); 43 | ASSERT.equal(0xff, buffer[3]); 44 | 45 | mod_ctype.wsint16(-1679, 'big', buffer, 1); 46 | mod_ctype.wsint16(-1679, 'little', buffer, 3); 47 | ASSERT.equal(0xf9, buffer[1]); 48 | ASSERT.equal(0x71, buffer[2]); 49 | ASSERT.equal(0x71, buffer[3]); 50 | ASSERT.equal(0xf9, buffer[4]); 51 | } 52 | 53 | function test32() 54 | { 55 | var buffer = new Buffer(8); 56 | mod_ctype.wsint32(0x23, 'big', buffer, 0); 57 | mod_ctype.wsint32(0x23, 'little', buffer, 4); 58 | ASSERT.equal(0x00, buffer[0]); 59 | ASSERT.equal(0x00, buffer[1]); 60 | ASSERT.equal(0x00, buffer[2]); 61 | ASSERT.equal(0x23, buffer[3]); 62 | ASSERT.equal(0x23, buffer[4]); 63 | ASSERT.equal(0x00, buffer[5]); 64 | ASSERT.equal(0x00, buffer[6]); 65 | ASSERT.equal(0x00, buffer[7]); 66 | 67 | mod_ctype.wsint32(-5, 'big', buffer, 0); 68 | mod_ctype.wsint32(-5, 'little', buffer, 4); 69 | ASSERT.equal(0xff, buffer[0]); 70 | ASSERT.equal(0xff, buffer[1]); 71 | ASSERT.equal(0xff, buffer[2]); 72 | ASSERT.equal(0xfb, buffer[3]); 73 | ASSERT.equal(0xfb, buffer[4]); 74 | ASSERT.equal(0xff, buffer[5]); 75 | ASSERT.equal(0xff, buffer[6]); 76 | ASSERT.equal(0xff, buffer[7]); 77 | 78 | mod_ctype.wsint32(-805306713, 'big', buffer, 0); 79 | mod_ctype.wsint32(-805306713, 'litle', buffer, 4); 80 | ASSERT.equal(0xcf, buffer[0]); 81 | ASSERT.equal(0xff, buffer[1]); 82 | ASSERT.equal(0xfe, buffer[2]); 83 | ASSERT.equal(0xa7, buffer[3]); 84 | ASSERT.equal(0xa7, buffer[4]); 85 | ASSERT.equal(0xfe, buffer[5]); 86 | ASSERT.equal(0xff, buffer[6]); 87 | ASSERT.equal(0xcf, buffer[7]); 88 | } 89 | 90 | test8(); 91 | test16(); 92 | test32(); 93 | -------------------------------------------------------------------------------- /tst/ctio/uint/tst.64.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Test our ability to read and write unsigned 64-bit integers. 3 | */ 4 | 5 | var mod_ctype = require('../../../ctio.js'); 6 | var ASSERT = require('assert'); 7 | 8 | function testRead() 9 | { 10 | var res, data; 11 | data = new Buffer(10); 12 | 13 | data[0] = 0x32; 14 | data[1] = 0x65; 15 | data[2] = 0x42; 16 | data[3] = 0x56; 17 | data[4] = 0x23; 18 | data[5] = 0xff; 19 | data[6] = 0xff; 20 | data[7] = 0xff; 21 | data[8] = 0x89; 22 | data[9] = 0x11; 23 | res = mod_ctype.ruint64(data, 'big', 0); 24 | ASSERT.equal(0x32654256, res[0]); 25 | ASSERT.equal(0x23ffffff, res[1]); 26 | res = mod_ctype.ruint64(data, 'big', 1); 27 | ASSERT.equal(0x65425623, res[0]); 28 | ASSERT.equal(0xffffff89, res[1]); 29 | res = mod_ctype.ruint64(data, 'big', 2); 30 | ASSERT.equal(0x425623ff, res[0]); 31 | ASSERT.equal(0xffff8911, res[1]); 32 | res = mod_ctype.ruint64(data, 'little', 0); 33 | ASSERT.equal(0xffffff23, res[0]); 34 | ASSERT.equal(0x56426532, res[1]); 35 | res = mod_ctype.ruint64(data, 'little', 1); 36 | ASSERT.equal(0x89ffffff, res[0]); 37 | ASSERT.equal(0x23564265, res[1]); 38 | res = mod_ctype.ruint64(data, 'little', 2); 39 | ASSERT.equal(0x1189ffff, res[0]); 40 | ASSERT.equal(0xff235642, res[1]); 41 | 42 | } 43 | 44 | function testReadOver() 45 | { 46 | var res, data; 47 | data = new Buffer(10); 48 | 49 | data[0] = 0x80; 50 | data[1] = 0xff; 51 | data[2] = 0x80; 52 | data[3] = 0xff; 53 | data[4] = 0x80; 54 | data[5] = 0xff; 55 | data[6] = 0x80; 56 | data[7] = 0xff; 57 | data[8] = 0x80; 58 | data[9] = 0xff; 59 | res = mod_ctype.ruint64(data, 'big', 0); 60 | ASSERT.equal(0x80ff80ff, res[0]); 61 | ASSERT.equal(0x80ff80ff, res[1]); 62 | res = mod_ctype.ruint64(data, 'big', 1); 63 | ASSERT.equal(0xff80ff80, res[0]); 64 | ASSERT.equal(0xff80ff80, res[1]); 65 | res = mod_ctype.ruint64(data, 'big', 2); 66 | ASSERT.equal(0x80ff80ff, res[0]); 67 | ASSERT.equal(0x80ff80ff, res[1]); 68 | res = mod_ctype.ruint64(data, 'little', 0); 69 | ASSERT.equal(0xff80ff80, res[0]); 70 | ASSERT.equal(0xff80ff80, res[1]); 71 | res = mod_ctype.ruint64(data, 'little', 1); 72 | ASSERT.equal(0x80ff80ff, res[0]); 73 | ASSERT.equal(0x80ff80ff, res[1]); 74 | res = mod_ctype.ruint64(data, 'little', 2); 75 | ASSERT.equal(0xff80ff80, res[0]); 76 | ASSERT.equal(0xff80ff80, res[1]); 77 | } 78 | 79 | function testWriteZero() 80 | { 81 | var data, buf; 82 | buf = new Buffer(10); 83 | 84 | buf.fill(0x66); 85 | data = [0, 0]; 86 | mod_ctype.wuint64(data, 'big', buf, 0); 87 | ASSERT.equal(0, buf[0]); 88 | ASSERT.equal(0, buf[1]); 89 | ASSERT.equal(0, buf[2]); 90 | ASSERT.equal(0, buf[3]); 91 | ASSERT.equal(0, buf[4]); 92 | ASSERT.equal(0, buf[5]); 93 | ASSERT.equal(0, buf[6]); 94 | ASSERT.equal(0, buf[7]); 95 | ASSERT.equal(0x66, buf[8]); 96 | ASSERT.equal(0x66, buf[9]); 97 | 98 | buf.fill(0x66); 99 | data = [0, 0]; 100 | mod_ctype.wuint64(data, 'big', buf, 1); 101 | ASSERT.equal(0x66, buf[0]); 102 | ASSERT.equal(0, buf[1]); 103 | ASSERT.equal(0, buf[2]); 104 | ASSERT.equal(0, buf[3]); 105 | ASSERT.equal(0, buf[4]); 106 | ASSERT.equal(0, buf[5]); 107 | ASSERT.equal(0, buf[6]); 108 | ASSERT.equal(0, buf[7]); 109 | ASSERT.equal(0, buf[8]); 110 | ASSERT.equal(0x66, buf[9]); 111 | 112 | buf.fill(0x66); 113 | data = [0, 0]; 114 | mod_ctype.wuint64(data, 'big', buf, 2); 115 | ASSERT.equal(0x66, buf[0]); 116 | ASSERT.equal(0x66, buf[1]); 117 | ASSERT.equal(0, buf[2]); 118 | ASSERT.equal(0, buf[3]); 119 | ASSERT.equal(0, buf[4]); 120 | ASSERT.equal(0, buf[5]); 121 | ASSERT.equal(0, buf[6]); 122 | ASSERT.equal(0, buf[7]); 123 | ASSERT.equal(0, buf[8]); 124 | ASSERT.equal(0, buf[9]); 125 | 126 | 127 | buf.fill(0x66); 128 | data = [0, 0]; 129 | mod_ctype.wuint64(data, 'little', buf, 0); 130 | ASSERT.equal(0, buf[0]); 131 | ASSERT.equal(0, buf[1]); 132 | ASSERT.equal(0, buf[2]); 133 | ASSERT.equal(0, buf[3]); 134 | ASSERT.equal(0, buf[4]); 135 | ASSERT.equal(0, buf[5]); 136 | ASSERT.equal(0, buf[6]); 137 | ASSERT.equal(0, buf[7]); 138 | ASSERT.equal(0x66, buf[8]); 139 | ASSERT.equal(0x66, buf[9]); 140 | 141 | buf.fill(0x66); 142 | data = [0, 0]; 143 | mod_ctype.wuint64(data, 'little', buf, 1); 144 | ASSERT.equal(0x66, buf[0]); 145 | ASSERT.equal(0, buf[1]); 146 | ASSERT.equal(0, buf[2]); 147 | ASSERT.equal(0, buf[3]); 148 | ASSERT.equal(0, buf[4]); 149 | ASSERT.equal(0, buf[5]); 150 | ASSERT.equal(0, buf[6]); 151 | ASSERT.equal(0, buf[7]); 152 | ASSERT.equal(0, buf[8]); 153 | ASSERT.equal(0x66, buf[9]); 154 | 155 | buf.fill(0x66); 156 | data = [0, 0]; 157 | mod_ctype.wuint64(data, 'little', buf, 2); 158 | ASSERT.equal(0x66, buf[0]); 159 | ASSERT.equal(0x66, buf[1]); 160 | ASSERT.equal(0, buf[2]); 161 | ASSERT.equal(0, buf[3]); 162 | ASSERT.equal(0, buf[4]); 163 | ASSERT.equal(0, buf[5]); 164 | ASSERT.equal(0, buf[6]); 165 | ASSERT.equal(0, buf[7]); 166 | ASSERT.equal(0, buf[8]); 167 | ASSERT.equal(0, buf[9]); 168 | } 169 | 170 | /* 171 | * Also include tests that are going to force us to go into a negative value and 172 | * insure that it's written correctly. 173 | */ 174 | function testWrite() 175 | { 176 | var data, buf; 177 | 178 | buf = new Buffer(10); 179 | data = [ 0x234456, 0x87 ]; 180 | buf.fill(0x66); 181 | mod_ctype.wuint64(data, 'big', buf, 0); 182 | ASSERT.equal(0x00, buf[0]); 183 | ASSERT.equal(0x23, buf[1]); 184 | ASSERT.equal(0x44, buf[2]); 185 | ASSERT.equal(0x56, buf[3]); 186 | ASSERT.equal(0x00, buf[4]); 187 | ASSERT.equal(0x00, buf[5]); 188 | ASSERT.equal(0x00, buf[6]); 189 | ASSERT.equal(0x87, buf[7]); 190 | ASSERT.equal(0x66, buf[8]); 191 | ASSERT.equal(0x66, buf[9]); 192 | 193 | buf.fill(0x66); 194 | mod_ctype.wuint64(data, 'big', buf, 1); 195 | ASSERT.equal(0x66, buf[0]); 196 | ASSERT.equal(0x00, buf[1]); 197 | ASSERT.equal(0x23, buf[2]); 198 | ASSERT.equal(0x44, buf[3]); 199 | ASSERT.equal(0x56, buf[4]); 200 | ASSERT.equal(0x00, buf[5]); 201 | ASSERT.equal(0x00, buf[6]); 202 | ASSERT.equal(0x00, buf[7]); 203 | ASSERT.equal(0x87, buf[8]); 204 | ASSERT.equal(0x66, buf[9]); 205 | 206 | buf.fill(0x66); 207 | mod_ctype.wuint64(data, 'big', buf, 2); 208 | ASSERT.equal(0x66, buf[0]); 209 | ASSERT.equal(0x66, buf[1]); 210 | ASSERT.equal(0x00, buf[2]); 211 | ASSERT.equal(0x23, buf[3]); 212 | ASSERT.equal(0x44, buf[4]); 213 | ASSERT.equal(0x56, buf[5]); 214 | ASSERT.equal(0x00, buf[6]); 215 | ASSERT.equal(0x00, buf[7]); 216 | ASSERT.equal(0x00, buf[8]); 217 | ASSERT.equal(0x87, buf[9]); 218 | 219 | buf.fill(0x66); 220 | mod_ctype.wuint64(data, 'little', buf, 0); 221 | ASSERT.equal(0x87, buf[0]); 222 | ASSERT.equal(0x00, buf[1]); 223 | ASSERT.equal(0x00, buf[2]); 224 | ASSERT.equal(0x00, buf[3]); 225 | ASSERT.equal(0x56, buf[4]); 226 | ASSERT.equal(0x44, buf[5]); 227 | ASSERT.equal(0x23, buf[6]); 228 | ASSERT.equal(0x00, buf[7]); 229 | ASSERT.equal(0x66, buf[8]); 230 | ASSERT.equal(0x66, buf[9]); 231 | 232 | buf.fill(0x66); 233 | mod_ctype.wuint64(data, 'little', buf, 1); 234 | ASSERT.equal(0x66, buf[0]); 235 | ASSERT.equal(0x87, buf[1]); 236 | ASSERT.equal(0x00, buf[2]); 237 | ASSERT.equal(0x00, buf[3]); 238 | ASSERT.equal(0x00, buf[4]); 239 | ASSERT.equal(0x56, buf[5]); 240 | ASSERT.equal(0x44, buf[6]); 241 | ASSERT.equal(0x23, buf[7]); 242 | ASSERT.equal(0x00, buf[8]); 243 | ASSERT.equal(0x66, buf[9]); 244 | 245 | 246 | buf.fill(0x66); 247 | mod_ctype.wuint64(data, 'little', buf, 2); 248 | ASSERT.equal(0x66, buf[0]); 249 | ASSERT.equal(0x66, buf[1]); 250 | ASSERT.equal(0x87, buf[2]); 251 | ASSERT.equal(0x00, buf[3]); 252 | ASSERT.equal(0x00, buf[4]); 253 | ASSERT.equal(0x00, buf[5]); 254 | ASSERT.equal(0x56, buf[6]); 255 | ASSERT.equal(0x44, buf[7]); 256 | ASSERT.equal(0x23, buf[8]); 257 | ASSERT.equal(0x00, buf[9]); 258 | 259 | data = [0xffff3421, 0x34abcdba]; 260 | buf.fill(0x66); 261 | mod_ctype.wuint64(data, 'big', buf, 0); 262 | ASSERT.equal(0xff, buf[0]); 263 | ASSERT.equal(0xff, buf[1]); 264 | ASSERT.equal(0x34, buf[2]); 265 | ASSERT.equal(0x21, buf[3]); 266 | ASSERT.equal(0x34, buf[4]); 267 | ASSERT.equal(0xab, buf[5]); 268 | ASSERT.equal(0xcd, buf[6]); 269 | ASSERT.equal(0xba, buf[7]); 270 | ASSERT.equal(0x66, buf[8]); 271 | ASSERT.equal(0x66, buf[9]); 272 | 273 | buf.fill(0x66); 274 | mod_ctype.wuint64(data, 'big', buf, 1); 275 | ASSERT.equal(0x66, buf[0]); 276 | ASSERT.equal(0xff, buf[1]); 277 | ASSERT.equal(0xff, buf[2]); 278 | ASSERT.equal(0x34, buf[3]); 279 | ASSERT.equal(0x21, buf[4]); 280 | ASSERT.equal(0x34, buf[5]); 281 | ASSERT.equal(0xab, buf[6]); 282 | ASSERT.equal(0xcd, buf[7]); 283 | ASSERT.equal(0xba, buf[8]); 284 | ASSERT.equal(0x66, buf[9]); 285 | 286 | buf.fill(0x66); 287 | mod_ctype.wuint64(data, 'big', buf, 2); 288 | ASSERT.equal(0x66, buf[0]); 289 | ASSERT.equal(0x66, buf[1]); 290 | ASSERT.equal(0xff, buf[2]); 291 | ASSERT.equal(0xff, buf[3]); 292 | ASSERT.equal(0x34, buf[4]); 293 | ASSERT.equal(0x21, buf[5]); 294 | ASSERT.equal(0x34, buf[6]); 295 | ASSERT.equal(0xab, buf[7]); 296 | ASSERT.equal(0xcd, buf[8]); 297 | ASSERT.equal(0xba, buf[9]); 298 | 299 | buf.fill(0x66); 300 | mod_ctype.wuint64(data, 'little', buf, 0); 301 | ASSERT.equal(0xba, buf[0]); 302 | ASSERT.equal(0xcd, buf[1]); 303 | ASSERT.equal(0xab, buf[2]); 304 | ASSERT.equal(0x34, buf[3]); 305 | ASSERT.equal(0x21, buf[4]); 306 | ASSERT.equal(0x34, buf[5]); 307 | ASSERT.equal(0xff, buf[6]); 308 | ASSERT.equal(0xff, buf[7]); 309 | ASSERT.equal(0x66, buf[8]); 310 | ASSERT.equal(0x66, buf[9]); 311 | 312 | buf.fill(0x66); 313 | mod_ctype.wuint64(data, 'little', buf, 1); 314 | ASSERT.equal(0x66, buf[0]); 315 | ASSERT.equal(0xba, buf[1]); 316 | ASSERT.equal(0xcd, buf[2]); 317 | ASSERT.equal(0xab, buf[3]); 318 | ASSERT.equal(0x34, buf[4]); 319 | ASSERT.equal(0x21, buf[5]); 320 | ASSERT.equal(0x34, buf[6]); 321 | ASSERT.equal(0xff, buf[7]); 322 | ASSERT.equal(0xff, buf[8]); 323 | ASSERT.equal(0x66, buf[9]); 324 | 325 | buf.fill(0x66); 326 | mod_ctype.wuint64(data, 'little', buf, 2); 327 | ASSERT.equal(0x66, buf[0]); 328 | ASSERT.equal(0x66, buf[1]); 329 | ASSERT.equal(0xba, buf[2]); 330 | ASSERT.equal(0xcd, buf[3]); 331 | ASSERT.equal(0xab, buf[4]); 332 | ASSERT.equal(0x34, buf[5]); 333 | ASSERT.equal(0x21, buf[6]); 334 | ASSERT.equal(0x34, buf[7]); 335 | ASSERT.equal(0xff, buf[8]); 336 | ASSERT.equal(0xff, buf[9]); 337 | } 338 | 339 | /* 340 | * Make sure we catch invalid writes. 341 | */ 342 | function testWriteInvalid() 343 | { 344 | var data, buf; 345 | 346 | /* Buffer too small */ 347 | buf = new Buffer(4); 348 | data = [ 0, 0]; 349 | ASSERT.throws(function () { 350 | mod_ctype.wuint64(data, 'big', buf, 0); 351 | }, Error, 'buffer too small'); 352 | ASSERT.throws(function () { 353 | mod_ctype.wuint64(data, 'little', buf, 0); 354 | }, Error, 'buffer too small'); 355 | 356 | /* Beyond the end of the buffer */ 357 | buf = new Buffer(12); 358 | data = [ 0, 0]; 359 | ASSERT.throws(function () { 360 | mod_ctype.wuint64(data, 'little', buf, 11); 361 | }, Error, 'write beyond end of buffer'); 362 | ASSERT.throws(function () { 363 | mod_ctype.wuint64(data, 'big', buf, 11); 364 | }, Error, 'write beyond end of buffer'); 365 | 366 | /* Write negative values */ 367 | buf = new Buffer(12); 368 | data = [ -3, 0 ]; 369 | ASSERT.throws(function () { 370 | mod_ctype.wuint64(data, 'big', buf, 1); 371 | }, Error, 'write negative number'); 372 | ASSERT.throws(function () { 373 | mod_ctype.wuint64(data, 'little', buf, 1); 374 | }, Error, 'write negative number'); 375 | 376 | data = [ 0, -3 ]; 377 | ASSERT.throws(function () { 378 | mod_ctype.wuint64(data, 'big', buf, 1); 379 | }, Error, 'write negative number'); 380 | ASSERT.throws(function () { 381 | mod_ctype.wuint64(data, 'little', buf, 1); 382 | }, Error, 'write negative number'); 383 | 384 | data = [ -3, -3 ]; 385 | ASSERT.throws(function () { 386 | mod_ctype.wuint64(data, 'big', buf, 1); 387 | }, Error, 'write negative number'); 388 | ASSERT.throws(function () { 389 | mod_ctype.wuint64(data, 'little', buf, 1); 390 | }, Error, 'write negative number'); 391 | 392 | 393 | /* Write fractional values */ 394 | buf = new Buffer(12); 395 | data = [ 3.33, 0 ]; 396 | ASSERT.throws(function () { 397 | mod_ctype.wuint64(data, 'big', buf, 1); 398 | }, Error, 'write fractions'); 399 | ASSERT.throws(function () { 400 | mod_ctype.wuint64(data, 'little', buf, 1); 401 | }, Error, 'write fractions'); 402 | 403 | data = [ 0, 3.3 ]; 404 | ASSERT.throws(function () { 405 | mod_ctype.wuint64(data, 'big', buf, 1); 406 | }, Error, 'write fractions'); 407 | ASSERT.throws(function () { 408 | mod_ctype.wuint64(data, 'little', buf, 1); 409 | }, Error, 'write fractions'); 410 | 411 | data = [ 3.33, 2.42 ]; 412 | ASSERT.throws(function () { 413 | mod_ctype.wuint64(data, 'big', buf, 1); 414 | }, Error, 'write fractions'); 415 | ASSERT.throws(function () { 416 | mod_ctype.wuint64(data, 'little', buf, 1); 417 | }, Error, 'write fractions'); 418 | 419 | /* Write values that are too large */ 420 | buf = new Buffer(12); 421 | data = [ 0xffffffffff, 23 ]; 422 | ASSERT.throws(function () { 423 | mod_ctype.wuint64(data, 'big', buf, 1); 424 | }, Error, 'write too large'); 425 | ASSERT.throws(function () { 426 | mod_ctype.wuint64(data, 'little', buf, 1); 427 | }, Error, 'write too large'); 428 | 429 | data = [ 0xffffffffff, 0xffffff238 ]; 430 | ASSERT.throws(function () { 431 | mod_ctype.wuint64(data, 'big', buf, 1); 432 | }, Error, 'write too large'); 433 | ASSERT.throws(function () { 434 | mod_ctype.wuint64(data, 'little', buf, 1); 435 | }, Error, 'write too large'); 436 | 437 | data = [ 0x23, 0xffffff238 ]; 438 | ASSERT.throws(function () { 439 | mod_ctype.wuint64(data, 'big', buf, 1); 440 | }, Error, 'write too large'); 441 | ASSERT.throws(function () { 442 | mod_ctype.wuint64(data, 'little', buf, 1); 443 | }, Error, 'write too large'); 444 | } 445 | 446 | 447 | testRead(); 448 | testReadOver(); 449 | testWriteZero(); 450 | testWrite(); 451 | testWriteInvalid(); 452 | -------------------------------------------------------------------------------- /tst/ctio/uint/tst.roundtrip.js: -------------------------------------------------------------------------------- 1 | /* 2 | * A battery of tests for sucessful round-trip between writes and reads 3 | */ 4 | 5 | var mod_ctype = require('../../../ctio.js'); 6 | var ASSERT = require('assert'); 7 | 8 | 9 | /* 10 | * What the heck, let's just test every value for 8-bits. 11 | */ 12 | 13 | function test8() { 14 | var data = new Buffer(1); 15 | var i; 16 | for (i = 0; i < 256; i++) { 17 | mod_ctype.wuint8(i, 'big', data, 0); 18 | ASSERT.equal(i, mod_ctype.ruint8(data, 'big', 0)); 19 | mod_ctype.wuint8(i, 'little', data, 0); 20 | ASSERT.equal(i, mod_ctype.ruint8(data, 'little', 0)); 21 | } 22 | ASSERT.ok(true); 23 | } 24 | 25 | /* 26 | * Test a random sample of 256 values in the 16-bit unsigned range 27 | */ 28 | 29 | function test16() { 30 | var data = new Buffer(2); 31 | var i = 0; 32 | for (i = 0; i < 256; i++) { 33 | var value = Math.round(Math.random() * Math.pow(2, 16)); 34 | mod_ctype.wuint16(value, 'big', data, 0); 35 | ASSERT.equal(value, mod_ctype.ruint16(data, 'big', 0)); 36 | mod_ctype.wuint16(value, 'little', data, 0); 37 | ASSERT.equal(value, mod_ctype.ruint16(data, 'little', 0)); 38 | } 39 | } 40 | 41 | /* 42 | * Test a random sample of 256 values in the 32-bit unsigned range 43 | */ 44 | 45 | function test32() { 46 | var data = new Buffer(4); 47 | var i = 0; 48 | for (i = 0; i < 256; i++) { 49 | var value = Math.round(Math.random() * Math.pow(2, 32)); 50 | mod_ctype.wuint32(value, 'big', data, 0); 51 | ASSERT.equal(value, mod_ctype.ruint32(data, 'big', 0)); 52 | mod_ctype.wuint32(value, 'little', data, 0); 53 | ASSERT.equal(value, mod_ctype.ruint32(data, 'little', 0)); 54 | } 55 | } 56 | 57 | /* 58 | * Test a random sample of 256 values in the 64-bit unsigned range 59 | */ 60 | 61 | function test64() { 62 | var data = new Buffer(8); 63 | var i = 0; 64 | for (i = 0; i < 256; i++) { 65 | var low = Math.round(Math.random() * Math.pow(2, 32)); 66 | var high = Math.round(Math.random() * Math.pow(2, 32)); 67 | mod_ctype.wuint64([high, low], 'big', data, 0); 68 | var result = mod_ctype.ruint64(data, 'big', 0); 69 | ASSERT.equal(high, result[0]); 70 | ASSERT.equal(low, result[1]); 71 | mod_ctype.wuint64([high, low], 'little', data, 0); 72 | result = mod_ctype.ruint64(data, 'little', 0); 73 | ASSERT.equal(high, result[0]); 74 | ASSERT.equal(low, result[1]); 75 | } 76 | } 77 | 78 | exports.test8 = test8; 79 | exports.test16 = test16; 80 | exports.test32 = test32; 81 | exports.test64 = test64; 82 | -------------------------------------------------------------------------------- /tst/ctio/uint/tst.ruint.js: -------------------------------------------------------------------------------- 1 | /* 2 | * A battery of tests to help us read a series of uints 3 | */ 4 | 5 | var mod_ctype = require('../../../ctio.js'); 6 | var ASSERT = require('assert'); 7 | 8 | /* 9 | * We need to check the following things: 10 | * - We are correctly resolving big endian (doesn't mean anything for 8 bit) 11 | * - Correctly resolving little endian (doesn't mean anything for 8 bit) 12 | * - Correctly using the offsets 13 | * - Correctly interpreting values that are beyond the signed range as unsigned 14 | */ 15 | function test8() 16 | { 17 | var data = new Buffer(4); 18 | data[0] = 23; 19 | data[1] = 23; 20 | data[2] = 23; 21 | data[3] = 23; 22 | ASSERT.equal(23, mod_ctype.ruint8(data, 'big', 0)); 23 | ASSERT.equal(23, mod_ctype.ruint8(data, 'little', 0)); 24 | ASSERT.equal(23, mod_ctype.ruint8(data, 'big', 1)); 25 | ASSERT.equal(23, mod_ctype.ruint8(data, 'little', 1)); 26 | ASSERT.equal(23, mod_ctype.ruint8(data, 'big', 2)); 27 | ASSERT.equal(23, mod_ctype.ruint8(data, 'little', 2)); 28 | ASSERT.equal(23, mod_ctype.ruint8(data, 'big', 3)); 29 | ASSERT.equal(23, mod_ctype.ruint8(data, 'little', 3)); 30 | data[0] = 255; /* If it became a signed int, would be -1 */ 31 | ASSERT.equal(255, mod_ctype.ruint8(data, 'big', 0)); 32 | ASSERT.equal(255, mod_ctype.ruint8(data, 'little', 0)); 33 | } 34 | 35 | /* 36 | * Test 16 bit unsigned integers. We need to verify the same set as 8 bit, only 37 | * now some of the issues actually matter: 38 | * - We are correctly resolving big endian 39 | * - Correctly resolving little endian 40 | * - Correctly using the offsets 41 | * - Correctly interpreting values that are beyond the signed range as unsigned 42 | */ 43 | function test16() 44 | { 45 | var data = new Buffer(4); 46 | /* Test signed values first */ 47 | data[0] = 0; 48 | data[1] = 0x23; 49 | data[2] = 0x42; 50 | data[3] = 0x3f; 51 | 52 | ASSERT.equal(0x23, mod_ctype.ruint16(data, 'big', 0)); 53 | ASSERT.equal(0x2342, mod_ctype.ruint16(data, 'big', 1)); 54 | ASSERT.equal(0x423f, mod_ctype.ruint16(data, 'big', 2)); 55 | 56 | ASSERT.equal(0x2300, mod_ctype.ruint16(data, 'little', 0)); 57 | ASSERT.equal(0x4223, mod_ctype.ruint16(data, 'little', 1)); 58 | ASSERT.equal(0x3f42, mod_ctype.ruint16(data, 'little', 2)); 59 | 60 | data[0] = 0xfe; 61 | data[1] = 0xfe; 62 | 63 | ASSERT.equal(0xfefe, mod_ctype.ruint16(data, 'big', 0)); 64 | ASSERT.equal(0xfefe, mod_ctype.ruint16(data, 'little', 0)); 65 | } 66 | 67 | /* 68 | * Test 32 bit unsigned integers. We need to verify the same set as 8 bit, only 69 | * now some of the issues actually matter: 70 | * - We are correctly resolving big endian 71 | * - Correctly using the offsets 72 | * - Correctly interpreting values that are beyond the signed range as unsigned 73 | */ 74 | function test32() 75 | { 76 | var data = new Buffer(8); 77 | data[0] = 0x32; 78 | data[1] = 0x65; 79 | data[2] = 0x42; 80 | data[3] = 0x56; 81 | data[4] = 0x23; 82 | data[5] = 0xff; 83 | 84 | ASSERT.equal(0x32654256, mod_ctype.ruint32(data, 'big', 0)); 85 | ASSERT.equal(0x65425623, mod_ctype.ruint32(data, 'big', 1)); 86 | ASSERT.equal(0x425623ff, mod_ctype.ruint32(data, 'big', 2)); 87 | 88 | ASSERT.equal(0x56426532, mod_ctype.ruint32(data, 'little', 0)); 89 | ASSERT.equal(0x23564265, mod_ctype.ruint32(data, 'little', 1)); 90 | ASSERT.equal(0xff235642, mod_ctype.ruint32(data, 'little', 2)); 91 | } 92 | 93 | test8(); 94 | test16(); 95 | test32(); 96 | -------------------------------------------------------------------------------- /tst/ctio/uint/tst.wuint.js: -------------------------------------------------------------------------------- 1 | /* 2 | * A battery of tests to help us read a series of uints 3 | */ 4 | 5 | var mod_ctype = require('../../../ctio.js'); 6 | var ASSERT = require('assert'); 7 | 8 | /* 9 | * We need to check the following things: 10 | * - We are correctly resolving big endian (doesn't mean anything for 8 bit) 11 | * - Correctly resolving little endian (doesn't mean anything for 8 bit) 12 | * - Correctly using the offsets 13 | * - Correctly interpreting values that are beyond the signed range as unsigned 14 | */ 15 | function test8() 16 | { 17 | var data = new Buffer(4); 18 | mod_ctype.wuint8(23, 'big', data, 0); 19 | mod_ctype.wuint8(23, 'big', data, 1); 20 | mod_ctype.wuint8(23, 'big', data, 2); 21 | mod_ctype.wuint8(23, 'big', data, 3); 22 | ASSERT.equal(23, data[0]); 23 | ASSERT.equal(23, data[1]); 24 | ASSERT.equal(23, data[2]); 25 | ASSERT.equal(23, data[3]); 26 | mod_ctype.wuint8(23, 'little', data, 0); 27 | mod_ctype.wuint8(23, 'little', data, 1); 28 | mod_ctype.wuint8(23, 'little', data, 2); 29 | mod_ctype.wuint8(23, 'little', data, 3); 30 | ASSERT.equal(23, data[0]); 31 | ASSERT.equal(23, data[1]); 32 | ASSERT.equal(23, data[2]); 33 | ASSERT.equal(23, data[3]); 34 | mod_ctype.wuint8(255, 'big', data, 0); 35 | ASSERT.equal(255, data[0]); 36 | mod_ctype.wuint8(255, 'little', data, 0); 37 | ASSERT.equal(255, data[0]); 38 | } 39 | 40 | function test16() 41 | { 42 | var value = 0x2343; 43 | var data = new Buffer(4); 44 | mod_ctype.wuint16(value, 'big', data, 0); 45 | ASSERT.equal(0x23, data[0]); 46 | ASSERT.equal(0x43, data[1]); 47 | mod_ctype.wuint16(value, 'big', data, 1); 48 | ASSERT.equal(0x23, data[1]); 49 | ASSERT.equal(0x43, data[2]); 50 | mod_ctype.wuint16(value, 'big', data, 2); 51 | ASSERT.equal(0x23, data[2]); 52 | ASSERT.equal(0x43, data[3]); 53 | 54 | mod_ctype.wuint16(value, 'little', data, 0); 55 | ASSERT.equal(0x23, data[1]); 56 | ASSERT.equal(0x43, data[0]); 57 | 58 | mod_ctype.wuint16(value, 'little', data, 1); 59 | ASSERT.equal(0x23, data[2]); 60 | ASSERT.equal(0x43, data[1]); 61 | 62 | mod_ctype.wuint16(value, 'little', data, 2); 63 | ASSERT.equal(0x23, data[3]); 64 | ASSERT.equal(0x43, data[2]); 65 | 66 | value = 0xff80; 67 | mod_ctype.wuint16(value, 'little', data, 0); 68 | ASSERT.equal(0xff, data[1]); 69 | ASSERT.equal(0x80, data[0]); 70 | 71 | mod_ctype.wuint16(value, 'big', data, 0); 72 | ASSERT.equal(0xff, data[0]); 73 | ASSERT.equal(0x80, data[1]); 74 | } 75 | 76 | function test32() 77 | { 78 | var data = new Buffer(6); 79 | var value = 0xe7f90a6d; 80 | 81 | mod_ctype.wuint32(value, 'big', data, 0); 82 | ASSERT.equal(0xe7, data[0]); 83 | ASSERT.equal(0xf9, data[1]); 84 | ASSERT.equal(0x0a, data[2]); 85 | ASSERT.equal(0x6d, data[3]); 86 | 87 | mod_ctype.wuint32(value, 'big', data, 1); 88 | ASSERT.equal(0xe7, data[1]); 89 | ASSERT.equal(0xf9, data[2]); 90 | ASSERT.equal(0x0a, data[3]); 91 | ASSERT.equal(0x6d, data[4]); 92 | 93 | mod_ctype.wuint32(value, 'big', data, 2); 94 | ASSERT.equal(0xe7, data[2]); 95 | ASSERT.equal(0xf9, data[3]); 96 | ASSERT.equal(0x0a, data[4]); 97 | ASSERT.equal(0x6d, data[5]); 98 | 99 | mod_ctype.wuint32(value, 'little', data, 0); 100 | ASSERT.equal(0xe7, data[3]); 101 | ASSERT.equal(0xf9, data[2]); 102 | ASSERT.equal(0x0a, data[1]); 103 | ASSERT.equal(0x6d, data[0]); 104 | 105 | mod_ctype.wuint32(value, 'little', data, 1); 106 | ASSERT.equal(0xe7, data[4]); 107 | ASSERT.equal(0xf9, data[3]); 108 | ASSERT.equal(0x0a, data[2]); 109 | ASSERT.equal(0x6d, data[1]); 110 | 111 | mod_ctype.wuint32(value, 'little', data, 2); 112 | ASSERT.equal(0xe7, data[5]); 113 | ASSERT.equal(0xf9, data[4]); 114 | ASSERT.equal(0x0a, data[3]); 115 | ASSERT.equal(0x6d, data[2]); 116 | } 117 | 118 | function test64() 119 | { 120 | var data = new Buffer(10); 121 | var value = 0x0007cda8e7f90a6d; 122 | var high = Math.floor(value / Math.pow(2, 32)); 123 | var low = value - (high * Math.pow(2, 32)); 124 | ASSERT.equal(0x0007cda8, high); 125 | ASSERT.equal(0xe7f90a6d, low); 126 | 127 | mod_ctype.wuint64([high, low], 'big', data, 0); 128 | ASSERT.equal(0x00, data[0]); 129 | ASSERT.equal(0x07, data[1]); 130 | ASSERT.equal(0xcd, data[2]); 131 | ASSERT.equal(0xa8, data[3]); 132 | ASSERT.equal(0xe7, data[4]); 133 | ASSERT.equal(0xf9, data[5]); 134 | ASSERT.equal(0x0a, data[6]); 135 | ASSERT.equal(0x6d, data[7]); 136 | 137 | mod_ctype.wuint64([high, low], 'little', data, 0); 138 | ASSERT.equal(0x6d, data[0]); 139 | ASSERT.equal(0x0a, data[1]); 140 | ASSERT.equal(0xf9, data[2]); 141 | ASSERT.equal(0xe7, data[3]); 142 | ASSERT.equal(0xa8, data[4]); 143 | ASSERT.equal(0xcd, data[5]); 144 | ASSERT.equal(0x07, data[6]); 145 | ASSERT.equal(0x00, data[7]); 146 | } 147 | 148 | test8(); 149 | test16(); 150 | test32(); 151 | test64(); 152 | 153 | exports.test8 = test8; 154 | exports.test16 = test16; 155 | exports.test32 = test32; 156 | exports.test64 = test64; 157 | -------------------------------------------------------------------------------- /tst/ctype/tst.basicr.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple does to see if it works at all 3 | */ 4 | var mod_ctype = require('../../ctype'); 5 | var ASSERT = require('assert'); 6 | var mod_util = require('util'); 7 | 8 | function test() 9 | { 10 | var ii, p, result, buffer; 11 | 12 | p = new mod_ctype.Parser({ endian: 'little' }); 13 | buffer = new Buffer(4); 14 | buffer[0] = 23; 15 | buffer[3] = 42; 16 | result = p.readData([ { x: { type: 'uint8_t' }}, 17 | { y: { type: 'uint8_t', offset: 3 }} 18 | ], buffer, 0); 19 | ASSERT.equal(23, result['x']); 20 | ASSERT.equal(42, result['y']); 21 | 22 | buffer = new Buffer(23); 23 | for (ii = 0; ii < 23; ii++) 24 | buffer[ii] = 0; 25 | 26 | buffer.write('Hello, world!'); 27 | result = p.readData([ { x: { type: 'char[20]' }} ], buffer, 0); 28 | 29 | /* 30 | * This is currently broken behvaior, need to redesign check 31 | * ASSERT.equal('Hello, world!', result['x'].toString('utf-8', 0, 32 | * result['x'].length)); 33 | */ 34 | 35 | buffer = new Buffer(4); 36 | buffer[0] = 0x03; 37 | buffer[1] = 0x24; 38 | buffer[2] = 0x25; 39 | buffer[3] = 0x26; 40 | result = p.readData([ { y: { type: 'uint8_t' }}, 41 | { x: { type: 'uint8_t[y]' }}], buffer, 0); 42 | console.log(mod_util.inspect(result, true)); 43 | 44 | p.typedef('ssize_t', 'int32_t'); 45 | ASSERT.deepEqual({ 'ssize_t': 'int32_t' }, p.lstypes()); 46 | result = p.readData([ { x: { type: 'ssize_t' } } ], buffer, 0); 47 | ASSERT.equal(0x26252403, result['x']); 48 | } 49 | 50 | test(); 51 | -------------------------------------------------------------------------------- /tst/ctype/tst.basicw.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple does it fucking work at all test 3 | */ 4 | 5 | var mod_ctype = require('../../ctype'); 6 | var ASSERT = require('assert'); 7 | var mod_util = require('util'); 8 | 9 | function test() 10 | { 11 | var ii, p, buffer, buf2; 12 | 13 | p = new mod_ctype.Parser({ endian: 'big' }); 14 | buffer = new Buffer(4); 15 | p.writeData([ { x: { type: 'uint8_t', value: 23 }}, 16 | { y: { type: 'uint8_t', offset: 3, value: 42 }} 17 | ], buffer, 0); 18 | ASSERT.equal(23, buffer[0]); 19 | ASSERT.equal(42, buffer[3]); 20 | 21 | buffer = new Buffer(20); 22 | for (ii = 0; ii < 20; ii++) 23 | buffer[ii] = 0; 24 | 25 | buffer.write('Hello, world!'); 26 | buf2 = new Buffer(22); 27 | p.writeData([ { x: { type: 'char[20]', value: buffer }} ], buf2, 0); 28 | for (ii = 0; ii < 20; ii++) 29 | ASSERT.equal(buffer[ii], buf2[ii]); 30 | /* 31 | * This is currently broken behvaior, need to redesign check 32 | * ASSERT.equal('Hello, world!', result['x'].toString('utf-8', 0, 33 | * result['x'].length)); 34 | */ 35 | 36 | buffer = new Buffer(4); 37 | p.writeData([ { y: { type: 'uint8_t', value: 3 }}, 38 | { x: { type: 'uint8_t[y]', value: [ 0x24, 0x25, 0x26] }}], 39 | buffer, 0); 40 | console.log(mod_util.inspect(buffer)); 41 | 42 | p.typedef('ssize_t', 'int32_t'); 43 | ASSERT.deepEqual({ 'ssize_t': 'int32_t' }, p.lstypes()); 44 | } 45 | -------------------------------------------------------------------------------- /tst/ctype/tst.char.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Test the different forms of reading characters: 3 | * 4 | * - the default, a single element buffer 5 | * - uint8, values are uint8_ts 6 | * - int8, values are int8_ts 7 | */ 8 | var mod_ctype = require('../../ctype'); 9 | var mod_assert = require('assert'); 10 | 11 | function test() 12 | { 13 | var p, buf, res; 14 | 15 | buf = new Buffer(1); 16 | buf[0] = 255; 17 | 18 | p = new mod_ctype.Parser({ endian: 'little'}); 19 | res = p.readData([ { c: { type: 'char' }} ], buf, 0); 20 | res = res['c']; 21 | mod_assert.ok(res instanceof Buffer); 22 | mod_assert.equal(255, res[0]); 23 | 24 | p = new mod_ctype.Parser({ endian: 'little', 25 | 'char-type': 'int8' }); 26 | res = p.readData([ { c: { type: 'char' }} ], buf, 0); 27 | res = res['c']; 28 | mod_assert.ok(typeof (res) == 'number', 'got typeof (res): ' + 29 | typeof (res)); 30 | mod_assert.equal(-1, res); 31 | 32 | p = new mod_ctype.Parser({ endian: 'little', 33 | 'char-type': 'uint8' }); 34 | res = p.readData([ { c: { type: 'char' }} ], buf, 0); 35 | res = res['c']; 36 | mod_assert.ok(typeof (res) == 'number', 'got typeof (res): ' + 37 | typeof (res)); 38 | mod_assert.equal(255, res); 39 | 40 | } 41 | 42 | test(); 43 | -------------------------------------------------------------------------------- /tst/ctype/tst.endian.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple test to make sure that the endian setting works. 3 | */ 4 | 5 | var mod_ctype = require('../../ctype.js'); 6 | var mod_assert = require('assert'); 7 | 8 | function test() 9 | { 10 | var parser, buf; 11 | 12 | parser = new mod_ctype.Parser({ 13 | endian: 'little' 14 | }); 15 | 16 | buf = new Buffer(2); 17 | parser.writeData([ { key: { type: 'uint16_t' } } ], buf, 0, [ 0x1234 ]); 18 | mod_assert.equal(buf[0], 0x34); 19 | mod_assert.equal(buf[1], 0x12); 20 | parser.setEndian('big'); 21 | 22 | parser.writeData([ { key: { type: 'uint16_t' } } ], buf, 0, [ 0x1234 ]); 23 | mod_assert.equal(buf[0], 0x12); 24 | mod_assert.equal(buf[1], 0x34); 25 | 26 | parser.setEndian('little'); 27 | parser.writeData([ { key: { type: 'uint16_t' } } ], buf, 0, [ 0x1234 ]); 28 | mod_assert.equal(buf[0], 0x34); 29 | mod_assert.equal(buf[1], 0x12); 30 | } 31 | 32 | function fail() 33 | { 34 | var parser; 35 | 36 | parser = new mod_ctype.Parser({ 37 | endian: 'little' 38 | }); 39 | mod_assert.throws(function () { 40 | parser.setEndian('littlebigwrong'); 41 | }); 42 | } 43 | 44 | test(); 45 | fail(); 46 | -------------------------------------------------------------------------------- /tst/ctype/tst.oldwrite.js: -------------------------------------------------------------------------------- 1 | /* 2 | * A long overdue test to go through and verify that we can read and write 3 | * structures as well as nested structures. 4 | */ 5 | 6 | var mod_ctype = require('../../ctype.js'); 7 | var mod_assert = require('assert'); 8 | 9 | function test() 10 | { 11 | var parser, buf, data; 12 | parser = new mod_ctype.Parser({ 13 | endian: 'little' 14 | }); 15 | parser.typedef('point_t', [ 16 | { x: { type: 'uint8_t' } }, 17 | { y: { type: 'uint8_t' } } 18 | ]); 19 | buf = new Buffer(2); 20 | data = [ 21 | { point: { type: 'point_t', value: [ 23, 42 ] } } 22 | ]; 23 | parser.writeData(data, buf, 0); 24 | mod_assert.ok(buf[0] == 23); 25 | mod_assert.ok(buf[1] == 42); 26 | } 27 | 28 | test(); 29 | -------------------------------------------------------------------------------- /tst/ctype/tst.readSize.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Testing to ensure we're reading the expected number bytes 3 | */ 4 | var mod_ctype = require('../../ctype'); 5 | var ASSERT = require('assert'); 6 | 7 | function testUint8() 8 | { 9 | var parser, result, buffer; 10 | parser = new mod_ctype.Parser({ endian: 'little' }); 11 | buffer = new Buffer('80', 'hex'); 12 | result = parser.readStruct([ { item: { type: 'uint8_t' } } ], buffer, 13 | 0); 14 | ASSERT.equal(result['size'], 1); 15 | } 16 | 17 | function testSint8() 18 | { 19 | var parser, result, buffer; 20 | parser = new mod_ctype.Parser({ endian: 'little' }); 21 | buffer = new Buffer('80', 'hex'); 22 | result = parser.readStruct([ { item: { type: 'int8_t' } } ], buffer, 0); 23 | ASSERT.equal(result['size'], 1); 24 | } 25 | 26 | function testUint16() 27 | { 28 | var parser, result, buffer; 29 | parser = new mod_ctype.Parser({ endian: 'little' }); 30 | buffer = new Buffer('8000', 'hex'); 31 | result = parser.readStruct([ { item: { type: 'uint16_t' } } ], buffer, 32 | 0); 33 | ASSERT.equal(result['size'], 2); 34 | } 35 | 36 | function testSint16() 37 | { 38 | var parser, result, buffer; 39 | parser = new mod_ctype.Parser({ endian: 'little' }); 40 | buffer = new Buffer('8000', 'hex'); 41 | result = parser.readStruct([ { item: { type: 'int16_t' } } ], buffer, 42 | 0); 43 | ASSERT.equal(result['size'], 2); 44 | } 45 | 46 | function testUint32() 47 | { 48 | var parser, result, buffer; 49 | parser = new mod_ctype.Parser({ endian: 'little' }); 50 | buffer = new Buffer('80000000', 'hex'); 51 | result = parser.readStruct([ { item: { type: 'uint32_t' } } ], buffer, 52 | 0); 53 | ASSERT.equal(result['size'], 4); 54 | } 55 | 56 | function testSint32() 57 | { 58 | var parser, result, buffer; 59 | parser = new mod_ctype.Parser({ endian: 'little' }); 60 | buffer = new Buffer('80000000', 'hex'); 61 | result = parser.readStruct([ { item: { type: 'int32_t' } } ], buffer, 62 | 0); 63 | ASSERT.equal(result['size'], 4); 64 | } 65 | 66 | function testUint64() 67 | { 68 | var parser, result, buffer; 69 | parser = new mod_ctype.Parser({ endian: 'little' }); 70 | buffer = new Buffer('8000000000000000', 'hex'); 71 | result = parser.readStruct([ { item: { type: 'uint64_t' } } ], buffer, 72 | 0); 73 | ASSERT.equal(result['size'], 8); 74 | } 75 | 76 | function testSint64() 77 | { 78 | var parser, result, buffer; 79 | parser = new mod_ctype.Parser({ endian: 'little' }); 80 | buffer = new Buffer('8000000000000000', 'hex'); 81 | result = parser.readStruct([ { item: { type: 'int64_t' } } ], buffer, 82 | 0); 83 | ASSERT.equal(result['size'], 8); 84 | } 85 | 86 | function testFloat() 87 | { 88 | var parser, result, buffer; 89 | parser = new mod_ctype.Parser({ endian: 'little' }); 90 | buffer = new Buffer('ABAAAA3E', 'hex'); 91 | result = parser.readStruct([ { item: { type: 'float' } } ], buffer, 0); 92 | ASSERT.equal(result['size'], 4); 93 | } 94 | 95 | function testDouble() 96 | { 97 | var parser, result, buffer; 98 | parser = new mod_ctype.Parser({ endian: 'little' }); 99 | buffer = new Buffer('000000000000F03F', 'hex'); 100 | result = parser.readStruct([ { item: { type: 'double' } } ], buffer, 0); 101 | ASSERT.equal(result['size'], 8); 102 | } 103 | 104 | function testChar() 105 | { 106 | var parser, result, buffer; 107 | parser = new mod_ctype.Parser({ endian: 'little' }); 108 | buffer = new Buffer('t'); 109 | result = parser.readStruct([ { item: { type: 'char' } } ], buffer, 0); 110 | ASSERT.equal(result['size'], 1); 111 | } 112 | 113 | function test() 114 | { 115 | testSint8(); 116 | testUint8(); 117 | testSint16(); 118 | testUint16(); 119 | testSint32(); 120 | testUint32(); 121 | testSint64(); 122 | testUint64(); 123 | testFloat(); 124 | testDouble(); 125 | testChar(); 126 | } 127 | 128 | test(); 129 | -------------------------------------------------------------------------------- /tst/ctype/tst.structw.js: -------------------------------------------------------------------------------- 1 | /* 2 | * A long overdue test to go through and verify that we can read and write 3 | * structures as well as nested structures. 4 | */ 5 | 6 | var mod_ctype = require('../../ctype.js'); 7 | var mod_assert = require('assert'); 8 | 9 | function test() 10 | { 11 | var parser, buf, data; 12 | parser = new mod_ctype.Parser({ 13 | endian: 'little' 14 | }); 15 | parser.typedef('point_t', [ 16 | { x: { type: 'uint8_t' } }, 17 | { y: { type: 'uint8_t' } } 18 | ]); 19 | buf = new Buffer(2); 20 | data = [ 21 | { point: { type: 'point_t' } } 22 | ]; 23 | parser.writeData(data, buf, 0, [ [ 23, 42 ] ]); 24 | mod_assert.ok(buf[0] == 23); 25 | mod_assert.ok(buf[1] == 42); 26 | } 27 | 28 | test(); 29 | -------------------------------------------------------------------------------- /tst/ctype/tst.writeStruct.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Test to verify that the offset is incremented when structures are written to. 3 | * Hopefully we will not regress issue #41 4 | */ 5 | 6 | var mod_ctype = require('../../ctype.js'); 7 | var mod_assert = require('assert'); 8 | 9 | function test() 10 | { 11 | var parser, buf, data; 12 | parser = new mod_ctype.Parser({ 13 | endian: 'little' 14 | }); 15 | parser.typedef('point_t', [ 16 | { x: { type: 'uint8_t' } }, 17 | { y: { type: 'uint8_t' } } 18 | ]); 19 | buf = new Buffer(4); 20 | data = [ 21 | { point1: { type: 'point_t' } }, 22 | { point2: { type: 'point_t' } } 23 | ]; 24 | parser.writeData(data, buf, 0, [ [ 23, 42 ], [ 91, 18 ] ]); 25 | mod_assert.ok(buf[0] == 23); 26 | mod_assert.ok(buf[1] == 42); 27 | mod_assert.ok(buf[2] == 91); 28 | mod_assert.ok(buf[3] == 18); 29 | } 30 | 31 | test(); 32 | --------------------------------------------------------------------------------