structurae
Advanced tools
Comparing version 1.4.0 to 1.5.0
@@ -7,2 +7,6 @@ # Changelog | ||
## [1.5.0] - 2019-06-28 | ||
### Added | ||
- Add StringArrayView class to support arrays of strings in ObjectView | ||
## [1.4.0] - 2019-06-20 | ||
@@ -34,14 +38,14 @@ ### Added | ||
### Added | ||
- RecordArray#fromObject ([b263...](https://github.com/zandaqo/structurae/commit/b263dc7503343a9114233e0a0ce027d6504d97cf)) | ||
- RecordArray#fromObject | ||
## [1.1.0] - 2019-06-07 | ||
### Added | ||
- BitArray ([6a35...](https://github.com/zandaqo/structurae/commit/6a35378c32810f024de18236a9f2dc63f45c805f)) | ||
- RankedBitArray ([4dce...](https://github.com/zandaqo/structurae/commit/4dce705e469f78bbdd1ac355876eaade0f131090)) | ||
- BitArray | ||
- RankedBitArray | ||
### Changed | ||
- Pool extends BitArray ([6a35...](https://github.com/zandaqo/structurae/commit/6a35378c32810f024de18236a9f2dc63f45c805f)) | ||
- Pool extends BitArray | ||
## [1.0.1] - 2019-06-04 | ||
### Fixed | ||
- Set correct size for Pool ([3ced...](https://github.com/zandaqo/structurae/commit/3ced870d1d0accb645d1ad2734fdeb5eb9759fb0)). | ||
- Set correct size for Pool. |
@@ -131,3 +131,2 @@ // Type definitions for structurae | ||
static getMatcher(matcher: UnpackedInt): Matcher; | ||
static [Symbol.iterator]: Iterable<number>; | ||
static fields: (Field|FieldName)[]; | ||
@@ -213,2 +212,16 @@ static size: number; | ||
declare class ArrayView extends ObjectView { | ||
size: number; | ||
get(index: number): ObjectView; | ||
set(index: number, value: object): this; | ||
setView(index: number, value: ObjectView): this; | ||
toObject(): object[]; | ||
static from(value: ArrayLike<object>, array?: ArrayView): ArrayView; | ||
static of(size: number): ArrayView; | ||
static getLength(size: number): number; | ||
} | ||
export declare function ArrayViewMixin<T extends ObjectView>(Base: Constructor<T>): Constructor<T & ArrayView> | ||
type ViewType = typeof ArrayView | typeof ObjectView | typeof TypedArrayView | typeof StringView; | ||
@@ -260,16 +273,39 @@ | ||
declare class ArrayView extends ObjectView { | ||
export declare class StringView extends Uint8Array { | ||
size: number; | ||
static masks: Int8Array; | ||
static encoder: TextEncoder; | ||
static decoder: TextDecoder; | ||
get(index: number): ObjectView; | ||
set(index: number, value: object): this; | ||
setView(index: number, value: ObjectView): this; | ||
toObject(): object[]; | ||
static from(value: ArrayLike<object>, array?: ArrayView): ArrayView; | ||
static of(size: number): ArrayView; | ||
static getLength(size: number): number; | ||
characters(): Iterable<string>; | ||
charAt(index?: number): string; | ||
private getCharEnd(index: number): number; | ||
private getCharStart(index: number, startCharIndex?: number, startIndex?: number): number; | ||
replace(pattern: Collection, replacement: Collection): this; | ||
reverse(): this; | ||
search(searchValue: Collection, fromIndex?: number): number; | ||
private searchNaive(searchValue: Collection, fromIndex?: number): number; | ||
private searchShiftOr(searchValue: Collection, fromIndex?: number): number; | ||
substring(indexStart: number, indexEnd?: number): string; | ||
private toChar(index: number): string; | ||
toString(): string; | ||
trim(): StringView; | ||
static fromString(string: string, size?: number): StringView; | ||
static getByteSize(string: string): number; | ||
} | ||
export declare function ArrayViewMixin<T extends ObjectView>(Base: Constructor<T>): Constructor<T & ArrayView> | ||
export declare class StringArrayView { | ||
size: number; | ||
stringLength: number; | ||
bytes: Uint8Array; | ||
constructor(buffer: ArrayBuffer, byteOffset: number, byteLength: number, stringLength: number); | ||
get(index: number): StringView; | ||
set(index: number, value: string|StringView): this; | ||
toObject(): Array<string>; | ||
static from(value: ArrayLike<string>, stringLength: number, array?: StringArrayView): StringArrayView; | ||
static getLength(size: number, stringLength: number): number; | ||
static of(size: number, stringLength: number): StringArrayView; | ||
} | ||
declare class TypedArrayView extends DataView { | ||
@@ -316,23 +352,2 @@ size: number; | ||
export declare class StringView extends Uint8Array { | ||
size: number; | ||
static masks: Int8Array; | ||
characters(): Iterable<string>; | ||
charAt(index?: number): string; | ||
private getCharEnd(index: number): number; | ||
private getCharStart(index: number, startCharIndex?: number, startIndex?: number): number; | ||
replace(pattern: Collection, replacement: Collection): this; | ||
reverse(): this; | ||
search(searchValue: Collection, fromIndex?: number): number; | ||
private searchNaive(searchValue: Collection, fromIndex?: number): number; | ||
private searchShiftOr(searchValue: Collection, fromIndex?: number): number; | ||
substring(indexStart: number, indexEnd?: number): string; | ||
private toChar(index: number): string; | ||
toString(): string; | ||
trim(): StringView; | ||
static fromString(string: string, size?: number): StringView; | ||
static getByteSize(string: string): number; | ||
} | ||
export declare class BinaryHeap extends Array { | ||
@@ -339,0 +354,0 @@ heapify(): this; |
@@ -18,2 +18,3 @@ const BitField = require('./lib/bit-field'); | ||
const StringView = require('./lib/string-view'); | ||
const StringArrayView = require('./lib/string-array-view'); | ||
const TypedArrayViewMixin = require('./lib/typed-array-view'); | ||
@@ -54,3 +55,4 @@ | ||
StringView, | ||
StringArrayView, | ||
TypedArrayViewMixin, | ||
}; |
const StringView = require('./string-view'); | ||
const DataArrayMixin = require('./array-view'); | ||
const StringArrayView = require('./string-array-view'); | ||
const ArrayViewMixin = require('./array-view'); | ||
const TypedArrayViewMixin = require('./typed-array-view'); | ||
@@ -36,3 +37,2 @@ | ||
biguint64: 8, | ||
string: 0, | ||
}; | ||
@@ -52,3 +52,3 @@ | ||
const { | ||
type, littleEndian, start, ctor, length, | ||
type, littleEndian, start, ctor, length, stringLength, | ||
} = this.constructor.schema[field]; | ||
@@ -66,2 +66,3 @@ switch (type) { | ||
case 'biguint64': return this.getBigUint64(start, littleEndian); | ||
case 'stringarray': return new StringArrayView(this.buffer, this.byteOffset + start, length, stringLength); | ||
default: return this.getView(start, length, ctor); | ||
@@ -90,2 +91,21 @@ } | ||
* @param {number} position | ||
* @param {number} size | ||
* @param {number} length | ||
* @param {number} stringLength | ||
* @returns {void} | ||
*/ | ||
getStringArray(position, size, length, stringLength) { | ||
const array = new Array(size); | ||
for (let i = 0; i < size; i++) { | ||
const string = new StringView( | ||
this.buffer, this.byteOffset + position + (i * stringLength), stringLength, | ||
); | ||
array[i] = string.toString(); | ||
} | ||
return array; | ||
} | ||
/** | ||
* @private | ||
* @param {number} position | ||
* @param {Class<TypedArrayView>} ctor | ||
@@ -116,3 +136,3 @@ * @param {number} size | ||
const { | ||
type, littleEndian, start, ctor: Ctor, length, size, | ||
type, littleEndian, start, ctor: Ctor, length, size, stringLength, | ||
} = schema[name]; | ||
@@ -134,2 +154,3 @@ let value; | ||
case 'typedarray': value = this.getTypedArray(position, Ctor, size); break; | ||
case 'stringarray': value = this.getStringArray(position, size, length, stringLength); break; | ||
case 'array': value = this.getArray(position, Ctor, size); break; | ||
@@ -216,2 +237,21 @@ default: value = this.getObject(Ctor.schema, position); | ||
* @param {number} position | ||
* @param {string} value | ||
* @param {number} size | ||
* @param {number} length | ||
* @param {number} stringLength | ||
* @returns {void} | ||
*/ | ||
setStringArray(position, value, size, length, stringLength) { | ||
const array = new Uint8Array(this.buffer, this.byteOffset + position, length); | ||
array.fill(0); | ||
const max = (size < value.length ? size : value.length); | ||
for (let i = 0; i < max; i++) { | ||
const string = StringView.fromString(value[i], stringLength); | ||
array.set(string, i * stringLength); | ||
} | ||
} | ||
/** | ||
* @private | ||
* @param {number} position | ||
* @param {ArrayLike<number>} value | ||
@@ -240,3 +280,3 @@ * @param {Class<TypedArrayView>} ctor | ||
const { | ||
type, littleEndian, start, ctor, length, size, | ||
type, littleEndian, start, ctor, length, size, stringLength, | ||
} = schema[field]; | ||
@@ -284,2 +324,5 @@ const position = offset + start; | ||
break; | ||
case 'stringarray': | ||
this.setStringArray(position, value, size, length, stringLength); | ||
break; | ||
default: | ||
@@ -295,4 +338,4 @@ this.setObject(position, value, ctor); | ||
* | ||
* @param {string} field | ||
* @param {ObjectView|ArrayView|TypedArrayView|StringView} value | ||
* @param {string} field the name of the field | ||
* @param {ObjectView|ArrayView|TypedArrayView|StringView} value the view to set | ||
* @returns {ObjectView} | ||
@@ -354,26 +397,44 @@ */ | ||
const field = schema[name]; | ||
const { type, size, littleEndian } = field; | ||
let byteSize = 0; | ||
const isPrimitive = typeof type === 'string'; | ||
const isTypedArray = isPrimitive && !!size; | ||
const isArray = !isTypedArray && !!size; | ||
// account for wrong primitive type | ||
if (isPrimitive && !Reflect.has(fieldSizes, type)) { | ||
throw TypeError(`Type "${type}" is not a valid type.`); | ||
const { | ||
type, size, littleEndian, length, | ||
} = field; | ||
field.start = lastOffset; | ||
switch (type) { | ||
case 'int8': | ||
case 'uint8': | ||
case 'int16': | ||
case 'uint16': | ||
case 'int32': | ||
case 'uint32': | ||
case 'float32': | ||
case 'float64': | ||
case 'bigint64': | ||
case 'biguint64': | ||
if (size) { | ||
field.ctor = TypedArrayViewMixin(type, littleEndian); | ||
field.type = 'typedarray'; | ||
field.length = field.ctor.getLength(size); | ||
} else { | ||
field.length = fieldSizes[type]; | ||
} | ||
break; | ||
case 'string': | ||
if (size) { | ||
field.type = 'stringarray'; | ||
field.stringLength = length; | ||
field.length = StringArrayView.getLength(size, length); | ||
} | ||
break; | ||
default: | ||
if (typeof type === 'string') throw TypeError(`Type "${type}" is not a valid type.`); | ||
if (size) { | ||
field.type = 'array'; | ||
field.ctor = ArrayViewMixin(type); | ||
field.length = field.ctor.getLength(size); | ||
} else { | ||
field.type = 'object'; | ||
field.ctor = type; | ||
field.length = type.getLength(); | ||
} | ||
} | ||
if (isTypedArray) { | ||
field.ctor = TypedArrayViewMixin(type, littleEndian); | ||
field.type = 'typedarray'; | ||
byteSize = field.ctor.getLength(size); | ||
} else if (isArray) { | ||
field.ctor = DataArrayMixin(type); | ||
field.type = 'array'; | ||
byteSize = field.ctor.getLength(size); | ||
} else if (!isPrimitive) { | ||
field.type = 'object'; | ||
field.ctor = type; | ||
byteSize = type.getLength(); | ||
} | ||
field.start = lastOffset; | ||
field.length = field.length || byteSize || fieldSizes[type]; | ||
lastOffset += field.length; | ||
@@ -380,0 +441,0 @@ } |
@@ -306,3 +306,2 @@ /** | ||
* Creates a StringView from a string. | ||
* todo use TextEncoder.encodeInto when supported by Node.js (FF supports already) | ||
* | ||
@@ -322,2 +321,3 @@ * @param {string} string the string to encode | ||
static fromString(string, size) { | ||
// todo use TextEncoder.encodeInto when supported by Node.js | ||
const encoded = this.encoder.encode(string); | ||
@@ -324,0 +324,0 @@ if (size) { |
{ | ||
"name": "structurae", | ||
"version": "1.4.0", | ||
"version": "1.5.0", | ||
"description": "Data structures for performance-sensitive modern JavaScript applications.", | ||
@@ -26,3 +26,3 @@ "main": "index.js", | ||
"doc:api": "jsdoc2md > doc/API.md", | ||
"benchmark": "node bench/benchmark.js" | ||
"benchmark": "node bench/index.js" | ||
}, | ||
@@ -29,0 +29,0 @@ "directories": { |
@@ -184,2 +184,28 @@ # Structurae | ||
``` | ||
#### StringArrayView | ||
An array of StringViews. Operates on an array of strings stored in an ArrayBuffer. | ||
```javascript | ||
const { StringArrayView } = require('structurae'); | ||
// create a StringArrayView from a given array of strings with maximum string length of 4 bytes | ||
const list = StringArrayView.from(['a', 'bc', 'defg'], 4); | ||
list.get(0); | ||
//=> StringView []; | ||
list.get(0).toString(); | ||
//=> 'a' | ||
list.toObject(); | ||
//=> ['a', 'bc', 'defg'] | ||
// create an empty array of 10 strings with maximum length of 5 bytes | ||
const emptyList = StringArrayView.of(3, 5); | ||
emptyList.get(0).toString(); | ||
//=> '' | ||
emptyList.set(0, 'ab').get(0).toString(); | ||
//=> 'ab' | ||
[...emptyList].map(i => i.toString()); | ||
//=> ['ab', '', ''] | ||
``` | ||
#### TypedArrayView | ||
@@ -186,0 +212,0 @@ TypedArrays in JavaScript have two limitations that make them cumbersome to use in conjunction with DataView. |
192051
28
5374
841