summaryrefslogtreecommitdiff
path: root/db/mork/src/morkEnv.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'db/mork/src/morkEnv.cpp')
-rw-r--r--db/mork/src/morkEnv.cpp615
1 files changed, 615 insertions, 0 deletions
diff --git a/db/mork/src/morkEnv.cpp b/db/mork/src/morkEnv.cpp
new file mode 100644
index 0000000000..083942f677
--- /dev/null
+++ b/db/mork/src/morkEnv.cpp
@@ -0,0 +1,615 @@
+/* -*- 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 _MDB_
+#include "mdb.h"
+#endif
+
+#ifndef _MORK_
+#include "mork.h"
+#endif
+
+#ifndef _MORKNODE_
+#include "morkNode.h"
+#endif
+
+#ifndef _MORKCH_
+#include "morkCh.h"
+#endif
+
+#ifndef _MORKENV_
+#include "morkEnv.h"
+#endif
+
+#ifndef _MORKFACTORY_
+#include "morkFactory.h"
+#endif
+
+//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
+
+// ````` ````` ````` ````` `````
+// { ===== begin morkNode interface =====
+
+/*public virtual*/ void
+morkEnv::CloseMorkNode(morkEnv* ev) /*i*/ // CloseEnv() only if open
+{
+ if ( this->IsOpenNode() )
+ {
+ this->MarkClosing();
+ this->CloseEnv(ev);
+ this->MarkShut();
+ }
+}
+
+/*public virtual*/
+morkEnv::~morkEnv() /*i*/ // assert CloseEnv() executed earlier
+{
+ CloseMorkNode(mMorkEnv);
+ if (mEnv_Heap)
+ {
+ mork_bool ownsHeap = mEnv_OwnsHeap;
+ nsIMdbHeap*saveHeap = mEnv_Heap;
+
+ if (ownsHeap)
+ {
+#ifdef MORK_DEBUG_HEAP_STATS
+ printf("%d blocks remaining \n", ((orkinHeap *) saveHeap)->HeapBlockCount());
+ mork_u4* array = (mork_u4*) this;
+ array -= 3;
+ // null out heap ptr in mem block so we won't crash trying to use it to
+ // delete the env.
+ *array = nullptr;
+#endif // MORK_DEBUG_HEAP_STATS
+ // whoops, this is our heap - hmm. Can't delete it, or not allocate env's from
+ // an orkinHeap.
+ delete saveHeap;
+ }
+
+ }
+// MORK_ASSERT(mEnv_SelfAsMdbEnv==0);
+ MORK_ASSERT(mEnv_ErrorHook==0);
+}
+
+/* choose morkBool_kTrue or morkBool_kFalse for kBeVerbose: */
+#define morkEnv_kBeVerbose morkBool_kFalse
+
+/*public non-poly*/
+morkEnv::morkEnv(const morkUsage& inUsage, nsIMdbHeap* ioHeap,
+ morkFactory* ioFactory, nsIMdbHeap* ioSlotHeap)
+: morkObject(inUsage, ioHeap, morkColor_kNone)
+, mEnv_Factory( ioFactory )
+, mEnv_Heap( ioSlotHeap )
+
+, mEnv_SelfAsMdbEnv( 0 )
+, mEnv_ErrorHook( 0 )
+, mEnv_HandlePool( 0 )
+
+, mEnv_ErrorCount( 0 )
+, mEnv_WarningCount( 0 )
+
+, mEnv_ErrorCode(NS_OK)
+
+, mEnv_DoTrace( morkBool_kFalse )
+, mEnv_AutoClear( morkAble_kDisabled )
+, mEnv_ShouldAbort( morkBool_kFalse )
+, mEnv_BeVerbose( morkEnv_kBeVerbose )
+, mEnv_OwnsHeap ( morkBool_kFalse )
+{
+ MORK_ASSERT(ioSlotHeap && ioFactory );
+ if ( ioSlotHeap )
+ {
+ // mEnv_Heap is NOT refcounted:
+ // nsIMdbHeap_SlotStrongHeap(ioSlotHeap, this, &mEnv_Heap);
+
+ mEnv_HandlePool = new morkPool(morkUsage::kGlobal,
+ (nsIMdbHeap*) 0, ioSlotHeap);
+
+ MORK_ASSERT(mEnv_HandlePool);
+ if ( mEnv_HandlePool && this->Good() )
+ {
+ mNode_Derived = morkDerived_kEnv;
+ mNode_Refs += morkEnv_kWeakRefCountEnvBonus;
+ }
+ }
+}
+
+/*public non-poly*/
+morkEnv::morkEnv(morkEnv* ev, /*i*/
+ const morkUsage& inUsage, nsIMdbHeap* ioHeap, nsIMdbEnv* inSelfAsMdbEnv,
+ morkFactory* ioFactory, nsIMdbHeap* ioSlotHeap)
+: morkObject(ev, inUsage, ioHeap, morkColor_kNone, (morkHandle*) 0)
+, mEnv_Factory( ioFactory )
+, mEnv_Heap( ioSlotHeap )
+
+, mEnv_SelfAsMdbEnv( inSelfAsMdbEnv )
+, mEnv_ErrorHook( 0 )
+, mEnv_HandlePool( 0 )
+
+, mEnv_ErrorCount( 0 )
+, mEnv_WarningCount( 0 )
+
+, mEnv_ErrorCode(NS_OK)
+
+, mEnv_DoTrace( morkBool_kFalse )
+, mEnv_AutoClear( morkAble_kDisabled )
+, mEnv_ShouldAbort( morkBool_kFalse )
+, mEnv_BeVerbose( morkEnv_kBeVerbose )
+, mEnv_OwnsHeap ( morkBool_kFalse )
+{
+ // $$$ do we need to refcount the inSelfAsMdbEnv nsIMdbEnv??
+
+ if ( ioFactory && inSelfAsMdbEnv && ioSlotHeap)
+ {
+ // mEnv_Heap is NOT refcounted:
+ // nsIMdbHeap_SlotStrongHeap(ioSlotHeap, ev, &mEnv_Heap);
+
+ mEnv_HandlePool = new(*ioSlotHeap, ev) morkPool(ev,
+ morkUsage::kHeap, ioSlotHeap, ioSlotHeap);
+
+ MORK_ASSERT(mEnv_HandlePool);
+ if ( mEnv_HandlePool && ev->Good() )
+ {
+ mNode_Derived = morkDerived_kEnv;
+ mNode_Refs += morkEnv_kWeakRefCountEnvBonus;
+ }
+ }
+ else
+ ev->NilPointerError();
+}
+
+NS_IMPL_ISUPPORTS_INHERITED(morkEnv, morkObject, nsIMdbEnv)
+/*public non-poly*/ void
+morkEnv::CloseEnv(morkEnv* ev) /*i*/ // called by CloseMorkNode();
+{
+ if ( this->IsNode() )
+ {
+ // $$$ release mEnv_SelfAsMdbEnv??
+ // $$$ release mEnv_ErrorHook??
+
+ mEnv_SelfAsMdbEnv = 0;
+ mEnv_ErrorHook = 0;
+
+ morkPool* savePool = mEnv_HandlePool;
+ morkPool::SlotStrongPool((morkPool*) 0, ev, &mEnv_HandlePool);
+ // free the pool
+ if (mEnv_SelfAsMdbEnv)
+ {
+ if (savePool && mEnv_Heap)
+ mEnv_Heap->Free(this->AsMdbEnv(), savePool);
+ }
+ else
+ {
+ if (savePool)
+ {
+ if (savePool->IsOpenNode())
+ savePool->CloseMorkNode(ev);
+ delete savePool;
+ }
+ // how do we free this? might need to get rid of asserts.
+ }
+ // mEnv_Factory is NOT refcounted
+
+ this->MarkShut();
+ }
+ else
+ this->NonNodeError(ev);
+}
+
+// } ===== end morkNode methods =====
+// ````` ````` ````` ````` `````
+
+mork_size
+morkEnv::OidAsHex(void* outBuf, const mdbOid& inOid)
+// sprintf(buf, "%lX:^%lX", (long) inOid.mOid_Id, (long) inOid.mOid_Scope);
+{
+ mork_u1* p = (mork_u1*) outBuf;
+ mork_size outSize = this->TokenAsHex(p, inOid.mOid_Id);
+ p += outSize;
+ *p++ = ':';
+
+ mork_scope scope = inOid.mOid_Scope;
+ if ( scope < 0x80 && morkCh_IsName((mork_ch) scope) )
+ {
+ *p++ = (mork_u1) scope;
+ *p = 0; // null termination
+ outSize += 2;
+ }
+ else
+ {
+ *p++ = '^';
+ mork_size scopeSize = this->TokenAsHex(p, scope);
+ outSize += scopeSize + 2;
+ }
+ return outSize;
+}
+
+
+mork_u1
+morkEnv::HexToByte(mork_ch inFirstHex, mork_ch inSecondHex)
+{
+ mork_u1 hi = 0; // high four hex bits
+ mork_flags f = morkCh_GetFlags(inFirstHex);
+ if ( morkFlags_IsDigit(f) )
+ hi = (mork_u1) (inFirstHex - (mork_ch) '0');
+ else if ( morkFlags_IsUpper(f) )
+ hi = (mork_u1) ((inFirstHex - (mork_ch) 'A') + 10);
+ else if ( morkFlags_IsLower(f) )
+ hi = (mork_u1) ((inFirstHex - (mork_ch) 'a') + 10);
+
+ mork_u1 lo = 0; // low four hex bits
+ f = morkCh_GetFlags(inSecondHex);
+ if ( morkFlags_IsDigit(f) )
+ lo = (mork_u1) (inSecondHex - (mork_ch) '0');
+ else if ( morkFlags_IsUpper(f) )
+ lo = (mork_u1) ((inSecondHex - (mork_ch) 'A') + 10);
+ else if ( morkFlags_IsLower(f) )
+ lo = (mork_u1) ((inSecondHex - (mork_ch) 'a') + 10);
+
+ return (mork_u1) ((hi << 4) | lo);
+}
+
+mork_size
+morkEnv::TokenAsHex(void* outBuf, mork_token inToken)
+ // TokenAsHex() is the same as sprintf(outBuf, "%lX", (long) inToken);
+{
+ static const char morkEnv_kHexDigits[] = "0123456789ABCDEF";
+ char* p = (char*) outBuf;
+ char* end = p + 32; // write no more than 32 digits for safety
+ if ( inToken )
+ {
+ // first write all the hex digits in backwards order:
+ while ( p < end && inToken ) // more digits to write?
+ {
+ *p++ = morkEnv_kHexDigits[ inToken & 0x0F ]; // low four bits
+ inToken >>= 4; // we fervently hope this does not sign extend
+ }
+ *p = 0; // end the string with a null byte
+ char* s = (char*) outBuf; // first byte in string
+ mork_size size = (mork_size) (p - s); // distance from start
+
+ // now reverse the string in place:
+ // note that p starts on the null byte, so we need predecrement:
+ while ( --p > s ) // need to swap another byte in the string?
+ {
+ char c = *p; // temp for swap
+ *p = *s;
+ *s++ = c; // move s forward here, and p backward in the test
+ }
+ return size;
+ }
+ else // special case for zero integer
+ {
+ *p++ = '0'; // write a zero digit
+ *p = 0; // end with a null byte
+ return 1; // one digit in hex representation
+ }
+}
+
+void
+morkEnv::StringToYarn(const char* inString, mdbYarn* outYarn)
+{
+ if ( outYarn )
+ {
+ mdb_fill fill = ( inString )? (mdb_fill) MORK_STRLEN(inString) : 0;
+
+ if ( fill ) // have nonempty content?
+ {
+ mdb_size size = outYarn->mYarn_Size; // max dest size
+ if ( fill > size ) // too much string content?
+ {
+ outYarn->mYarn_More = fill - size; // extra string bytes omitted
+ fill = size; // copy no more bytes than size of yarn buffer
+ }
+ void* dest = outYarn->mYarn_Buf; // where bytes are going
+ if ( !dest ) // nil destination address buffer?
+ fill = 0; // we can't write any content at all
+
+ if ( fill ) // anything to copy?
+ MORK_MEMCPY(dest, inString, fill); // copy fill bytes to yarn
+
+ outYarn->mYarn_Fill = fill; // tell yarn size of copied content
+ }
+ else // no content to put into the yarn
+ {
+ outYarn->mYarn_Fill = 0; // tell yarn that string has no bytes
+ }
+ outYarn->mYarn_Form = 0; // always update the form slot
+ }
+ else
+ this->NilPointerError();
+}
+
+char*
+morkEnv::CopyString(nsIMdbHeap* ioHeap, const char* inString)
+{
+ char* outString = 0;
+ if ( ioHeap && inString )
+ {
+ mork_size size = MORK_STRLEN(inString) + 1;
+ ioHeap->Alloc(this->AsMdbEnv(), size, (void**) &outString);
+ if ( outString )
+ MORK_STRCPY(outString, inString);
+ }
+ else
+ this->NilPointerError();
+ return outString;
+}
+
+void
+morkEnv::FreeString(nsIMdbHeap* ioHeap, char* ioString)
+{
+ if ( ioHeap )
+ {
+ if ( ioString )
+ ioHeap->Free(this->AsMdbEnv(), ioString);
+ }
+ else
+ this->NilPointerError();
+}
+
+void
+morkEnv::NewError(const char* inString)
+{
+ MORK_ASSERT(morkBool_kFalse); // get developer's attention
+
+ ++mEnv_ErrorCount;
+ mEnv_ErrorCode = NS_ERROR_FAILURE;
+
+ if ( mEnv_ErrorHook )
+ mEnv_ErrorHook->OnErrorString(this->AsMdbEnv(), inString);
+}
+
+void
+morkEnv::NewWarning(const char* inString)
+{
+ MORK_ASSERT(morkBool_kFalse); // get developer's attention
+
+ ++mEnv_WarningCount;
+ if ( mEnv_ErrorHook )
+ mEnv_ErrorHook->OnWarningString(this->AsMdbEnv(), inString);
+}
+
+void
+morkEnv::StubMethodOnlyError()
+{
+ this->NewError("method is stub only");
+}
+
+void
+morkEnv::OutOfMemoryError()
+{
+ this->NewError("out of memory");
+}
+
+void
+morkEnv::CantMakeWhenBadError()
+{
+ this->NewError("can't make an object when ev->Bad()");
+}
+
+static const char morkEnv_kNilPointer[] = "nil pointer";
+
+void
+morkEnv::NilPointerError()
+{
+ this->NewError(morkEnv_kNilPointer);
+}
+
+void
+morkEnv::NilPointerWarning()
+{
+ this->NewWarning(morkEnv_kNilPointer);
+}
+
+void
+morkEnv::NewNonEnvError()
+{
+ this->NewError("non-env instance");
+}
+
+void
+morkEnv::NilEnvSlotError()
+{
+ if ( !mEnv_HandlePool || !mEnv_Factory )
+ {
+ if ( !mEnv_HandlePool )
+ this->NewError("nil mEnv_HandlePool");
+ if ( !mEnv_Factory )
+ this->NewError("nil mEnv_Factory");
+ }
+ else
+ this->NewError("unknown nil env slot");
+}
+
+
+void morkEnv::NonEnvTypeError(morkEnv* ev)
+{
+ ev->NewError("non morkEnv");
+}
+
+void
+morkEnv::ClearMorkErrorsAndWarnings()
+{
+ mEnv_ErrorCount = 0;
+ mEnv_WarningCount = 0;
+ mEnv_ErrorCode = NS_OK;
+ mEnv_ShouldAbort = morkBool_kFalse;
+}
+
+void
+morkEnv::AutoClearMorkErrorsAndWarnings()
+{
+ if ( this->DoAutoClear() )
+ {
+ mEnv_ErrorCount = 0;
+ mEnv_WarningCount = 0;
+ mEnv_ErrorCode = NS_OK;
+ mEnv_ShouldAbort = morkBool_kFalse;
+ }
+}
+
+/*static*/ morkEnv*
+morkEnv::FromMdbEnv(nsIMdbEnv* ioEnv) // dynamic type checking
+{
+ morkEnv* outEnv = 0;
+ if ( ioEnv )
+ {
+ // Note this cast is expected to perform some address adjustment of the
+ // pointer, so oenv likely does not equal ioEnv. Do not cast to void*
+ // first to force an exactly equal pointer (we tried it and it's wrong).
+ morkEnv* ev = (morkEnv*) ioEnv;
+ if ( ev && ev->IsEnv() )
+ {
+ if ( ev->DoAutoClear() )
+ {
+ ev->mEnv_ErrorCount = 0;
+ ev->mEnv_WarningCount = 0;
+ ev->mEnv_ErrorCode = NS_OK;
+ }
+ outEnv = ev;
+ }
+ else
+ MORK_ASSERT(outEnv);
+ }
+ else
+ MORK_ASSERT(outEnv);
+ return outEnv;
+}
+
+
+NS_IMETHODIMP
+morkEnv::GetErrorCount(mdb_count* outCount,
+ mdb_bool* outShouldAbort)
+{
+ if ( outCount )
+ *outCount = mEnv_ErrorCount;
+ if ( outShouldAbort )
+ *outShouldAbort = mEnv_ShouldAbort;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+morkEnv::GetWarningCount(mdb_count* outCount,
+ mdb_bool* outShouldAbort)
+{
+ if ( outCount )
+ *outCount = mEnv_WarningCount;
+ if ( outShouldAbort )
+ *outShouldAbort = mEnv_ShouldAbort;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+morkEnv::GetEnvBeVerbose(mdb_bool* outBeVerbose)
+{
+ NS_ENSURE_ARG_POINTER(outBeVerbose);
+ *outBeVerbose = mEnv_BeVerbose;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+morkEnv::SetEnvBeVerbose(mdb_bool inBeVerbose)
+{
+ mEnv_BeVerbose = inBeVerbose;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+morkEnv::GetDoTrace(mdb_bool* outDoTrace)
+{
+ NS_ENSURE_ARG_POINTER(outDoTrace);
+ *outDoTrace = mEnv_DoTrace;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+morkEnv::SetDoTrace(mdb_bool inDoTrace)
+{
+ mEnv_DoTrace = inDoTrace;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+morkEnv::GetAutoClear(mdb_bool* outAutoClear)
+{
+ NS_ENSURE_ARG_POINTER(outAutoClear);
+ *outAutoClear = DoAutoClear();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+morkEnv::SetAutoClear(mdb_bool inAutoClear)
+{
+ if ( inAutoClear )
+ EnableAutoClear();
+ else
+ DisableAutoClear();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+morkEnv::GetErrorHook(nsIMdbErrorHook** acqErrorHook)
+{
+ NS_ENSURE_ARG_POINTER(acqErrorHook);
+ *acqErrorHook = mEnv_ErrorHook;
+ NS_IF_ADDREF(mEnv_ErrorHook);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+morkEnv::SetErrorHook(
+ nsIMdbErrorHook* ioErrorHook) // becomes referenced
+{
+ mEnv_ErrorHook = ioErrorHook;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+morkEnv::GetHeap(nsIMdbHeap** acqHeap)
+{
+ NS_ENSURE_ARG_POINTER(acqHeap);
+ nsIMdbHeap* outHeap = mEnv_Heap;
+
+ if ( acqHeap )
+ *acqHeap = outHeap;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+morkEnv::SetHeap(
+ nsIMdbHeap* ioHeap) // becomes referenced
+{
+ nsIMdbHeap_SlotStrongHeap(ioHeap, this, &mEnv_Heap);
+ return NS_OK;
+}
+// } ----- end attribute methods -----
+
+NS_IMETHODIMP
+morkEnv::ClearErrors() // clear errors beore re-entering db API
+{
+ mEnv_ErrorCount = 0;
+ mEnv_ErrorCode = NS_OK;
+ mEnv_ShouldAbort = morkBool_kFalse;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+morkEnv::ClearWarnings() // clear warning
+{
+ mEnv_WarningCount = 0;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+morkEnv::ClearErrorsAndWarnings() // clear both errors & warnings
+{
+ ClearMorkErrorsAndWarnings();
+ return NS_OK;
+}
+// } ===== end nsIMdbEnv methods =====
+
+
+//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789