Show More
Commit Description:
fig bugs in login report
Commit Description:
fig bugs in login report
References:
File last commit:
Show/Diff file:
Action:
node_modules/restructure/src/Pointer.coffee
| 125 lines
| 3.0 KiB
| text/coffeescript
| CoffeeScriptLexer
|
r789 | utils = require './utils' | |||
class Pointer | ||||
constructor: (@offsetType, @type, @options = {}) -> | ||||
@type = null if @type is 'void' | ||||
@options.type ?= 'local' | ||||
@options.allowNull ?= true | ||||
@options.nullValue ?= 0 | ||||
@options.lazy ?= false | ||||
if @options.relativeTo | ||||
@relativeToGetter = new Function('ctx', "return ctx.#{@options.relativeTo}") | ||||
decode: (stream, ctx) -> | ||||
offset = @offsetType.decode(stream, ctx) | ||||
# handle NULL pointers | ||||
if offset is @options.nullValue and @options.allowNull | ||||
return null | ||||
relative = switch @options.type | ||||
when 'local' then ctx._startOffset | ||||
when 'immediate' then stream.pos - @offsetType.size() | ||||
when 'parent' then ctx.parent._startOffset | ||||
else | ||||
c = ctx | ||||
while c.parent | ||||
c = c.parent | ||||
c._startOffset or 0 | ||||
if @options.relativeTo | ||||
relative += @relativeToGetter ctx | ||||
ptr = offset + relative | ||||
if @type? | ||||
val = null | ||||
decodeValue = => | ||||
return val if val? | ||||
pos = stream.pos | ||||
stream.pos = ptr | ||||
val = @type.decode(stream, ctx) | ||||
stream.pos = pos | ||||
return val | ||||
# If this is a lazy pointer, define a getter to decode only when needed. | ||||
# This obviously only works when the pointer is contained by a Struct. | ||||
if @options.lazy | ||||
return new utils.PropertyDescriptor | ||||
get: decodeValue | ||||
return decodeValue() | ||||
else | ||||
return ptr | ||||
size: (val, ctx) -> | ||||
parent = ctx | ||||
switch @options.type | ||||
when 'local', 'immediate' | ||||
break | ||||
when 'parent' | ||||
ctx = ctx.parent | ||||
else # global | ||||
while ctx.parent | ||||
ctx = ctx.parent | ||||
type = @type | ||||
unless type? | ||||
unless val instanceof VoidPointer | ||||
throw new Error "Must be a VoidPointer" | ||||
type = val.type | ||||
val = val.value | ||||
if val and ctx | ||||
ctx.pointerSize += type.size(val, parent) | ||||
return @offsetType.size() | ||||
encode: (stream, val, ctx) -> | ||||
parent = ctx | ||||
if not val? | ||||
@offsetType.encode(stream, @options.nullValue) | ||||
return | ||||
switch @options.type | ||||
when 'local' | ||||
relative = ctx.startOffset | ||||
when 'immediate' | ||||
relative = stream.pos + @offsetType.size(val, parent) | ||||
when 'parent' | ||||
ctx = ctx.parent | ||||
relative = ctx.startOffset | ||||
else # global | ||||
relative = 0 | ||||
while ctx.parent | ||||
ctx = ctx.parent | ||||
if @options.relativeTo | ||||
relative += @relativeToGetter parent.val | ||||
@offsetType.encode(stream, ctx.pointerOffset - relative) | ||||
type = @type | ||||
unless type? | ||||
unless val instanceof VoidPointer | ||||
throw new Error "Must be a VoidPointer" | ||||
type = val.type | ||||
val = val.value | ||||
ctx.pointers.push | ||||
type: type | ||||
val: val | ||||
parent: parent | ||||
ctx.pointerOffset += type.size(val, parent) | ||||
# A pointer whose type is determined at decode time | ||||
class VoidPointer | ||||
constructor: (@type, @value) -> | ||||
exports.Pointer = Pointer | ||||
exports.VoidPointer = VoidPointer | ||||