! ========================================================================
! Copyright (C) by VMware, Inc. 1991-2011.  All Rights Reserved
!
! $Id: cbuffer.gs,v 1.10 2008-01-09 22:50:09 stever Exp $
!
! ========================================================================

expectvalue %String
run
Object _newKernelSubclass: #CBuffer
  instVarNames: #(#offset)
  classVars: #()
  classInstVars: #()
  poolDictionaries: #()
  inDictionary: Globals
  constraints: #[ #[#offset, SmallInteger]]
  instancesInvariant: false
  isModifiable: false
  reservedOop: 923
%
removeallmethods CBuffer
removeallclassmethods CBuffer

! ------------------- Class methods for CBuffer
category: 'For Documentation Installation only'
classmethod
installDocumentation
| doc txt |
doc := GsClassDocumentation newForClass: self.

txt := (GsDocText new) details:
'CBuffer represents a an instance of some C or C++ type allocated in C heap
 memory.' .

doc documentClassWith: txt.

self description: doc.
%

category: 'Error Handling'
classmethod: CBuffer
_errorMallocFailed

"Raise an error because a call to malloc failed in the user action library."

self _error: #hostErrMemoryAlloc args: #()
%
category: 'Error Handling'
classmethod: CBuffer
_errorNotEnoughBuffers

"Raise an error because there were not enough C buffers available,
as defined by the shared library."

self _error: #rtErrNotEnoughCBuffers args: #()
%
category: 'Testing'
classmethod: CBuffer
_isBufferAvailable

"Return whether there is a buffer available that can be allocated."

^ self _zeroArgPrim: -2
%
category: 'Constants'
classmethod: CBuffer
_numAvailableBuffers

"Return the number of available buffers that can allocated on the heap."

^ self _zeroArgPrim: -1
%
category: 'Primitives'
classmethod: CBuffer
_zeroArgPrim: opcode

"Execute the zero arg primitive according to the given opcodes.
For this class method, opcode must be negative.

Acceptable values:
      -1: CBuffer(C) | _numAvailableBuffers
      -2: CBuffer(C) | _isBufferAvailable
"

<primitive: 197>

self _primitiveFailed: #_zeroArgPrim: .
self _uncontinuableError
%
category: 'Instance Creation'
classmethod: CBuffer
new: size

"Create a new instance and allocate the given number of bytes in the heap."

| newOne status |
newOne := self basicNew initialize.
status := newOne allocate: size.

status == 1
  ifTrue: [^newOne].
status == -1
  ifTrue: [ self _errorNotEnoughBuffers ].
status == 0
  ifTrue: [ self _errorMallocFailed ].

^ self _halt: 'Unknown error when allocating CBuffer:' , status asString
%
! ------------------- Instance methods for CBuffer
category: 'Primitives'
method: CBuffer
_oneArgPrim: opcode arg: arg

"Execute the one arg primitive according to the given opcodes.
	0 = allocate:
	1 = setObjId:
	2 = setOclass: 
	3 = setSegmentId:    
	4 = setIsInvariant: 
	5 = setNamedSize: 
	6 = setObjSize: 
	7 = setIdxSize: 
	8 = setValueBuffSize: 
	9 = setFirstOffset: 
	10 = setFormat: 
	11 = incrementActualBufferSize: 
	12 = getByteObjectInto: 
	13 = copyObjectReportInto: 
	14 = valueBufferPutOverlayAt:
	15 = setComplete:
"

<primitive: 198>
self _primitiveFailed: #_oneArgPrim:arg: .
self _uncontinuableError
%
category: 'Primitives'
method: CBuffer
_twoArgPrim: opcode arg: arg1 arg: arg2

"Execute the two arg primitive according to the given opcodes.
	0 = setBytes:startingAt:
	1 = valueBufferAt:put: 
"

<primitive: 199>
self _primitiveFailed: #_twoArgPrim:arg:arg: .
self _uncontinuableError
%
category: 'Primitives'
method: CBuffer
_zeroArgPrim: opcode

"Execute the zero arg primitive according to the given opcodes.

	0 = allocatedSize
	1 = free
	2 = complete
	3 = objId
	4 = oclass
	5 = segment (obsolete)
	6 = currentObjectIsInvariant 
	7 = namedSize
	8 = objSize 
	9 = idxSize 
	10 = valueBuffSize 
	11 = firstOffset 
	12 = currentObjectIsSpecial 
	13 = currentObjectIsOop 
	14 = currentObjectIsByte 
	15 = currentObjectIsNsc 
	16 = actualBufferSize 
	17 = nextObjectReport 
	18 = setNextObjectReport 
	19 = setFirstObjectReport 
	20 = nextValueBufferOop 
	21 = getByteObject 
	22 = initTraversalBuffer 
	23 = objectReportHeaderSize
	24 = bytesToEnd 
	26 = isPartial
	27 = setNextObjectReport
	29 = advanceValueBufferOop
	30 = currentValueBufferOopIsSpecial
	31 = valueBufferSpecialOop
"

<primitive: 197>
self _primitiveFailed: #_zeroArgPrim:.
self _uncontinuableError
%
category: 'Allocation'
method: CBuffer
allocate: size

"Allocate C heap memory and set the receiver to point to it.  Return a SmallInteger
which indicates the status of the allocation:

-1 = not enought C buffers
0 = malloc failed
1 = allocation succeeded
"

<protected>

^ self _oneArgPrim: 0 arg: size.
%
category: 'Allocation'
method: CBuffer
allocatedSize

"Return the amount of heap memory allocated, in bytes."

^ self _zeroArgPrim: 0.
%
category: 'Allocation'
method: CBuffer
free

"Free previously allocated C heap memory."

<protected>

^ self _zeroArgPrim: 1.
%
category: 'Initialization'
method: CBuffer
initialize

"Initialize a new instance."

%

