Skip to content

Instantly share code, notes, and snippets.

@x1nixmzeng
Last active July 31, 2021 20:43
Show Gist options
  • Save x1nixmzeng/3805536 to your computer and use it in GitHub Desktop.
Save x1nixmzeng/3805536 to your computer and use it in GitHub Desktop.
Binary template for reading strings of known or unknown length
//--------------------------------------
//--- 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
@x1nixmzeng
Copy link
Author

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