mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 764436 - Shared code;r=taras
This commit is contained in:
parent
3478c7cf0e
commit
fbba8e7c30
@ -440,6 +440,147 @@
|
||||
ctypes.ssize_t,
|
||||
projector(ctypes.ssize_t, true));
|
||||
|
||||
|
||||
/**
|
||||
* Utility class, used to build a |struct| type
|
||||
* from a set of field names, types and offsets.
|
||||
*
|
||||
* @param {string} name The name of the |struct| type.
|
||||
* @param {number} size The total size of the |struct| type in bytes.
|
||||
*/
|
||||
function HollowStructure(name, size) {
|
||||
if (!name) {
|
||||
throw new TypeError("HollowStructure expects a name");
|
||||
}
|
||||
if (!size || size < 0) {
|
||||
throw new TypeError("HollowStructure expects a (positive) size");
|
||||
}
|
||||
|
||||
// A mapping from offsets in the struct to name/type pairs
|
||||
// (or nothing if no field starts at that offset).
|
||||
this.offset_to_field_info = [];
|
||||
|
||||
// The name of the struct
|
||||
this.name = name;
|
||||
|
||||
// The size of the struct, in bytes
|
||||
this.size = size;
|
||||
|
||||
// The number of paddings inserted so far.
|
||||
// Used to give distinct names to padding fields.
|
||||
this._paddings = 0;
|
||||
}
|
||||
HollowStructure.prototype = {
|
||||
/**
|
||||
* Add a field at a given offset.
|
||||
*
|
||||
* @param {number} offset The offset at which to insert the field.
|
||||
* @param {string} name The name of the field.
|
||||
* @param {CType|Type} type The type of the field.
|
||||
*/
|
||||
add_field_at: function add_field_at(offset, name, type) {
|
||||
if (offset === null) {
|
||||
throw new TypeError("add_field_at requires a non-null offset");
|
||||
}
|
||||
if (!name) {
|
||||
throw new TypeError("add_field_at requires a non-null name");
|
||||
}
|
||||
if (!type) {
|
||||
throw new TypeError("add_field_at requires a non-null type");
|
||||
}
|
||||
if (type instanceof Type) {
|
||||
type = type.implementation;
|
||||
}
|
||||
if (this.offset_to_field_info[offset]) {
|
||||
throw new Error("HollowStructure " + this.name +
|
||||
" already has a field at offset " + offset);
|
||||
}
|
||||
if (offset + type.size > this.size) {
|
||||
throw new Error("HollowStructure " + this.name +
|
||||
" cannot place a value of type " + type +
|
||||
" at offset " + offset +
|
||||
" without exceeding its size of " + this.size);
|
||||
}
|
||||
let field = {name: name, type:type};
|
||||
this.offset_to_field_info[offset] = field;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a pseudo-field that will only serve as padding.
|
||||
*
|
||||
* @param {number} size The number of bytes in the field.
|
||||
* @return {Object} An association field-name => field-type,
|
||||
* as expected by |ctypes.StructType|.
|
||||
*/
|
||||
_makePaddingField: function makePaddingField(size) {
|
||||
let field = ({});
|
||||
field["padding_" + this._paddings] =
|
||||
ctypes.ArrayType(ctypes.uint8_t, size);
|
||||
this._paddings++;
|
||||
return field;
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert this |HollowStructure| into a |Type|.
|
||||
*/
|
||||
getType: function getType() {
|
||||
// Contents of the structure, in the format expected
|
||||
// by ctypes.StructType.
|
||||
let struct = [];
|
||||
|
||||
let i = 0;
|
||||
while (i < this.size) {
|
||||
let currentField = this.offset_to_field_info[i];
|
||||
if (!currentField) {
|
||||
// No field was specified at this offset, we need to
|
||||
// introduce some padding.
|
||||
|
||||
// Firstly, determine how many bytes of padding
|
||||
let padding_length = 1;
|
||||
while (i + padding_length < this.size
|
||||
&& !this.offset_to_field_info[i + padding_length]) {
|
||||
++padding_length;
|
||||
}
|
||||
|
||||
// Then add the padding
|
||||
struct.push(this._makePaddingField(padding_length));
|
||||
|
||||
// And proceed
|
||||
i += padding_length;
|
||||
} else {
|
||||
// We have a field at this offset.
|
||||
|
||||
// Firstly, ensure that we do not have two overlapping fields
|
||||
for (let j = 1; j < currentField.type.size; ++j) {
|
||||
let candidateField = this.offset_to_field_info[i + j];
|
||||
if (candidateField) {
|
||||
throw new Error("Fields " + currentField.name +
|
||||
" and " + candidateField.name +
|
||||
" overlap at position " + (i + j));
|
||||
}
|
||||
}
|
||||
|
||||
// Then add the field
|
||||
let field = ({});
|
||||
field[currentField.name] = currentField.type;
|
||||
struct.push(field);
|
||||
|
||||
// And proceed
|
||||
i += currentField.type.size;
|
||||
}
|
||||
}
|
||||
let result = new Type(this.name, ctypes.StructType(this.name, struct));
|
||||
if (result.implementation.size != this.size) {
|
||||
throw new Error("Wrong size for type " + this.name +
|
||||
": expected " + this.size +
|
||||
", found " + result.implementation.size +
|
||||
" (" + result.implementation.toSource() + ")");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
exports.OS.Shared.HollowStructure = HollowStructure;
|
||||
|
||||
/**
|
||||
* Declare a function through js-ctypes
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user