From 36c40760a5a38db733e20c948b2170ab78bb2607 Mon Sep 17 00:00:00 2001 From: Ankit Meel Date: Fri, 21 Jan 2022 14:45:21 +0530 Subject: .obj: simplify templates in FileHandler, add comments - Remove redundant template from `FormattingSyntax`. - Replace one enable_if with static assert for readability - Add comments No functional change expected. Reviewed by: jacqueslucke Differential Revision: https://developer.blender.org/D13882 --- .../exporter/obj_export_file_writer.cc | 2 +- .../exporter/obj_export_file_writer.hh | 6 +- .../io/wavefront_obj/exporter/obj_export_io.hh | 82 +++++++++++++--------- 3 files changed, 51 insertions(+), 39 deletions(-) (limited to 'source') diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc index 8c845c34db2..d31353c4a76 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc @@ -394,7 +394,7 @@ MTLWriter::MTLWriter(const char *obj_filepath) noexcept(false) if (!ok) { throw std::system_error(ENAMETOOLONG, std::system_category(), ""); } - file_handler_ = std::make_unique>(mtl_filepath_); + file_handler_ = std::make_unique>(mtl_filepath_); } void MTLWriter::write_header(const char *blen_filepath) const diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh index 1cad179a70c..7385d9fabe2 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh +++ b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh @@ -49,14 +49,14 @@ struct IndexOffsets { class OBJWriter : NonMovable, NonCopyable { private: const OBJExportParams &export_params_; - std::unique_ptr> file_handler_ = nullptr; + std::unique_ptr> file_handler_ = nullptr; IndexOffsets index_offsets_{0, 0, 0}; public: OBJWriter(const char *filepath, const OBJExportParams &export_params) noexcept(false) : export_params_(export_params) { - file_handler_ = std::make_unique>(filepath); + file_handler_ = std::make_unique>(filepath); } void write_header() const; @@ -172,7 +172,7 @@ class OBJWriter : NonMovable, NonCopyable { */ class MTLWriter : NonMovable, NonCopyable { private: - std::unique_ptr> file_handler_ = nullptr; + std::unique_ptr> file_handler_ = nullptr; std::string mtl_filepath_; Vector mtlmaterials_; /* Map from a Material* to an index into mtlmaterials_. */ diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh index a6f0174d68b..e88a76fc4e8 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh +++ b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh @@ -88,6 +88,7 @@ enum class eMTLSyntaxElement { template struct FileTypeTraits; +/* Used to prevent mixing of say OBJ file format with MTL syntax elements. */ template<> struct FileTypeTraits { using SyntaxType = eOBJSyntaxElement; }; @@ -96,15 +97,19 @@ template<> struct FileTypeTraits { using SyntaxType = eMTLSyntaxElement; }; -template struct Formatting { +struct FormattingSyntax { + /* Formatting syntax with the file format key like `newmtl %s\n`. */ const char *fmt = nullptr; + /* Number of arguments needed by the syntax. */ const int total_args = 0; - /* Fail to compile by default. */ - const bool is_type_valid = false; + /* Whether types of the given arguments are accepted by the syntax above. Fail to compile by + * default. + */ + const bool are_types_valid = false; }; /** - * Type dependent but always false. Use to add a conditional compile-time error. + * Type dependent but always false. Use to add a constexpr-conditional compile-time error. */ template struct always_false : std::false_type { }; @@ -118,9 +123,8 @@ constexpr bool is_type_integral = (... && std::is_integral_v>); template constexpr bool is_type_string_related = (... && std::is_constructible_v); -template -constexpr std::enable_if_t> -syntax_elem_to_formatting(const eOBJSyntaxElement key) +template +constexpr FormattingSyntax syntax_elem_to_formatting(const eOBJSyntaxElement key) { switch (key) { case eOBJSyntaxElement::vertex_coords: { @@ -201,9 +205,8 @@ syntax_elem_to_formatting(const eOBJSyntaxElement key) } } -template -constexpr std::enable_if_t> -syntax_elem_to_formatting(const eMTLSyntaxElement key) +template +constexpr FormattingSyntax syntax_elem_to_formatting(const eMTLSyntaxElement key) { switch (key) { case eMTLSyntaxElement::newmtl: { @@ -261,21 +264,25 @@ syntax_elem_to_formatting(const eMTLSyntaxElement key) } } -template class FileHandler : NonCopyable, NonMovable { +/** + * File format and syntax agnostic file writer. + */ +template class FormattedFileHandler : NonCopyable, NonMovable { private: - FILE *outfile_ = nullptr; + std::FILE *outfile_ = nullptr; std::string outfile_path_; public: - FileHandler(std::string outfile_path) noexcept(false) : outfile_path_(std::move(outfile_path)) + FormattedFileHandler(std::string outfile_path) noexcept(false) + : outfile_path_(std::move(outfile_path)) { outfile_ = std::fopen(outfile_path_.c_str(), "w"); if (!outfile_) { - throw std::system_error(errno, std::system_category(), "Cannot open file"); + throw std::system_error(errno, std::system_category(), "Cannot open file " + outfile_path_); } } - ~FileHandler() + ~FormattedFileHandler() { if (outfile_ && std::fclose(outfile_)) { std::cerr << "Error: could not close the file '" << outfile_path_ @@ -283,17 +290,24 @@ template class FileHandler : NonCopyable, NonMovable { } } + /** + * Example invocation: `writer->write("foo")`. + * + * \param key Must match what the instance's filetype expects; i.e., `eMTLSyntaxElement` for + * `eFileType::MTL`. + */ template::SyntaxType key, typename... T> constexpr void write(T &&...args) const { - constexpr Formatting fmt_nargs_valid = syntax_elem_to_formatting( - key); - write__impl(fmt_nargs_valid.fmt, std::forward(args)...); - /* Types of all arguments and the number of arguments should match - * what the formatting specifies. */ - return std::enable_if_t < fmt_nargs_valid.is_type_valid && - (sizeof...(T) == fmt_nargs_valid.total_args), - void > (); + /* Get format syntax, number of arguments expected and whether types of given arguments are + * valid. + */ + constexpr FormattingSyntax fmt_nargs_valid = syntax_elem_to_formatting(key); + BLI_STATIC_ASSERT(fmt_nargs_valid.are_types_valid && + (sizeof...(T) == fmt_nargs_valid.total_args), + "Types of all arguments and the number of arguments should match what the " + "formatting specifies."); + write_impl(fmt_nargs_valid.fmt, std::forward(args)...); } private: @@ -301,11 +315,11 @@ template class FileHandler : NonCopyable, NonMovable { template using remove_cvref_t = std::remove_cv_t>; /** - * Make #std::string etc., usable for `fprintf` family. + * Make #std::string etc., usable for `fprintf` family. int float etc. are not affected. * \return: `const char *` or the original argument if the argument is * not related to #std::string. */ - template constexpr auto string_to_primitive(T &&arg) const + template constexpr auto convert_to_primitive(T &&arg) const { if constexpr (std::is_same_v, std::string> || std::is_same_v, blender::StringRefNull>) { @@ -319,21 +333,19 @@ template class FileHandler : NonCopyable, NonMovable { return; } else { + /* For int, float etc. */ return std::forward(arg); } } - template - constexpr std::enable_if_t<(total_args != 0), void> write__impl(const char *fmt, - T &&...args) const - { - std::fprintf(outfile_, fmt, string_to_primitive(std::forward(args))...); - } - template - constexpr std::enable_if_t<(total_args == 0), void> write__impl(const char *fmt, - T &&...args) const + template constexpr void write_impl(const char *fmt, T &&...args) const { - std::fputs(fmt, outfile_); + if constexpr (sizeof...(T) == 0) { + std::fputs(fmt, outfile_); + } + else { + std::fprintf(outfile_, fmt, convert_to_primitive(std::forward(args))...); + } } }; -- cgit v1.2.3