Per scrivere dati binari di qualunque lunghezza in esadecimale:
codice:
//Structure
void INISection::PutKey(const std::_tcstring & Key, const void * Struct, size_t StructSize)
{
unsigned char checksum=0;
const unsigned char * castedStruct=(const unsigned char *)Struct;
strStream.clear();
strStream.str(_T(""));
TCHAR oldFill=strStream.fill(_T('0'));
strStream<<std::hex;
for(const unsigned char * readPtr=castedStruct;readPtr<castedStruct+StructSize;readPtr++)
{
strStream<<std::setw(2)<<*readPtr;
checksum=checksum+*readPtr;
}
strStream<<std::setw(2)<<checksum; //<-- se non ti serve il checksum, togli tutta la parte che lo riguarda
PutKey(Key,strStream.str()); //<-- nel tuo caso qui scriverai su file
strStream<<std::dec;
strStream.fill(oldFill);
}
Per rileggere questa roba:
codice:
//Structure
void INISection::GetKey(const std::_tcstring & Key, void * Struct, size_t StructSize) const
{
if(!KeyExists(Key))
return;
unsigned char checksum=0, checksum2=0;
unsigned char * castedStruct=(unsigned char *)Struct;
//Get the string
std::_tcstring strValue=GetKey(Key,_T("")); //<-- nel tuo caso qui leggerai dal file
if(strValue.size()==0)
return;
const TCHAR * readPtr=strValue.c_str();
//Length check
if(strValue.size()<(StructSize+1)*2)
throw std::runtime_error(ERROR_STD_PROLOG "The stored value is not valid for this structure.");
//Convert the string
for(unsigned char * writePtr=castedStruct;
writePtr<castedStruct+StructSize;
writePtr++,readPtr+=2)
{
*writePtr=getByte(readPtr);
checksum=checksum+*writePtr;
}
checksum2=getByte(readPtr);
//Compare the checksums
if(checksum!=checksum2)
throw std::runtime_error(ERROR_STD_PROLOG "Invalid checksum.");
}
//Returns a byte from a pair of hexadecimal digits
unsigned char INISection::getByte(const TCHAR * str)
{
unsigned char ret=0;
TCHAR ch;
for(int i=0;i<2;i++)
{
ch=_totupper(str[i]);
if(BETWEEN(ch,_T('0'),_T('9')))
ret|=(ch-_T('0'))<<((1-i)<<2);
else if(BETWEEN(ch,_T('A'),_T('F')))
ret|=(ch-_T('A')+10)<<((1-i)<<2);
else
throw std::runtime_error(ERROR_STD_PROLOG "Invalid character.");
}
return ret;
}
Ignora ERROR_STD_PROLOG (è una macro usata per aggiungere qualche informazione al messaggio di errore*); _tcstring è un typedef per std::basic_string<TCHAR>; BETWEEN è definita come
codice:
#define BETWEEN(n,min,max) ((n)>=(min)&&(n)<=(max))
/*
Note that the argument n is evaluated two times.
Example of use of the BETWEEN macro:
int n;
//...
if(BETWEEN(n,15,17))
cout<<"n is between 15 and 17";
*/
e serve semplicemente per verificare se il primo parametro passato sta tra due valori.
* per i curiosi:
codice:
#define ERROR_STD_PROLOG "Exception thrown in function: " __FUNCSIG__ " (in " __FILE__ ", last modified on " __TIMESTAMP__ ", line " TOSTRING( __LINE__ ) ").\nMessage: "
ci sono modi migliori per fare questo, ma non avevo tempo né voglia di cambiare tutte le classi di eccezioni.