<div id="__MailbirdStyleContent" style="font-size: 10pt;font-family: Arial;color: #000000;text-align: left" dir="ltr">
<div>Hi all!</div><div><br></div>Sorry for the feature-mix in this commit.<div class="mb_sig"></div>
<div><br></div><div>Please let me know whether those are good names:</div><div>#writer</div><div>#zeroMemory</div><div><br></div><div>I know "ZeroMemory(...)" from the win32-API. And "writer" is just small enough to squeeze it in when changing a composite struct:</div><div><span style="font-size: 13.3333px"><br></span></div><div><span style="font-size: 13.3333px">composite := FFITestSUfdUdSi2 new. "object memory / byte array"</span><br></div><div><span style="font-size: 13.3333px">composite writer udSii2 sii1 i1: 42.</span><br></div><div><br></div><div>Best,</div><div>Marcel</div><blockquote class="history_container" type="cite" style="border-left-style: solid;border-width: 1px;margin-top: 20px;margin-left: 0px;padding-left: 10px;min-width: 500px">
<p style="color: #AAAAAA; margin-top: 10px;">Am 03.05.2021 18:54:03 schrieb commits@source.squeak.org <commits@source.squeak.org>:</p><div style="font-family:Arial,Helvetica,sans-serif">Marcel Taeumel uploaded a new version of FFI-Kernel to project FFI:<br>http://source.squeak.org/FFI/FFI-Kernel-mt.126.mcz<br><br>==================== Summary ====================<br><br>Name: FFI-Kernel-mt.126<br>Author: mt<br>Time: 3 May 2021, 6:53:53.131479 pm<br>UUID: efa27be5-2153-1c47-b30f-b8d9ca10b1c8<br>Ancestors: FFI-Kernel-mt.125<br><br>Adds a transparent way to write into composite structures that reside in object memory: #writer. (Name is up for discussion, especially since the namespace for custom structs is limited.)<br><br>Adds #zeroMemory to remove information from internal or external memory. <br><br>Fixes regression in ExternalData >> #free.<br><br>Adds sanity checks to ExternalStructure #new and #externalNew, which both made no sense for type aliases.<br><br>=============== Diff against FFI-Kernel-mt.125 ===============<br><br>Item was added:<br>+ ----- Method: ByteArray>>zeroMemory (in category '*FFI-Kernel') -----<br>+ zeroMemory<br>+ <br>+ self atAllPut: 0.!<br><br>Item was added:<br>+ ----- Method: ByteArray>>zeroMemory: (in category '*FFI-Kernel') -----<br>+ zeroMemory: numBytes<br>+ <br>+ 1 to: numBytes do: [:index |<br>+ self byteAt: index put: 0].!<br><br>Item was added:<br>+ ProtoObject subclass: #ByteArrayWriter<br>+ instanceVariableNames: 'byteOffset byteSize byteArray'<br>+ classVariableNames: ''<br>+ poolDictionaries: ''<br>+ category: 'FFI-Kernel'!<br>+ <br>+ !ByteArrayWriter commentStamp: 'mt 5/3/2021 17:44' prior: 0!<br>+ I am a transparent wrapper over byte-array handles to allow access and manipulation just like through an external address.!<br><br>Item was added:<br>+ ----- Method: ByteArrayWriter class>>on: (in category 'instance creation') -----<br>+ on: handle<br>+ <br>+ self assert: [handle isInternalMemory].<br>+ ^ self new setArray: handle!<br><br>Item was added:<br>+ ----- Method: ByteArrayWriter>>doesNotUnderstand: (in category 'system primitives') -----<br>+ doesNotUnderstand: aMessage<br>+ <br>+ | selector args |<br>+ selector := aMessage selector.<br>+ args := aMessage arguments.<br>+ args size caseOf: {<br>+ [ 1 ] -> [ (selector endsWith: 'At:') ifTrue: [ args at: 1 put: args first + byteOffset ] ].<br>+ [ 2 ] -> [ (selector endsWith: 'length:')<br>+ ifTrue: [<br>+ args at: 1 put: args first + byteOffset.<br>+ args first + args second > byteSize<br>+ ifTrue: [self errorSubscriptBounds: args first + args second] ]<br>+ ifFalse: [(selector endsWith: 'put:') ifTrue: [<br>+ args at: 1 put: args first + byteOffset ]] ].<br>+ [ 3 ] -> [ (selector endsWith: 'length:')<br>+ ifTrue: [<br>+ args at: 1 put: args first + byteOffset.<br>+ args first + args third > byteSize<br>+ ifTrue: [self errorSubscriptBounds: args first + args third]]] <br>+ } otherwise: []. <br>+ ^ aMessage sendTo: byteArray!<br><br>Item was added:<br>+ ----- Method: ByteArrayWriter>>errorSubscriptBounds: (in category 'initialization') -----<br>+ errorSubscriptBounds: index<br>+ <br>+ Error signal: 'subscript is out of bounds: ' , index printString.!<br><br>Item was added:<br>+ ----- Method: ByteArrayWriter>>setArray: (in category 'initialization') -----<br>+ setArray: aByteArray<br>+ <br>+ byteArray := aByteArray.<br>+ byteOffset := 0.<br>+ byteSize := aByteArray size.!<br><br>Item was added:<br>+ ----- Method: ByteArrayWriter>>setArray:offset:size: (in category 'initialization') -----<br>+ setArray: aByteArray offset: aByteOffset size: aByteSize<br>+ <br>+ byteArray := aByteArray.<br>+ byteOffset := aByteOffset.<br>+ byteSize := aByteSize.<br>+ <br>+ (byteOffset + byteSize > byteArray size)<br>+ ifTrue: [self errorSubscriptBounds: byteOffset + byteSize].!<br><br>Item was added:<br>+ ----- Method: ByteArrayWriter>>structAt:length: (in category 'accessing') -----<br>+ structAt: newByteOffset length: newLength<br>+ <br>+ ^ ByteArrayWriter new<br>+ setArray: byteArray<br>+ offset: byteOffset + newByteOffset - 1<br>+ size: newLength!<br><br>Item was added:<br>+ ----- Method: ByteArrayWriter>>structAt:put:length: (in category 'accessing') -----<br>+ structAt: newByteOffset put: value length: newLength<br>+ <br>+ (newByteOffset + newLength > byteSize)<br>+ ifTrue: [self errorSubscriptBounds: newByteOffset + newLength].<br>+ <br>+ ^ byteArray<br>+ structAt: byteOffset + newByteOffset - 1<br>+ put: value<br>+ length: newLength!<br><br>Item was added:<br>+ ----- Method: Character class>>zero (in category '*FFI-Kernel') -----<br>+ zero<br>+ "See ExternalStructure >> #zeroMemory."<br>+ <br>+ ^ $0!<br><br>Item was added:<br>+ ----- Method: ExternalAddress>>zeroMemory (in category 'initialize-release') -----<br>+ zeroMemory<br>+ "We need length information in bytes."<br>+ self shouldNotImplement.!<br><br>Item was added:<br>+ ----- Method: ExternalData>>free (in category 'initialize-release') -----<br>+ free<br>+ <br>+ super free.<br>+ size := nil.!<br><br>Item was added:<br>+ ----- Method: ExternalData>>zeroMemory (in category 'initialize-release') -----<br>+ zeroMemory<br>+ "Remove all information but keep the memory allocated."<br>+ <br>+ self sizeCheck.<br>+ <br>+ handle isExternalAddress<br>+ ifTrue: [handle zeroMemory: self size * self contentType byteSize]<br>+ ifFalse: [ "ByteArray" handle zeroMemory].!<br><br>Item was changed:<br> ----- Method: ExternalStructure class>>externalNew (in category 'instance creation') -----<br> externalNew<br> "Create an instance of the receiver on the external heap"<br>+ <br>+ ^ self fromHandle: (self externalType isTypeAliasForAtomic<br>+ ifTrue: [self error: 'This is an alias-for-atomic type. You must use #fromHandle:']<br>+ ifFalse: [<br>+ self externalType isTypeAliasForPointer<br>+ ifTrue: [ByteArray new: self byteSize]<br>+ ifFalse: [ExternalAddress allocate: self byteSize]])!<br>- ^self fromHandle: (ExternalAddress allocate: self byteSize)!<br><br>Item was changed:<br> ----- Method: ExternalStructure class>>new (in category 'instance creation') -----<br> new<br>+ ^self fromHandle: (self externalType isTypeAliasForAtomic<br>+ ifTrue: [self error: 'This is an alias-for-atomic type. You must use #fromHandle:']<br>+ ifFalse: [ByteArray new: self byteSize]).!<br>- ^self fromHandle: (ByteArray new: self byteSize)!<br><br>Item was added:<br>+ ----- Method: ExternalStructure class>>newZero (in category 'instance creation') -----<br>+ newZero<br>+ <br>+ ^ self new<br>+ zeroMemory;<br>+ yourself!<br><br>Item was added:<br>+ ----- Method: ExternalStructure>>writer (in category 'accessing') -----<br>+ writer<br>+ <br>+ ^ handle isInternalMemory<br>+ "Wrap handle into helper to address offsets in the byte array."<br>+ ifTrue: [self class fromHandle: (ByteArrayWriter on: handle)]<br>+ "Either alias-to-atomic or already in external memory."<br>+ ifFalse: [self]!<br><br>Item was added:<br>+ ----- Method: ExternalStructure>>zeroMemory (in category 'initialize-release') -----<br>+ zeroMemory<br>+ "Remove all information but keep the memory allocated."<br>+ <br>+ handle isExternalAddress<br>+ ifTrue: [handle zeroMemory: self externalType byteSize]<br>+ ifFalse: [handle isInternalMemory<br>+ ifTrue: [handle zeroMemory]<br>+ ifFalse: [<br>+ "Alias-to-atomic type."<br>+ handle := handle class zero]].!<br><br><br></div></blockquote></div>