duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

state_wrapper.cpp (3225B)


      1 // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
      2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
      3 
      4 #include "state_wrapper.h"
      5 #include "common/log.h"
      6 #include "common/small_string.h"
      7 #include <cinttypes>
      8 #include <cstring>
      9 Log_SetChannel(StateWrapper);
     10 
     11 StateWrapper::StateWrapper(std::span<u8> data, Mode mode, u32 version)
     12   : m_data(data.data()), m_size(data.size()), m_mode(mode), m_version(version)
     13 {
     14 }
     15 
     16 StateWrapper::StateWrapper(std::span<const u8> data, Mode mode, u32 version)
     17   : m_data(const_cast<u8*>(data.data())), m_size(data.size()), m_mode(mode), m_version(version)
     18 {
     19   Assert(mode == Mode::Read);
     20 }
     21 
     22 StateWrapper::~StateWrapper() = default;
     23 
     24 void StateWrapper::DoBytes(void* data, size_t length)
     25 {
     26   if (m_mode == Mode::Read)
     27   {
     28     if (!ReadData(data, length))
     29       std::memset(data, 0, length);
     30   }
     31   else
     32   {
     33     WriteData(data, length);
     34   }
     35 }
     36 
     37 void StateWrapper::DoBytesEx(void* data, size_t length, u32 version_introduced, const void* default_value)
     38 {
     39   if (m_mode == Mode::Read && m_version < version_introduced)
     40   {
     41     std::memcpy(data, default_value, length);
     42     return;
     43   }
     44 
     45   DoBytes(data, length);
     46 }
     47 
     48 void StateWrapper::Do(bool* value_ptr)
     49 {
     50   if (m_mode == Mode::Read)
     51   {
     52     u8 value = 0;
     53     if (!(m_error = m_error || (m_pos + 1) > m_size)) [[likely]]
     54       value = m_data[m_pos++];
     55     *value_ptr = (value != 0);
     56   }
     57   else
     58   {
     59     if (!(m_error = m_error || (m_pos + 1) > m_size)) [[likely]]
     60       m_data[m_pos++] = static_cast<u8>(*value_ptr);
     61   }
     62 }
     63 
     64 void StateWrapper::Do(std::string* value_ptr)
     65 {
     66   u32 length = static_cast<u32>(value_ptr->length());
     67   Do(&length);
     68   if (m_mode == Mode::Read)
     69   {
     70     if ((m_error = (m_error || ((m_pos + length) > m_size)))) [[unlikely]]
     71       return;
     72     value_ptr->resize(length);
     73   }
     74   DoBytes(&(*value_ptr)[0], length);
     75   value_ptr->resize(std::strlen(&(*value_ptr)[0]));
     76 }
     77 
     78 void StateWrapper::Do(SmallStringBase* value_ptr)
     79 {
     80   u32 length = static_cast<u32>(value_ptr->length());
     81   Do(&length);
     82   if (m_mode == Mode::Read)
     83   {
     84     if ((m_error = (m_error || ((m_pos + length) > m_size)))) [[unlikely]]
     85       return;
     86     value_ptr->resize(length);
     87   }
     88   DoBytes(value_ptr->data(), length);
     89   value_ptr->update_size();
     90 }
     91 
     92 void StateWrapper::Do(std::string_view* value_ptr)
     93 {
     94   Assert(m_mode == Mode::Write);
     95   u32 length = static_cast<u32>(value_ptr->length());
     96   Do(&length);
     97   DoBytes(const_cast<char*>(value_ptr->data()), length);
     98 }
     99 
    100 bool StateWrapper::DoMarker(const char* marker)
    101 {
    102   SmallString file_value(marker);
    103   Do(&file_value);
    104   if (m_error)
    105     return false;
    106 
    107   if (m_mode == Mode::Write || file_value.equals(marker))
    108     return true;
    109 
    110   ERROR_LOG("Marker mismatch at offset {}: found '{}' expected '{}'", m_pos, file_value, marker);
    111   return false;
    112 }
    113 
    114 bool StateWrapper::ReadData(void* buf, size_t size)
    115 {
    116   if ((m_error = (m_error || (m_pos + size) > m_size))) [[unlikely]]
    117     return false;
    118 
    119   std::memcpy(buf, &m_data[m_pos], size);
    120   m_pos += size;
    121   return true;
    122 }
    123 
    124 bool StateWrapper::WriteData(const void* buf, size_t size)
    125 {
    126   if ((m_error = (m_error || (m_pos + size) > m_size))) [[unlikely]]
    127     return false;
    128 
    129   std::memcpy(&m_data[m_pos], buf, size);
    130   m_pos += size;
    131   return true;
    132 }