Skip to content

Commit eb4550f

Browse files
d3m3vilurrTooTallNate
authored andcommitted
Implement pack option
Fixes #2. Closes #21. Squashed commit of the following: commit 093212b Author: Lee, SungUk <[email protected]> Date: Wed Aug 3 10:33:09 2016 +0900 Change Struct's second argument type to object Applied review comments; - Constructor arugments type change boolean to object - Assign of `StructType.isPacked` use ternary operator - Remove `usePack` method - `sizeof` and `alignof` calculation move to C++ code commit a1e8f66 Author: Lee, SungUk <[email protected]> Date: Tue Jan 5 15:11:11 2016 +0900 Fix broken unittests of appveyor commit d5415f3 Author: Lee, SungUk <[email protected]> Date: Tue Jan 5 13:15:27 2016 +0900 Resolve #2 Implement `usePack` - Apply [Alexander Seliverstov's method][1] - Now, `Struct` use 2nd arguments - `usePack()` switch padding mode [1]: https://groups.google.com/d/msg/nodejs/2wKCYmGPT5E/DLi4Pjt7j_4J
1 parent c595fb9 commit eb4550f

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

lib/struct.js

+11-3
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,12 @@ function Struct () {
117117
StructType.toString = toString
118118
StructType.fields = {}
119119

120+
var opt = (arguments.length > 0 && arguments[1]) ? arguments[1] : {};
120121
// Setup the ref "type" interface. The constructor doubles as the "type" object
121122
StructType.size = 0
122123
StructType.alignment = 0
123124
StructType.indirection = 1
125+
StructType.isPacked = opt.packed ? Boolean(opt.packed) : false
124126
StructType.get = get
125127
StructType.set = set
126128

@@ -245,7 +247,11 @@ function recalc (struct) {
245247
if (type.indirection > 1) {
246248
alignment = ref.alignof.pointer
247249
}
248-
struct.alignment = Math.max(struct.alignment, alignment)
250+
if (struct.isPacked) {
251+
struct.alignment = Math.min(struct.alignment || alignment, alignment)
252+
} else {
253+
struct.alignment = Math.max(struct.alignment, alignment)
254+
}
249255
})
250256

251257
// second loop through sets the `offset` property on each "field"
@@ -270,12 +276,14 @@ function recalc (struct) {
270276
function addType (type) {
271277
var offset = struct.size
272278
var align = type.indirection === 1 ? type.alignment : ref.alignof.pointer
273-
var padding = (align - (offset % align)) % align
279+
var padding = struct.isPacked ? 0 : (align - (offset % align)) % align
274280
var size = type.indirection === 1 ? type.size : ref.sizeof.pointer
275281

276282
offset += padding
277283

278-
assert.equal(offset % align, 0, "offset should align")
284+
if (!struct.isPacked) {
285+
assert.equal(offset % align, 0, "offset should align")
286+
}
279287

280288
// adjust the "size" of the struct type
281289
struct.size = offset + size

test/struct.js

+14
Original file line numberDiff line numberDiff line change
@@ -379,4 +379,18 @@ describe('Struct', function () {
379379

380380
})
381381

382+
describe('packed struct', function () {
383+
384+
it('with-padding/no-padding struct', function () {
385+
var np = Struct({ a: 'char', p: ref.refType('void') }, {packed: true})
386+
assert.equal(bindings['test20 sizeof'], np.size)
387+
assert.equal(bindings['test20 alignof'], np.alignment)
388+
389+
var wp = Struct({ a: 'char', p: ref.refType('void') })
390+
assert.equal(bindings['test21 sizeof'], wp.size)
391+
assert.equal(bindings['test21 alignof'], wp.alignment)
392+
})
393+
394+
})
395+
382396
})

test/struct_tests.cc

+17
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,18 @@ typedef struct _test19 {
145145
in an album or playlist struct */
146146
} test19;
147147

148+
#pragma pack(1)
149+
typedef struct _test20 {
150+
char a;
151+
void *p;
152+
} test20;
153+
154+
#pragma pack()
155+
typedef struct _test21 {
156+
char a;
157+
void *p;
158+
} test21;
159+
148160
void Initialize(v8::Handle<v8::Object> target) {
149161
Nan::HandleScope scope;
150162

@@ -275,6 +287,11 @@ void Initialize(v8::Handle<v8::Object> target) {
275287
target->Set(Nan::New<v8::String>("test19 offsetof popularity").ToLocalChecked(), Nan::New<v8::Number>(offsetof(test19, popularity)));
276288
target->Set(Nan::New<v8::String>("test19 offsetof next").ToLocalChecked(), Nan::New<v8::Number>(offsetof(test19, next)));
277289

290+
target->Set(Nan::New<v8::String>("test20 sizeof").ToLocalChecked(), Nan::New<v8::Number>(sizeof(test20)));
291+
target->Set(Nan::New<v8::String>("test20 alignof").ToLocalChecked(), Nan::New<v8::Number>(__alignof__(test20)));
292+
293+
target->Set(Nan::New<v8::String>("test21 sizeof").ToLocalChecked(), Nan::New<v8::Number>(sizeof(test21)));
294+
target->Set(Nan::New<v8::String>("test21 alignof").ToLocalChecked(), Nan::New<v8::Number>(__alignof__(test21)));
278295
}
279296

280297
} // anonymous namespace

0 commit comments

Comments
 (0)