Refactoring: Split code into multiple projects

This commit is contained in:
Daniel Wolf 2016-11-15 21:56:39 +01:00
parent c19ad1c8d0
commit 3e34425c11
65 changed files with 376 additions and 173 deletions

View File

@ -64,26 +64,34 @@ set(Boost_USE_MULTITHREADED ON) # Enable multithreading support
set(Boost_USE_STATIC_RUNTIME ON) # Use static C++ runtime
find_package(Boost 1.54 REQUIRED COMPONENTS filesystem locale system)
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
link_libraries(${Boost_LIBRARIES}) # Just about every project needs Boost
# ... C++ Format
include_directories(SYSTEM "lib/cppformat")
FILE(GLOB cppFormatFiles "lib/cppformat/*.cc")
add_library(cppFormat ${cppFormatFiles})
target_include_directories(cppFormat SYSTEM PUBLIC "lib/cppformat")
target_compile_options(cppFormat PRIVATE ${disableWarningsFlags})
set_target_properties(cppFormat PROPERTIES FOLDER lib)
# ... sphinxbase
include_directories(SYSTEM "lib/sphinxbase-rev13216/include" "lib/sphinxbase-rev13216/src" "lib/sphinx_config")
FILE(GLOB_RECURSE sphinxbaseFiles "lib/sphinxbase-rev13216/src/libsphinxbase/*.c")
add_library(sphinxbase ${sphinxbaseFiles})
target_include_directories(sphinxbase SYSTEM PUBLIC
"lib/sphinxbase-rev13216/include"
"lib/sphinxbase-rev13216/src"
"lib/sphinx_config"
)
target_compile_options(sphinxbase PRIVATE ${disableWarningsFlags})
target_compile_definitions(sphinxbase PUBLIC __SPHINXBASE_EXPORT_H__=1 SPHINXBASE_EXPORT=) # Compile as static lib
set_target_properties(sphinxbase PROPERTIES FOLDER lib)
# ... PocketSphinx
include_directories(SYSTEM "lib/pocketsphinx-rev13216/include" "lib/pocketsphinx-rev13216/src/libpocketsphinx")
FILE(GLOB pocketSphinxFiles "lib/pocketsphinx-rev13216/src/libpocketsphinx/*.c")
add_library(pocketSphinx ${pocketSphinxFiles})
target_include_directories(pocketSphinx SYSTEM PUBLIC
"lib/pocketsphinx-rev13216/include"
"lib/pocketsphinx-rev13216/src/libpocketsphinx"
)
target_link_libraries(pocketSphinx sphinxbase)
target_compile_options(pocketSphinx PRIVATE ${disableWarningsFlags})
target_compile_definitions(pocketSphinx PUBLIC __POCKETSPHINX_EXPORT_H__=1 POCKETSPHINX_EXPORT=) # Compile as static lib
@ -103,7 +111,6 @@ set_target_properties(gtest_main PROPERTIES FOLDER lib)
include_directories(SYSTEM "lib/gsl/include")
# ... WebRTC
include_directories(SYSTEM "lib/webrtc-8d2248ff")
set(webRTCFiles
lib/webrtc-8d2248ff/webrtc/common_audio/signal_processing/cross_correlation.c
lib/webrtc-8d2248ff/webrtc/common_audio/signal_processing/division_operations.c
@ -124,6 +131,7 @@ set(webRTCFiles
lib/webrtc-8d2248ff/webrtc/common_audio/vad/webrtc_vad.c
)
add_library(webRTC ${webRTCFiles})
target_include_directories(webRTC SYSTEM PUBLIC "lib/webrtc-8d2248ff")
target_compile_options(webRTC PRIVATE ${disableWarningsFlags})
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
target_compile_options(webRTC PRIVATE -pthread -lpthread)
@ -134,12 +142,11 @@ endif()
set_target_properties(webRTC PROPERTIES FOLDER lib)
# ... whereami
include_directories(SYSTEM "lib/whereami/src")
add_library(whereami lib/whereami/src/whereami.c)
target_include_directories(whereami SYSTEM PUBLIC "lib/whereami/src")
set_target_properties(whereami PROPERTIES FOLDER lib)
# ... Flite
include_directories("lib/flite-1.4/include" "lib/flite-1.4")
set(fliteFiles
lib/flite-1.4/lang/cmulex/cmu_lex.c
lib/flite-1.4/lang/cmulex/cmu_lex_data.c
@ -200,54 +207,184 @@ set(fliteFiles
lib/flite-1.4/src/utils/cst_val_user.c
)
add_library(flite ${fliteFiles})
target_include_directories(flite SYSTEM PUBLIC
"lib/flite-1.4/include"
"lib/flite-1.4"
)
target_compile_options(flite PRIVATE ${disableWarningsFlags})
set_target_properties(flite PROPERTIES FOLDER lib)
# Define executable
include_directories("src" "src/audio_input")
configure_file(src/appInfo.cpp.in src/appInfo.cpp ESCAPE_QUOTES)
set(SOURCE_FILES
${CMAKE_CURRENT_BINARY_DIR}/src/appInfo.cpp
src/main.cpp
src/Phone.cpp src/Phone.h
src/Shape.cpp src/Shape.h
src/centiseconds.cpp src/centiseconds.h
src/EnumConverter.h
src/Viseme.cpp src/Viseme.h
src/mouthAnimation.cpp src/mouthAnimation.h
src/phoneRecognition.cpp src/phoneRecognition.h
src/platformTools.cpp src/platformTools.h
src/tools.cpp src/tools.h
src/audio/AudioClip.cpp src/audio/AudioClip.h
src/audio/AudioSegment.cpp src/audio/AudioSegment.h
src/audio/DCOffset.cpp src/audio/DCOffset.h
src/audio/SampleRateConverter.cpp src/audio/SampleRateConverter.h
src/audio/voiceActivityDetection.cpp src/audio/voiceActivityDetection.h
src/audio/WaveFileReader.cpp src/audio/WaveFileReader.h
src/audio/waveFileWriting.cpp src/audio/waveFileWriting.h
src/audio/processing.cpp src/audio/processing.h
src/stringTools.cpp src/stringTools.h
src/NiceCmdLineOutput.cpp src/NiceCmdLineOutput.h
src/TablePrinter.cpp src/TablePrinter.h
src/ProgressBar.cpp src/ProgressBar.h
src/logging.cpp src/logging.h
src/Timed.h
src/TimeRange.cpp src/TimeRange.h
src/Timeline.h
src/BoundedTimeline.h
src/ContinuousTimeline.h
src/pairs.h
src/Exporter.cpp src/Exporter.h
src/tokenization.cpp src/tokenization.h
src/g2p.cpp src/g2p.h
src/languageModels.cpp src/languageModels.h
src/tupleHash.h
src/parallel.h
src/ObjectPool.h
src/Lazy.h
# Define Rhubarb libraries
# ... rhubarb-animation
add_library(rhubarb-animation
src/animation/mouthAnimation.cpp
src/animation/mouthAnimation.h
src/animation/Viseme.cpp
src/animation/Viseme.h
)
target_include_directories(rhubarb-animation PUBLIC "src/animation")
target_link_libraries(rhubarb-animation
rhubarb-core
rhubarb-logging
rhubarb-time
)
# ... rhubarb-audio
add_library(rhubarb-audio
src/audio/AudioClip.cpp
src/audio/AudioClip.h
src/audio/AudioSegment.cpp
src/audio/AudioSegment.h
src/audio/DCOffset.cpp
src/audio/DCOffset.h
src/audio/ioTools.h
src/audio/processing.cpp
src/audio/processing.h
src/audio/SampleRateConverter.cpp
src/audio/SampleRateConverter.h
src/audio/voiceActivityDetection.cpp
src/audio/voiceActivityDetection.h
src/audio/WaveFileReader.cpp
src/audio/WaveFileReader.h
src/audio/waveFileWriting.cpp
src/audio/waveFileWriting.h
)
target_include_directories(rhubarb-audio PUBLIC "src/audio")
target_link_libraries(rhubarb-audio
webRTC
rhubarb-logging
rhubarb-time
rhubarb-tools
)
# ... rhubarb-core
configure_file(src/core/appInfo.cpp.in appInfo.cpp ESCAPE_QUOTES)
add_library(rhubarb-core
${CMAKE_CURRENT_BINARY_DIR}/appInfo.cpp
src/core/appInfo.h
src/core/Phone.cpp
src/core/Phone.h
src/core/Shape.cpp
src/core/Shape.h
)
target_include_directories(rhubarb-core PUBLIC "src/core")
target_link_libraries(rhubarb-core
rhubarb-tools
)
# ... rhubarb-exporters
add_library(rhubarb-exporters
src/exporters/Exporter.cpp
src/exporters/Exporter.h
)
target_include_directories(rhubarb-exporters PUBLIC "src/exporters")
target_link_libraries(rhubarb-exporters
rhubarb-core
rhubarb-time
)
# ... rhubarb-lib
add_library(rhubarb-lib
src/lib/rhubarbLib.cpp
src/lib/rhubarbLib.h
)
target_include_directories(rhubarb-lib PUBLIC "src/lib")
target_link_libraries(rhubarb-lib
rhubarb-animation
rhubarb-audio
rhubarb-core
rhubarb-recognition
rhubarb-time
rhubarb-tools
)
# ... rhubarb-logging
add_library(rhubarb-logging
src/logging/logging.cpp
src/logging/logging.h
)
target_include_directories(rhubarb-logging PUBLIC "src/logging")
target_link_libraries(rhubarb-logging
rhubarb-tools
)
# ... rhubarb-recognition
add_library(rhubarb-recognition
src/recognition/g2p.cpp
src/recognition/g2p.h
src/recognition/languageModels.cpp
src/recognition/languageModels.h
src/recognition/phoneRecognition.cpp
src/recognition/phoneRecognition.h
src/recognition/tokenization.cpp
src/recognition/tokenization.h
)
target_include_directories(rhubarb-recognition PUBLIC "src/recognition")
target_link_libraries(rhubarb-recognition
flite
pocketSphinx
rhubarb-audio
rhubarb-core
rhubarb-logging
)
# ... rhubarb-time
add_library(rhubarb-time
src/time/BoundedTimeline.h
src/time/centiseconds.cpp
src/time/centiseconds.h
src/time/ContinuousTimeline.h
src/time/Timed.h
src/time/timedLogging.h
src/time/Timeline.h
src/time/TimeRange.cpp
src/time/TimeRange.h
)
target_include_directories(rhubarb-time PUBLIC "src/time")
target_link_libraries(rhubarb-time
cppFormat
rhubarb-logging
)
# ... rhubarb-tools
add_library(rhubarb-tools
src/tools/EnumConverter.h
src/tools/exceptions.cpp
src/tools/exceptions.h
src/tools/Lazy.h
src/tools/NiceCmdLineOutput.cpp
src/tools/NiceCmdLineOutput.h
src/tools/ObjectPool.h
src/tools/pairs.h
src/tools/parallel.h
src/tools/platformTools.cpp
src/tools/platformTools.h
src/tools/ProgressBar.cpp
src/tools/ProgressBar.h
src/tools/stringTools.cpp
src/tools/stringTools.h
src/tools/TablePrinter.cpp
src/tools/TablePrinter.h
src/tools/textFiles.cpp
src/tools/textFiles.h
src/tools/tools.cpp
src/tools/tools.h
src/tools/tupleHash.h
)
target_include_directories(rhubarb-tools PUBLIC "src/tools")
target_link_libraries(rhubarb-tools
cppFormat
whereami
)
# Define Rhubarb executable
add_executable(rhubarb src/main.cpp)
target_include_directories(rhubarb PUBLIC "src")
target_link_libraries(rhubarb
rhubarb-exporters
rhubarb-lib
)
add_executable(rhubarb ${SOURCE_FILES})
target_link_libraries(rhubarb ${Boost_LIBRARIES} cppFormat sphinxbase pocketSphinx flite webRTC whereami)
target_compile_options(rhubarb PUBLIC ${enableWarningsFlags})
# Define test project
@ -261,21 +398,15 @@ set(TEST_FILES
tests/tokenizationTests.cpp
tests/g2pTests.cpp
tests/LazyTests.cpp
src/stringTools.cpp src/stringTools.h
src/platformTools.cpp src/platformTools.h
src/Timeline.h
src/TimeRange.cpp src/TimeRange.h
src/centiseconds.cpp src/centiseconds.h
src/pairs.h
src/Phone.cpp src/Phone.h
src/tokenization.cpp src/tokenization.h
src/g2p.cpp src/g2p.h
src/logging.cpp src/logging.h
src/tools.cpp src/tools.h
src/Lazy.h
)
add_executable(runTests ${TEST_FILES})
target_link_libraries(runTests ${Boost_LIBRARIES} gtest gmock gmock_main flite cppFormat whereami)
target_link_libraries(runTests
gtest
gmock
gmock_main
rhubarb-recognition
rhubarb-time
)
set(CPACK_PACKAGE_NAME ${appName})
string(REPLACE " " "-" CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME}")

View File

@ -4,6 +4,7 @@
#include <unordered_map>
#include <boost/algorithm/clamp.hpp>
#include "Viseme.h"
#include "timedLogging.h"
using std::map;
using std::unordered_set;
@ -278,7 +279,7 @@ ContinuousTimeline<Shape> animate(const BoundedTimeline<Phone> &phones) {
}
for (const auto& timedShape : shapes) {
logging::logTimedEvent("shape", timedShape);
logTimedEvent("shape", timedShape);
}
return shapes;

View File

@ -1,4 +1,5 @@
#pragma once
#include <memory>
#include "TimeRange.h"
#include <functional>

View File

@ -1,4 +1,5 @@
#pragma once
#include "AudioClip.h"
class AudioSegment : public AudioClip {

View File

@ -2,7 +2,7 @@
#include <vector>
#include <functional>
#include "audio/AudioClip.h"
#include "AudioClip.h"
#include "ProgressBar.h"
void process16bitAudioClip(const AudioClip& audioClip, std::function<void(const std::vector<int16_t>&)> processBuffer, size_t bufferCapacity, ProgressSink& progressSink);

View File

@ -1,13 +1,13 @@
#include "voiceActivityDetection.h"
#include <audio/DCOffset.h>
#include <audio/SampleRateConverter.h>
#include <logging.h>
#include <pairs.h>
#include "DCOffset.h"
#include "SampleRateConverter.h"
#include "logging.h"
#include "pairs.h"
#include <boost/range/adaptor/transformed.hpp>
#include <webrtc/common_audio/vad/include/webrtc_vad.h>
#include "processing.h"
#include <gsl_util.h>
#include <parallel.h>
#include "parallel.h"
#include "AudioSegment.h"
using std::vector;

39
src/lib/rhubarbLib.cpp Normal file
View File

@ -0,0 +1,39 @@
#include "rhubarbLib.h"
#include "Phone.h"
#include "phoneRecognition.h"
#include "textFiles.h"
#include "mouthAnimation.h"
#include "WaveFileReader.h"
using boost::optional;
using std::u32string;
using boost::filesystem::path;
using std::unique_ptr;
ContinuousTimeline<Shape> animateAudioClip(
const AudioClip& audioClip,
optional<u32string> dialog,
int maxThreadCount,
ProgressSink& progressSink)
{
BoundedTimeline<Phone> phones = recognizePhones(audioClip, dialog, maxThreadCount, progressSink);
ContinuousTimeline<Shape> result = animate(phones);
return result;
}
unique_ptr<AudioClip> createWaveAudioClip(path filePath) {
try {
return std::make_unique<WaveFileReader>(filePath);
} catch (...) {
std::throw_with_nested(std::runtime_error(fmt::format("Could not open sound file '{0}'.", filePath.string())));
}
}
ContinuousTimeline<Shape> animateWaveFile(
path filePath,
optional<u32string> dialog,
int maxThreadCount,
ProgressSink& progressSink)
{
return animateAudioClip(*createWaveAudioClip(filePath), dialog, maxThreadCount, progressSink);
}

19
src/lib/rhubarbLib.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include "Shape.h"
#include "ContinuousTimeline.h"
#include "AudioClip.h"
#include "ProgressBar.h"
#include <boost/filesystem.hpp>
ContinuousTimeline<Shape> animateAudioClip(
const AudioClip& audioClip,
boost::optional<std::u32string> dialog,
int maxThreadCount,
ProgressSink& progressSink);
ContinuousTimeline<Shape> animateWaveFile(
boost::filesystem::path filePath,
boost::optional<std::u32string> dialog,
int maxThreadCount,
ProgressSink& progressSink);

View File

@ -1,10 +1,8 @@
#pragma once
#include <string>
#include <vector>
#include <mutex>
#include "tools.h"
#include "Timed.h"
#include "EnumConverter.h"
namespace logging {
@ -124,20 +122,4 @@ namespace logging {
LOG_WITH_LEVEL(warn, Warn)
LOG_WITH_LEVEL(error, Error)
LOG_WITH_LEVEL(fatal, Fatal)
template<typename TValue>
void logTimedEvent(const std::string& eventName, const Timed<TValue> timedValue) {
debugFormat("##{0}[{1}-{2}]: {3}",
eventName, formatDuration(timedValue.getStart()), formatDuration(timedValue.getEnd()), timedValue.getValue());
}
template<typename TValue>
void logTimedEvent(const std::string& eventName, const TimeRange& timeRange, const TValue& value) {
logTimedEvent(eventName, Timed<TValue>(timeRange, value));
}
template<typename TValue>
void logTimedEvent(const std::string& eventName, centiseconds start, centiseconds end, const TValue& value) {
logTimedEvent(eventName, Timed<TValue>(start, end, value));
}
}

View File

@ -1,10 +1,6 @@
#include <iostream>
#include <boost/optional.hpp>
#include <format.h>
#include <tclap/CmdLine.h>
#include "audio/WaveFileReader.h"
#include "phoneRecognition.h"
#include "mouthAnimation.h"
#include "appInfo.h"
#include "NiceCmdLineOutput.h"
#include "ProgressBar.h"
@ -17,6 +13,9 @@
#include <boost/range/adaptor/transformed.hpp>
#include <boost/filesystem/fstream.hpp>
#include "parallel.h"
#include "exceptions.h"
#include "textFiles.h"
#include "rhubarbLib.h"
using std::exception;
using std::string;
@ -34,25 +33,6 @@ using boost::adaptors::transformed;
namespace tclap = TCLAP;
string getMessage(const exception& e) {
string result(e.what());
try {
std::rethrow_if_nested(e);
} catch(const exception& innerException) {
result += "\n" + getMessage(innerException);
} catch(...) {}
return result;
}
unique_ptr<AudioClip> createAudioClip(path filePath) {
try {
return std::make_unique<WaveFileReader>(filePath);
} catch (...) {
std::throw_with_nested(std::runtime_error(fmt::format("Could not open sound file '{0}'.", filePath.string())));
}
}
// Tell TCLAP how to handle our types
namespace TCLAP {
template<>
@ -82,22 +62,16 @@ void addFileSink(path path, logging::Level minLevel) {
logging::addSink(levelFilter);
}
u32string readTextFile(path filePath) {
if (!exists(filePath)) {
throw std::invalid_argument(fmt::format("File {} does not exist.", filePath));
}
try {
boost::filesystem::ifstream file;
file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
file.open(filePath);
string utf8Text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
try {
return utf8ToUtf32(utf8Text);
} catch (...) {
std::throw_with_nested(std::runtime_error(fmt::format("File encoding is not ASCII or UTF-8.", filePath)));
}
} catch (...) {
std::throw_with_nested(std::runtime_error(fmt::format("Error reading file {0}.", filePath)));
unique_ptr<Exporter> createExporter(ExportFormat exportFormat) {
switch (exportFormat) {
case ExportFormat::TSV:
return make_unique<TSVExporter>();
case ExportFormat::XML:
return make_unique<XMLExporter>();
case ExportFormat::JSON:
return make_unique<JSONExporter>();
default:
throw std::runtime_error("Unknown export format.");
}
}
@ -146,44 +120,24 @@ int main(int argc, char *argv[]) {
logging::infoFormat("Application startup. Command line: {}", join(
vector<char*>(argv, argv + argc) | transformed([](char* arg) { return fmt::format("\"{}\"", arg); }), " "));
// Detect phones
const int columnWidth = 30;
std::cerr << std::left;
std::cerr << std::setw(columnWidth) << "Analyzing input file";
BoundedTimeline<Phone> phones(TimeRange::zero());
std::cerr << "Processing input file. ";
ContinuousTimeline<Shape> animation(TimeRange::zero(), Shape::X);
{
ProgressBar progressBar;
phones = recognizePhones(
*createAudioClip(inputFileName.getValue()),
dialogFile.isSet() ? readTextFile(path(dialogFile.getValue())) : boost::optional<u32string>(),
// Animate the recording
animation = animateWaveFile(
inputFileName.getValue(),
dialogFile.isSet() ? readUTF8File(path(dialogFile.getValue())) : boost::optional<u32string>(),
maxThreadCount.getValue(),
progressBar);
}
std::cerr << "Done" << std::endl;
std::cerr << "Done." << std::endl << std::endl;
// Generate mouth shapes
std::cerr << std::setw(columnWidth) << "Generating mouth shapes";
ContinuousTimeline<Shape> shapes = animate(phones);
std::cerr << "Done" << std::endl;
// Export animation
unique_ptr<Exporter> exporter = createExporter(exportFormat.getValue());
exporter->exportShapes(path(inputFileName.getValue()), animation, std::cout);
std::cerr << std::endl;
// Export
unique_ptr<Exporter> exporter;
switch (exportFormat.getValue()) {
case ExportFormat::TSV:
exporter = make_unique<TSVExporter>();
break;
case ExportFormat::XML:
exporter = make_unique<XMLExporter>();
break;
case ExportFormat::JSON:
exporter = make_unique<JSONExporter>();
break;
default:
throw std::runtime_error("Unknown export format.");
}
exporter->exportShapes(path(inputFileName.getValue()), shapes, std::cout);
logging::info("Exiting application normally.");
return 0;

View File

@ -1,4 +1,5 @@
#pragma once
#include <vector>
#include "tools.h"

View File

@ -1,6 +1,6 @@
#include <boost/filesystem.hpp>
#include "phoneRecognition.h"
#include "audio/SampleRateConverter.h"
#include "SampleRateConverter.h"
#include "platformTools.h"
#include "tools.h"
#include <format.h>
@ -8,18 +8,19 @@
#include <regex>
#include <gsl_util.h>
#include <logging.h>
#include <audio/DCOffset.h>
#include <Timeline.h>
#include <audio/voiceActivityDetection.h>
#include "audio/AudioSegment.h"
#include "DCOffset.h"
#include "Timeline.h"
#include "voiceActivityDetection.h"
#include "AudioSegment.h"
#include "languageModels.h"
#include "tokenization.h"
#include "g2p.h"
#include "ContinuousTimeline.h"
#include "audio/processing.h"
#include "processing.h"
#include "parallel.h"
#include <boost/version.hpp>
#include "ObjectPool.h"
#include "timedLogging.h"
extern "C" {
#include <pocketsphinx.h>
@ -372,12 +373,12 @@ Timeline<Phone> utteranceToPhones(
}
text += word;
}
logging::logTimedEvent("utterance", utteranceTimeRange, text);
logTimedEvent("utterance", utteranceTimeRange, text);
// Log words
for (Timed<string> timedWord : words) {
timedWord.getTimeRange().shift(paddedTimeRange.getStart());
logging::logTimedEvent("word", timedWord);
logTimedEvent("word", timedWord);
}
// Convert word strings to word IDs using dictionary
@ -398,7 +399,7 @@ Timeline<Phone> utteranceToPhones(
// Log raw phones
for (const auto& timedPhone : utterancePhones) {
logging::logTimedEvent("rawPhone", timedPhone);
logTimedEvent("rawPhone", timedPhone);
}
// Guess positions of noise sounds
@ -409,7 +410,7 @@ Timeline<Phone> utteranceToPhones(
// Log phones
for (const auto& timedPhone : utterancePhones) {
logging::logTimedEvent("phone", timedPhone);
logTimedEvent("phone", timedPhone);
}
return utterancePhones;

View File

@ -1,6 +1,6 @@
#pragma once
#include "audio/AudioClip.h"
#include "AudioClip.h"
#include "Phone.h"
#include "ProgressBar.h"
#include "BoundedTimeline.h"

22
src/time/timedLogging.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include "centiseconds.h"
#include "TimeRange.h"
#include "Timed.h"
#include "logging.h"
template<typename TValue>
void logTimedEvent(const std::string& eventName, const Timed<TValue> timedValue) {
logging::debugFormat("##{0}[{1}-{2}]: {3}",
eventName, formatDuration(timedValue.getStart()), formatDuration(timedValue.getEnd()), timedValue.getValue());
}
template<typename TValue>
void logTimedEvent(const std::string& eventName, const TimeRange& timeRange, const TValue& value) {
logTimedEvent(eventName, Timed<TValue>(timeRange, value));
}
template<typename TValue>
void logTimedEvent(const std::string& eventName, centiseconds start, centiseconds end, const TValue& value) {
logTimedEvent(eventName, Timed<TValue>(start, end, value));
}

View File

@ -1,4 +1,5 @@
#pragma once
#include <memory>
#include <mutex>

View File

@ -1,6 +1,5 @@
#pragma once
#include <initializer_list>
#include <ostream>
#include <vector>

15
src/tools/exceptions.cpp Normal file
View File

@ -0,0 +1,15 @@
#include "exceptions.h"
using std::string;
using std::exception;
string getMessage(const exception& e) {
string result(e.what());
try {
rethrow_if_nested(e);
} catch (const exception& innerException) {
result += "\n" + getMessage(innerException);
} catch (...) {}
return result;
}

5
src/tools/exceptions.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <string>
std::string getMessage(const std::exception& e);

View File

@ -6,7 +6,6 @@
#include <boost/uuid/uuid_io.hpp>
#include "platformTools.h"
#include <whereami.h>
#include "logging.h"
using boost::filesystem::path;
using std::string;
@ -19,7 +18,6 @@ path getBinPath() {
if (pathLength == -1) {
throw std::runtime_error("Error determining path length.");
}
logging::debugFormat("Bin path has length {}.", pathLength);
// Get path
// Note: According to documentation, pathLength does *not* include the trailing zero. Actually, it does.
@ -32,7 +30,6 @@ path getBinPath() {
// Convert to boost::filesystem::path
string pathString(buffer.data());
logging::debugFormat("Bin path: '{}'", pathString);
path result(boost::filesystem::canonical(pathString).make_preferred());
return result;
} catch (...) {

29
src/tools/textFiles.cpp Normal file
View File

@ -0,0 +1,29 @@
#include "textFiles.h"
#include <boost/filesystem/operations.hpp>
#include <format.h>
#include <boost/filesystem/fstream.hpp>
#include "stringTools.h"
using std::string;
using std::u32string;
using boost::filesystem::path;
u32string readUTF8File(path filePath) {
if (!exists(filePath)) {
throw std::invalid_argument(fmt::format("File {} does not exist.", filePath));
}
try {
boost::filesystem::ifstream file;
file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
file.open(filePath);
string utf8Text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
try {
return utf8ToUtf32(utf8Text);
} catch (...) {
std::throw_with_nested(std::runtime_error(fmt::format("File encoding is not ASCII or UTF-8.", filePath)));
}
} catch (...) {
std::throw_with_nested(std::runtime_error(fmt::format("Error reading file {0}.", filePath)));
}
}

5
src/tools/textFiles.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <boost/filesystem/path.hpp>
std::u32string readUTF8File(boost::filesystem::path filePath);