Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: src/plugin/COM_Value.h

Issue 5140323101573120: Issue #276 - introduce classes BSTR_ParamArgument and BSTR_ParamResult (Closed)
Patch Set: Created Aug. 4, 2014, 2:41 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/plugin/AdblockPlusDomTraverser.cpp ('k') | src/plugin/COM_Value.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/plugin/COM_Value.h
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/plugin/COM_Value.h
@@ -0,0 +1,174 @@
+/**
+ * \file COM_Value.h Support for the values used in COM and Automation.
+ *
+ * \par BSTR
+ * MSDN BSTR http://msdn.microsoft.com/en-us/library/windows/desktop/ms221069%28v=vs.85%29.aspx
+ *
+ * \par VARIANT
+ * MSDN VARIANT structure http://msdn.microsoft.com/en-us/library/windows/desktop/ms221627%28v=vs.85%29.aspx
+ * MSDN VARENUM enumeration http://msdn.microsoft.com/en-us/library/windows/desktop/ms221170%28v=vs.85%29.aspx
+ */
+#ifndef COM_VALUE_H
+#define COM_VALUE_H
+
+#include <wtypes.h>
+#include <string>
+
+namespace AdblockPlus
+{
+ namespace COM
+ {
+ /**
+ * Base class for BSTR life cycle manager classes, used to pass BSTR to a COM call.
+ *
+ * There are two different life cycles for BSTR relevant here.
+ * In the first, the BSTR acts as an ordinary argument; in the second, the BSTR is a return value.
+ * Both these are implemented as arguments to a COM function;
+ * the difference is that one is an [in] param and the other is an [out] param.
+ * The subclass for [in] params is BSTR_ParamArgument.
+ * The subclass for [out] params is BSTR_ParamResult.
+ *
+ * These two life cycles differ in allocation, but not in deallocation.
+ * When used as an argument, the caller must allocate.
+ * BSTR_ParamArgument uses the non-trivial constructor, which allocates a copy of its argument.
+ * When used for a result, the called function allocates.
+ * BSTR_ParamResult uses the default constructor and implements an address-of operator;
+ * the address-of operator does not allocate and its pointer must be assigned an allocated value.
+ * In both cases the caller deallocates the BSTR.
+ * Because of this commonality, the present base class implements a destructor common to its subclasses.
+ *
+ * Copy/move constructor/assignment are all deleted, not because they couldn't be implemented,
+ * but because these class are meant to be used in tight conjunction with API calls.
+ * Their design use requires that they not leave this proximity.
+ * Deleting copy and move helps to ensure this.
+ *
+ * \par Design Notes
+ * This class is a base class only.
+ * It turns out that it's not felicitous to combine the subclasses with the base.
+ * The trouble is that having conversions both to BSTR and std::wstring causes problems in practice.
+ * Both of these string types define implicit conversions to wchar_t *.
+ * Having both conversions defined on a single class leads to lots of unnecessary explicit conversions.
+ *
+ * \par Reference
+ * MSDN "Allocating and Releasing Memory for a BSTR" http://msdn.microsoft.com/en-us/library/vstudio/xda6xzx7%28v=vs.120%29.aspx
+ * "When you call into a function that expects a BSTR argument, you must allocate the memory for the BSTR before the call and release it afterwards."
+ * "When you call into a function that returns a BSTR, you must free the string yourself."
+ *
+ * \invariant Either bstr == nullptr or bstr is a non-null system-allocated BSTR.
+ */
+ class BSTR_Param
+ {
+ protected:
+ /**
+ * The underlying BSTR pointer.
+ */
+ BSTR bstr;
+
+ /**
+ * Regular constructor has the value of the empty string.
+ *
+ * Subclasses have the responsibility to maintain out class invariant regarding member `bstr`.
+ */
+ BSTR_Param(BSTR b)
+ : bstr(b)
+ {
+ }
+
+ /**
+ * Destructor
+ *
+ * The destructor frees the BSTR.
+ * Do not use this class when freeing the BSTR is not our responsibility.
+ */
+ ~BSTR_Param();
+
+ private:
+ /**
+ * Copy constructor is deleted
+ */
+ BSTR_Param(const BSTR_Param&); // = delete
+
+ /**
+ * Move constructor is deleted
+ */
+ BSTR_Param(BSTR_Param&&); // = delete
+
+ /**
+ * Copy assignment is deleted
+ */
+ BSTR_Param& operator=(const BSTR_Param&); // = delete
+
+ /**
+ * Move assignment is deleted
+ */
+ BSTR_Param& operator=(BSTR_Param&&); // = delete
+ };
+
+ /**
+ * BSTR life cycle manager.
+ * Used by a caller to pass a BSTR parameter as an argument to a COM function.
+ *
+ * This class passes a BSTR value to an [in] parameter of a COM call.
+ * As a conversion class std::wstring --> BSTR.
+ */
+ class BSTR_ParamArgument
+ : protected BSTR_Param
+ {
+ public:
+ /**
+ * Constructor from std::wstring.
+ */
+ BSTR_ParamArgument(const std::wstring& s);
+
+ /**
+ * Conversion operator to BSTR.
+ */
+ operator BSTR() const
+ {
+ return bstr;
+ }
+ };
+
+ /**
+ * BSTR life cycle manager.
+ * Used by a caller to pass a BSTR parameter to receive a result from a COM function.
+ *
+ * This class receives a BSTR value from an [out] parameter of a COM call.
+ * As a conversion class, it converts only in the direction BSTR --> std::wstring.
+ */
+ class BSTR_ParamResult
+ : protected BSTR_Param
+ {
+ public:
+ /**
+ * As the receiver of an external value, BSTR_ParamResult always has an empty initial value.
+ */
+ BSTR_ParamResult()
+ : BSTR_Param(nullptr)
+ {
+ }
+
+ /**
+ * Conversion operator to std::wstring
+ */
+ operator std::wstring() const;
+
+ /**
+ * Address-of operator.
+ *
+ * This operator is used for assignment directly into our underlying pointer.
+ * In order to avoid leaking memory, this operator also implicitly assigns the null string.
+ * Specifically, this operator is not 'const'.
+ *
+ * \par postcondition
+ * - bstr == nullptr
+ * - return value is not null
+ * - does not throw
+ */
+ BSTR* operator&(); // noexcept
+ };
+
+ }
+}
+
+#endif
« no previous file with comments | « src/plugin/AdblockPlusDomTraverser.cpp ('k') | src/plugin/COM_Value.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld