Code archives/File Utilities/EFFIcient Map (etc) Saving
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
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