Code archives/File Utilities/EFFIcient Map (etc) Saving

This code has been declared by its author to be Public Domain code.

Download source code

EFFIcient Map (etc) Saving by StreaksyMay
Say you want to save a 2D map of tiles or 3D map of blocks to a file, for a common example. If there are less than 256 tiles/blocks then you save as bytes. If there are more then you will use Shorts or Ints, but that is wasteful if there are, say, 300 tiles/blocks because most indices will be lower than 256 and the extra byte[s] is/are a waste of disk space and loading time most of the time. Know what I mean?

I came up with this method of writing values to files. Here are the specs:

* Values 250 and under save as one byte
* Values 502 and under save as two bytes
* Values 65534 and under save as three bytes
* Values 16777215 and under save as four bytes
* Values 2147483648 and under saves as five bytes
* Negative values write an extra byte

So, the lower the value, the fewer bytes it takes up. Negative values take up a whole extra byte but when saving grids of map info - which this was primarily made for - negative values won't even be used, but I thought I'd support them anyway.

I hope you find it useful. Let me know if you do.
'Effi is an efficient file value storage method that works best with small values.

' * Values 250 and under save as one byte
' * Values 502 and under save as two bytes
' * Values 65534 and under save as three bytes
' * Values 16777215 and under save as four bytes
' * Values 2147483648 and under saves as five bytes
' * Negative values write an extra byte



Global maxthrib=(256*256*256)-1










	
' FILE READING / WRITING





Function WriteEffi(s:TStream,val:Long)	'Writes up to the value of an unsigned integer including negative sign  (-2147483648 to 2147483648)
	If val<0 Then WriteByte s,255;val=Abs(val)							'CHR 255 = NEGATIVE
	If val=<250 Then WriteByte s,val;Return								'CHR<250 = BYTE
	If val=<251+251 Then WriteByte s,251;WriteByte s,val-251;Return		'CHR 251 = BYTE+251
	If val=<65535 Then WriteByte s,252;WriteShort s,val;Return			'CHR 252 = CONTROL BYTE + UNSIGNED SHORT
	If val=<maxthrib Then WriteByte s,253;WriteThrib s,val;Return		'CHR 253 = CONTROL BYTE + UNSIGNED 3-BYTE
	WriteByte s,254;WriteUSInt s,val;Return								'CHR 254 = CONTROL BYTE + UNSIGNED INT
End Function


Function ReadEffi:Long(s:TStream)	'Reads up to the value of an unsigned integer including negative sign  (-2147483648 to 2147483648)
	Local sign=1
	Local b=ReadByte(s)
	If b=255 Then sign=-1;b=ReadByte(s)
	If b=<250 Then Return b*sign
	If b=251 Then Return (251+ReadByte(s))*sign
	If b=252 Then Return ReadShort(s)*sign
	If b=253 Then Return ReadThrib(s)*sign	'unsigned 3-byte value
	If b=254 Then Return ReadUSInt(s)*sign	'unsigned integer
End Function




Function WriteThrib(s:TStream,v)		'Unsigned 3-byte value (between a short and an int)
	WriteByte s, (v Shr 16) & $ff
	WriteByte s, (v Shr 8) & $ff
	WriteByte s, v & $ff
End Function
Function ReadThrib(s:TStream)			'Unsigned 3-byte value (between a short and an int)
	Local b1=ReadByte(s)
	Local b2=ReadByte(s)
	Local b3=ReadByte(s)
	Return (b1 Shl 16) | (b2 Shl 8) | b3
End Function


Function WriteUSInt(s:TStream,v:Long)			'Unsigned Integer
	WriteByte s, (v Shr 24) & $ff
	WriteByte s, (v Shr 16) & $ff
	WriteByte s, (v Shr 8) & $ff
	WriteByte s, v & $ff
End Function
Function ReadUSInt:Long(s:TStream)				'Unsigned Integer
	Local b1=ReadByte(s)
	Local b2=ReadByte(s)
	Local b3=ReadByte(s)
	Local b4=ReadByte(s)
	Return (b1 Shl 24) | (b2 Shl 16) | (b3 Shl 8) | b4
End Function






' QUICK CONVERSION IF NEEDED (USING STRINGS)


Function Effi$(val:Long)
	Local o$
	If val<0 Then o=Chr(255);val=Abs(val)
	If val=<250 Then o:+Chr(val);Return o
	If val=<251+251 Then o:+Chr(251);o:+Chr(val-251);Return o
	If val=<65535 Then o:+Chr(252);o:+Chr((val Shr 8) & $ff);o:+Chr(val & $ff);Return o
	If val=<maxthrib Then o:+Chr(253);o:+Chr((val Shr 16) & $ff);o:+Chr((val Shr 8) & $ff);o:+Chr(val & $ff);Return o
	o:+Chr(254);o:+Chr((val Shr 24) & $ff);o:+Chr((val Shr 16) & $ff);o:+Chr((val Shr 8) & $ff);o:+Chr(val & $ff);Return o
End Function

Function UnEffi:Long(i$)
	Local sign=1
	Local b=Asc(Mid(i,1,1))
	If b=255 Then sign=-1;i=Right(i,Len(i)-1);b=Asc(Mid(i,1,1))
	If b=<250 Then Return b*sign
	If b=251 Then Return (251+Asc(Mid(i,2,1)))*sign
	If b=252 Then Return ( (Asc(Mid(i,2,1)) Shl 8) | Asc(Mid(i,3,1))		)*sign
	If b=253 Then Return ( (Asc(Mid(i,2,1)) Shl 16) | (Asc(Mid(i,3,1)) Shl 8) | Asc(Mid(i,4,1))		)*sign
	If b=254 Then Return ( (Asc(Mid(i,2,1)) Shl 24) | (Asc(Mid(i,3,1)) Shl 16) | (Asc(Mid(i,4,1)) Shl 8) | Asc(Mid(i,5,1))		)*sign
End Function

Comments

None.

Code Archives Forum