Skip to content

Commit

Permalink
Merge cdb5795 into 0cc99f0
Browse files Browse the repository at this point in the history
  • Loading branch information
Lord-Kamina committed Apr 18, 2022
2 parents 0cc99f0 + cdb5795 commit 3bbf4ac
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 76 deletions.
2 changes: 1 addition & 1 deletion cmake/Modules/FindJson.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ set(Json_FIND_QUIETLY TRUE)
libfind_pkg_detect(Json nlohmann_json FIND_PATH nlohmann/json.hpp)
libfind_process(Json)

if (Json_FOUND)
if (Json_FOUND AND Json_PKGCONF_VERSION VERSION_GREATER_EQUAL 3.6.0)
set(Json_VERSION ${Json_PKGCONF_VERSION})
else ()
message("-- Fetching nlohmann_json from github...")
Expand Down
58 changes: 29 additions & 29 deletions game/fs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,16 @@ namespace {
using Lock = std::lock_guard<std::mutex>;
}

BinaryBuffer readFile(fs::path const& path) {
BinaryBuffer ret;
fs::ifstream f(path, std::ios::binary);
f.seekg(0, std::ios::end);
ret.resize(f.tellg());
f.seekg(0);
f.read(reinterpret_cast<char*>(ret.data()), ret.size());
if (!f) throw std::runtime_error("File cannot be read: " + path.string());
return ret;
}
BinaryBuffer readFile(fs::path const& path) {
BinaryBuffer ret;
fs::ifstream f(path, std::ios::binary);
f.seekg(0, std::ios::end);
ret.resize(f.tellg());
f.seekg(0);
f.read(reinterpret_cast<char*>(ret.data()), ret.size());
if (!f) throw std::runtime_error("File cannot be read: " + path.string());
return ret;
}

void copyDirectoryRecursively(const fs::path& sourceDir, const fs::path& destinationDir)
{
Expand Down Expand Up @@ -128,20 +128,20 @@ Paths getThemePaths() {
std::string theme = config["game/theme"].getEnumName();
Paths paths = getPaths();
Paths infixes = {
themes / theme,
themes / theme / www,
themes / theme / www / js,
themes / theme / www / css,
themes / theme / www / images,
themes / theme / www / fonts,

themes / def,
themes / def / www,
themes / def / www / js,
themes / def / www / css,
themes / def / www / images,
themes / def / www / fonts,
fs::path() };
themes / theme,
themes / theme / www,
themes / theme / www / js,
themes / theme / www / css,
themes / theme / www / images,
themes / theme / www / fonts,

themes / def,
themes / def / www,
themes / def / www / js,
themes / def / www / css,
themes / def / www / images,
themes / def / www / fonts,
fs::path() };
if (!theme.empty() && theme != def) infixes.push_front(themes / theme);
// Build combinations of paths and infixes
Paths themePaths;
Expand All @@ -164,21 +164,21 @@ fs::path findFile(fs::path const& filename) {
if (fs::exists(p)) return p.string();
}
std::string logmsg = "fs/error: Unable to locate data file, tried:\n";
for (auto const& p: list) logmsg += " " + p.string() + '\n';
for (auto const& p: list) logmsg += " " + p.string() + '\n';
std::clog << logmsg << std::flush;
throw std::runtime_error("Cannot find file \"" + filename.string() + "\" in Performous theme or data folders");
}

Paths listFiles(fs::path const& dir) {
if (dir.is_absolute()) throw std::logic_error("listFiles expects a folder name without path.");
std::set<fs::path> found; // Filenames already found
Paths files; // Full paths of files found
std::set<fs::path> found; // Filenames already found
Paths files; // Full paths of files found
for (fs::path path: getThemePaths()) {
fs::path subdir = path / dir;
if (!fs::is_directory(subdir))
continue;
for (const auto &d : fs::recursive_directory_iterator(subdir)) {
fs::path name = d.path().filename(); // FIXME: Extract full path from current folder, not just the filename
fs::path name = d.path().filename(); // FIXME: Extract full path from current folder, not just the filename
// If successfully inserted to "found", it wasn't found before, so add to paths.
if (found.insert(name).second) files.push_back(d);
}
Expand All @@ -205,7 +205,7 @@ Paths getPathsConfig(std::string const& confOption) {
Lock l(mutex);
Paths ret;
for (auto const& str: config[confOption].sl()) {
ret.splice(ret.end(), cache.pathExpand(str)); // Add expanded paths to ret.
ret.splice(ret.end(), cache.pathExpand(str)); // Add expanded paths to ret.
}
return ret;
}
35 changes: 35 additions & 0 deletions game/json.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "json.hh"

#include "log.hh"

#include <fstream>

nlohmann::json readJSON(fs::path const& filename) {
nlohmann::json json = nlohmann::json::array();
std::clog << "json/debug: Will try to parse JSON in: " << filename.string() << std::endl;
try {
std::ifstream file(filename.string());
if (!file.is_open()) throw std::runtime_error("Can't open file.");
json = nlohmann::json::parse(file);
} catch(nlohmann::json::exception const& e) {
std::clog << "json/error: " << e.what() << std::endl;
} catch(std::exception const& e) {
std::clog << "fs/error: " << e.what() << std::endl;
}
return json;
}

void writeJSON(nlohmann::json const& json, fs::path const& filename) {
try {
std::ofstream outFile(filename.string());
if (!outFile.is_open()) throw std::runtime_error("Can't open file.");
const int spacesCount = 4;
outFile << json.dump(spacesCount);
std::clog << "json/info: saved " + std::to_string(json.size()) + " objects to JSON file: " + filename.string() << std::endl;

} catch (nlohmann::json::exception const& e) {
std::clog << "json/error: Could not serialize json." << std::endl;
} catch (std::exception const& e) {
std::clog << "fs/error: Could not save " + filename.string() + ": " + e.what() << std::endl;
}
}
4 changes: 4 additions & 0 deletions game/json.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#include <nlohmann/json.hpp>

nlohmann::json readJSON(fs::path const& filename); ///< Reads a JSON file into memory.
void writeJSON(nlohmann::json const& json, fs::path const& filename); ///< Write a JSON file.
4 changes: 2 additions & 2 deletions game/song.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ extern "C" {
}

template <typename T> std::optional<T> getJsonEntry(nlohmann::json const& json, const char *name) {
if (json.count(name) > 0) return json.at(name).get<T>();
if (json.contains(name)) return json.at(name).get<T>();
return {};
}

Expand Down Expand Up @@ -66,7 +66,7 @@ Song::Song(nlohmann::json const& song): dummyVocal(TrackName::LEAD_VOCAL), rando
if (getJsonEntry<bool>(song, "guitarTracks").value_or(false)) {
instrumentTracks.insert(std::make_pair(TrackName::GUITAR, InstrumentTrack(TrackName::GUITAR)));
}
if (song.count("bpm") > 0) {
if (song.contains("bpm")) {
m_bpms.push_back(BPM(0, 0, song.at("bpm").get<double>()));
}
collateUpdate();
Expand Down
59 changes: 15 additions & 44 deletions game/songs.cc
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
#include "songs.hh"

#include "configuration.hh"
#include "fs.hh"
#include "song.hh"
#include "database.hh"
#include "fs.hh"
#include "i18n.hh"
#include "profiler.hh"
#include "libxml++-impl.hh"
#include "unicode.hh"
#include "log.hh"
#include "platform.hh"
#include "profiler.hh"
#include "song.hh"
#include "unicode.hh"

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <regex>
#include <stdexcept>

#include "fs.hh"
#include <boost/format.hpp>
#include <unicode/stsearch.h>

#include <fstream>
#include <nlohmann/json.hpp>
#include <unicode/stsearch.h>

Songs::Songs(Database & database, std::string const& songlist): m_songlist(songlist), m_database(database), m_order(config["songs/sort-order"].i()) {
m_updateTimer.setTarget(getInf()); // Using this as a simple timer counting seconds
Expand All @@ -41,25 +39,23 @@ void Songs::reload() {
}
// Run loading thread
m_loading = true;
if (m_thread) m_thread->join();
m_thread = std::make_unique<std::thread>([this]{ reload_internal(); });
}

void Songs::reload_internal() {
{
std::unique_lock<std::shared_mutex> l(m_mutex);
m_songs.clear();
m_dirty = true;
}
#ifdef USE_WEBSERVER
if (m_thread) m_thread->join();
std::clog << "songs/notice: Starting to load all songs from cache." << std::endl;
LoadCache();
// the following code is used to check that load <=> save are idempotent
//CacheSonglist();
//return;
std::clog << "songs/notice: Done loading the cache. You now have " << loadedSongs() << " songs in your list." << std::endl;
#endif
std::clog << "songs/notice: Starting to load all songs from disk, to update the cache." << std::endl;
m_thread = std::make_unique<std::thread>([this]{ reload_internal(); });
}

void Songs::reload_internal() {
Profiler prof("songloader");
Paths systemSongs = getPathsConfig("paths/system-songs");
Paths paths = getPathsConfig("paths/songs");
Expand Down Expand Up @@ -91,24 +87,8 @@ const std::string SONGS_CACHE_JSON_FILE = "songs.json";

void Songs::LoadCache() {
const fs::path songsMetaFile = getCacheDir() / SONGS_CACHE_JSON_FILE;
std::ifstream file(songsMetaFile.string());
auto jsonRoot = nlohmann::json::array();
if (file) {
try {
std::stringstream buffer;
buffer << file.rdbuf();
file.close();
jsonRoot = nlohmann::json::parse(buffer);
} catch(std::exception const& e) {
std::clog << "songs/error: " << e.what() << std::endl;
file.close();
return;
}
} else {
std::clog << "songs/info: Could not open songs meta cache file " << songsMetaFile.string() << std::endl;
return;
}

auto jsonRoot = readJSON(songsMetaFile);
if (jsonRoot.empty()) return;
std::vector<std::string> allPaths;
for(const auto& songPaths : {getPathsConfig("paths/system-songs"), getPathsConfig("paths/songs")}) {
for(const auto& songPath: songPaths) {
Expand Down Expand Up @@ -233,17 +213,8 @@ void Songs::CacheSonglist() {
}

fs::path cacheDir = getCacheDir() / SONGS_CACHE_JSON_FILE;

try {
std::ofstream outFile(cacheDir.string());
const int spacesCount = 4;
outFile << jsonRoot.dump(spacesCount);
outFile.close();
} catch (std::exception const& e) {
std::clog << "songs/error: Could not save " + cacheDir.string() + ": " + e.what() << std::endl;
return;
writeJSON(jsonRoot, cacheDir);
}
}

void Songs::reload_internal(fs::path const& parent) {
if (std::distance(parent.begin(), parent.end()) > 20) { std::clog << "songs/info: >>> Not scanning: " << parent.string() << " (maximum depth reached, possibly due to cyclic symlinks)\n"; return; }
Expand Down

0 comments on commit 3bbf4ac

Please sign in to comment.