[Bf-blender-cvs] [36c40760a5a] master: .obj: simplify templates in FileHandler, add comments

Ankit Meel noreply at git.blender.org
Fri Jan 21 11:04:59 CET 2022


Commit: 36c40760a5a38db733e20c948b2170ab78bb2607
Author: Ankit Meel
Date:   Fri Jan 21 14:45:21 2022 +0530
Branches: master
https://developer.blender.org/rB36c40760a5a38db733e20c948b2170ab78bb2607

.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

===================================================================

M	source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
M	source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh
M	source/blender/io/wavefront_obj/exporter/obj_export_io.hh

===================================================================

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))...);
+    }
   }
 };



More information about the Bf-blender-cvs mailing list