1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-  */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef _MORKENV_
7 #define _MORKENV_ 1
8 
9 #ifndef _MORK_
10 #  include "mork.h"
11 #endif
12 
13 #ifndef _MORKOBJECT_
14 #  include "morkObject.h"
15 #endif
16 
17 #ifndef _MORKPOOL_
18 #  include "morkPool.h"
19 #endif
20 
21 // sean was here
22 #include "mozilla/Path.h"
23 #include "nsError.h"
24 
25 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
26 
27 #define morkDerived_kEnv /*i*/ 0x4576 /* ascii 'Ev' */
28 
29 // use NS error codes to make Mork easier to use with the rest of mozilla
30 #define morkEnv_kNoError NS_SUCCEEDED /* no error has happened */
31 #define morkEnv_kNonEnvTypeError \
32   NS_ERROR_FAILURE /* morkEnv::IsEnv() is false */
33 
34 #define morkEnv_kStubMethodOnlyError NS_ERROR_NO_INTERFACE
35 #define morkEnv_kOutOfMemoryError NS_ERROR_OUT_OF_MEMORY
36 #define morkEnv_kNilPointerError NS_ERROR_NULL_POINTER
37 #define morkEnv_kNewNonEnvError NS_ERROR_FAILURE
38 #define morkEnv_kNilEnvSlotError NS_ERROR_FAILURE
39 
40 #define morkEnv_kBadFactoryError NS_ERROR_FACTORY_NOT_LOADED
41 #define morkEnv_kBadFactoryEnvError NS_ERROR_FACTORY_NOT_LOADED
42 #define morkEnv_kBadEnvError NS_ERROR_FAILURE
43 
44 #define morkEnv_kNonHandleTypeError NS_ERROR_FAILURE
45 #define morkEnv_kNonOpenNodeError NS_ERROR_FAILURE
46 
47 /* try NOT to leak all env instances */
48 #define morkEnv_kWeakRefCountEnvBonus 0
49 
50 /*| morkEnv:
51 |*/
52 class morkEnv : public morkObject, public nsIMdbEnv {
53   using PathChar = mozilla::filesystem::Path::value_type;
54   NS_DECL_ISUPPORTS_INHERITED
55 
56   // public: // slots inherited from morkObject (meant to inform only)
57   // nsIMdbHeap*       mNode_Heap;
58 
59   // mork_base      mNode_Base;     // must equal morkBase_kNode
60   // mork_derived   mNode_Derived;  // depends on specific node subclass
61 
62   // mork_access    mNode_Access;   // kOpen, kClosing, kShut, or kDead
63   // mork_usage     mNode_Usage;    // kHeap, kStack, kMember, kGlobal, kNone
64   // mork_able      mNode_Mutable;  // can this node be modified?
65   // mork_load      mNode_Load;     // is this node clean or dirty?
66 
67   // mork_uses      mNode_Uses;     // refcount for strong refs
68   // mork_refs      mNode_Refs;     // refcount for strong refs + weak refs
69 
70   // mork_color   mBead_Color;   // ID for this bead
71   // morkHandle*  mObject_Handle;  // weak ref to handle for this object
72 
73  public:  // state is public because the entire Mork system is private
74   morkFactory* mEnv_Factory;  // NON-refcounted factory
75   nsIMdbHeap* mEnv_Heap;      // NON-refcounted heap
76 
77   nsIMdbEnv* mEnv_SelfAsMdbEnv;
78   nsIMdbErrorHook* mEnv_ErrorHook;
79 
80   morkPool* mEnv_HandlePool;  // pool for re-using handles
81 
82   mork_u2 mEnv_ErrorCount;
83   mork_u2 mEnv_WarningCount;
84 
85   nsresult mEnv_ErrorCode;
86 
87   mork_bool mEnv_DoTrace;
88   mork_able mEnv_AutoClear;
89   mork_bool mEnv_ShouldAbort;
90   mork_bool mEnv_BeVerbose;
91   mork_bool mEnv_OwnsHeap;
92 
93   // { ===== begin morkNode interface =====
94  public:                                             // morkNode virtual methods
95   virtual void CloseMorkNode(morkEnv* ev) override;  // CloseEnv() only if open
96   virtual ~morkEnv();  // assert that CloseEnv() executed earlier
97 
98   // { ----- begin attribute methods -----
99   NS_IMETHOD GetErrorCount(mdb_count* outCount,
100                            mdb_bool* outShouldAbort) override;
101   NS_IMETHOD GetWarningCount(mdb_count* outCount,
102                              mdb_bool* outShouldAbort) override;
103 
104   NS_IMETHOD GetEnvBeVerbose(mdb_bool* outBeVerbose) override;
105   NS_IMETHOD SetEnvBeVerbose(mdb_bool inBeVerbose) override;
106 
107   NS_IMETHOD GetDoTrace(mdb_bool* outDoTrace) override;
108   NS_IMETHOD SetDoTrace(mdb_bool inDoTrace) override;
109 
110   NS_IMETHOD GetAutoClear(mdb_bool* outAutoClear) override;
111   NS_IMETHOD SetAutoClear(mdb_bool inAutoClear) override;
112 
113   NS_IMETHOD GetErrorHook(nsIMdbErrorHook** acqErrorHook) override;
114   NS_IMETHOD SetErrorHook(
115       nsIMdbErrorHook* ioErrorHook) override;  // becomes referenced
116 
117   NS_IMETHOD GetHeap(nsIMdbHeap** acqHeap) override;
118   NS_IMETHOD SetHeap(nsIMdbHeap* ioHeap) override;  // becomes referenced
119   // } ----- end attribute methods -----
120 
121   NS_IMETHOD ClearErrors() override;    // clear errors beore re-entering db API
122   NS_IMETHOD ClearWarnings() override;  // clear warnings
123   NS_IMETHOD ClearErrorsAndWarnings() override;  // clear both errors & warnings
124   // } ===== end nsIMdbEnv methods =====
125  public:  // morkEnv construction & destruction
126   morkEnv(const morkUsage& inUsage, nsIMdbHeap* ioHeap, morkFactory* ioFactory,
127           nsIMdbHeap* ioSlotHeap);
128   morkEnv(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap,
129           nsIMdbEnv* inSelfAsMdbEnv, morkFactory* ioFactory,
130           nsIMdbHeap* ioSlotHeap);
131   void CloseEnv(morkEnv* ev);  // called by CloseMorkNode();
132 
133  private:  // copying is not allowed
134   morkEnv(const morkEnv& other);
135   morkEnv& operator=(const morkEnv& other);
136 
137  public:  // dynamic type identification
IsEnv()138   mork_bool IsEnv() const {
139     return IsNode() && mNode_Derived == morkDerived_kEnv;
140   }
141   // } ===== end morkNode methods =====
142 
143  public:  // utility env methods
144   mork_u1 HexToByte(mork_ch inFirstHex, mork_ch inSecondHex);
145 
146   mork_size TokenAsHex(void* outBuf, mork_token inToken);
147   // TokenAsHex() is the same as sprintf(outBuf, "%lX", (long) inToken);
148 
149   mork_size OidAsHex(void* outBuf, const mdbOid& inOid);
150   // sprintf(buf, "%lX:^%lX", (long) inOid.mOid_Id, (long) inOid.mOid_Scope);
151 
152   PathChar* CopyString(nsIMdbHeap* ioHeap, const PathChar* inString);
153   void FreeString(nsIMdbHeap* ioHeap, PathChar* ioString);
154   void StringToYarn(const PathChar* inString, mdbYarn* outYarn);
155 
156  public:  // other env methods
NewHandle(mork_size inSize)157   morkHandleFace* NewHandle(mork_size inSize) {
158     return mEnv_HandlePool->NewHandle(this, inSize, (morkZone*)0);
159   }
160 
ZapHandle(morkHandleFace * ioHandle)161   void ZapHandle(morkHandleFace* ioHandle) {
162     mEnv_HandlePool->ZapHandle(this, ioHandle);
163   }
164 
EnableAutoClear()165   void EnableAutoClear() { mEnv_AutoClear = morkAble_kEnabled; }
DisableAutoClear()166   void DisableAutoClear() { mEnv_AutoClear = morkAble_kDisabled; }
167 
DoAutoClear()168   mork_bool DoAutoClear() const { return mEnv_AutoClear == morkAble_kEnabled; }
169 
170   void NewError(const char* inString);
171   void NewWarning(const char* inString);
172 
173   void ClearMorkErrorsAndWarnings();      // clear both errors & warnings
174   void AutoClearMorkErrorsAndWarnings();  // clear if auto is enabled
175 
176   void StubMethodOnlyError();
177   void OutOfMemoryError();
178   void NilPointerError();
179   void NilPointerWarning();
180   void CantMakeWhenBadError();
181   void NewNonEnvError();
182   void NilEnvSlotError();
183 
184   void NonEnvTypeError(morkEnv* ev);
185 
186   // canonical env convenience methods to check for presence of errors:
Good()187   mork_bool Good() const { return (mEnv_ErrorCount == 0); }
Bad()188   mork_bool Bad() const { return (mEnv_ErrorCount != 0); }
189 
AsMdbEnv()190   nsIMdbEnv* AsMdbEnv() { return (nsIMdbEnv*)this; }
191   static morkEnv* FromMdbEnv(nsIMdbEnv* ioEnv);  // dynamic type checking
192 
AsErr()193   nsresult AsErr() const { return mEnv_ErrorCode; }
194 
195  public:  // typesafe refcounting inlines calling inherited morkNode methods
SlotWeakEnv(morkEnv * me,morkEnv * ev,morkEnv ** ioSlot)196   static void SlotWeakEnv(morkEnv* me, morkEnv* ev, morkEnv** ioSlot) {
197     morkNode::SlotWeakNode((morkNode*)me, ev, (morkNode**)ioSlot);
198   }
199 
SlotStrongEnv(morkEnv * me,morkEnv * ev,morkEnv ** ioSlot)200   static void SlotStrongEnv(morkEnv* me, morkEnv* ev, morkEnv** ioSlot) {
201     morkNode::SlotStrongNode((morkNode*)me, ev, (morkNode**)ioSlot);
202   }
203 };
204 
205 #undef MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING
206 #ifdef MOZ_IS_DESTRUCTIBLE
207 #  define MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(X)                              \
208     static_assert(                                                           \
209         !MOZ_IS_DESTRUCTIBLE(X) || mozilla::IsSame<X, morkEnv>::value,       \
210         "Reference-counted class " #X                                        \
211         " should not have a public destructor. "                             \
212         "Try to make this class's destructor non-public. If that is really " \
213         "not possible, you can whitelist this class by providing a "         \
214         "HasDangerousPublicDestructor specialization for it.");
215 #else
216 #  define MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(X)
217 #endif
218 
219 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
220 
221 #endif /* _MORKENV_ */
222