summaryrefslogtreecommitdiff
path: root/db/mork/src/morkEnv.h
blob: 827a56d72a0c2b1bed2703336e76c4977d7830ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-  */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef _MORKENV_
#define _MORKENV_ 1

#ifndef _MORK_
#include "mork.h"
#endif

#ifndef _MORKOBJECT_
#include "morkObject.h"
#endif

#ifndef _MORKPOOL_
#include "morkPool.h"
#endif

// sean was here
#include "nsError.h"

//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

#define morkDerived_kEnv     /*i*/ 0x4576 /* ascii 'Ev' */

// use NS error codes to make Mork easier to use with the rest of mozilla 
#define morkEnv_kNoError         NS_SUCCEEDED /* no error has happened */
#define morkEnv_kNonEnvTypeError NS_ERROR_FAILURE /* morkEnv::IsEnv() is false */

#define morkEnv_kStubMethodOnlyError NS_ERROR_NO_INTERFACE
#define morkEnv_kOutOfMemoryError    NS_ERROR_OUT_OF_MEMORY
#define morkEnv_kNilPointerError     NS_ERROR_NULL_POINTER
#define morkEnv_kNewNonEnvError      NS_ERROR_FAILURE 
#define morkEnv_kNilEnvSlotError     NS_ERROR_FAILURE

#define morkEnv_kBadFactoryError     NS_ERROR_FACTORY_NOT_LOADED
#define morkEnv_kBadFactoryEnvError  NS_ERROR_FACTORY_NOT_LOADED
#define morkEnv_kBadEnvError         NS_ERROR_FAILURE

#define morkEnv_kNonHandleTypeError  NS_ERROR_FAILURE
#define morkEnv_kNonOpenNodeError    NS_ERROR_FAILURE 


#define morkEnv_kWeakRefCountEnvBonus 0 /* try NOT to leak all env instances */

/*| morkEnv:
|*/
class morkEnv : public morkObject, public nsIMdbEnv {
  NS_DECL_ISUPPORTS_INHERITED

// public: // slots inherited from morkObject (meant to inform only)
  // nsIMdbHeap*       mNode_Heap;

  // mork_base      mNode_Base;     // must equal morkBase_kNode
  // mork_derived   mNode_Derived;  // depends on specific node subclass
  
  // mork_access    mNode_Access;   // kOpen, kClosing, kShut, or kDead
  // mork_usage     mNode_Usage;    // kHeap, kStack, kMember, kGlobal, kNone
  // mork_able      mNode_Mutable;  // can this node be modified?
  // mork_load      mNode_Load;     // is this node clean or dirty?
  
  // mork_uses      mNode_Uses;     // refcount for strong refs
  // mork_refs      mNode_Refs;     // refcount for strong refs + weak refs

  // mork_color   mBead_Color;   // ID for this bead
  // morkHandle*  mObject_Handle;  // weak ref to handle for this object

public: // state is public because the entire Mork system is private
  
  morkFactory*      mEnv_Factory;  // NON-refcounted factory
  nsIMdbHeap*       mEnv_Heap;     // NON-refcounted heap

  nsIMdbEnv*        mEnv_SelfAsMdbEnv;
  nsIMdbErrorHook*  mEnv_ErrorHook;
  
  morkPool*         mEnv_HandlePool; // pool for re-using handles
    
  mork_u2           mEnv_ErrorCount; 
  mork_u2           mEnv_WarningCount; 

  nsresult          mEnv_ErrorCode;

  mork_bool         mEnv_DoTrace;
  mork_able         mEnv_AutoClear;
  mork_bool         mEnv_ShouldAbort;
  mork_bool         mEnv_BeVerbose;
  mork_bool         mEnv_OwnsHeap;
  
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
  virtual void CloseMorkNode(morkEnv* ev) override; // CloseEnv() only if open
  virtual ~morkEnv(); // assert that CloseEnv() executed earlier
  
  // { ----- begin attribute methods -----
  NS_IMETHOD GetErrorCount(mdb_count* outCount,
    mdb_bool* outShouldAbort) override;
  NS_IMETHOD GetWarningCount(mdb_count* outCount,
    mdb_bool* outShouldAbort) override;
  
  NS_IMETHOD GetEnvBeVerbose(mdb_bool* outBeVerbose) override;
  NS_IMETHOD SetEnvBeVerbose(mdb_bool inBeVerbose) override;
  
  NS_IMETHOD GetDoTrace(mdb_bool* outDoTrace) override;
  NS_IMETHOD SetDoTrace(mdb_bool inDoTrace) override;
  
  NS_IMETHOD GetAutoClear(mdb_bool* outAutoClear) override;
  NS_IMETHOD SetAutoClear(mdb_bool inAutoClear) override;
  
  NS_IMETHOD GetErrorHook(nsIMdbErrorHook** acqErrorHook) override;
  NS_IMETHOD SetErrorHook(
    nsIMdbErrorHook* ioErrorHook) override; // becomes referenced
  
  NS_IMETHOD GetHeap(nsIMdbHeap** acqHeap) override;
  NS_IMETHOD SetHeap(nsIMdbHeap* ioHeap) override; // becomes referenced
  // } ----- end attribute methods -----
  
  NS_IMETHOD ClearErrors() override; // clear errors beore re-entering db API
  NS_IMETHOD ClearWarnings() override; // clear warnings
  NS_IMETHOD ClearErrorsAndWarnings() override; // clear both errors & warnings
// } ===== end nsIMdbEnv methods =====
public: // morkEnv construction & destruction
  morkEnv(const morkUsage& inUsage, nsIMdbHeap* ioHeap,
    morkFactory* ioFactory, nsIMdbHeap* ioSlotHeap);
  morkEnv(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap, 
     nsIMdbEnv* inSelfAsMdbEnv, morkFactory* ioFactory,
     nsIMdbHeap* ioSlotHeap);
  void CloseEnv(morkEnv* ev); // called by CloseMorkNode();

private: // copying is not allowed
  morkEnv(const morkEnv& other);
  morkEnv& operator=(const morkEnv& other);

public: // dynamic type identification
  mork_bool IsEnv() const
  { return IsNode() && mNode_Derived == morkDerived_kEnv; }
// } ===== end morkNode methods =====

public: // utility env methods

  mork_u1 HexToByte(mork_ch inFirstHex, mork_ch inSecondHex);

  mork_size TokenAsHex(void* outBuf, mork_token inToken);
  // TokenAsHex() is the same as sprintf(outBuf, "%lX", (long) inToken);
 
  mork_size OidAsHex(void* outBuf, const mdbOid& inOid);
  // sprintf(buf, "%lX:^%lX", (long) inOid.mOid_Id, (long) inOid.mOid_Scope);
 
  char* CopyString(nsIMdbHeap* ioHeap, const char* inString);
  void  FreeString(nsIMdbHeap* ioHeap, char* ioString);
  void  StringToYarn(const char* inString, mdbYarn* outYarn);

public: // other env methods

  morkHandleFace*  NewHandle(mork_size inSize)
  { return mEnv_HandlePool->NewHandle(this, inSize, (morkZone*) 0); }
  
  void ZapHandle(morkHandleFace* ioHandle)
  { mEnv_HandlePool->ZapHandle(this, ioHandle); }

  void EnableAutoClear() { mEnv_AutoClear = morkAble_kEnabled; }
  void DisableAutoClear() { mEnv_AutoClear = morkAble_kDisabled; }
  
  mork_bool DoAutoClear() const
  { return mEnv_AutoClear == morkAble_kEnabled; }

  void NewError(const char* inString);
  void NewWarning(const char* inString);

  void ClearMorkErrorsAndWarnings(); // clear both errors & warnings
  void AutoClearMorkErrorsAndWarnings(); // clear if auto is enabled
  
  void StubMethodOnlyError();
  void OutOfMemoryError();
  void NilPointerError();
  void NilPointerWarning();
  void CantMakeWhenBadError();
  void NewNonEnvError();
  void NilEnvSlotError();
    
  void NonEnvTypeError(morkEnv* ev);
  
  // canonical env convenience methods to check for presence of errors:
  mork_bool Good() const { return ( mEnv_ErrorCount == 0 ); }
  mork_bool Bad() const { return ( mEnv_ErrorCount != 0 ); }
  
  nsIMdbEnv* AsMdbEnv() { return (nsIMdbEnv *) this; }
  static morkEnv* FromMdbEnv(nsIMdbEnv* ioEnv); // dynamic type checking

  nsresult AsErr() const { return mEnv_ErrorCode; }

public: // typesafe refcounting inlines calling inherited morkNode methods
  static void SlotWeakEnv(morkEnv* me,
    morkEnv* ev, morkEnv** ioSlot)
  { morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
  
  static void SlotStrongEnv(morkEnv* me,
    morkEnv* ev, morkEnv** ioSlot)
  { morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};

#undef MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING
#ifdef MOZ_IS_DESTRUCTIBLE
#define MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(X) \
  static_assert(!MOZ_IS_DESTRUCTIBLE(X) || \
                mozilla::IsSame<X, morkEnv>::value, \
                "Reference-counted class " #X " should not have a public destructor. " \
                "Try to make this class's destructor non-public. If that is really " \
                "not possible, you can whitelist this class by providing a " \
                "HasDangerousPublicDestructor specialization for it.");
#else
#define MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(X)
#endif

//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

#endif /* _MORKENV_ */