@ -24,6 +24,8 @@ limitations under the License.
# include <string>
# include <vector>
# include <QDebug>
namespace VDFParser {
namespace crc {
template < typename CONT >
@ -67,6 +69,7 @@ static constexpr const char k_Devkit[] = {"Devkit"};
static constexpr const char k_DevkitGameID [ ] = { " DevkitGameID " } ;
static constexpr const char k_DevkitOverrideAppID [ ] = { " DevkitOverrideAppID " } ;
static constexpr const char k_LastPlayTime [ ] = { " LastPlayTime " } ;
static constexpr const char k_FlatpakAppID [ ] = { " FlatpakAppID " } ;
static constexpr const char k_tags [ ] = { " tags " } ;
enum VDFTypeId {
@ -75,7 +78,7 @@ enum VDFTypeId {
Number ,
} ;
template < const char * const keyname , typename type , const uint8_t const _type_id >
template < const char * const keyname , typename type , const uint8_t _type_id >
struct VDFKeyPair {
VDFKeyPair ( ) { }
explicit VDFKeyPair ( type _value ) : value ( _value ) { }
@ -104,58 +107,37 @@ struct VDFKeyPair {
}
} ;
template < uint8_t initialByte >
struct VDFIdx {
VDFIdx ( ) { } ;
VDFIdx ( const VDFIdx & other )
{
data [ 0 ] = other . data [ 0 ] ;
data [ 1 ] = other . data [ 1 ] ;
data = other . data ;
} ;
VDFIdx ( VDFIdx & & other )
{
data [ 0 ] = std : : move ( other . data [ 0 ] ) ;
data [ 1 ] = std : : move ( other . data [ 1 ] ) ;
data = std : : move ( other . data ) ;
} ;
VDFIdx ( int idx )
{
if ( idx > 99 ) {
data [ 0 ] = initialByte ;
data [ 1 ] = 0 ;
}
else if ( idx < 10 ) {
data [ 1 ] = std : : to_string ( idx ) . c_str ( ) [ 0 ] ;
}
else {
auto meh = std : : to_string ( idx ) . c_str ( ) ;
data [ 0 ] = meh [ 0 ] + initialByte ;
data [ 1 ] = meh [ 1 ] ;
}
data = std : : to_string ( idx ) ;
}
char data [ 2 ] = { initialByte , 0x0 } ;
std : : string data ;
operator int ( ) const
{
if ( data [ 0 ] = = initialByte ) {
int res = 0 ;
std : : from_chars ( & data [ 1 ] , & data [ 1 ] , res ) ;
return res ;
}
int res = 0 ;
char copy [ 2 ] = { data [ 0 ] - initialByte , data [ 1 ] } ;
std : : from_chars ( & copy [ 0 ] , & copy [ 1 ] , res ) ;
std : : from_chars ( data . data ( ) , data . data ( ) + data . size ( ) , res ) ;
return res ;
}
VDFIdx & operator = ( const VDFIdx & other )
{
data [ 0 ] = other . data [ 0 ] ;
data [ 1 ] = other . data [ 1 ] ;
data = other . data ;
return * this ;
}
VDFIdx & operator = ( VDFIdx & & other )
{
data [ 0 ] = std : : move ( other . data [ 0 ] ) ;
data [ 1 ] = std : : move ( other . data [ 1 ] ) ;
data = std : : move ( other . data ) ;
return * this ;
}
} ;
@ -164,30 +146,34 @@ struct ShortcutTag {
ShortcutTag ( ) { } ;
ShortcutTag ( const ShortcutTag & other )
{
idx = other . idx ;
value = other . value ;
} ;
ShortcutTag ( ShortcutTag & & other )
{
idx = std : : move ( other . idx ) ;
value = std : : move ( other . value ) ;
} ;
VDFIdx < 0x01 > idx ; // I Hope this is how it works... See VDFIdx
VDFIdx idx ;
std : : string value ;
const uint16_t end_marker = 0x0808 ;
ShortcutTag & operator = ( const ShortcutTag & other )
{
idx = other . idx ;
value = other . value ;
return * this ;
}
ShortcutTag & operator = ( ShortcutTag & & other )
{
idx = std : : move ( other . idx ) ;
value = std : : move ( other . value ) ;
return * this ;
}
} ;
struct Shortcut {
VDFIdx < 0x00 > idx ;
VDFIdx idx ;
VDFKeyPair < k_appid , uint32_t , VDFTypeId : : Number > appId { 0x000000 } ;
VDFKeyPair < k_appname , std : : string , VDFTypeId : : String > appName { " " } ;
VDFKeyPair < k_exe , std : : string , VDFTypeId : : String > exe { " \" \" " } ; // Qouted
@ -203,6 +189,7 @@ struct Shortcut {
VDFKeyPair < k_DevkitGameID , std : : string , VDFTypeId : : String > DevkitGameID { " " } ;
VDFKeyPair < k_DevkitOverrideAppID , uint32_t , VDFTypeId : : Number > DevkitOverrideAppID { 0 } ; //
VDFKeyPair < k_LastPlayTime , uint32_t , VDFTypeId : : Number > LastPlayTime { 0 } ; //
VDFKeyPair < k_FlatpakAppID , std : : string , VDFTypeId : : String > FlatpakAppID { " " } ; //
VDFKeyPair < k_tags , std : : vector < ShortcutTag > , VDFTypeId : : StringList > tags { } ;
Shortcut & operator = ( const Shortcut & other )
{
@ -223,6 +210,7 @@ struct Shortcut {
DevkitGameID = other . DevkitGameID ;
DevkitOverrideAppID = other . DevkitOverrideAppID ;
LastPlayTime = other . LastPlayTime ;
FlatpakAppID = other . FlatpakAppID ;
tags = other . tags ;
return * this ;
}
@ -326,7 +314,7 @@ class Parser {
{
VDFFile vdffile ;
ifile . open ( path .string ( ) , std : : ios : : binary | std : : ios : : in ) ;
ifile . open ( path , std : : ios : : binary | std : : ios : : in ) ;
if ( ! ifile . is_open ( ) ) {
return { } ;
}
@ -352,34 +340,17 @@ class Parser {
}
char b = ' \x0 ' ;
readVDFBuffer ( & b , 1 ) ; // skip 0 byte
if ( b ! = ' \x0 ' )
buff . push_back ( b ) ;
do {
if ( ifile . eof ( ) ) {
break ;
}
readVDFBuffer ( & b , 1 ) ; // 1-2 bytes idx, 0x00 delmiter
if ( b ! = ' \x0 ' )
buff . push_back ( b ) ;
} while ( b ! = ' \x0 ' ) ;
if ( buff [ 0 ] = = 0x08 & & buff [ 1 ] = = 0x08 ) {
break ;
}
Shortcut shortcut ;
if ( buff . size ( ) = = 2 ) {
shortcut . idx . data [ 0 ] = buff [ 0 ] ;
shortcut . idx . data [ 1 ] = buff [ 1 ] ;
}
else {
shortcut . idx . data [ 0 ] = ' \x0 ' ;
shortcut . idx . data [ 1 ] = buff [ 0 ] ;
shortcut . idx . data = readVDFString ( ) ;
if ( shortcut . idx . data = = " \x08 \x08 " ) {
break ;
}
while ( true ) // TODO;
{
if ( ifile . eof ( ) ) {
break ;
}
VDFTypeId tid = static_cast < VDFTypeId > ( readVDFValue < uint8_t > ( ) ) ;
const auto tid = static_cast < VDFTypeId > ( readVDFValue < uint8_t > ( ) ) ;
if ( tid = = 0x08 ) {
auto nextbyte = readVDFValue < uint8_t > ( ) ;
if ( nextbyte = = 0x08 ) {
@ -455,29 +426,35 @@ class Parser {
shortcut . LastPlayTime . value = readVDFValue < uint32_t > ( ) ;
continue ;
}
if ( key = = shortcut . FlatpakAppID . key ) {
shortcut . FlatpakAppID . value = readVDFString ( ) ;
continue ;
}
if ( key = = shortcut . tags . key ) {
// TODO: read tags
ShortcutTag tag ;
while ( true ) {
if ( ifile . eof ( ) ) {
break ;
}
char tbuff [ 2 ] ;
readVDFBuffer ( tbuff , 2 ) ; // 2 bytes idx
readVDFBuffer ( tbuff , 2 ) ; // 2 bytes POSSIBLE end marker
ifile . seekg ( - 1 , std : : ios_base : : cur ) ; // go one back, skip typeId
if ( tbuff [ 0 ] = = 0x08 & & tbuff [ 1 ] = = 0x08 ) {
ifile . seekg ( - 1 , std : : ios_base : : cur ) ; // another back
break ;
}
tag . idx . data = readVDFString ( ) ;
if ( tag . idx . data = = " \x08 \x08 " ) {
ifile . seekg ( - 2 , std : : ios_base : : cur ) ;
break ;
}
tag . idx . data [ 0 ] = tbuff [ 0 ] ;
tag . idx . data [ 1 ] = tbuff [ 1 ] ;
ifile . seekg ( 1 , std : : ios_base : : cur ) ;
tag . value = readVDFString ( ) ;
shortcut . tags . value . push_back ( tag ) ;
}
continue ;
}
}
if ( ! ( shortcut . idx . data [ 0 ] = = 0x0 & & shortcut . idx . data [ 1 ] = = 0x0 ) ) {
if ( ! ( shortcut . idx . data = = " \x00 \x00 " ) ) {
vdffile . shortcuts . push_back ( shortcut ) ;
}
}
@ -489,9 +466,16 @@ class Parser {
static inline bool writeShortcuts ( std : : filesystem : : path path , const VDFFile & vdffile )
{
const auto copied = std : : filesystem : : copy_file ( path , path . string ( ) + " .bak " , std : : filesystem : : copy_options : : update_existing ) ;
const auto backupFileName = path . wstring ( ) + L " .bak " ;
if ( std : : filesystem : : exists ( path ) & & ! std : : filesystem : : exists ( backupFileName ) ) {
qDebug ( ) < < " No shortcuts backup detected... Creating now... " ;
const auto copied = std : : filesystem : : copy_file ( path , backupFileName , std : : filesystem : : copy_options : : update_existing ) ;
if ( ! copied ) {
qDebug ( ) < < " failed to copy shortcuts.vdf to backup! " ;
}
}
ofile . open ( path . string ( ) , std : : ios : : binary | std : : ios : : out ) ;
ofile . open ( path . w string( ) , std : : ios : : binary | std : : ios : : out ) ;
if ( ! ofile . is_open ( ) ) {
return false ;
}
@ -499,10 +483,8 @@ class Parser {
ofile . write ( vdffile . identifier . data ( ) , vdffile . identifier . length ( ) ) ;
ofile . write ( " \x00 " , 1 ) ;
for ( auto & shortcut : vdffile . shortcuts ) {
if ( shortcut . idx . data [ 0 ] ! = ' \x0 ' ) {
ofile . write ( " \x00 " , 1 ) ;
}
ofile . write ( shortcut . idx . data , 2 ) ;
ofile . write ( " \x00 " , 1 ) ;
ofile . write ( shortcut . idx . data . data ( ) , shortcut . idx . data . length ( ) ) ;
ofile . write ( " \x00 " , 1 ) ;
//
ofile . write ( ( char * ) & shortcut . appId . type_id , 1 ) ;
@ -586,11 +568,17 @@ class Parser {
ofile . write ( shortcut . LastPlayTime . key , 13 ) ;
ofile . write ( ( char * ) & shortcut . LastPlayTime . value , 4 ) ;
//
ofile . write ( ( char * ) & shortcut . FlatpakAppID . type_id , 1 ) ;
ofile . write ( shortcut . FlatpakAppID . key , 13 ) ;
ofile . write ( shortcut . FlatpakAppID . value . data ( ) , shortcut . FlatpakAppID . value . length ( ) ) ;
ofile . write ( " \x00 " , 1 ) ;
//
ofile . write ( ( char * ) & shortcut . tags . type_id , 1 ) ;
ofile . write ( shortcut . tags . key , 5 ) ;
for ( auto & tag : shortcut . tags . value ) {
ofile . write ( tag . idx . data , 2 ) ;
ofile . write ( tag . idx . data .data ( ) , tag . idx . data . length ( ) ) ;
ofile . write ( " \x00 " , 1 ) ;
ofile . write ( tag . value . data ( ) , tag . value . length ( ) ) ;
ofile . write ( " \x00 " , 1 ) ;