Browse Source

Added user memory DataBuffers.

Mark Sibly 7 years ago
parent
commit
732c279f39

+ 87 - 5
modules/std/memory/databuffer.monkey2

@@ -7,8 +7,17 @@ Using std.stream
 #end
 #end
 Class DataBuffer Extends std.resource.Resource
 Class DataBuffer Extends std.resource.Resource
 
 
-	#rem monkeydoc Creates a new databuffer.
+	#rem monkeydoc Creates a new data buffer.
 	
 	
+	Creates a data buffer with a newly allocated or existing block of memory.
+	
+	If you provide a `start` pointer value when creating a data buffer, it should point to a valid block of memory at least `length` bytes in size.
+	This pointer value will be used as the 'base address' when poking/peeking the data buffer, and will be returned by the [[Data]] property.
+	Such data buffer cannot be [[Resize]]d.
+		
+	If you do not provide a `start` value, a block of memory `length` bytes long is allocated for you. This memory will be released when the data 
+	buffer is discarded or becomes unreachable by the garbage collector.
+		
 	The new databuffer initally uses little endian byte order. You can change this via the ByteOrder property.
 	The new databuffer initally uses little endian byte order. You can change this via the ByteOrder property.
 	
 	
 	When you have finished with the data buffer, you should call its inherited [[Resource.Discard]] method.
 	When you have finished with the data buffer, you should call its inherited [[Resource.Discard]] method.
@@ -37,17 +46,29 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	@end
 	@end
 	
 	
-	@param length The length of the databuffer to create, in bytes.
+	@param start The start of the data buffer memory.
 	
 	
+	@param length The length of the data buffer memory in bytes.
+
 	@param byteOrder Initial byte order of the data.
 	@param byteOrder Initial byte order of the data.
 	
 	
 	#end
 	#end
 	Method New( length:Int,byteOrder:ByteOrder=std.memory.ByteOrder.LittleEndian )
 	Method New( length:Int,byteOrder:ByteOrder=std.memory.ByteOrder.LittleEndian )
 		
 		
-		_length=length
 		_data=Cast<UByte Ptr>( GCMalloc( length ) )
 		_data=Cast<UByte Ptr>( GCMalloc( length ) )
+		_length=length
+		_byteOrder=byteOrder
+		_swapEndian=(_byteOrder=ByteOrder.BigEndian)
+		_free=True
+	End
+	
+	Method New( data:Void Ptr,length:Int,byteOrder:ByteOrder=std.memory.ByteOrder.LittleEndian )
+		
+		_data=Cast<UByte Ptr>( data )
+		_length=length
 		_byteOrder=byteOrder
 		_byteOrder=byteOrder
 		_swapEndian=(_byteOrder=ByteOrder.BigEndian)
 		_swapEndian=(_byteOrder=ByteOrder.BigEndian)
+		_free=False
 	End
 	End
 	
 	
 	#rem monkeydoc A raw pointer to the databuffer's internal memory.
 	#rem monkeydoc A raw pointer to the databuffer's internal memory.
@@ -56,20 +77,25 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Property Data:UByte Ptr()
 	Property Data:UByte Ptr()
+		
 		Return _data
 		Return _data
 	End
 	End
 	
 	
 	#rem monkeydoc The length of the databuffer in bytes.
 	#rem monkeydoc The length of the databuffer in bytes.
 	#end
 	#end
 	Property Length:Int()
 	Property Length:Int()
+		
 		Return _length
 		Return _length
 	End
 	End
 	
 	
 	#rem monkeydoc The byte order of the databuffer.
 	#rem monkeydoc The byte order of the databuffer.
 	#end
 	#end
 	Property ByteOrder:ByteOrder()
 	Property ByteOrder:ByteOrder()
+		
 		Return _byteOrder
 		Return _byteOrder
+		
 	Setter( byteOrder:ByteOrder )
 	Setter( byteOrder:ByteOrder )
+		
 		_byteOrder=byteOrder
 		_byteOrder=byteOrder
 		_swapEndian=(_byteOrder=ByteOrder.BigEndian)
 		_swapEndian=(_byteOrder=ByteOrder.BigEndian)
 	End
 	End
@@ -82,6 +108,9 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end	
 	#end	
 	Method Resize( length:Int )
 	Method Resize( length:Int )
+		
+		If Not _free RuntimeError( "DataBuffer memory cannot be resized" )
+		
 		Local data:=Cast<UByte Ptr>( GCMalloc( length ) )
 		Local data:=Cast<UByte Ptr>( GCMalloc( length ) )
 		libc.memcpy( data,_data,Min( length,_length ) )
 		libc.memcpy( data,_data,Min( length,_length ) )
 		GCFree( _data )
 		GCFree( _data )
@@ -99,6 +128,7 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PeekByte:Byte( offset:Int )
 	Method PeekByte:Byte( offset:Int )
+		
 		DebugAssert( offset>=0 And offset<_length )
 		DebugAssert( offset>=0 And offset<_length )
 		
 		
 		Return Cast<Byte Ptr>( _data+offset )[0]
 		Return Cast<Byte Ptr>( _data+offset )[0]
@@ -114,6 +144,7 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PeekUByte:UByte( offset:Int )
 	Method PeekUByte:UByte( offset:Int )
+		
 		DebugAssert( offset>=0 And offset<_length )
 		DebugAssert( offset>=0 And offset<_length )
 
 
 		Return Cast<UByte Ptr>( _data+offset )[0]
 		Return Cast<UByte Ptr>( _data+offset )[0]
@@ -129,10 +160,13 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PeekShort:Short( offset:Int )
 	Method PeekShort:Short( offset:Int )
+		
 		DebugAssert( offset>=0 And offset<_length-1 )
 		DebugAssert( offset>=0 And offset<_length-1 )
 		
 		
 		Local t:=Cast<Short Ptr>( _data+offset )[0]
 		Local t:=Cast<Short Ptr>( _data+offset )[0]
+		
 		If _swapEndian Swap2( Varptr t )
 		If _swapEndian Swap2( Varptr t )
+			
 		Return t
 		Return t
 	End
 	End
 	
 	
@@ -146,10 +180,13 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PeekUShort:UShort( offset:Int )
 	Method PeekUShort:UShort( offset:Int )
+		
 		DebugAssert( offset>=0 And offset<_length-1 )
 		DebugAssert( offset>=0 And offset<_length-1 )
 
 
 		Local t:=Cast<UShort Ptr>( _data+offset )[0]
 		Local t:=Cast<UShort Ptr>( _data+offset )[0]
+		
 		If _swapEndian Swap2( Varptr t )
 		If _swapEndian Swap2( Varptr t )
+			
 		Return t
 		Return t
 	End
 	End
 	
 	
@@ -163,10 +200,13 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PeekInt:Int( offset:Int )
 	Method PeekInt:Int( offset:Int )
+		
 		DebugAssert( offset>=0 And offset<_length-3 )
 		DebugAssert( offset>=0 And offset<_length-3 )
 	
 	
 		Local t:=Cast<Int Ptr>( _data+offset )[0]
 		Local t:=Cast<Int Ptr>( _data+offset )[0]
+		
 		If _swapEndian Swap4( Varptr t )
 		If _swapEndian Swap4( Varptr t )
+			
 		Return t
 		Return t
 	End
 	End
 	
 	
@@ -180,10 +220,13 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PeekUInt:UInt( offset:Int )
 	Method PeekUInt:UInt( offset:Int )
+		
 		DebugAssert( offset>=0 And offset<_length-3 )
 		DebugAssert( offset>=0 And offset<_length-3 )
 
 
 		Local t:=Cast<UInt Ptr>( _data+offset )[0]
 		Local t:=Cast<UInt Ptr>( _data+offset )[0]
+		
 		If _swapEndian Swap4( Varptr t )
 		If _swapEndian Swap4( Varptr t )
+			
 		Return t
 		Return t
 	End
 	End
 	
 	
@@ -197,10 +240,13 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PeekLong:Long( offset:Int )
 	Method PeekLong:Long( offset:Int )
+		
 		DebugAssert( offset>=0 And offset<_length-7 )
 		DebugAssert( offset>=0 And offset<_length-7 )
 		
 		
 		Local t:=Cast<Long Ptr>( _data+offset )[0]
 		Local t:=Cast<Long Ptr>( _data+offset )[0]
+		
 		If _swapEndian Swap8( Varptr t )
 		If _swapEndian Swap8( Varptr t )
+			
 		Return t
 		Return t
 	End
 	End
 		
 		
@@ -214,10 +260,13 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PeekULong:ULong( offset:Int )
 	Method PeekULong:ULong( offset:Int )
+		
 		DebugAssert( offset>=0 And offset<_length-7 )
 		DebugAssert( offset>=0 And offset<_length-7 )
 
 
 		Local t:=Cast<ULong Ptr>( _data+offset )[0]
 		Local t:=Cast<ULong Ptr>( _data+offset )[0]
+		
 		If _swapEndian Swap8( Varptr t )
 		If _swapEndian Swap8( Varptr t )
+			
 		Return t
 		Return t
 	End
 	End
 	
 	
@@ -231,10 +280,13 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PeekFloat:Float( offset:Int )
 	Method PeekFloat:Float( offset:Int )
+		
 		DebugAssert( offset>=0 And offset<_length-3 )
 		DebugAssert( offset>=0 And offset<_length-3 )
 
 
 		Local t:=Cast<Float Ptr>( _data+offset )[0]
 		Local t:=Cast<Float Ptr>( _data+offset )[0]
+		
 		If _swapEndian Swap4( Varptr t )
 		If _swapEndian Swap4( Varptr t )
+			
 		Return t
 		Return t
 	End
 	End
 	
 	
@@ -248,10 +300,13 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PeekDouble:Double( offset:Int )
 	Method PeekDouble:Double( offset:Int )
+		
 		DebugAssert( offset>=0 And offset<_length-7 )
 		DebugAssert( offset>=0 And offset<_length-7 )
 	
 	
 		Local t:=Cast<Double Ptr>( _data+offset )[0]
 		Local t:=Cast<Double Ptr>( _data+offset )[0]
+		
 		If _swapEndian Swap8( Varptr t )
 		If _swapEndian Swap8( Varptr t )
+			
 		Return t
 		Return t
 	End
 	End
 	
 	
@@ -265,12 +320,14 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PeekString:String( offset:Int )
 	Method PeekString:String( offset:Int )
+		
 		DebugAssert( offset>=0 And offset<=_length )
 		DebugAssert( offset>=0 And offset<=_length )
 		
 		
 		Return PeekString( offset,_length-offset )
 		Return PeekString( offset,_length-offset )
 	End
 	End
 	
 	
 	Method PeekString:String( offset:Int,count:Int )
 	Method PeekString:String( offset:Int,count:Int )
+		
 		DebugAssert( offset>=0 And count>=0 And offset+count<=_length )
 		DebugAssert( offset>=0 And count>=0 And offset+count<=_length )
 
 
 		Return String.FromCString( _data+offset,count )
 		Return String.FromCString( _data+offset,count )
@@ -279,6 +336,7 @@ Class DataBuffer Extends std.resource.Resource
 	#rem monkeydoc Reads a null terminated CString from the databuffer.
 	#rem monkeydoc Reads a null terminated CString from the databuffer.
 	#end
 	#end
 	Method PeekCString:String( offset:Int )
 	Method PeekCString:String( offset:Int )
+		
 		DebugAssert( offset>=0 And offset<=_length )
 		DebugAssert( offset>=0 And offset<=_length )
 		
 		
 		Local i:=offset
 		Local i:=offset
@@ -297,6 +355,7 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PokeByte( offset:Int,value:Byte )
 	Method PokeByte( offset:Int,value:Byte )
+		
 		DebugAssert( offset>=0 And offset<_length )
 		DebugAssert( offset>=0 And offset<_length )
 	
 	
 		Cast<Byte Ptr>( _data+offset )[0]=value
 		Cast<Byte Ptr>( _data+offset )[0]=value
@@ -310,6 +369,7 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PokeUByte( offset:Int,value:UByte )
 	Method PokeUByte( offset:Int,value:UByte )
+		
 		DebugAssert( offset>=0 And offset<_length )
 		DebugAssert( offset>=0 And offset<_length )
 
 
 		Cast<UByte Ptr>( _data+offset )[0]=value
 		Cast<UByte Ptr>( _data+offset )[0]=value
@@ -323,9 +383,11 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PokeShort( offset:Int,value:Short )
 	Method PokeShort( offset:Int,value:Short )
+		
 		DebugAssert( offset>=0 And offset<_length-1 )
 		DebugAssert( offset>=0 And offset<_length-1 )
 	
 	
 		If _swapEndian Swap2( Varptr value )
 		If _swapEndian Swap2( Varptr value )
+			
 		Cast<Short Ptr>( _data+offset )[0]=value
 		Cast<Short Ptr>( _data+offset )[0]=value
 	End
 	End
 	
 	
@@ -337,9 +399,11 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PokeUShort( offset:Int,value:UShort )
 	Method PokeUShort( offset:Int,value:UShort )
+		
 		DebugAssert( offset>=0 And offset<_length-1 )
 		DebugAssert( offset>=0 And offset<_length-1 )
 
 
 		If _swapEndian Swap2( Varptr value )
 		If _swapEndian Swap2( Varptr value )
+			
 		Cast<UShort Ptr>( _data+offset )[0]=value
 		Cast<UShort Ptr>( _data+offset )[0]=value
 	End
 	End
 	
 	
@@ -351,9 +415,11 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PokeInt( offset:Int,value:Int )
 	Method PokeInt( offset:Int,value:Int )
+		
 		DebugAssert( offset>=0 And offset<_length-3 )
 		DebugAssert( offset>=0 And offset<_length-3 )
 	
 	
 		If _swapEndian Swap4( Varptr value )
 		If _swapEndian Swap4( Varptr value )
+			
 		Cast<Int Ptr>( _data+offset )[0]=value
 		Cast<Int Ptr>( _data+offset )[0]=value
 	End
 	End
 	
 	
@@ -365,9 +431,11 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PokeUInt( offset:Int,value:UInt )
 	Method PokeUInt( offset:Int,value:UInt )
+		
 		DebugAssert( offset>=0 And offset<_length-3 )
 		DebugAssert( offset>=0 And offset<_length-3 )
 
 
 		If _swapEndian Swap4( Varptr value )
 		If _swapEndian Swap4( Varptr value )
+			
 		Cast<UInt Ptr>( _data+offset )[0]=value
 		Cast<UInt Ptr>( _data+offset )[0]=value
 	End
 	End
 	
 	
@@ -379,9 +447,11 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PokeLong( offset:Int,value:Long )
 	Method PokeLong( offset:Int,value:Long )
+		
 		DebugAssert( offset>=0 And offset<_length-7 )
 		DebugAssert( offset>=0 And offset<_length-7 )
 
 
 		If _swapEndian Swap8( Varptr value )
 		If _swapEndian Swap8( Varptr value )
+			
 		Cast<Long Ptr>( _data+offset )[0]=value
 		Cast<Long Ptr>( _data+offset )[0]=value
 	End
 	End
 	
 	
@@ -393,9 +463,11 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PokeULong( offset:Int,value:ULong )
 	Method PokeULong( offset:Int,value:ULong )
+		
 		DebugAssert( offset>=0 And offset<_length-7 )
 		DebugAssert( offset>=0 And offset<_length-7 )
 		
 		
 		If _swapEndian Swap8( Varptr value )
 		If _swapEndian Swap8( Varptr value )
+			
 		Cast<ULong Ptr>( _data+offset )[0]=value
 		Cast<ULong Ptr>( _data+offset )[0]=value
 	End
 	End
 	
 	
@@ -407,9 +479,11 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PokeFloat( offset:Int,value:Float )
 	Method PokeFloat( offset:Int,value:Float )
+		
 		DebugAssert( offset>=0 And offset<_length-3 )
 		DebugAssert( offset>=0 And offset<_length-3 )
 	
 	
 		If _swapEndian Swap4( Varptr value )
 		If _swapEndian Swap4( Varptr value )
+			
 		Cast<Float Ptr>( _data+offset )[0]=value
 		Cast<Float Ptr>( _data+offset )[0]=value
 	End
 	End
 	
 	
@@ -421,9 +495,11 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method PokeDouble( offset:Int,value:Double )
 	Method PokeDouble( offset:Int,value:Double )
+		
 		DebugAssert( offset>=0 And offset<_length-7 )
 		DebugAssert( offset>=0 And offset<_length-7 )
 	
 	
 		If _swapEndian Swap8( Varptr value )
 		If _swapEndian Swap8( Varptr value )
+			
 		Cast<Double Ptr>( _data+offset )[0]=value
 		Cast<Double Ptr>( _data+offset )[0]=value
 	End
 	End
 
 
@@ -439,16 +515,20 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end	
 	#end	
 	Method PokeString( offset:Int,value:String )
 	Method PokeString( offset:Int,value:String )
+		
 		DebugAssert( offset>=0 And offset<=_length )
 		DebugAssert( offset>=0 And offset<=_length )
 		
 		
 		Local count:=value.CStringLength
 		Local count:=value.CStringLength
+		
 		If offset+count>_length count=_length-offset
 		If offset+count>_length count=_length-offset
+			
 		value.ToCString( _data+offset,count )
 		value.ToCString( _data+offset,count )
 	End
 	End
 	
 	
 	#rem monkeydoc Writes a null terminated CString to the data buffer.
 	#rem monkeydoc Writes a null terminated CString to the data buffer.
 	#end
 	#end
 	Method PokeCString( offset:Int,value:String )
 	Method PokeCString( offset:Int,value:String )
+		
 		DebugAssert( offset>=0 And offset<=_length )
 		DebugAssert( offset>=0 And offset<=_length )
 		
 		
 		value.ToCString( _data+offset,_length-offset )
 		value.ToCString( _data+offset,_length-offset )
@@ -500,6 +580,7 @@ Class DataBuffer Extends std.resource.Resource
 	
 	
 	#end
 	#end
 	Method CopyTo( dst:DataBuffer,srcOffset:Int,dstOffset:Int,count:Int )
 	Method CopyTo( dst:DataBuffer,srcOffset:Int,dstOffset:Int,count:Int )
+		
 		DebugAssert( srcOffset>=0 And srcOffset+count<=_length And dstOffset>=0 And dstOffset+count<=dst._length )
 		DebugAssert( srcOffset>=0 And srcOffset+count<=_length And dstOffset>=0 And dstOffset+count<=dst._length )
 		
 		
 		libc.memmove( dst._data+dstOffset,_data+srcOffset,count )
 		libc.memmove( dst._data+dstOffset,_data+srcOffset,count )
@@ -549,7 +630,7 @@ Class DataBuffer Extends std.resource.Resource
 	#end	
 	#end	
 	Method OnDiscard() Override
 	Method OnDiscard() Override
 		
 		
-		GCFree( _data )
+		If _free GCFree( _data )
 		
 		
 		_data=Null
 		_data=Null
 	End
 	End
@@ -558,7 +639,7 @@ Class DataBuffer Extends std.resource.Resource
 	#end	
 	#end	
 	Method OnFinalize() Override
 	Method OnFinalize() Override
 		
 		
-		GCFree( _data )
+		If _free GCFree( _data )
 	End
 	End
 	
 	
 	Private
 	Private
@@ -567,6 +648,7 @@ Class DataBuffer Extends std.resource.Resource
 	Field _length:Int
 	Field _length:Int
 	Field _byteOrder:ByteOrder
 	Field _byteOrder:ByteOrder
 	Field _swapEndian:Bool
 	Field _swapEndian:Bool
+	Field _free:Bool
 	
 	
 	Function Swap2( v:Void Ptr )
 	Function Swap2( v:Void Ptr )
 		Local t:=Cast<UShort Ptr>( v )[0]
 		Local t:=Cast<UShort Ptr>( v )[0]

+ 28 - 1
modules/std/memory/datastream.monkey2

@@ -20,7 +20,6 @@ Class DataStream Extends std.stream.Stream
 	#end
 	#end
 	Method New( buf:DataBuffer,offset:Int=0 )
 	Method New( buf:DataBuffer,offset:Int=0 )
 		Self.New( buf,offset,buf.Length-offset )
 		Self.New( buf,offset,buf.Length-offset )
-		
 	End
 	End
 
 
 	Method New( buf:DataBuffer,offset:Int,count:Int )
 	Method New( buf:DataBuffer,offset:Int,count:Int )
@@ -110,6 +109,34 @@ Class DataStream Extends std.stream.Stream
 		
 		
 		Return count
 		Return count
 	End
 	End
+	
+	#rem monkeydoc Opens a data stream.
+	
+	`path` should begin with a parenthesis enclosed, comma separated pair of values representing start and length of memory.
+	
+	For example: "(10000,100)" represents 100 bytes starting at memory address 10000.
+	
+	#end
+	Function Open:DataStream( path:String,mode:String )
+		
+		path=path.Trim()
+		
+		If Not path.StartsWith( "(" ) Return Null
+		
+		Local i:=path.Find( ",",1 )
+		If i=-1 Return Null
+		
+		Local e:=path.Find( ")",i+1 )
+		If e=-1 Return Null
+		
+		Local start:=ULong( path.Slice( 1,i ) )
+		
+		Local length:=Int( path.Slice( i+1,e ) )
+		
+		Local data:=New DataBuffer( Cast<Void Ptr>( start ),length )
+		
+		Return New DataStream( data )
+	End
 
 
 	Private
 	Private
 	
 	

+ 5 - 0
modules/std/std.monkey2

@@ -101,6 +101,11 @@ Function Main()
 		Return FileStream.Open( path,mode )
 		Return FileStream.Open( path,mode )
 	End
 	End
 	
 	
+	Stream.OpenFuncs["memblock"]=Lambda:Stream( proto:String,path:String,mode:String )
+	
+		Return DataStream.Open( path,mode )
+	End
+	
 #If __MOBILE_TARGET__
 #If __MOBILE_TARGET__
 	
 	
 	Stream.OpenFuncs["internal"]=Lambda:Stream( proto:String,path:String,mode:String )
 	Stream.OpenFuncs["internal"]=Lambda:Stream( proto:String,path:String,mode:String )