Rewrite json_loader to use cata_path and contextually relevant cache paths.
This commit is contained in:
parent
d329307a51
commit
e0027464e2
|
@ -13,6 +13,7 @@
|
|||
/bindist/
|
||||
/build/
|
||||
/build-start-time
|
||||
/cache/
|
||||
/cmake-build-debug/
|
||||
/config/
|
||||
/data/*.template
|
||||
|
|
|
@ -60,13 +60,9 @@ class cata_path
|
|||
// Returns an fs::path constructed by concatenating the 'actual' path
|
||||
// value for the logical root with the relative path stored in this.
|
||||
// path with root_path::unknown are returned as-is.
|
||||
// If the contained path is not relative, simply returns the root path.
|
||||
inline fs::path get_unrelative_path() const {
|
||||
fs::path result = get_logical_root_path();
|
||||
// TODO check for '..' components?
|
||||
if( relative_path_.is_relative() ) {
|
||||
result /= relative_path_;
|
||||
}
|
||||
result /= relative_path_;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -327,8 +327,7 @@ class flexbuffer_disk_cache
|
|||
flexbuffer_cache::flexbuffer_cache( const fs::path &cache_directory,
|
||||
const fs::path &root_directory )
|
||||
{
|
||||
disk_cache_ = flexbuffer_disk_cache::init_from_folder( cache_directory,
|
||||
root_directory );
|
||||
disk_cache_ = flexbuffer_disk_cache::init_from_folder( cache_directory, root_directory );
|
||||
}
|
||||
|
||||
flexbuffer_cache::~flexbuffer_cache() = default;
|
||||
|
|
|
@ -55,10 +55,8 @@ class flexbuffer_cache
|
|||
explicit flexbuffer_cache( const fs::path &cache_directory, const fs::path &root_directory );
|
||||
~flexbuffer_cache();
|
||||
|
||||
size_t drop_cache() noexcept;
|
||||
|
||||
// Throw exceptions on IO and parse errors.
|
||||
shared_flexbuffer parse( fs::path json_source_path, size_t offset = 0 ) noexcept( false );
|
||||
static shared_flexbuffer parse( fs::path json_source_path, size_t offset = 0 ) noexcept( false );
|
||||
shared_flexbuffer parse_and_cache( fs::path json_source_path,
|
||||
size_t offset = 0 ) noexcept( false ) ;
|
||||
|
||||
|
|
|
@ -5,24 +5,123 @@
|
|||
|
||||
#include <ghc/fs_std_fwd.hpp>
|
||||
|
||||
#include "filesystem.h"
|
||||
#include "flexbuffer_cache.h"
|
||||
#include "flexbuffer_json.h"
|
||||
#include "path_info.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
flexbuffer_cache &global_cache()
|
||||
flexbuffer_cache &base_cache()
|
||||
{
|
||||
static flexbuffer_cache cache{ fs::u8path( PATH_INFO::cache_dir() ), fs::u8path( PATH_INFO::base_path() ) };
|
||||
static flexbuffer_cache cache{ fs::u8path( PATH_INFO::base_path() ) / "cache", fs::u8path( PATH_INFO::base_path() ) };
|
||||
return cache;
|
||||
}
|
||||
|
||||
// The file pointed to by source_file must exist.
|
||||
cata::optional<JsonValue> from_path_at_offset_opt_impl( fs::path source_file, size_t offset )
|
||||
flexbuffer_cache &config_cache()
|
||||
{
|
||||
std::shared_ptr<parsed_flexbuffer> buffer = global_cache().parse_and_cache(
|
||||
std::move( source_file ), offset );
|
||||
static flexbuffer_cache cache{ fs::u8path( PATH_INFO::config_dir() ) / "cache", fs::u8path( PATH_INFO::config_dir() ) };
|
||||
return cache;
|
||||
}
|
||||
|
||||
flexbuffer_cache &data_cache()
|
||||
{
|
||||
static flexbuffer_cache cache{ fs::u8path( PATH_INFO::datadir() ) / "cache", fs::u8path( PATH_INFO::datadir() ) };
|
||||
return cache;
|
||||
}
|
||||
|
||||
flexbuffer_cache &memorial_cache()
|
||||
{
|
||||
static flexbuffer_cache cache{ fs::u8path( PATH_INFO::memorialdir() ) / "cache", fs::u8path( PATH_INFO::memorialdir() ) };
|
||||
return cache;
|
||||
}
|
||||
|
||||
flexbuffer_cache &user_cache()
|
||||
{
|
||||
static flexbuffer_cache cache{ fs::u8path( PATH_INFO::user_dir() ) / "cache", fs::u8path( PATH_INFO::user_dir() ) };
|
||||
return cache;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::unique_ptr<flexbuffer_cache>> save_caches;
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<flexbuffer_cache>>>
|
||||
world_to_character_caches;
|
||||
|
||||
flexbuffer_cache &cache_for_save( const cata_path &path )
|
||||
{
|
||||
// Assume lexically normal path
|
||||
auto path_it = path.get_relative_path().begin();
|
||||
// First path element is the world name
|
||||
std::string worldname = path_it->u8string();
|
||||
++path_it;
|
||||
// Next element is either a file, a character folder, or the maps folder
|
||||
std::string folder_or_file = path_it->u8string();
|
||||
++path_it;
|
||||
|
||||
auto it = save_caches.find( worldname );
|
||||
if( it == save_caches.end() ) {
|
||||
it = save_caches.emplace( worldname,
|
||||
std::make_unique<flexbuffer_cache>( fs::u8path( PATH_INFO::savedir() ) / worldname / "cache",
|
||||
fs::u8path( PATH_INFO::savedir() ) / worldname ) ).first;
|
||||
}
|
||||
|
||||
if( folder_or_file == "maps" ) {
|
||||
// Generic per-save cache is fine.
|
||||
return *it->second;
|
||||
}
|
||||
|
||||
// Either a global save file or a per-character file.
|
||||
fs::path test_path = fs::u8path( PATH_INFO::savedir() ) / worldname / folder_or_file;
|
||||
if( fs::is_directory( test_path ) ) {
|
||||
// Character file.
|
||||
const std::string &character_name = folder_or_file;
|
||||
std::unordered_map<std::string, std::unique_ptr<flexbuffer_cache>> &character_caches_for_world =
|
||||
world_to_character_caches[worldname];
|
||||
it = character_caches_for_world.find( character_name );
|
||||
if( it == character_caches_for_world.end() ) {
|
||||
it = character_caches_for_world.emplace( character_name,
|
||||
std::make_unique<flexbuffer_cache>( test_path / "cache", test_path ) ).first;
|
||||
}
|
||||
}
|
||||
return *it->second;
|
||||
}
|
||||
|
||||
flexbuffer_cache &cache_for_lexically_normal_path( const cata_path &path )
|
||||
{
|
||||
switch( path.get_logical_root() ) {
|
||||
case cata_path::root_path::base:
|
||||
return base_cache();
|
||||
case cata_path::root_path::config:
|
||||
return config_cache();
|
||||
case cata_path::root_path::data:
|
||||
return data_cache();
|
||||
case cata_path::root_path::memorial:
|
||||
return memorial_cache();
|
||||
case cata_path::root_path::save:
|
||||
// Saves we store data one per save.
|
||||
// But also... per character per save.
|
||||
return cache_for_save( path );
|
||||
case cata_path::root_path::user:
|
||||
return user_cache();
|
||||
case cata_path::root_path::unknown:
|
||||
default:
|
||||
cata_fatal( "Cannot create cache for unknown path %s",
|
||||
path.generic_u8string() );
|
||||
}
|
||||
}
|
||||
|
||||
// The file pointed to by source_file must exist.
|
||||
cata::optional<JsonValue> from_path_at_offset_opt_impl( const cata_path &source_file,
|
||||
size_t offset )
|
||||
{
|
||||
cata_path lexically_normal_path = source_file.lexically_normal();
|
||||
std::shared_ptr<parsed_flexbuffer> buffer;
|
||||
if( lexically_normal_path.get_logical_root() != cata_path::root_path::unknown ) {
|
||||
flexbuffer_cache &cache = cache_for_lexically_normal_path( lexically_normal_path );
|
||||
buffer = cache.parse_and_cache(
|
||||
lexically_normal_path.get_unrelative_path(), offset );
|
||||
} else {
|
||||
buffer = flexbuffer_cache::parse( lexically_normal_path.get_unrelative_path(), offset );
|
||||
}
|
||||
if( !buffer ) {
|
||||
return cata::nullopt;
|
||||
}
|
||||
|
@ -33,35 +132,38 @@ cata::optional<JsonValue> from_path_at_offset_opt_impl( fs::path source_file, si
|
|||
|
||||
} // namespace
|
||||
|
||||
cata::optional<JsonValue> json_loader::from_path_at_offset_opt( fs::path source_file,
|
||||
cata::optional<JsonValue> json_loader::from_path_at_offset_opt( const cata_path &source_file,
|
||||
size_t offset ) noexcept( false )
|
||||
{
|
||||
if( !file_exist( source_file ) ) {
|
||||
if( !file_exist( source_file.get_unrelative_path() ) ) {
|
||||
return cata::nullopt;
|
||||
}
|
||||
return from_path_at_offset_opt_impl( std::move( source_file ), offset );
|
||||
return from_path_at_offset_opt_impl( source_file, offset );
|
||||
}
|
||||
|
||||
cata::optional<JsonValue> json_loader::from_path_opt( fs::path source_file ) noexcept( false )
|
||||
cata::optional<JsonValue> json_loader::from_path_opt( const cata_path &source_file ) noexcept(
|
||||
false )
|
||||
{
|
||||
return from_path_at_offset_opt( std::move( source_file ), 0 );
|
||||
return from_path_at_offset_opt( source_file, 0 );
|
||||
}
|
||||
|
||||
JsonValue json_loader::from_path_at_offset( const fs::path &source_file,
|
||||
JsonValue json_loader::from_path_at_offset( const cata_path &source_file,
|
||||
size_t offset ) noexcept( false )
|
||||
{
|
||||
if( !file_exist( source_file ) ) {
|
||||
throw JsonError( source_file.generic_u8string() + " does not exist." );
|
||||
fs::path unrelative_path = source_file.get_unrelative_path();
|
||||
if( !file_exist( unrelative_path ) ) {
|
||||
throw JsonError( unrelative_path.generic_u8string() + " does not exist." );
|
||||
}
|
||||
auto obj = from_path_at_offset_opt_impl( source_file, offset );
|
||||
|
||||
if( !obj ) {
|
||||
throw JsonError( "Json file " + source_file.generic_u8string() + " did not contain valid json" );
|
||||
throw JsonError( "Json file " + unrelative_path.generic_u8string() +
|
||||
" did not contain valid json" );
|
||||
}
|
||||
return std::move( *obj );
|
||||
}
|
||||
|
||||
JsonValue json_loader::from_path( const fs::path &source_file ) noexcept( false )
|
||||
JsonValue json_loader::from_path( const cata_path &source_file ) noexcept( false )
|
||||
{
|
||||
return from_path_at_offset( source_file, 0 );
|
||||
}
|
||||
|
@ -76,3 +178,26 @@ JsonValue json_loader::from_string( std::string const &data ) noexcept( false )
|
|||
flexbuffers::Reference buffer_root = flexbuffer_root_from_storage( buffer->get_storage() );
|
||||
return JsonValue( std::move( buffer ), buffer_root, nullptr, 0 );
|
||||
}
|
||||
|
||||
cata::optional<JsonValue> json_loader::from_path_at_offset_opt( fs::path source_file,
|
||||
size_t offset ) noexcept( false )
|
||||
{
|
||||
return from_path_at_offset_opt( cata_path{ cata_path::root_path::unknown, std::move( source_file ) },
|
||||
offset );
|
||||
}
|
||||
|
||||
cata::optional<JsonValue> json_loader::from_path_opt( fs::path source_file ) noexcept( false )
|
||||
{
|
||||
return from_path_opt( cata_path{ cata_path::root_path::unknown, std::move( source_file ) } );
|
||||
}
|
||||
|
||||
JsonValue json_loader::from_path_at_offset( const fs::path &source_file,
|
||||
size_t offset ) noexcept( false )
|
||||
{
|
||||
return from_path_at_offset( cata_path{ cata_path::root_path::unknown, source_file }, offset );
|
||||
}
|
||||
|
||||
JsonValue json_loader::from_path( const fs::path &source_file ) noexcept( false )
|
||||
{
|
||||
return from_path( cata_path{ cata_path::root_path::unknown, source_file } );
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <ghc/fs_std_fwd.hpp>
|
||||
|
||||
#include "path_info.h"
|
||||
#include "flexbuffer_json.h"
|
||||
|
||||
class json_loader
|
||||
|
@ -16,10 +17,17 @@ class json_loader
|
|||
static JsonValue from_path_at_offset( const fs::path &source_file,
|
||||
size_t offset = 0 ) noexcept( false );
|
||||
|
||||
static JsonValue from_path( const cata_path &source_file ) noexcept( false );
|
||||
static JsonValue from_path_at_offset( const cata_path &source_file,
|
||||
size_t offset = 0 ) noexcept( false );
|
||||
|
||||
// Like json_loader::from_path, except does not throw if the file does not exist. It will still throw if the json cannot be parsed.
|
||||
static cata::optional<JsonValue> from_path_opt( fs::path source_file ) noexcept( false );
|
||||
static cata::optional<JsonValue> from_path_at_offset_opt( fs::path source_file,
|
||||
size_t offset = 0 ) noexcept( false );
|
||||
static cata::optional<JsonValue> from_path_opt( const cata_path &source_file ) noexcept( false );
|
||||
static cata::optional<JsonValue> from_path_at_offset_opt( const cata_path &source_file,
|
||||
size_t offset = 0 ) noexcept( false );
|
||||
|
||||
// Like json_loader::from_path, except instead of parsing data from a file, will parse data from a string in memory.
|
||||
static JsonValue from_string( std::string const &data ) noexcept( false );
|
||||
|
|
Loading…
Reference in New Issue