Commit f90c9415 authored by Martin Marinov's avatar Martin Marinov Committed by GitHub Enterprise

UNWRAP-128 Clean up and improve journal capabilities to support UNWRAP (#6)

* Move type_name<> to JournalCppDefs.hh and namespace Cpp and enable automatic handling on *, & and const types

* Add JOURNAL_ADD_TYPE, JOURNAL_ADD_TYPE_INTERNAL, JOURNAL_TYPE_EXTERNAL 

* Leverage argument<> for CArrayT<> elements

* Add Journal::to_lower() and improve object naming when the class name is all capitals

* Prevent de-referencing of possibly invalid argument pointers

* Add define_consrtuct[_default] to simplify for non-opaque data constructors, e.g., vectors, planes, matrices, transforms, etc.

* Fix a bug where references to a pointer could inadvertently dereference an invalid pointer

* Disable automatic includes by default; enable them by defining JOURNAL_AUTO_INCLUDE.

* Add JOURNAL_MAIN_VOID to prevent return from the main() function in C++ journals.

* Add extract_directory() and replace_filename() in JournalFileSystem.hh/cc
parent a0c5f510
......@@ -23,43 +23,74 @@ namespace Journal
namespace Cpp
{
#ifdef JOURNAL_USE_BOOST
void filter_type_name(String& _type_name)
{
const char PTR64_STR[] = " __ptr64";
const auto pos = _type_name.find(PTR64_STR);
if (pos != String::npos)
_type_name.erase(pos, sizeof(PTR64_STR) - 1);
}
#endif
template <> Data define(Stream&, const std::nullptr_t&)
{
return Data("nullptr");
}
template <> Data define(Stream&, const bool& _b)
JOURNAL_ADD_TYPE_EXTERNAL(bool, _b)
{
_strm; // prevent warnings
return Data(_b ? "true" : "false");
}
template <> Data define(Stream&, const short& _i)
JOURNAL_ADD_TYPE(char, _c)
{// TODO: (unsigned char can be output as a symbol in many cases)
_strm; // prevent warnings
return Data(to_string(_c));
}
JOURNAL_ADD_TYPE_EXTERNAL(unsigned char, _c)
{
_strm; // prevent warnings
return Data(to_string(_c));
}
JOURNAL_ADD_TYPE_EXTERNAL(short, _i)
{
_strm; // prevent warnings
return Data(to_string(_i));
}
template <> Data define(Stream&, const unsigned short& _u)
JOURNAL_ADD_TYPE_EXTERNAL(unsigned short, _u)
{
_strm; // prevent warnings
return Data(to_string(_u));
}
template <> Data define(Stream&, const int& _i)
JOURNAL_ADD_TYPE_EXTERNAL(int, _i)
{
_strm; // prevent warnings
return Data(to_string(_i));
}
template <> Data define(Stream&, const unsigned int& _u)
JOURNAL_ADD_TYPE_EXTERNAL(unsigned int, _u)
{
_strm; // prevent warnings
return Data(to_string(_u));
}
template <> Data define(Stream&, const size_t& _s)
JOURNAL_ADD_TYPE_EXTERNAL(size_t, _s)
{
_strm; // prevent warnings
return Data(to_string(_s));
}
template <> Data define(Stream&, const float& _f)
JOURNAL_ADD_TYPE_EXTERNAL(float, _f)
{
_strm; // prevent warnings
Base::OStringStream os;
os << _f;
......@@ -73,8 +104,9 @@ template <> Data define(Stream&, const float& _f)
return Data(os.str);
}
template <> Data define(Stream&, const double& _d)
JOURNAL_ADD_TYPE_EXTERNAL(double, _d)
{
_strm; // prevent warnings
return Data(to_string(_d));
}
......
This diff is collapsed.
......@@ -33,7 +33,8 @@ Stream::CppImpl::CppImpl(const char* const _cmpn_name, const char* const _base_p
Stream::CppImpl::~CppImpl()
{
os() << "return 0;" << ENDL;
if (rtnr_int_)
os() << "return 0;" << ENDL;
close_scope();
}
......@@ -89,7 +90,7 @@ void Stream::CppImpl::include(const char* const _flnm)
const auto& emit_include = [this](const char* const _flnm)
{// TODO: cache emitted includes and don't repeat them
hh_fs_ << "#include <" << _flnm << ">" << std::endl;
hh_fs_ << "#include \"" << _flnm << '"' << std::endl;
};
if (last_cmpn == _flnm)
......@@ -116,13 +117,14 @@ void Stream::CppImpl::include(const char* const _flnm)
emit_include(flnm.c_str());
}
void Stream::CppImpl::main(const char* const _main_fnct)
void Stream::CppImpl::main(const char* const _main_fnct, const bool _rtnr_int)
{
blank_line();
add_includes();
blank_line();
os() << (_main_fnct == nullptr ? "int main()" : _main_fnct) << ENDL;
open_scope();
rtnr_int_ = _rtnr_int;
}
void Stream::CppImpl::code_line(const char* const _line)
......
......@@ -28,7 +28,7 @@ public:
// Language-specific API
Base::IOutputStream& comment_os() override;
void include(const char* const _flnm) override;
void main(const char* const _main_fnct) override;
void main(const char* const _main_fnct, const bool _rtnr_int) override;
void code_line(const char* const _line);
void end_line();
......@@ -71,6 +71,7 @@ private:
std::string path_trns_;
int indt_ = 0;
const int SCOPE_INDENT_SPACE_NMBR = 2;
bool rtnr_int_ = true;
private:
void open_scope();
......
......@@ -177,6 +177,24 @@ String extract_filename(const String& _path)
return path.filename().string();
}
String extract_directory(const String& _path)
{
fs::path path(_path);
return path.parent_path().string();
}
String replace_filename(const String& _path, const String& _flnm)
{
fs::path path(_path);
#ifdef JOURNAL_USE_BOOST
path.remove_filename();
path /= _flnm;
#else
path.replace_filename(_flnm);
#endif//JOURNAL_USE_BOOST
return path.string();
}
}//namespace Journal
#endif//JOURNAL_ON
......@@ -51,6 +51,12 @@ String compose_next_filename(const String& _jrnl_path, const char* const _name);
//! Extract the filename from a path
String extract_filename(const String& _path);
//! Extract the directory of a file from a full filename path
String extract_directory(const String& _path);
//! Replace the filename in the provided path with the given filename
String replace_filename(const String& _path, const String& _flnm);
}//namespace Journal
#endif//JOURNAL_ON
......
......@@ -34,13 +34,13 @@ void Stream::SchemeImpl::line(const String& _str)
scm_fs_.flush();
}
void Stream::SchemeImpl::set_path_transform(const char* const /*_trns*/) {}
void Stream::SchemeImpl::set_path_transform(const char* const) {}
void Stream::SchemeImpl::transform_path(String& /*_path*/) const {}
void Stream::SchemeImpl::transform_path(String&) const {}
void Stream::SchemeImpl::include(const char* const /*_flnm*/) {}
void Stream::SchemeImpl::include(const char* const) {}
void Stream::SchemeImpl::main(const char* const /*_main_fnct*/) {}
void Stream::SchemeImpl::main(const char* const, const bool) {}
void Stream::SchemeImpl::code_line(const char* const _line)
{
......
......@@ -28,7 +28,7 @@ public:
// Language-specific API
Base::IOutputStream& comment_os() override;
void include(const char* const _flnm) override;
void main(const char* const _main_fnct) override;
void main(const char* const _main_fnct, const bool) override;
void code_line(const char* const _line);
void end_line();
......
......@@ -150,9 +150,9 @@ void Stream::include(const char* const _flnm)
JOURNAL_WRAP(impl_->include(_flnm));
}
void Stream::main(const char* const _main_fnct)
void Stream::main(const char* const _main_fnct, const bool _rtnr_int)
{
JOURNAL_WRAP(impl_->main(_main_fnct));
JOURNAL_WRAP(impl_->main(_main_fnct, _rtnr_int));
}
void Stream::end_line() { JOURNAL_WRAP(impl_->end_line()); }
......@@ -218,14 +218,6 @@ bool set_on(const Language _lngg, const bool _on,
return true;
}
void filter_type_name(String& _type_name)
{
const char PTR64_STR[] = " __ptr64";
const auto pos = _type_name.find(PTR64_STR);
if (pos != String::npos)
_type_name.erase(pos, sizeof(PTR64_STR) - 1);
}
} // namespace Journal
#endif // JOURNAL_ON
......@@ -13,10 +13,6 @@
#include <Base/Utils/IOutputStream.hh>
#ifdef JOURNAL_USE_BOOST
#include <boost/core/typeinfo.hpp>
#endif // JOURNAL_USE_BOOST
#include <string>
#include <vector>
#include <type_traits>
......@@ -62,36 +58,6 @@ struct Data
typedef std::vector<Data> DataVector;
// If Boost is available for use in Journal, we provide a default type_name()
// implementation based on RTTI and Boost demangling. Otherwise type_info()
// has to be specialized for any type that is used as an output argument.
#ifdef JOURNAL_USE_BOOST
//! Correct some known issues with automatic type_name()
void filter_type_name(String& _type_name);
// Automatic type-name extraction using boost
template <class T> String type_name()
{
auto str = boost::core::demangled_name(BOOST_CORE_TYPEID(T));
#ifdef _MSC_VER
// on MSVC, pointer types contain __ptr64 which is MSVC only, so filter it out
filter_type_name(str);
#endif // _MSC_VER
return str;
}
#else // JOURNAL_USE_BOOST
/*!
Override this for any type that is used as output data for C/C++ journals.
See #define JOURNAL_TYPE_NAME(TYPE) template <> type_name<TYPE>() { return #TYPE; }
*/
template <class T> String type_name();
#endif // JOURNAL_USE_BOOST
//! Enumerate the Languages supported by Journal
enum class Language
{
......@@ -253,11 +219,13 @@ public:
*/
void transform_path(String& _path) const;
/*
Journal the start of the main function. The signature can be customized or if
left blank is set to int main().
/*!
Journal the start of the main() function (C++ specific). The signature can be
customized or if left blank is set to int main().
\optionally specify if the main function is void, or returns int (default).
*/
void main(const char* const _main_fnct = nullptr);
void main(
const char* const _main_fnct = nullptr, const bool _rtrn_int = true);
//! Journal a custom code line.
void code_line(const char* const _line);
......@@ -277,7 +245,7 @@ private:
return {dispatch_define(_args)...};
}
template <typename ArgT> Data dispatch_define(const ArgT& _arg)
template <typename T> Data dispatch_define(const T& _arg)
{
return define_in_language(*this, _arg);
}
......@@ -413,7 +381,6 @@ template <typename T> auto argument(T& _vrbl, const char* const _name)
return Arg(_vrbl, _name);
}
/*!
Helper to allow generic modification of ArgT.vrbl by ArgLinkT, cannot be made
private due to partial specialization rules.
......@@ -548,7 +515,11 @@ template <typename T> auto argument_link(T& _vrbl, const char* const _name,
#define JOURNAL_CALL(CALL, ...) \
::Journal::stream().CALL(__JOURNAL_FUNCTION__, ##__VA_ARGS__)
#ifdef JOURNAL_AUTO_INCLUDE
#define JOURNAL_INCLUDE_THIS ::Journal::stream().include(__FILE__)
#else
#define JOURNAL_INCLUDE_THIS
#endif//JOURNAL_AUTO_INCLUDE
#define JOURNAL_INCLUDE(FILE) \
{ JOURNAL_CHECK ::Journal::stream().include(FILE); }
......@@ -563,8 +534,7 @@ template <typename T> auto argument_link(T& _vrbl, const char* const _name,
#define JOURNAL_INC(CALL, ...) { JOURNAL_CHECK \
{ JOURNAL_INCLUDE_THIS; JOURNAL_CALL(CALL, ##__VA_ARGS__); } }
#define JOURNAL_CONSTRUCTOR(...) { JOURNAL_CHECK \
{ JOURNAL_INCLUDE_THIS; JOURNAL_CALL(constructor, this, ##__VA_ARGS__); } }
#define JOURNAL_CONSTRUCTOR(...) JOURNAL_INC(constructor, this, ##__VA_ARGS__)
#define JOURNAL_DESTRUCTOR JOURNAL(destructor, this)
#define JOURNAL_METHOD_OUTCOME(...) JOURNAL(method_outcome, this, ##__VA_ARGS__)
#define JOURNAL_METHOD_VOID(...) JOURNAL(method_void, this, ##__VA_ARGS__)
......@@ -596,6 +566,7 @@ template <typename T> auto argument_link(T& _vrbl, const char* const _name,
#define JOURNAL_PATH_TRANSFORM(TRNS) \
::Journal::stream().set_path_transform(TRNS)
#define JOURNAL_MAIN(MAIN) ::Journal::stream().main(MAIN)
#define JOURNAL_MAIN_VOID(MAIN) ::Journal::stream().main(MAIN, false)
#define JOURNAL_CODE_LINE(CODE) ::Journal::stream().code_line(CODE)
#define JOURNAL_BLANK_LINE ::Journal::stream().blank_line()
......@@ -606,9 +577,6 @@ template <typename T> auto argument_link(T& _vrbl, const char* const _name,
#define JT(ARG) ::Journal::argument<decltype(ARG)>(ARG, #ARG)
#define JOURNAL_TYPE_NAME(TYPE) \
template <> String type_name<TYPE>() { return String(#TYPE); }
#else
#define JOURNAL_INCLUDE_THIS
......@@ -631,6 +599,7 @@ template <typename T> auto argument_link(T& _vrbl, const char* const _name,
#define JOURNAL_PATH_TRANSFORM(TRNS)
#define JOURNAL_MAIN(MAIN)
#define JOURNAL_MAIN_VOID(MAIN)
#define JOURNAL_CODE_LINE(CODE)
#define JOURNAL_BLANK_LINE
......
......@@ -102,7 +102,8 @@ IOutputStream& Stream::Impl::print(const char* const _str)
String Stream::Impl::make_unique_name(const char* const _name)
{
return String(_name) + "_" + to_string(name_idx_++);
return String(_name[0] == '_' ? _name + 1 : _name) + "_" +
to_string(name_idx_++);
}
const char* Stream::Impl::book_unique_name(const char* const _name)
......
......@@ -57,7 +57,7 @@ public:
// Language-specific API
virtual IOutputStream& comment_os() = 0;
virtual void include(const char* const _flnm) = 0;
virtual void main(const char* const _main_fnct) = 0;
virtual void main(const char* const _main_fnct, const bool _rtnr_int) = 0;
virtual void code_line(const char* const _line) = 0;
virtual void end_line() = 0;
......
......@@ -63,9 +63,21 @@ String object_name(const String& _clss)
const auto first_column = _clss.find_first_of(':');
std::locale loc{"C"};
bool has_lower_alpha = false; // support for fully capitalized class names
for (const auto c : _clss) // check if there are any "lower" letters
{
if (std::isalpha(c, loc) && std::islower(c, loc))
{
has_lower_alpha = true;
break;
}
}
for (size_t i = first_column + 2, n = _clss.size(); i < n; ++i)
{
const auto c = _clss[i];
auto c = _clss[i];
if (!has_lower_alpha) // if no lower letter, de-capitalize everything
c = std::tolower(c, loc);
if (std::isalpha(c, loc))
{
if (std::isupper(c, loc)) // start of a new word?
......@@ -101,6 +113,12 @@ void to_upper(String& _str)
c = static_cast<char>(::toupper(c));
}
void to_lower(String& _str)
{
for (auto& c : _str)
c = static_cast<char>(::tolower(c));
}
} // namespace Journal
#endif // JOURNAL_ON
......@@ -27,6 +27,9 @@ template <class T> String to_string(const T& _v)
// capitalize the input string
void to_upper(String& _str);
// de-capitalize the input string
void to_lower(String& _str);
// replace a character in the supplied string
void replace_char(String& _str, const char _old_char, const char _rplc_char);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment