diff options
author | Ankit Meel <ankitjmeel@gmail.com> | 2022-01-21 12:15:21 +0300 |
---|---|---|
committer | Ankit Meel <ankitjmeel@gmail.com> | 2022-01-21 12:58:04 +0300 |
commit | 36c40760a5a38db733e20c948b2170ab78bb2607 (patch) | |
tree | a760b7f4c98915e96018fb8b3decf1d84ca8acd8 /source/blender/io/wavefront_obj/exporter | |
parent | 23fa5bb723049684b06192afbdd1714e4109be72 (diff) |
.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
Diffstat (limited to 'source/blender/io/wavefront_obj/exporter')
3 files changed, 51 insertions, 39 deletions
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<FileHandler<eFileType::MTL>>(mtl_filepath_); + file_handler_ = std::make_unique<FormattedFileHandler<eFileType::MTL>>(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<FileHandler<eFileType::OBJ>> file_handler_ = nullptr; + std::unique_ptr<FormattedFileHandler<eFileType::OBJ>> 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<FileHandler<eFileType::OBJ>>(filepath); + file_handler_ = std::make_unique<FormattedFileHandler<eFileType::OBJ>>(filepath); } void write_header() const; @@ -172,7 +172,7 @@ class OBJWriter : NonMovable, NonCopyable { */ class MTLWriter : NonMovable, NonCopyable { private: - std::unique_ptr<FileHandler<eFileType::MTL>> file_handler_ = nullptr; + std::unique_ptr<FormattedFileHandler<eFileType::MTL>> file_handler_ = nullptr; std::string mtl_filepath_; Vector<MTLMaterial> 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<eFileType filetype> struct FileTypeTraits; +/* Used to prevent mixing of say OBJ file format with MTL syntax elements. */ template<> struct FileTypeTraits<eFileType::OBJ> { using SyntaxType = eOBJSyntaxElement; }; @@ -96,15 +97,19 @@ template<> struct FileTypeTraits<eFileType::MTL> { using SyntaxType = eMTLSyntaxElement; }; -template<eFileType type> 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<typename T> struct always_false : std::false_type { }; @@ -118,9 +123,8 @@ constexpr bool is_type_integral = (... && std::is_integral_v<std::decay_t<T>>); template<typename... T> constexpr bool is_type_string_related = (... && std::is_constructible_v<std::string, T>); -template<eFileType filetype, typename... T> -constexpr std::enable_if_t<filetype == eFileType::OBJ, Formatting<filetype>> -syntax_elem_to_formatting(const eOBJSyntaxElement key) +template<typename... T> +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<eFileType filetype, typename... T> -constexpr std::enable_if_t<filetype == eFileType::MTL, Formatting<filetype>> -syntax_elem_to_formatting(const eMTLSyntaxElement key) +template<typename... T> +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<eFileType filetype> class FileHandler : NonCopyable, NonMovable { +/** + * File format and syntax agnostic file writer. + */ +template<eFileType filetype> 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<eFileType filetype> class FileHandler : NonCopyable, NonMovable { } } + /** + * Example invocation: `writer->write<eMTLSyntaxElement::newmtl>("foo")`. + * + * \param key Must match what the instance's filetype expects; i.e., `eMTLSyntaxElement` for + * `eFileType::MTL`. + */ template<typename FileTypeTraits<filetype>::SyntaxType key, typename... T> constexpr void write(T &&...args) const { - constexpr Formatting<filetype> fmt_nargs_valid = syntax_elem_to_formatting<filetype, T...>( - key); - write__impl<fmt_nargs_valid.total_args>(fmt_nargs_valid.fmt, std::forward<T>(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<T...>(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<T>(args)...); } private: @@ -301,11 +315,11 @@ template<eFileType filetype> class FileHandler : NonCopyable, NonMovable { template<typename T> using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<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<typename T> constexpr auto string_to_primitive(T &&arg) const + template<typename T> constexpr auto convert_to_primitive(T &&arg) const { if constexpr (std::is_same_v<remove_cvref_t<T>, std::string> || std::is_same_v<remove_cvref_t<T>, blender::StringRefNull>) { @@ -319,21 +333,19 @@ template<eFileType filetype> class FileHandler : NonCopyable, NonMovable { return; } else { + /* For int, float etc. */ return std::forward<T>(arg); } } - template<int total_args, typename... T> - 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<T>(args))...); - } - template<int total_args, typename... T> - constexpr std::enable_if_t<(total_args == 0), void> write__impl(const char *fmt, - T &&...args) const + template<typename... T> 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<T>(args))...); + } } }; |