1
0
Fork 0

DBG: various changes to the encodemap

This commit is contained in:
mrexodia 2016-06-24 02:46:27 +02:00
parent 7315183855
commit 2956b01962
No known key found for this signature in database
GPG Key ID: D72F9A4FAA0073B4
10 changed files with 407 additions and 292 deletions

View File

@ -86,7 +86,9 @@ void DbSave(DbLoadSaveType saveType)
break;
}
plugincbcall(CBTYPE::CB_SAVEDB, &pluginSaveDb);
json_object_set_new(root, "plugins", pluginRoot);
if(json_object_size(pluginRoot))
json_object_set(root, "plugins", pluginRoot);
json_decref(pluginRoot);
}
auto wdbpath = StringUtils::Utf8ToUtf16(dbpath);
@ -165,7 +167,7 @@ void DbLoad(DbLoadSaveType loadType)
// Deserialize JSON and validate
JSON root = json_loads(databaseText.c_str(), JSON_ALLOW_NUL, 0);
JSON root = json_loads(databaseText.c_str(), 0, 0);
if(!root)
{

View File

@ -1,10 +1,10 @@
#include "datainst_helper.h"
#include "encodemap.h"
#include "stringutils.h"
#include "value.h"
#include <capstone_wrapper.h>
std::unordered_map<ENCODETYPE, std::string> disasmMap;
std::unordered_map<std::string, ENCODETYPE> assembleMap;
void initDataInstMap()
@ -42,12 +42,8 @@ void initDataInstMap()
}
String GetDataTypeString(void* buffer, duint size, ENCODETYPE type)
{
switch(type)
{
case enc_byte:
@ -57,23 +53,23 @@ String GetDataTypeString(void* buffer, duint size, ENCODETYPE type)
case enc_dword:
return StringUtils::ToIntegralString<unsigned int>(buffer);
case enc_fword:
return StringUtils::ToHex((char*)buffer, 6, true);
return StringUtils::ToHex((unsigned char*)buffer, 6, true);
case enc_qword:
return StringUtils::ToIntegralString<unsigned long long int>(buffer);
case enc_tbyte:
return StringUtils::ToHex((char*)buffer, 10, true);
return StringUtils::ToHex((unsigned char*)buffer, 10, true);
case enc_oword:
return StringUtils::ToHex((char*)buffer, 16, true);
return StringUtils::ToHex((unsigned char*)buffer, 16, true);
case enc_mmword:
case enc_xmmword:
case enc_ymmword:
return StringUtils::ToHex((char*)buffer, size, false);
return StringUtils::ToHex((unsigned char*)buffer, size, false);
case enc_real4:
return StringUtils::ToFloatingString<float>(buffer);
case enc_real8:
return StringUtils::ToFloatingString<double>(buffer);
case enc_real10:
return StringUtils::ToHex((char*)buffer, 10, true);
return StringUtils::ToHex((unsigned char*)buffer, 10, true);
//return ToLongDoubleString(buffer);
case enc_ascii:
return String((const char*)buffer, size);
@ -118,13 +114,13 @@ duint decodesimpledata(const unsigned char* buffer, ENCODETYPE type)
struct DataInstruction
{
ENCODETYPE type;
String oprand;
String operand;
};
bool parsedatainstruction(const char* instruction, DataInstruction & di)
{
di.type = enc_unknown;
di.oprand = "";
di.operand = "";
String instStr = StringUtils::Trim(String(instruction));
size_t pos = instStr.find_first_of(" \t");
String opcode = instStr.substr(0, pos);
@ -135,7 +131,7 @@ bool parsedatainstruction(const char* instruction, DataInstruction & di)
pos = instStr.find_first_not_of(" \t", pos);
if(pos == String::npos)
return false;
di.oprand = instStr.substr(pos);
di.operand = instStr.substr(pos);
return true;
}
@ -152,126 +148,161 @@ bool tryassembledata(duint addr, unsigned char* dest, int destsize, int* size, c
DataInstruction di;
if(!parsedatainstruction(instruction, di))
{
if(di.oprand == "")
strcpy_s(error, MAX_ERROR_SIZE, "Missing oprand");
if(di.operand == "")
strcpy_s(error, MAX_ERROR_SIZE, "missing operand");
return false;
}
duint retsize = 0;
duint retsize = GetEncodeTypeSize(di.type);
String buffer;
try
switch(di.type)
{
switch(di.type)
case enc_byte:
case enc_word:
case enc_dword:
case enc_fword:
case enc_qword:
{
unsigned long long result = 0;
if(!convertLongLongNumber(di.operand.c_str(), result, 16))
{
case enc_byte:
case enc_word:
case enc_dword:
case enc_fword:
case enc_qword:
case enc_tbyte:
case enc_oword:
{
retsize = GetEncodeTypeSize(di.type);
buffer = StringUtils::FromHex(di.oprand, retsize, true);
break;
}
case enc_mmword:
case enc_xmmword:
case enc_ymmword:
{
retsize = GetEncodeTypeSize(di.type);
if(retsize > destsize)
{
strcpy_s(error, MAX_ERROR_SIZE, "insufficient buffer");
if(size)
{
*size = int(retsize); //return correct size
return dest == nullptr;
}
return false;
}
else
{
buffer = StringUtils::FromHex(di.oprand, retsize, false);
}
break;
}
case enc_real4:
{
retsize = 4;
float f = std::stof(di.oprand);
buffer = String((char*)&f, 4);
break;
}
case enc_real8:
{
retsize = 8;
double d = std::stod(di.oprand);
buffer = String((char*)&d, 8);
break;
}
case enc_real10:
strcpy_s(error, MAX_ERROR_SIZE, "80bit extended float is not supported");
return false; //80 bit float is not supported in MSVC, need to add other library
case enc_ascii:
{
if(di.oprand.size() > destsize)
{
strcpy_s(error, MAX_ERROR_SIZE, "string too long");
if(size)
{
*size = int(di.oprand.size()); //return correct size
return dest == nullptr;
}
return false;
}
else
{
retsize = di.oprand.size();
buffer = di.oprand;
}
break;
}
case enc_unicode:
{
WString unicode = StringUtils::Utf8ToUtf16(di.oprand);
if(unicode.size()*sizeof(wchar_t) > destsize)
{
strcpy_s(error, MAX_ERROR_SIZE, "string too long");
if(size)
{
retsize = unicode.size() * 2; //return correct size
return dest == nullptr;
}
return false;
}
else
{
retsize = unicode.size() * 2;
buffer = String((char*)unicode.c_str(), retsize);
}
break;
}
default:
strcpy_s(error, MAX_ERROR_SIZE, "failed to convert operand");
return false;
}
auto buf = (char*)&result;
for(auto i = retsize; i < sizeof(result); i++)
if(buf[i])
{
strcpy_s(error, MAX_ERROR_SIZE, "operand value too big");
return false;
}
buffer = String(buf, retsize);
}
catch(const std::exception & e)
break;
case enc_tbyte:
case enc_oword:
{
strcpy_s(error, MAX_ERROR_SIZE, e.what());
std::vector<unsigned char> data;
if(!StringUtils::FromHex(StringUtils::PadLeft(di.operand, retsize * 2, '0'), data, true))
{
strcpy_s(error, MAX_ERROR_SIZE, "invalid operand (FromHex failed)");
return false;
}
if(data.size() != retsize)
{
sprintf_s(error, MAX_ERROR_SIZE, "invalid size (expected %" fext "u, got %" fext "u)", retsize, data.size());
return false;
}
buffer = String((char*)data.data(), data.size());
}
break;
case enc_mmword:
case enc_xmmword:
case enc_ymmword:
{
std::vector<unsigned char> data;
if(!StringUtils::FromHex(StringUtils::PadLeft(di.operand, retsize * 2, '0'), data, false))
{
strcpy_s(error, MAX_ERROR_SIZE, "invalid operand (FromHex failed)");
return false;
}
if(data.size() != retsize)
{
sprintf_s(error, MAX_ERROR_SIZE, "invalid size (expected %" fext "u, got %" fext "u)", retsize, data.size());
return false;
}
buffer = String((char*)data.data(), data.size());
}
break;
case enc_real4:
{
retsize = 4;
float f = std::stof(di.operand);
buffer = String((char*)&f, 4);
break;
}
case enc_real8:
{
retsize = 8;
double d = std::stod(di.operand);
buffer = String((char*)&d, 8);
break;
}
case enc_real10:
strcpy_s(error, MAX_ERROR_SIZE, "80bit extended float is not supported");
return false; //80 bit float is not supported in MSVC, need to add other library
case enc_ascii:
{
String unescaped;
if(!StringUtils::Unescape(di.operand, unescaped))
{
strcpy_s(error, MAX_ERROR_SIZE, "invalid string literal");
return false;
}
if(unescaped.size() > size_t(destsize))
{
strcpy_s(error, MAX_ERROR_SIZE, "string too long");
if(size)
{
*size = int(unescaped.size()); //return correct size
return dest == nullptr;
}
return false;
}
retsize = unescaped.size();
buffer = unescaped;
}
break;
case enc_unicode:
{
String unescaped;
if(!StringUtils::Unescape(di.operand, unescaped))
{
strcpy_s(error, MAX_ERROR_SIZE, "invalid string literal");
return false;
}
WString unicode = StringUtils::Utf8ToUtf16(unescaped);
if(unicode.size()*sizeof(wchar_t) > size_t(destsize))
{
strcpy_s(error, MAX_ERROR_SIZE, "string too long");
if(size)
{
retsize = unicode.size() * 2; //return correct size
return dest == nullptr;
}
return false;
}
retsize = unicode.size() * 2;
buffer = String((char*)unicode.c_str(), retsize);
}
break;
default:
return false;
}
if(retsize > size_t(destsize))
{
strcpy_s(error, MAX_ERROR_SIZE, "dest buffer too small");
return false;
}
if(size)
*size = int(retsize);
if(dest)
memcpy_s((char*)dest, retsize, buffer.c_str(), retsize);
return true;
}

View File

@ -2,11 +2,7 @@
#include "_global.h"
void initDataInstMap();
bool isdatainstruction(const char* instruction);
bool tryassembledata(duint addr, unsigned char* dest, int destsize, int* size, const char* instruction, char* error);
bool trydisasm(const unsigned char* buffer, duint addr, DISASM_INSTR* instr, duint codesize);
bool trydisasmfast(const unsigned char* buffer, duint addr, BASIC_INSTRUCTION_INFO* basicinfo, duint codesize);

View File

@ -1004,7 +1004,7 @@ static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo)
if(!bFileIsDll && !bIsAttached) //Set entry breakpoint
{
pDebuggedBase = pCreateProcessBase; //debugged base = executable
char command[256] = "";
char command[deflen] = "";
if(settingboolget("Events", "TlsCallbacks"))
{
@ -1025,7 +1025,7 @@ static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo)
duint callbackVA = TLSCallBacks()[i] - ImageBase + pDebuggedBase;
if(MemIsValidReadPtr(callbackVA))
{
sprintf(command, "bp " fhex ",\"TLS Callback %d\",ss", callbackVA, i + 1);
sprintf_s(command, "bp " fhex ",\"TLS Callback %d\",ss", callbackVA, i + 1);
cmddirectexec(command);
}
else
@ -1039,7 +1039,7 @@ static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo)
if(settingboolget("Events", "EntryBreakpoint"))
{
sprintf(command, "bp " fhex ",\"entry breakpoint\",ss", (duint)CreateProcessInfo->lpStartAddress);
sprintf_s(command, "bp " fhex ",\"entry breakpoint\",ss", (duint)CreateProcessInfo->lpStartAddress);
cmddirectexec(command);
}
}

View File

@ -1,7 +1,6 @@
#include "encodemap.h"
#include <unordered_map>
#include "addrinfo.h"
#include <algorithm>
#include <capstone_wrapper.h>
struct ENCODEMAP : AddrInfo
@ -48,9 +47,8 @@ struct EncodeMapSerializer : AddrInfoSerializer<ENCODEMAP>
{
bool Save(const ENCODEMAP & value) override
{
AddrInfoSerializer::Save(value);
set("data", json_stringn((const char*)value.data, value.size));
setString("data", StringUtils::ToCompressedHex(value.data, value.size).c_str());
return true;
}
@ -58,11 +56,17 @@ struct EncodeMapSerializer : AddrInfoSerializer<ENCODEMAP>
{
if(!AddrInfoSerializer::Load(value))
return false;
auto data = get("data");
value.size = json_string_length(data);
auto dataJson = get("data");
if(!dataJson)
return false;
std::vector<unsigned char> data;
if(!StringUtils::FromCompressedHex(json_string_value(dataJson), data))
return false;
value.size = data.size();
value.data = (byte*)VirtualAlloc(NULL, value.size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if(value.data == NULL) return false;
memcpy(value.data, (byte*)json_string_value(data), value.size);
if(!value.data)
return false;
memcpy(value.data, data.data(), data.size());
IncreaseReferenceCount(value.data, false);
return true;
}
@ -106,21 +110,19 @@ bool EncodeMapGetorCreate(duint addr, ENCODEMAP & map)
void* EncodeMapGetBuffer(duint addr, bool create)
{
duint base, size;
if(!MemIsValidReadPtr(addr))
return nullptr;
base = MemFindBaseAddr(addr, &size);
duint size;
auto base = MemFindBaseAddr(addr, &size);
ENCODEMAP map;
bool result = create ? EncodeMapGetorCreate(addr, map) : encmaps.Get(EncodeMap::VaKey(base), map);
auto result = create ? EncodeMapGetorCreate(addr, map) : encmaps.Get(EncodeMap::VaKey(base), map);
if(result)
{
duint offset = addr - base;
if(offset >= map.size)
return nullptr;
IncreaseReferenceCount(map.data);
return map.data;
auto offset = addr - base;
if(offset < map.size)
{
IncreaseReferenceCount(map.data);
return map.data;
}
}
return nullptr;
}
@ -136,25 +138,6 @@ void EncodeMapReleaseBuffer(void* buffer)
EncodeMapReleaseBuffer(buffer, true);
}
bool IsRangeConflict(byte* typebuffer, duint size, duint codesize)
{
if(codesize > size)
return true;
size = min(size, codesize);
if(size <= 0)
return false;
ENCODETYPE type = (ENCODETYPE)typebuffer[0];
if(type == enc_middle)
return true;
for(int i = 1; i < size; i++)
{
if((ENCODETYPE)typebuffer[i] != enc_unknown && (ENCODETYPE)typebuffer[i] != enc_middle)
return true;
}
return false;
}
duint GetEncodeTypeSize(ENCODETYPE type)
{
switch(type)
@ -194,73 +177,44 @@ duint GetEncodeTypeSize(ENCODETYPE type)
}
}
bool IsCodeType(ENCODETYPE type)
static bool IsCodeType(ENCODETYPE type)
{
return type == enc_code || type == enc_junk;
}
ENCODETYPE EncodeMapGetType(duint addr, duint codesize)
{
duint base, size;
base = MemFindBaseAddr(addr, &size);
if(!base)
return ENCODETYPE::enc_unknown;
duint size;
auto base = MemFindBaseAddr(addr, &size);
ENCODEMAP map;
if(encmaps.Get(EncodeMap::VaKey(base), map))
if(base && encmaps.Get(EncodeMap::VaKey(base), map))
{
duint offset = addr - base;
auto offset = addr - base;
if(offset >= map.size)
return ENCODETYPE::enc_unknown;
ENCODETYPE type = (ENCODETYPE)map.data[offset];
if((type == enc_unknown || type == enc_middle) && IsRangeConflict(map.data + offset, size - offset, codesize))
return enc_byte;
else
return type;
return enc_unknown;
return ENCODETYPE(map.data[offset]);
}
return ENCODETYPE::enc_unknown;
return enc_unknown;
}
duint EncodeMapGetSize(duint addr, duint codesize)
{
duint base;
base = MemFindBaseAddr(addr, 0);
auto base = MemFindBaseAddr(addr, nullptr);
if(!base)
return codesize;
ENCODEMAP map;
if(encmaps.Get(EncodeMap::VaKey(base), map))
{
duint offset = addr - base;
auto offset = addr - base;
if(offset >= map.size)
return 1;
ENCODETYPE type = (ENCODETYPE)map.data[offset];
auto type = ENCODETYPE(map.data[offset]);
duint datasize = GetEncodeTypeSize(type);
if(type == enc_unknown || type == enc_code || type == enc_junk)
{
if(IsRangeConflict(map.data + offset, map.size - offset, codesize) || codesize == 0)
return datasize;
else
return codesize;
}
else if(type == enc_ascii || type == enc_unicode)
{
duint totalsize = 0;
for(auto i = offset; i < map.size; i += datasize)
{
if(map.data[i] == type)
totalsize += datasize;
else
break;
}
return totalsize;
}
else
auto datasize = GetEncodeTypeSize(type);
if(!IsCodeType(type))
return datasize;
}
@ -269,19 +223,16 @@ duint EncodeMapGetSize(duint addr, duint codesize)
bool EncodeMapSetType(duint addr, duint size, ENCODETYPE type)
{
duint base;
base = MemFindBaseAddr(addr, 0);
auto base = MemFindBaseAddr(addr, nullptr);
if(!base)
return false;
ENCODEMAP map;
if(!EncodeMapGetorCreate(base, map))
return false;
duint offset = addr - base;
auto offset = addr - base;
size = min(map.size - offset, size);
duint datasize = GetEncodeTypeSize(type);
auto datasize = GetEncodeTypeSize(type);
if(datasize == 1 && !IsCodeType(type))
{
memset(map.data + offset, (byte)type, size);
@ -292,24 +243,20 @@ bool EncodeMapSetType(duint addr, duint size, ENCODETYPE type)
if(IsCodeType(type) && size > 1)
{
Capstone cp;
unsigned char* buffer = new unsigned char[size];
if(!MemRead(addr, buffer, size))
{
delete[] buffer;
Memory<unsigned char*> buffer(size);
if(!MemRead(addr, buffer(), size))
return false;
}
duint buffersize = size, bufferoffset = 0, cmdsize;
for(auto i = offset; i < offset + size;)
{
map.data[i] = (byte)type;
cp.Disassemble(base + i, buffer + bufferoffset, int(buffersize));
cp.Disassemble(base + i, buffer() + bufferoffset, int(buffersize - bufferoffset));
cmdsize = cp.Success() ? cp.Size() : 1;
i += cmdsize;
bufferoffset += cmdsize;
buffersize -= cmdsize;
}
}
else
{

View File

@ -2,25 +2,14 @@
#include "_global.h"
void* EncodeMapGetBuffer(duint addr, bool create = false);
void EncodeMapReleaseBuffer(void* buffer);
ENCODETYPE EncodeMapGetType(duint addr, duint codesize);
duint EncodeMapGetSize(duint addr, duint codesize);
void EncodeMapDelSegment(duint addr);
void EncodeMapDelRange(duint addr, duint size);
bool EncodeMapSetType(duint addr, duint size, ENCODETYPE type);
void EncodeMapDelRange(duint Start, duint End);
void EncodeMapCacheSave(JSON Root);
void EncodeMapCacheLoad(JSON Root);
void EncodeMapClear();
duint GetEncodeTypeSize(ENCODETYPE type);

View File

@ -1,5 +1,6 @@
#include "stringutils.h"
#include "memory.h"
#include "value.h"
#include "dynamicmem.h"
#include <windows.h>
#include <cstdint>
@ -71,6 +72,87 @@ String StringUtils::Escape(const String & s)
return escaped;
}
bool StringUtils::Unescape(const String & s, String & result, bool quoted)
{
int mLastChar;
size_t i = 0;
auto nextChar = [&]()
{
if(i == s.length())
return mLastChar = EOF;
return mLastChar = s[i++];
};
if(quoted)
{
nextChar();
if(mLastChar != '\"') //start of quoted string literal
return false; //invalid string literal
}
result.reserve(s.length());
while(true)
{
nextChar();
if(mLastChar == EOF) //end of file
{
if(!quoted)
break;
return false; //unexpected end of file in string literal (1)
}
if(mLastChar == '\r' || mLastChar == '\n')
return false; //unexpected newline in string literal (1)
if(quoted && mLastChar == '\"') //end of quoted string literal
break;
if(mLastChar == '\\') //escape sequence
{
nextChar();
if(mLastChar == EOF)
return false; //unexpected end of file in string literal (2)
if(mLastChar == '\r' || mLastChar == '\n')
return false; //unexpected newline in string literal (2)
if(mLastChar == '\'' || mLastChar == '\"' || mLastChar == '?' || mLastChar == '\\')
mLastChar = mLastChar;
else if(mLastChar == 'a')
mLastChar = '\a';
else if(mLastChar == 'b')
mLastChar = '\b';
else if(mLastChar == 'f')
mLastChar = '\f';
else if(mLastChar == 'n')
mLastChar = '\n';
else if(mLastChar == 'r')
mLastChar = '\r';
else if(mLastChar == 't')
mLastChar = '\t';
else if(mLastChar == 'v')
mLastChar = '\v';
else if(mLastChar == '0')
mLastChar = '\0';
else if(mLastChar == 'x') //\xHH
{
auto ch1 = nextChar();
auto ch2 = nextChar();
if(isxdigit(ch1) && isxdigit(ch2))
{
char byteStr[3] = "";
byteStr[0] = ch1;
byteStr[1] = ch2;
uint64_t hexData;
auto error = convertLongLongNumber(byteStr, hexData, 16);
if(error)
return false; //convertNumber failed (%s) for hex sequence \"\\x%c%c\" in string literal
mLastChar = hexData & 0xFF;
}
else
return false; //invalid hex sequence \"\\x%c%c\" in string literal
}
else
return false; //invalid escape sequence \"\\%c\" in string literal
}
result.push_back(mLastChar);
}
return true;
}
//Trim functions taken from: http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring/16743707#16743707
const String StringUtils::WHITESPACE = " \n\r\t";
@ -91,6 +173,17 @@ String StringUtils::TrimRight(const String & s, String delim)
return (endpos == String::npos) ? "" : s.substr(0, endpos + 1);
}
String StringUtils::PadLeft(const String & s, size_t minLength, char ch)
{
if(s.length() >= minLength)
return s;
String pad;
pad.resize(minLength - s.length());
for(size_t i = 0; i < pad.length(); i++)
pad[i] = ch;
return pad + s;
}
//Conversion functions taken from: http://www.nubaria.com/en/blog/?p=289
String StringUtils::Utf16ToUtf8(const WString & wstr)
{
@ -202,67 +295,115 @@ bool StringUtils::StartsWith(const String & h, const String & n)
return strstr(h.c_str(), n.c_str()) == h.c_str();
}
int char2int(char input)
static int hex2int(char ch)
{
if(input >= '0' && input <= '9')
return input - '0';
if(input >= 'A' && input <= 'F')
return input - 'A' + 10;
if(input >= 'a' && input <= 'f')
return input - 'a' + 10;
throw std::invalid_argument("invalid character");
if(ch >= '0' && ch <= '9')
return ch - '0';
if(ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
if(ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
return -1;
}
String StringUtils::FromHex(const String & s, size_t size, bool reverse)
bool StringUtils::FromHex(const String & text, std::vector<unsigned char> & data, bool reverse)
{
std::stringstream ss;
bool high = false;
if(s.length() > size * 2)
throw std::invalid_argument("string too long");
char ch = 0;
auto odd = s.size() % 2;
size_t cursize = 0;
for(dsint i = s.size() - 1; i >= 0; i--)
auto size = text.size();
if(size % 2)
return false;
data.resize(size / 2);
for(size_t i = 0, j = 0; i < size; i += 2, j++)
{
ch |= char2int(s[i]) << (high ? 4 : 0);
if(high || odd && i == 0)
auto high = hex2int(text[i]);
auto low = hex2int(text[i + 1]);
if(high == -1 || low == -1)
return false;
data[reverse ? data.size() - j - 1 : j] = (high << 4) | low;
}
return true;
}
String StringUtils::ToHex(unsigned long long value)
{
char buf[32];
sprintf_s(buf, "%llX", value);
return buf;
}
#define HEXLOOKUP "0123456789ABCDEF"
String StringUtils::ToHex(unsigned char* buffer, size_t size, bool reverse)
{
String result;
result.resize(size * 2);
for(size_t i = 0, j = 0; i < size; i++, j += 2)
{
auto ch = buffer[reverse ? size - i - 1 : i];
result[j] = HEXLOOKUP[(ch >> 4) & 0xF];
result[j + 1] = HEXLOOKUP[ch & 0xF];
}
return result;
}
String StringUtils::ToCompressedHex(unsigned char* buffer, size_t size)
{
if(!size)
return "";
String result;
result.reserve(size * 2);
for(size_t i = 0; i < size;)
{
size_t repeat = 0;
auto lastCh = buffer[i];
result.push_back(HEXLOOKUP[(lastCh >> 4) & 0xF]);
result.push_back(HEXLOOKUP[lastCh & 0xF]);
for(; i < size && buffer[i] == lastCh; i++)
repeat++;
result.append(StringUtils::sprintf("{%" fext "X}", repeat));
}
return result;
}
bool StringUtils::FromCompressedHex(const String & text, std::vector<unsigned char> & data)
{
auto size = text.size();
if(size < 2)
return false;
data.clear();
data.reserve(size); //TODO: better initial estimate
String repeatStr;
for(size_t i = 0; i < size;)
{
auto high = hex2int(text[i++]); //eat high nibble
if(i >= size)
return false;
auto low = hex2int(text[i++]); //eat low nibble
if(high == -1 || low == -1)
return false;
auto lastCh = (high << 4) | low;
data.push_back(lastCh);
if(i >= size)
break;
if(text[i] == '{')
{
ss.put(ch);
cursize++;
ch = 0;
repeatStr.clear();
i++; //eat '{'
while(text[i] != '}')
{
repeatStr.push_back(text[i++]); //eat character
if(i >= size)
return false;
}
i++; //eat '}'
duint repeat = 0;
if(!convertNumber(repeatStr.c_str(), repeat, 16) || !repeat)
return false;
for(size_t j = 1; j < repeat; j++)
data.push_back(lastCh);
}
high = !high;
}
for(auto i = cursize; i < size; i++)
ss.put('\0');
String res = ss.str();
if(!reverse)
std::reverse(res.begin(), res.end());
return res;
}
String StringUtils::ToHex(duint value)
{
std::stringstream ss;
ss << std::hex;
ss << value;
return ss.str();
}
String StringUtils::ToHex(void* buffer, size_t size, bool reverse)
{
std::stringstream ss;
ss << std::hex;
if(reverse)
{
for(dsint i = size - 1; i >= 0; i--)
ss << ((char*)buffer)[i];
}
else
{
for(size_t i = 0; i < size; i++)
ss << ((char*)buffer)[i];
}
return ss.str();
}
return true;
}

View File

@ -18,9 +18,11 @@ public:
static StringList Split(const String & s, char delim, std::vector<String> & elems);
static StringList Split(const String & s, char delim);
static String Escape(const String & s);
static bool Unescape(const String & s, String & result, bool quoted = true);
static String Trim(const String & s, String delim = StringUtils::WHITESPACE);
static String TrimLeft(const String & s, String delim = StringUtils::WHITESPACE);
static String TrimRight(const String & s, String delim = StringUtils::WHITESPACE);
static String PadLeft(const String & s, size_t minLength, char ch);
static String Utf16ToUtf8(const WString & wstr);
static String Utf16ToUtf8(const wchar_t* wstr);
static WString Utf8ToUtf16(const String & str);
@ -31,9 +33,11 @@ public:
static WString sprintf(const wchar_t* format, ...);
static String ToLower(const String & s);
static bool StartsWith(const String & h, const String & n);
static String FromHex(const String & s, size_t size, bool reverse = false);
static String ToHex(duint value);
static String ToHex(void* buffer, size_t size, bool reverse = false);
static bool FromHex(const String & text, std::vector<unsigned char> & data, bool reverse = false);
static String ToHex(unsigned long long value);
static String ToHex(unsigned char* buffer, size_t size, bool reverse = false);
static String ToCompressedHex(unsigned char* buffer, size_t size);
static bool FromCompressedHex(const String & text, std::vector<unsigned char> & data);
template<typename T>
static String ToFloatingString(void* buffer)
@ -51,7 +55,6 @@ public:
return ToHex(value);
}
private:
static const String WHITESPACE;
};

View File

@ -1490,14 +1490,19 @@ static bool ishexnumber(const char* string)
}
bool convertNumber(const char* str, duint & result, int radix)
{
unsigned long long llr;
if(!convertLongLongNumber(str, llr, radix))
return false;
result = duint(llr);
return true;
}
bool convertLongLongNumber(const char* str, unsigned long long & result, int radix)
{
errno = 0;
char* end;
#ifdef _WIN64
result = strtoull(str, &end, radix);
#else
result = strtoul(str, &end, radix);
#endif //_WIN64
if(!result && end == str)
return false;
if(result == ULLONG_MAX && errno)

View File

@ -8,6 +8,7 @@ bool valuesignedcalc();
void valuesetsignedcalc(bool a);
bool valapifromstring(const char* name, duint* value, int* value_size, bool printall, bool silent, bool* hexonly);
bool convertNumber(const char* str, duint & result, int radix);
bool convertLongLongNumber(const char* str, unsigned long long & result, int radix);
bool valfromstring_noexpr(const char* string, duint* value, bool silent = true, bool baseonly = false, int* value_size = nullptr, bool* isvar = nullptr, bool* hexonly = nullptr);
bool valfromstring(const char* string, duint* value, bool silent = true, bool baseonly = false, int* value_size = nullptr, bool* isvar = nullptr, bool* hexonly = nullptr);
bool valflagfromstring(duint eflags, const char* string);