Last active
July 31, 2021 20:43
-
-
Save x1nixmzeng/3805536 to your computer and use it in GitHub Desktop.
Binary template for reading strings of known or unknown length
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//-------------------------------------- | |
//--- 010 Editor v5.0.0 Binary Template | |
// | |
// File: prelen.bt | |
// Author: x1nixmzeng/WRS | |
// Revision: v1.03 | |
// Purpose: Reading strings of known length | |
// History | |
// v1.03 Added optional STR_ENCODING macro to specify the charset | |
// used to format the template results | |
// Added optional PRELEN_REQUIRE macro for future versions | |
// v1.02 Added new alignment type for null-length strings | |
// v1.01 Added guards to avoid errors when included more than once | |
// v1.00 NOTE: The prelenType enum values have been updated | |
// NOTE: Unicode strings have been separately defined (wstr) | |
// Supports | |
// * 32/16/8 size descriptions | |
// * Null-terminated strings | |
// * Fixed length strings | |
// ------------------------------------ | |
// v0.05 Now supports strings of known length | |
// v0.04 Added support for null-terminated strings | |
// v0.03 Added supported for wide strings (prepend 'w' to prelenType) | |
// v0.02 strRead function replaced with GetStrValue | |
// Cleaner GetStrValue method | |
// String displayed for empty values can now be defined outside script | |
//-------------------------------------- | |
#ifndef PRELEN_BT_ | |
#define PRELEN_BT_ | |
#define PRELEN_VERSION 103 | |
RequiresVersion(5); | |
#ifndef STR_EMPTY | |
// Default value used for empty values | |
#define STR_EMPTY "" | |
#endif | |
#ifndef STR_ENCODING | |
// Default source encoding | |
#define STR_ENCODING GetFileCharSet() | |
#endif | |
#ifdef PRELEN_REQUIRE | |
if(PRELEN_REQUIRE > PRELEN_VERSION) | |
{ | |
Warning("Version %u of prelen.bt is required (have %u)", PRELEN_REQUIRE, PRELEN_VERSION); | |
Exit(-1); | |
} | |
#endif | |
//#define PRELEN_DISABLE_CHECKS | |
// Length flags | |
enum prelenType | |
{ | |
pnt8 = -6, // null-terminated size descriptor, string padded to 8 bytes | |
pnt4 = -5, // null-terminated size descriptor, string padded to 4 bytes | |
plen32 = -4, // 32-bit size descriptor | |
plen16 = -3, // 16-bit size descriptor | |
plen8 = -2, // 8-bit size descriptor | |
pnt = -1, // null-terminated size descriptor | |
pblank = 0 // Empty string | |
}; | |
// | |
// Helpers | |
// | |
int Align(int val, int align) | |
{ | |
return ((val+(align-1)) & (~(align-1))) - val; | |
} | |
// | |
// Structures | |
// | |
// ASCII | |
struct prelenStr( prelenType t ) | |
{ | |
if( t == pblank ) | |
{ | |
// NOTE: This will give an empty structure warning | |
local uint len = 0; | |
} | |
else | |
{ | |
if( t > pblank ) | |
{ | |
local uint len = t; | |
char val[len]; | |
} | |
else | |
if( t == pnt || t == pnt4 || t == pnt8 ) | |
{ | |
string val; | |
local uint len = Strlen( val ); | |
if( len > 0 && t != pnt ) | |
{ | |
local int pad = 0; | |
local uint size = len +1; | |
switch( t ) | |
{ | |
case pnt4 : pad = Align(size, 4); break; | |
case pnt8 : pad = Align(size, 8); break; | |
} | |
if( pad > 0 ) | |
FSkip( pad ); | |
} | |
} | |
else | |
{ | |
switch( t ) | |
{ | |
case plen32 : uint len; break; | |
case plen16 : ushort len; break; | |
case plen8 : ubyte len; break; | |
default : Assert( false, "Unknown prelenType" ); | |
} | |
#ifndef PRELEN_DISABLE_CHECKS | |
if( FTell() + len > FileSize() ) | |
Warning("prelen.bt :: String out of bounds"); | |
#endif | |
if( len > 0 ) | |
char val[len]; | |
} | |
} | |
}; | |
// Unicode | |
struct prelenWStr( prelenType t ) | |
{ | |
if( t == pblank ) | |
{ | |
// NOTE: This will give an empty structure warning | |
local uint len = 0; | |
} | |
else | |
{ | |
if( t > pblank ) | |
{ | |
local uint len = t; | |
wchar_t val[len]; | |
} | |
else | |
if( t == pnt || t == pnt4 || t == pnt8 ) | |
{ | |
wstring val; | |
local uint len = WStrlen( val ); | |
if( len > 0 && t != pnt ) | |
{ | |
local int pad = 0; | |
local uint size = (len +1) * sizeof(wchar_t); | |
switch( t ) | |
{ | |
case pnt4 : pad = Align(size, 4); break; | |
case pnt8 : pad = Align(size, 8); break; | |
} | |
if( pad > 0 ) | |
FSkip( pad ); | |
} | |
} | |
else | |
{ | |
switch( t ) | |
{ | |
case plen32 : uint len; break; | |
case plen16 : ushort len; break; | |
case plen8 : ubyte len; break; | |
default : Assert( false, "Unknown prelenType" ); | |
} | |
if( len > 0 ) | |
wchar_t val[len]; | |
} | |
} | |
}; | |
// | |
// Type definitions | |
// | |
// ASCII | |
typedef prelenStr str <read=GetStrValue >; | |
// Unicode | |
typedef prelenWStr wstr <read=GetWStrValue>; | |
// | |
// Accessor functions | |
// | |
// ASCII | |
wstring GetStrValue(str &t) | |
{ | |
// Return string or empty string | |
return( t.len ? StringToWString(t.val, STR_ENCODING) : STR_EMPTY ); | |
} | |
// Unicode | |
wstring GetWStrValue(wstr &t) | |
{ | |
// Return string or empty string | |
return( t.len ? t.val : STR_EMPTY ); | |
} | |
#endif | |
// EOF |
Updated to v1.00 which allows for fixed-length strings, with some minor changes to how Unicode strings are handled.
Updated to v1.02 which adds support for padding null-terminated strings to support 4 or 8 byte alignment
Updated to v1.03 which includes an optional macro for target character set (for display in the template results). Example usage:
#define STR_ENCODING CHARSET_CHINESE_S
#include "prelen.bt"
str ChineseString(plen32);
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This template was adapted from the version posted on XeNTaX: http://forum.xentax.com/viewtopic.php?p=77375#p77375
From v0.03, it contains a few performance fixes and adds supported for fixed-length widestrings!