Compare commits

..

1 Commits

Author SHA1 Message Date
(no author)
258dc9fead This commit was manufactured by cvs2svn to create branch 'src'.
git-svn-id: svn://10.0.0.236/branches/src@33658 18797224-902f-48f8-a5cc-f745e15eee43
1999-06-03 23:10:01 +00:00
1381 changed files with 18431 additions and 279724 deletions

View File

@@ -1,24 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..\..\..
#tests src no tests or src yet
DIRS=public
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,19 +0,0 @@
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
#
# This is a list of local files which get copied to the mozilla:dist:mailnews directory
#
mdb.h

View File

@@ -1,33 +0,0 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1999 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH = ../../../..
topsrcdir = @top_srcdir@
VPATH = @srcdir@
srcdir = @srcdir@
MODULE = msgmdb
include $(DEPTH)/config/autoconf.mk
EXPORTS= \
mdb.h \
$(NULL)
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/config/rules.mk

View File

@@ -1,29 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..\..\..\..
MODULE=msgmdb
XPIDLSRCS = \
$(NULL)
EXPORTS = \
mdb.h \
$(NULL)
include <$(DEPTH)\config\rules.mak>

File diff suppressed because it is too large Load Diff

View File

@@ -1,34 +0,0 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH = ../../..
topsrcdir = @top_srcdir@
VPATH = @srcdir@
srcdir = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src build
ifdef ENABLE_TESTS
DIRS += tests
endif
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/config/rules.mk

View File

@@ -1,21 +0,0 @@
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998-1999 Netscape Communications Corporation. All Rights
# Reserved.
#
# This is a list of local files which get copied to the mozilla:dist:mailnews directory
#
nsMorkCID.h
nsIMdbFactoryFactory.h

View File

@@ -1,52 +0,0 @@
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
VPATH = @srcdir@
srcdir = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = mork
LIBRARY_NAME = mork
IS_COMPONENT = 1
CPPSRCS = nsMorkFactory.cpp
EXPORTS = \
nsMorkCID.h \
nsIMdbFactoryFactory.h \
$(NULL)
SHARED_LIBRARY_LIBS = $(DIST)/lib/libmsgmork_s.a
EXTRA_DSO_LDOPTS = \
$(MKSHLIB_FORCE_ALL) \
$(SHARED_LIBRARY_LIBS) \
$(MKSHLIB_UNFORCE_ALL) \
-L$(DIST)/bin \
-L$(DIST)/lib \
-lxpcom \
-lxp \
-lmsgbaseutil \
$(NULL)
include $(topsrcdir)/config/rules.mk
$(LIBRARY) $(SHARED_LIBRARY): $(SHARED_LIBRARY_LIBS) Makefile

View File

@@ -1,50 +0,0 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..\..\..\..
MODULE=msgmork
################################################################################
## exports
EXPORTS= \
nsMorkCID.h \
nsIMdbFactoryFactory.h \
$(NULL)
################################################################################
## library
LIBNAME = .\$(OBJDIR)\mork
DLL = $(LIBNAME).dll
CPP_OBJS= \
.\$(OBJDIR)\nsMorkFactory.obj \
$(NULL)
LLIBS= \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\msgmork_s.lib \
$(LIBNSPR) \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) $(LIBNAME).$(DLL_SUFFIX) $(DIST)\bin\components
$(MAKE_INSTALL) $(LIBNAME).$(LIB_SUFFIX) $(DIST)\lib

View File

@@ -1,41 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsIMdbFactoryFactory_h__
#define nsIMdbFactoryFactory_h__
#include "nsISupports.h"
#include "nsIFactory.h"
#include "nsIComponentManager.h"
class nsIMdbFactory;
// d5440650-2807-11d3-8d75-00805f8a6617
#define NS_IMDBFACTORYFACTORY_IID \
{ 0xd5440650, 0x2807, 0x11d3, { 0x8d, 0x75, 0x00, 0x80, 0x5f, 0x8a, 0x66, 0x17}}
// because Mork doesn't support XPCOM, we have to wrap the mdb factory interface
// with an interface that gives you an mdb factory.
class nsIMdbFactoryFactory : public nsISupports
{
public:
static const nsIID& GetIID(void) { static nsIID iid = NS_IMDBFACTORYFACTORY_IID; return iid; }
NS_IMETHOD GetMdbFactory(nsIMdbFactory **aFactory) = 0;
};
#endif

View File

@@ -1,31 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsMorkCID_h__
#define nsMorkCID_h__
#include "nsISupports.h"
#include "nsIFactory.h"
#include "nsIComponentManager.h"
// 36d90300-27f5-11d3-8d74-00805f8a6617
#define NS_MORK_CID \
{ 0x36d90300, 0x27f5, 0x11d3, \
{ 0x8d, 0x74, 0x00, 0x80, 0x5f, 0x8a, 0x66, 0x17 } }
#endif

View File

@@ -1,232 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "msgCore.h" // for pre-compiled headers...
#include "nsIServiceManager.h"
#include "nsIFactory.h"
#include "nsISupports.h"
#include "nsMorkCID.h"
#include "nsIMdbFactoryFactory.h"
#include "pratom.h"
#include "mdb.h"
// include files for components this factory creates...
static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
static NS_DEFINE_CID(kCMorkFactory, NS_MORK_CID);
////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////
static PRInt32 g_InstanceCount = 0;
static PRInt32 g_LockCount = 0;
class nsMorkFactory : public nsIFactory
{
public:
// nsISupports methods
NS_DECL_ISUPPORTS
nsMorkFactory(const nsCID &aClass, const char* aClassName, const char* aProgID);
// nsIFactory methods
NS_IMETHOD CreateInstance(nsISupports *aOuter, const nsIID &aIID, void **aResult);
NS_IMETHOD LockFactory(PRBool aLock);
protected:
virtual ~nsMorkFactory();
nsCID mClassID;
char* mClassName;
char* mProgID;
};
class nsMorkFactoryFactory : public nsIMdbFactoryFactory
{
public:
nsMorkFactoryFactory();
// nsISupports methods
NS_DECL_ISUPPORTS
NS_IMETHOD GetMdbFactory(nsIMdbFactory **aFactory);
};
nsMorkFactory::nsMorkFactory(const nsCID &aClass, const char* aClassName, const char* aProgID)
: mClassID(aClass), mClassName(nsCRT::strdup(aClassName)), mProgID(nsCRT::strdup(aProgID))
{
NS_INIT_REFCNT();
}
nsMorkFactory::~nsMorkFactory()
{
NS_ASSERTION(mRefCnt == 0, "non-zero refcnt at destruction");
PL_strfree(mClassName);
PL_strfree(mProgID);
}
nsresult nsMorkFactory::QueryInterface(const nsIID &aIID, void **aResult)
{
if (aResult == NULL)
return NS_ERROR_NULL_POINTER;
// Always NULL result, in case of failure
*aResult = NULL;
// we support two interfaces....nsISupports and nsFactory.....
if (aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID()))
*aResult = (void *)(nsISupports*)this;
else if (aIID.Equals(nsIFactory::GetIID()))
*aResult = (void *)(nsIFactory*)this;
if (*aResult == NULL)
return NS_NOINTERFACE;
AddRef(); // Increase reference count for caller
return NS_OK;
}
NS_IMPL_ADDREF(nsMorkFactory)
NS_IMPL_RELEASE(nsMorkFactory)
// OK, we're cheating here, since Mork doesn't support XPCOM, i.e., nsIMDBFactory
// doesn't inherit from nsISupports. I could create a wrapper interface for an nsIMDBFactory
// object that returns a real nsISupports object, and msgdb could use this object
// to get hold of the actual nsIMDBFactory interface object.
nsresult nsMorkFactory::CreateInstance(nsISupports *aOuter, const nsIID &aIID, void **aResult)
{
nsresult rv = NS_OK;
if (aResult == NULL)
return NS_ERROR_NULL_POINTER;
*aResult = NULL;
// ClassID check happens here
// Whenever you add a new class that supports an interface, plug it in here!!!
// do they want a mork factory ?
if (mClassID.Equals(kCMorkFactory))
{
*aResult = MakeMdbFactory();
}
return rv;
}
nsresult nsMorkFactory::LockFactory(PRBool aLock)
{
if (aLock) {
PR_AtomicIncrement(&g_LockCount);
} else {
PR_AtomicDecrement(&g_LockCount);
}
return NS_OK;
}
// return the proper factory to the caller.
extern "C" NS_EXPORT nsresult NSGetFactory(nsISupports* aServMgr,
const nsCID &aClass,
const char *aClassName,
const char *aProgID,
nsIFactory **aFactory)
{
if (nsnull == aFactory)
return NS_ERROR_NULL_POINTER;
// If we decide to implement multiple factories in the msg.dll, then we need to check the class
// type here and create the appropriate factory instead of always creating a nsMsgFactory...
*aFactory = new nsMorkFactory(aClass, aClassName, aProgID);
if (aFactory)
return (*aFactory)->QueryInterface(nsIFactory::GetIID(), (void**)aFactory); // they want a Factory Interface so give it to them
else
return NS_ERROR_OUT_OF_MEMORY;
}
extern "C" NS_EXPORT PRBool NSCanUnload(nsISupports* aServMgr)
{
return PRBool(g_InstanceCount == 0 && g_LockCount == 0);
}
extern "C" NS_EXPORT nsresult
NSRegisterSelf(nsISupports* aServMgr, const char* path)
{
nsresult rv = NS_OK;
nsresult finalResult = NS_OK;
NS_WITH_SERVICE1(nsIComponentManager, compMgr, aServMgr, kComponentManagerCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = compMgr->RegisterComponent(kCMorkFactory, nsnull, nsnull,
path, PR_TRUE, PR_TRUE);
if (NS_FAILED(rv))finalResult = rv;
return finalResult;
}
extern "C" NS_EXPORT nsresult
NSUnregisterSelf(nsISupports* aServMgr, const char* path)
{
nsresult rv = NS_OK;
nsresult finalResult = NS_OK;
NS_WITH_SERVICE1(nsIComponentManager, compMgr, aServMgr, kComponentManagerCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = compMgr->UnregisterComponent(kCMorkFactory, path);
if (NS_FAILED(rv)) finalResult = rv;
return finalResult;
}
static nsIMdbFactory *gMDBFactory = nsnull;
NS_IMPL_ADDREF(nsMorkFactoryFactory)
NS_IMPL_RELEASE(nsMorkFactoryFactory)
NS_IMETHODIMP
nsMorkFactoryFactory::QueryInterface(REFNSIID iid, void** result)
{
if (! result)
return NS_ERROR_NULL_POINTER;
*result = nsnull;
if(iid.Equals(nsIMdbFactoryFactory::GetIID()) ||
iid.Equals(nsCOMTypeInfo<nsISupports>::GetIID())) {
*result = NS_STATIC_CAST(nsIMdbFactoryFactory*, this);
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
nsMorkFactoryFactory::nsMorkFactoryFactory()
{
NS_INIT_REFCNT();
}
NS_IMETHODIMP nsMorkFactoryFactory::GetMdbFactory(nsIMdbFactory **aFactory)
{
if (!gMDBFactory)
gMDBFactory = MakeMdbFactory();
*aFactory = gMDBFactory;
return (gMDBFactory) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}

Binary file not shown.

View File

@@ -1,21 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "MacPrefix.h"

View File

@@ -1,21 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "MacPrefix_debug.h"

View File

@@ -1,24 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..\..\..
#tests no tests yet or public yet
DIRS=src build
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,95 +0,0 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH = ../../../..
topsrcdir = @top_srcdir@
VPATH = @srcdir@
srcdir = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = msgmork
LIBRARY_NAME=msgmork_s
EXPORTS = \
$(NULL)
CPPSRCS = \
orkinCell.cpp\
orkinEnv.cpp\
orkinFactory.cpp\
orkinHeap.cpp\
orkinPortTableCursor.cpp\
orkinRow.cpp\
orkinRowCellCursor.cpp\
orkinStore.cpp\
orkinTable.cpp\
orkinTableRowCursor.cpp\
orkinThumb.cpp\
morkArray.cpp\
morkAtom.cpp\
morkAtomMap.cpp\
morkAtomSpace.cpp\
morkBlob.cpp\
morkBuilder.cpp\
morkCell.cpp\
morkCellObject.cpp\
morkCh.cpp\
morkConfig.cpp\
morkCursor.cpp \
morkDeque.cpp\
morkEnv.cpp\
morkFactory.cpp\
morkFile.cpp\
morkHandle.cpp\
morkIntMap.cpp\
morkMap.cpp\
morkNode.cpp\
morkNodeMap.cpp\
morkObject.cpp\
morkParser.cpp\
morkPool.cpp\
morkRow.cpp\
morkRowCellCursor.cpp\
morkRowMap.cpp\
morkRowObject.cpp\
morkRowSpace.cpp\
morkSink.cpp\
morkSpace.cpp\
morkStore.cpp\
morkStream.cpp\
morkTable.cpp\
morkPortTableCursor.cpp\
morkTableRowCursor.cpp\
morkThumb.cpp\
morkWriter.cpp\
morkYarn.cpp\
$(NULL)
EXTRA_DSO_LDOPTS =\
-L$(DIST)/bin \
-L$(DIST)/lib \
$(NSPR_LIBS) \
$(NULL)
override NO_SHARED_LIB=1
override NO_STATIC_LIB=
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/config/rules.mk

View File

@@ -1,93 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998-1999 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..\..\..\..
MODULE= msgmork
include <$(DEPTH)\config\config.mak>
################################################################################
## exports
EXPORTS= \
$(NULL)
################################################################################
## library
LIBRARY_NAME=msgmork_s
CPP_OBJS= .\$(OBJDIR)\orkinCell.obj \
.\$(OBJDIR)\orkinEnv.obj \
.\$(OBJDIR)\orkinFactory.obj \
.\$(OBJDIR)\orkinHeap.obj \
.\$(OBJDIR)\orkinPortTableCursor.obj \
.\$(OBJDIR)\orkinRow.obj \
.\$(OBJDIR)\orkinRowCellCursor.obj \
.\$(OBJDIR)\orkinStore.obj \
.\$(OBJDIR)\orkinTable.obj \
.\$(OBJDIR)\orkinTableRowCursor.obj \
.\$(OBJDIR)\orkinThumb.obj \
.\$(OBJDIR)\morkArray.obj \
.\$(OBJDIR)\morkAtom.obj \
.\$(OBJDIR)\morkAtomMap.obj \
.\$(OBJDIR)\morkAtomSpace.obj \
.\$(OBJDIR)\morkBlob.obj \
.\$(OBJDIR)\morkBuilder.obj \
.\$(OBJDIR)\morkCell.obj \
.\$(OBJDIR)\morkCellObject.obj \
.\$(OBJDIR)\morkCh.obj \
.\$(OBJDIR)\morkConfig.obj \
.\$(OBJDIR)\morkCursor.obj \
.\$(OBJDIR)\morkDeque.obj \
.\$(OBJDIR)\morkEnv.obj \
.\$(OBJDIR)\morkFactory.obj \
.\$(OBJDIR)\morkFile.obj \
.\$(OBJDIR)\morkHandle.obj \
.\$(OBJDIR)\morkIntMap.obj \
.\$(OBJDIR)\morkMap.obj \
.\$(OBJDIR)\morkNode.obj \
.\$(OBJDIR)\morkNodeMap.obj \
.\$(OBJDIR)\morkObject.obj \
.\$(OBJDIR)\morkParser.obj \
.\$(OBJDIR)\morkPool.obj \
.\$(OBJDIR)\morkPortTableCursor.obj \
.\$(OBJDIR)\morkRow.obj \
.\$(OBJDIR)\morkRowCellCursor.obj \
.\$(OBJDIR)\morkRowMap.obj \
.\$(OBJDIR)\morkRowObject.obj \
.\$(OBJDIR)\morkRowSpace.obj \
.\$(OBJDIR)\morkSink.obj \
.\$(OBJDIR)\morkSpace.obj \
.\$(OBJDIR)\morkStore.obj \
.\$(OBJDIR)\morkStream.obj \
.\$(OBJDIR)\morkTable.obj \
.\$(OBJDIR)\morkTableRowCursor.obj \
.\$(OBJDIR)\morkThumb.obj \
.\$(OBJDIR)\morkWriter.obj \
.\$(OBJDIR)\morkYarn.obj \
$(NULL)
include <$(DEPTH)\config\rules.mak>
libs:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -1,215 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORK_
#define _MORK_ 1
#ifndef _MDB_
#include "mdb.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// { %%%%% begin disable unused param warnings %%%%%
#define MORK_USED_1(x) (void)(&x)
#define MORK_USED_2(x,y) (void)(&x);(void)(&y);
#define MORK_USED_3(x,y,z) (void)(&x);(void)(&y);(void)(&z);
#define MORK_USED_4(w,x,y,z) (void)(&w);(void)(&x);(void)(&y);(void)(&z);
// } %%%%% end disable unused param warnings %%%%%
// { %%%%% begin macro for finding class member offset %%%%%
/*| OffsetOf: the unsigned integer offset of a class or struct
**| field from the beginning of that class or struct. This is
**| the same as the similarly named public domain IronDoc macro,
**| and is also the same as another macro appearing in stdlib.h.
**| We want these offsets so we can correctly convert pointers
**| to member slots back into pointers to enclosing objects, and
**| have this exactly match what the compiler thinks is true.
**|
**|| Bascially we are asking the compiler to determine the offset at
**| compile time, and we use the definition of address artithmetic
**| to do this. By casting integer zero to a pointer of type obj*,
**| we can reference the address of a slot in such an object that
**| is hypothetically physically placed at address zero, but without
**| actually dereferencing a memory location. The absolute address
**| of slot is the same as offset of that slot, when the object is
**| placed at address zero.
|*/
#define mork_OffsetOf(obj,slot) ((unsigned int)&((obj*) 0)->slot)
// } %%%%% end macro for finding class member offset %%%%%
// { %%%%% begin specific-size integer scalar typedefs %%%%%
typedef unsigned char mork_u1; // make sure this is one byte
typedef unsigned short mork_u2; // make sure this is two bytes
typedef short mork_i2; // make sure this is two bytes
typedef unsigned long mork_u4; // make sure this is four bytes
typedef long mork_i4; // make sure this is four bytes
typedef long mork_ip; // make sure sizeof(mork_ip) == sizeof(void*)
typedef mork_u1 mork_ch; // small byte-sized character (never wide)
typedef mork_u1 mork_flags; // one byte's worth of predicate bit flags
typedef mork_u2 mork_base; // 2-byte magic class signature slot in object
typedef mork_u2 mork_derived; // 2-byte magic class signature slot in object
typedef mork_u2 mork_uses; // 2-byte strong uses count
typedef mork_u2 mork_refs; // 2-byte actual reference count
typedef mork_u4 mork_token; // unsigned token for atomized string
typedef mork_token mork_scope; // token used to id scope for rows
typedef mork_token mork_kind; // token used to id kind for tables
typedef mork_token mork_cscode; // token used to id charset names
typedef mork_token mork_aid; // token used to id atomize cell values
typedef mork_token mork_column; // token used to id columns for rows
typedef mork_column mork_delta; // mork_column plus mork_change
typedef mork_u4 mork_magic; // unsigned magic signature
typedef mork_u4 mork_seed; // unsigned collection change counter
typedef mork_u4 mork_count; // unsigned collection member count
typedef mork_count mork_num; // synonym for count
typedef mork_u4 mork_size; // unsigned physical media size
typedef mork_u4 mork_fill; // unsigned logical content size
typedef mork_u4 mork_more; // more available bytes for larger buffer
typedef mdb_u4 mork_percent; // 0..100, with values >100 same as 100
typedef mork_i4 mork_pos; // negative means "before first" (at zero pos)
typedef mork_i4 mork_line; // negative means "before first line in file"
typedef mork_u1 mork_usage; // 1-byte magic usage signature slot in object
typedef mork_u1 mork_access; // 1-byte magic access signature slot in object
typedef mork_u1 mork_change; // add, cut, put, set, nil
typedef mork_u1 mork_priority; // 0..9, for a total of ten different values
typedef mork_u1 mork_able; // on, off, asleep (clone IronDoc's fe_able)
typedef mork_u1 mork_load; // dirty or clean (clone IronDoc's fe_load)
// } %%%%% end specific-size integer scalar typedefs %%%%%
// { %%%%% begin constants for Mork scalar types %%%%%
#define morkPriority_kHi ((mork_priority) 0) /* best priority */
#define morkPriority_kMin ((mork_priority) 0) /* best priority is smallest */
#define morkPriority_kLo ((mork_priority) 9) /* worst priority */
#define morkPriority_kMax ((mork_priority) 9) /* worst priority is biggest */
#define morkPriority_kCount 10 /* number of distinct priority values */
#define morkAble_kEnabled ((mork_able) 0x55) /* same as IronDoc constant */
#define morkAble_kDisabled ((mork_able) 0xAA) /* same as IronDoc constant */
#define morkAble_kAsleep ((mork_able) 0x5A) /* same as IronDoc constant */
#define morkChange_kAdd 'a' /* add member */
#define morkChange_kCut 'c' /* cut member */
#define morkChange_kPut 'p' /* put member */
#define morkChange_kSet 's' /* set all members */
#define morkChange_kNil 0 /* no change in this member */
#define morkChange_kDup 'd' /* duplicate changes have no effect */
// kDup is intended to replace another change constant in an object as a
// conclusion about change feasibility while staging intended alterations.
#define morkLoad_kDirty ((mork_load) 0xDD) /* same as IronDoc constant */
#define morkLoad_kClean ((mork_load) 0x22) /* same as IronDoc constant */
#define morkAccess_kOpen 'o'
#define morkAccess_kClosing 'c'
#define morkAccess_kShut 's'
#define morkAccess_kDead 'd'
// } %%%%% end constants for Mork scalar types %%%%%
// { %%%%% begin non-specific-size integer scalar typedefs %%%%%
typedef int mork_char; // nominal type for ints used to hold input byte
#define morkChar_IsWhite(c) \
((c) == 0xA || (c) == 0x9 || (c) == 0xD || (c) == ' ')
// } %%%%% end non-specific-size integer scalar typedefs %%%%%
// { %%%%% begin mdb-driven scalar typedefs %%%%%
// easier to define bool exactly the same as mdb:
typedef mdb_bool mork_bool; // unsigned byte with zero=false, nonzero=true
/* canonical boolean constants provided only for code clarity: */
#define morkBool_kTrue ((mork_bool) 1) /* actually any nonzero means true */
#define morkBool_kFalse ((mork_bool) 0) /* only zero means false */
// mdb clients can assign these, so we cannot pick maximum size:
typedef mdb_id mork_id; // unsigned object identity in a scope
typedef mork_id mork_rid; // unsigned row identity inside scope
typedef mork_id mork_tid; // unsigned table identity inside scope
typedef mork_id mork_gid; // unsigned group identity without any scope
// we only care about neg, zero, pos -- so we don't care about size:
typedef mdb_order mork_order; // neg:lessthan, zero:equalto, pos:greaterthan
// } %%%%% end mdb-driven scalar typedefs %%%%%
#define morkId_kMinusOne ((mdb_id) -1)
// { %%%%% begin class forward defines %%%%%
// try to put these in alphabetical order for easier examination:
class morkMid;
class morkAtom;
class morkAtomSpace;
class morkBookAtom;
class morkBuf;
class morkBuilder;
class morkCell;
class morkCellObject;
class morkCursor;
class morkEnv;
class morkFactory;
class morkFile;
class morkHandle;
class morkHandleFace; // just an opaque cookie type
class morkHandleFrame;
class morkHashArrays;
class morkMap;
class morkNode;
class morkObject;
class morkOidAtom;
class morkParser;
class morkPool;
class morkPlace;
class morkPort;
class morkPortTableCursor;
class morkRow;
class morkRowCellCursor;
class morkRowObject;
class morkRowSpace;
class morkSpace;
class morkSpan;
class morkStore;
class morkStream;
class morkTable;
class morkTableChange;
class morkTableRowCursor;
class morkThumb;
class morkWriter;
// } %%%%% end class forward defines %%%%%
// include this config file last for platform & environment specific stuff:
#ifndef _MORKCONFIG_
#include "morkConfig.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORK_ */

View File

@@ -1,311 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKARRAY_
#include "morkArray.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkArray::CloseMorkNode(morkEnv* ev) // CloseTable() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseArray(ev);
this->MarkShut();
}
}
/*public virtual*/
morkArray::~morkArray() // assert CloseTable() executed earlier
{
MORK_ASSERT(this->IsShutNode());
MORK_ASSERT(mArray_Slots==0);
}
/*public non-poly*/
morkArray::morkArray(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, mork_size inSize, nsIMdbHeap* ioSlotHeap)
: morkNode(ev, inUsage, ioHeap)
, mArray_Slots( 0 )
, mArray_Heap( 0 )
, mArray_Fill( 0 )
, mArray_Size( 0 )
, mArray_Seed( (mork_u4) this ) // "random" integer assignment
{
if ( ev->Good() )
{
if ( ioSlotHeap )
{
nsIMdbHeap_SlotStrongHeap(ioSlotHeap, ev, &mArray_Heap);
if ( ev->Good() )
{
if ( inSize < 3 )
inSize = 3;
mdb_size byteSize = inSize * sizeof(void*);
void** block = 0;
ioSlotHeap->Alloc(ev->AsMdbEnv(), byteSize, (void**) &block);
if ( block && ev->Good() )
{
mArray_Slots = block;
mArray_Size = inSize;
MORK_MEMSET(mArray_Slots, 0, byteSize);
if ( ev->Good() )
mNode_Derived = morkDerived_kArray;
}
}
}
else
ev->NilPointerError();
}
}
/*public non-poly*/ void
morkArray::CloseArray(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
if ( mArray_Heap && mArray_Slots )
mArray_Heap->Free(ev->AsMdbEnv(), mArray_Slots);
mArray_Slots = 0;
mArray_Size = 0;
mArray_Fill = 0;
++mArray_Seed;
nsIMdbHeap_SlotStrongHeap((nsIMdbHeap*) 0, ev, &mArray_Heap);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
/*static*/ void
morkArray::NonArrayTypeError(morkEnv* ev)
{
ev->NewError("non morkArray");
}
/*static*/ void
morkArray::IndexBeyondEndError(morkEnv* ev)
{
ev->NewError("array index beyond end");
}
/*static*/ void
morkArray::NilSlotsAddressError(morkEnv* ev)
{
ev->NewError("nil mArray_Slots");
}
/*static*/ void
morkArray::FillBeyondSizeError(morkEnv* ev)
{
ev->NewError("mArray_Fill > mArray_Size");
}
mork_bool
morkArray::Grow(morkEnv* ev, mork_size inNewSize)
// Grow() returns true if capacity becomes >= inNewSize and ev->Good()
{
if ( ev->Good() && inNewSize > mArray_Size ) // make array larger?
{
if ( mArray_Fill <= mArray_Size ) // fill and size fit the invariant?
{
if ( inNewSize - mArray_Size < 3 ) // actually want a few more slots?
inNewSize = mArray_Size + 3;
mdb_size newByteSize = inNewSize * sizeof(void*);
void** newBlock = 0;
mArray_Heap->Alloc(ev->AsMdbEnv(), newByteSize, (void**) &newBlock);
if ( newBlock && ev->Good() ) // okay new block?
{
void** oldSlots = mArray_Slots;
void** oldEnd = oldSlots + mArray_Fill;
void** newSlots = newBlock;
void** newEnd = newBlock + inNewSize;
while ( oldSlots < oldEnd )
*newSlots++ = *oldSlots++;
while ( newSlots < newEnd )
*newSlots++ = (void*) 0;
oldSlots = mArray_Slots;
mArray_Size = inNewSize;
mArray_Slots = newBlock;
mArray_Heap->Free(ev->AsMdbEnv(), oldSlots);
}
}
else
this->FillBeyondSizeError(ev);
}
++mArray_Seed; // always modify seed, since caller intends to add slots
return ( ev->Good() && mArray_Size >= inNewSize );
}
void*
morkArray::SafeAt(morkEnv* ev, mork_pos inPos)
{
if ( mArray_Slots )
{
if ( inPos >= 0 && inPos < (mork_pos) mArray_Fill )
return mArray_Slots[ inPos ];
else
this->IndexBeyondEndError(ev);
}
else
this->NilSlotsAddressError(ev);
return (void*) 0;
}
void
morkArray::SafeAtPut(morkEnv* ev, mork_pos inPos, void* ioSlot)
{
if ( mArray_Slots )
{
if ( inPos >= 0 && inPos < (mork_pos) mArray_Fill )
{
mArray_Slots[ inPos ] = ioSlot;
++mArray_Seed;
}
else
this->IndexBeyondEndError(ev);
}
else
this->NilSlotsAddressError(ev);
}
mork_pos
morkArray::AppendSlot(morkEnv* ev, void* ioSlot)
{
mork_pos outPos = -1;
if ( mArray_Slots )
{
mork_fill fill = mArray_Fill;
if ( this->Grow(ev, fill+1) )
{
outPos = (mork_pos) fill;
mArray_Slots[ fill ] = ioSlot;
mArray_Fill = fill + 1;
// note Grow() increments mArray_Seed
}
}
else
this->NilSlotsAddressError(ev);
return outPos;
}
void
morkArray::AddSlot(morkEnv* ev, mork_pos inPos, void* ioSlot)
{
if ( mArray_Slots )
{
mork_fill fill = mArray_Fill;
if ( this->Grow(ev, fill+1) )
{
void** slot = mArray_Slots; // the slot vector
void** end = slot + fill; // one past the last used array slot
slot += inPos; // the slot to be added
while ( --end >= slot ) // another slot to move upward?
end[ 1 ] = *end;
*slot = ioSlot;
mArray_Fill = fill + 1;
// note Grow() increments mArray_Seed
}
}
else
this->NilSlotsAddressError(ev);
}
void
morkArray::CutSlot(morkEnv* ev, mork_pos inPos)
{
MORK_USED_1(ev);
mork_fill fill = mArray_Fill;
if ( inPos >= 0 && inPos < (mork_pos) fill ) // cutting slot in used array portion?
{
void** slot = mArray_Slots; // the slot vector
void** end = slot + fill; // one past the last used array slot
slot += inPos; // the slot to be cut
while ( ++slot < end ) // another slot to move downward?
slot[ -1 ] = *slot;
slot[ -1 ] = 0; // clear the last used slot which is now unused
// note inPos<fill implies fill>0, so fill-1 must be nonnegative:
mArray_Fill = fill - 1;
++mArray_Seed;
}
}
void
morkArray::CutAllSlots(morkEnv* ev)
{
if ( mArray_Slots )
{
if ( mArray_Fill <= mArray_Size )
{
mdb_size oldByteSize = mArray_Fill * sizeof(void*);
MORK_MEMSET(mArray_Slots, 0, oldByteSize);
}
else
this->FillBeyondSizeError(ev);
}
else
this->NilSlotsAddressError(ev);
++mArray_Seed;
mArray_Fill = 0;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,111 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKARRAY_
#define _MORKARRAY_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kArray /*i*/ 0x4179 /* ascii 'Ay' */
class morkArray : public morkNode { // row iterator
// public: // slots inherited from morkObject (meant to inform only)
// nsIMdbHeap* mNode_Heap;
// mork_able mNode_Mutable; // can this node be modified?
// mork_load mNode_Load; // is this node clean or dirty?
// 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_uses mNode_Uses; // refcount for strong refs
// mork_refs mNode_Refs; // refcount for strong refs + weak refs
public: // state is public because the entire Mork system is private
void** mArray_Slots; // array of pointers
nsIMdbHeap* mArray_Heap; // required heap for allocating mArray_Slots
mork_fill mArray_Fill; // logical count of used slots in mArray_Slots
mork_size mArray_Size; // physical count of mArray_Slots ( >= Fill)
mork_seed mArray_Seed; // change counter for syncing with iterators
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseArray()
virtual ~morkArray(); // assert that close executed earlier
public: // morkArray construction & destruction
morkArray(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, mork_size inSize, nsIMdbHeap* ioSlotHeap);
void CloseArray(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkArray(const morkArray& other);
morkArray& operator=(const morkArray& other);
public: // dynamic type identification
mork_bool IsArray() const
{ return IsNode() && mNode_Derived == morkDerived_kArray; }
// } ===== end morkNode methods =====
public: // typing & errors
static void NonArrayTypeError(morkEnv* ev);
static void IndexBeyondEndError(morkEnv* ev);
static void NilSlotsAddressError(morkEnv* ev);
static void FillBeyondSizeError(morkEnv* ev);
public: // other table row cursor methods
mork_fill Length() const { return mArray_Fill; }
mork_size Capacity() const { return mArray_Size; }
mork_bool Grow(morkEnv* ev, mork_size inNewSize);
// Grow() returns true if capacity becomes >= inNewSize and ev->Good()
void* At(mork_pos inPos) const { return mArray_Slots[ inPos ]; }
void AtPut(mork_pos inPos, void* ioSlot)
{ mArray_Slots[ inPos ] = ioSlot; }
void* SafeAt(morkEnv* ev, mork_pos inPos);
void SafeAtPut(morkEnv* ev, mork_pos inPos, void* ioSlot);
mork_pos AppendSlot(morkEnv* ev, void* ioSlot);
void AddSlot(morkEnv* ev, mork_pos inPos, void* ioSlot);
void CutSlot(morkEnv* ev, mork_pos inPos);
void CutAllSlots(morkEnv* ev);
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakArray(morkArray* me,
morkEnv* ev, morkArray** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongArray(morkArray* me,
morkEnv* ev, morkArray** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKTABLEROWCURSOR_ */

View File

@@ -1,532 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKBLOB_
#include "morkBlob.h"
#endif
#ifndef _MORKATOM_
#include "morkAtom.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKATOMSPACE_
#include "morkAtomSpace.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
mork_bool
morkAtom::GetYarn(mdbYarn* outYarn) const
{
const void* source = 0;
mdb_fill fill = 0;
mdb_cscode form = 0;
outYarn->mYarn_More = 0;
if ( this )
{
if ( this->IsWeeBook() )
{
morkWeeBookAtom* weeBook = (morkWeeBookAtom*) this;
source = weeBook->mWeeBookAtom_Body;
fill = weeBook->mAtom_Size;
}
else if ( this->IsBigBook() )
{
morkBigBookAtom* bigBook = (morkBigBookAtom*) this;
source = bigBook->mBigBookAtom_Body;
fill = bigBook->mBigBookAtom_Size;
form = bigBook->mBigBookAtom_Form;
}
else if ( this->IsWeeAnon() )
{
morkWeeAnonAtom* weeAnon = (morkWeeAnonAtom*) this;
source = weeAnon->mWeeAnonAtom_Body;
fill = weeAnon->mAtom_Size;
}
else if ( this->IsBigAnon() )
{
morkBigAnonAtom* bigAnon = (morkBigAnonAtom*) this;
source = bigAnon->mBigAnonAtom_Body;
fill = bigAnon->mBigAnonAtom_Size;
form = bigAnon->mBigAnonAtom_Form;
}
}
if ( source && fill ) // have an atom with nonempty content?
{
// if we have too many bytes, and yarn seems growable:
if ( fill > outYarn->mYarn_Size && outYarn->mYarn_Grow ) // try grow?
(*outYarn->mYarn_Grow)(outYarn, (mdb_size) fill); // request bigger
mdb_size size = outYarn->mYarn_Size; // max dest size
if ( fill > size ) // too much atom content?
{
outYarn->mYarn_More = fill - size; // extra atom 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, source, 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 atom has no bytes
}
outYarn->mYarn_Form = form; // always update the form slot
return ( source != 0 );
}
mork_bool
morkAtom::AsBuf(morkBuf& outBuf) const
{
const morkAtom* atom = this;
if ( atom )
{
if ( atom->IsWeeBook() )
{
morkWeeBookAtom* weeBook = (morkWeeBookAtom*) atom;
outBuf.mBuf_Body = weeBook->mWeeBookAtom_Body;
outBuf.mBuf_Fill = weeBook->mAtom_Size;
}
else if ( atom->IsBigBook() )
{
morkBigBookAtom* bigBook = (morkBigBookAtom*) atom;
outBuf.mBuf_Body = bigBook->mBigBookAtom_Body;
outBuf.mBuf_Fill = bigBook->mBigBookAtom_Size;
}
else if ( atom->IsWeeAnon() )
{
morkWeeAnonAtom* weeAnon = (morkWeeAnonAtom*) atom;
outBuf.mBuf_Body = weeAnon->mWeeAnonAtom_Body;
outBuf.mBuf_Fill = weeAnon->mAtom_Size;
}
else if ( atom->IsBigAnon() )
{
morkBigAnonAtom* bigAnon = (morkBigAnonAtom*) atom;
outBuf.mBuf_Body = bigAnon->mBigAnonAtom_Body;
outBuf.mBuf_Fill = bigAnon->mBigAnonAtom_Size;
}
else
atom = 0; // show desire to put empty content in yarn
}
if ( !atom ) // empty content for yarn?
{
outBuf.mBuf_Body = 0;
outBuf.mBuf_Fill = 0;
}
return ( atom != 0 );
}
mork_bool
morkAtom::AliasYarn(mdbYarn* outYarn) const
{
outYarn->mYarn_More = 0;
outYarn->mYarn_Form = 0;
const morkAtom* atom = this;
if ( atom )
{
if ( atom->IsWeeBook() )
{
morkWeeBookAtom* weeBook = (morkWeeBookAtom*) atom;
outYarn->mYarn_Buf = weeBook->mWeeBookAtom_Body;
outYarn->mYarn_Fill = weeBook->mAtom_Size;
outYarn->mYarn_Size = weeBook->mAtom_Size;
}
else if ( atom->IsBigBook() )
{
morkBigBookAtom* bigBook = (morkBigBookAtom*) atom;
outYarn->mYarn_Buf = bigBook->mBigBookAtom_Body;
outYarn->mYarn_Fill = bigBook->mBigBookAtom_Size;
outYarn->mYarn_Size = bigBook->mBigBookAtom_Size;
outYarn->mYarn_Form = bigBook->mBigBookAtom_Form;
}
else if ( atom->IsWeeAnon() )
{
morkWeeAnonAtom* weeAnon = (morkWeeAnonAtom*) atom;
outYarn->mYarn_Buf = weeAnon->mWeeAnonAtom_Body;
outYarn->mYarn_Fill = weeAnon->mAtom_Size;
outYarn->mYarn_Size = weeAnon->mAtom_Size;
}
else if ( atom->IsBigAnon() )
{
morkBigAnonAtom* bigAnon = (morkBigAnonAtom*) atom;
outYarn->mYarn_Buf = bigAnon->mBigAnonAtom_Body;
outYarn->mYarn_Fill = bigAnon->mBigAnonAtom_Size;
outYarn->mYarn_Size = bigAnon->mBigAnonAtom_Size;
outYarn->mYarn_Form = bigAnon->mBigAnonAtom_Form;
}
else
atom = 0; // show desire to put empty content in yarn
}
if ( !atom ) // empty content for yarn?
{
outYarn->mYarn_Buf = 0;
outYarn->mYarn_Fill = 0;
outYarn->mYarn_Size = 0;
// outYarn->mYarn_Grow = 0; // please don't modify the Grow slot
}
return ( atom != 0 );
}
mork_aid
morkAtom::GetBookAtomAid() const // zero or book atom's ID
{
return ( this->IsBook() )? ((morkBookAtom*) this)->mBookAtom_Id : 0;
}
mork_scope
morkAtom::GetBookAtomSpaceScope(morkEnv* ev) const // zero or book's space's scope
{
mork_scope outScope = 0;
if ( this->IsBook() )
{
const morkBookAtom* bookAtom = (const morkBookAtom*) this;
morkAtomSpace* space = bookAtom->mBookAtom_Space;
if ( space->IsAtomSpace() )
outScope = space->mSpace_Scope;
else
space->NonAtomSpaceTypeError(ev);
}
return outScope;
}
void
morkAtom::MakeCellUseForever(morkEnv* ev)
{
MORK_USED_1(ev);
mAtom_CellUses = morkAtom_kForeverCellUses;
}
mork_u1
morkAtom::AddCellUse(morkEnv* ev)
{
MORK_USED_1(ev);
if ( mAtom_CellUses < morkAtom_kMaxCellUses ) // not already maxed out?
++mAtom_CellUses;
return mAtom_CellUses;
}
mork_u1
morkAtom::CutCellUse(morkEnv* ev)
{
if ( mAtom_CellUses ) // any outstanding uses to cut?
{
if ( mAtom_CellUses < morkAtom_kMaxCellUses ) // not frozen at max?
--mAtom_CellUses;
}
else
this->CellUsesUnderflowWarning(ev);
return mAtom_CellUses;
}
/*static*/ void
morkAtom::CellUsesUnderflowWarning(morkEnv* ev)
{
ev->NewWarning("mAtom_CellUses underflow");
}
/*static*/ void
morkAtom::BadAtomKindError(morkEnv* ev)
{
ev->NewError("bad mAtom_Kind");
}
/*static*/ void
morkAtom::ZeroAidError(morkEnv* ev)
{
ev->NewError("zero atom ID");
}
/*static*/ void
morkAtom::AtomSizeOverflowError(morkEnv* ev)
{
ev->NewError("atom mAtom_Size overflow");
}
void
morkOidAtom::InitRowOidAtom(morkEnv* ev, const mdbOid& inOid)
{
MORK_USED_1(ev);
mAtom_CellUses = 0;
mAtom_Kind = morkAtom_kKindRowOid;
mAtom_Change = morkChange_kNil;
mAtom_Size = 0;
mOidAtom_Oid = inOid; // bitwise copy
}
void
morkOidAtom::InitTableOidAtom(morkEnv* ev, const mdbOid& inOid)
{
MORK_USED_1(ev);
mAtom_CellUses = 0;
mAtom_Kind = morkAtom_kKindTableOid;
mAtom_Change = morkChange_kNil;
mAtom_Size = 0;
mOidAtom_Oid = inOid; // bitwise copy
}
void
morkWeeAnonAtom::InitWeeAnonAtom(morkEnv* ev, const morkBuf& inBuf)
{
mAtom_Kind = 0;
mAtom_Change = morkChange_kNil;
if ( inBuf.mBuf_Fill <= morkAtom_kMaxByteSize )
{
mAtom_CellUses = 0;
mAtom_Kind = morkAtom_kKindWeeAnon;
mork_size size = inBuf.mBuf_Fill;
mAtom_Size = (mork_u1) size;
if ( size && inBuf.mBuf_Body )
MORK_MEMCPY(mWeeAnonAtom_Body, inBuf.mBuf_Body, size);
mWeeAnonAtom_Body[ size ] = 0;
}
else
this->AtomSizeOverflowError(ev);
}
void
morkBigAnonAtom::InitBigAnonAtom(morkEnv* ev, const morkBuf& inBuf,
mork_cscode inForm)
{
MORK_USED_1(ev);
mAtom_CellUses = 0;
mAtom_Kind = morkAtom_kKindBigAnon;
mAtom_Change = morkChange_kNil;
mAtom_Size = 0;
mBigAnonAtom_Form = inForm;
mork_size size = inBuf.mBuf_Fill;
mBigAnonAtom_Size = size;
if ( size && inBuf.mBuf_Body )
MORK_MEMCPY(mBigAnonAtom_Body, inBuf.mBuf_Body, size);
mBigAnonAtom_Body[ size ] = 0;
}
/*static*/ void
morkBookAtom::NonBookAtomTypeError(morkEnv* ev)
{
ev->NewError("non morkBookAtom");
}
mork_u4
morkBookAtom::HashFormAndBody(morkEnv* ev) const
{
// This hash is obviously a variation of the dragon book string hash.
// (I won't bother to explain or rationalize this usage for you.)
register mork_u4 outHash = 0; // hash value returned
register unsigned char c; // next character
register const mork_u1* body; // body of bytes to hash
mork_size size = 0; // the number of bytes to hash
if ( this->IsWeeBook() )
{
size = mAtom_Size;
body = ((const morkWeeBookAtom*) this)->mWeeBookAtom_Body;
}
else if ( this->IsBigBook() )
{
size = ((const morkBigBookAtom*) this)->mBigBookAtom_Size;
body = ((const morkBigBookAtom*) this)->mBigBookAtom_Body;
}
else
this->NonBookAtomTypeError(ev);
const mork_u1* end = body + size;
while ( body < end )
{
c = *body++;
outHash <<= 4;
outHash += c;
mork_u4 top = outHash & 0xF0000000L; // top four bits
if ( top ) // any of high four bits equal to one?
{
outHash ^= (top >> 24); // fold down high bits
outHash ^= top; // zero top four bits
}
}
return outHash;
}
mork_bool
morkBookAtom::EqualFormAndBody(morkEnv* ev, const morkBookAtom* inAtom) const
{
mork_bool outEqual = morkBool_kFalse;
const mork_u1* body = 0; // body of inAtom bytes to compare
mork_size size; // the number of inAtom bytes to compare
mork_cscode form; // nominal charset for ioAtom
if ( inAtom->IsWeeBook() )
{
size = inAtom->mAtom_Size;
body = ((const morkWeeBookAtom*) inAtom)->mWeeBookAtom_Body;
form = 0;
}
else if ( inAtom->IsBigBook() )
{
size = ((const morkBigBookAtom*) inAtom)->mBigBookAtom_Size;
body = ((const morkBigBookAtom*) inAtom)->mBigBookAtom_Body;
form = ((const morkBigBookAtom*) inAtom)->mBigBookAtom_Form;
}
else
inAtom->NonBookAtomTypeError(ev);
const mork_u1* thisBody = 0; // body of bytes in this to compare
mork_size thisSize; // the number of bytes in this to compare
mork_cscode thisForm; // nominal charset for this atom
if ( this->IsWeeBook() )
{
thisSize = mAtom_Size;
thisBody = ((const morkWeeBookAtom*) this)->mWeeBookAtom_Body;
thisForm = 0;
}
else if ( this->IsBigBook() )
{
thisSize = ((const morkBigBookAtom*) this)->mBigBookAtom_Size;
thisBody = ((const morkBigBookAtom*) this)->mBigBookAtom_Body;
thisForm = ((const morkBigBookAtom*) this)->mBigBookAtom_Form;
}
else
this->NonBookAtomTypeError(ev);
if ( body && thisBody && size == thisSize && form == thisForm )
outEqual = (MORK_MEMCMP(body, thisBody, size) == 0);
return outEqual;
}
void
morkBookAtom::CutBookAtomFromSpace(morkEnv* ev)
{
morkAtomSpace* space = mBookAtom_Space;
if ( space )
{
mBookAtom_Space = 0;
space->mAtomSpace_AtomBodies.CutAtom(ev, this);
space->mAtomSpace_AtomAids.CutAtom(ev, this);
}
else
ev->NilPointerError();
}
morkWeeBookAtom::morkWeeBookAtom(mork_aid inAid)
{
mAtom_Kind = morkAtom_kKindWeeBook;
mAtom_CellUses = 0;
mAtom_Change = morkChange_kNil;
mAtom_Size = 0;
mBookAtom_Space = 0;
mBookAtom_Id = inAid;
mWeeBookAtom_Body[ 0 ] = 0;
}
void
morkWeeBookAtom::InitWeeBookAtom(morkEnv* ev, const morkBuf& inBuf,
morkAtomSpace* ioSpace, mork_aid inAid)
{
mAtom_Kind = 0;
mAtom_Change = morkChange_kNil;
if ( ioSpace )
{
if ( inAid )
{
if ( inBuf.mBuf_Fill <= morkAtom_kMaxByteSize )
{
mAtom_CellUses = 0;
mAtom_Kind = morkAtom_kKindWeeBook;
mBookAtom_Space = ioSpace;
mBookAtom_Id = inAid;
mork_size size = inBuf.mBuf_Fill;
mAtom_Size = (mork_u1) size;
if ( size && inBuf.mBuf_Body )
MORK_MEMCPY(mWeeBookAtom_Body, inBuf.mBuf_Body, size);
mWeeBookAtom_Body[ size ] = 0;
}
else
this->AtomSizeOverflowError(ev);
}
else
this->ZeroAidError(ev);
}
else
ev->NilPointerError();
}
void
morkBigBookAtom::InitBigBookAtom(morkEnv* ev, const morkBuf& inBuf,
mork_cscode inForm, morkAtomSpace* ioSpace, mork_aid inAid)
{
mAtom_Kind = 0;
mAtom_Change = morkChange_kNil;
if ( ioSpace )
{
if ( inAid )
{
mAtom_CellUses = 0;
mAtom_Kind = morkAtom_kKindBigBook;
mAtom_Size = 0;
mBookAtom_Space = ioSpace;
mBookAtom_Id = inAid;
mBigBookAtom_Form = inForm;
mork_size size = inBuf.mBuf_Fill;
mBigBookAtom_Size = size;
if ( size && inBuf.mBuf_Body )
MORK_MEMCPY(mBigBookAtom_Body, inBuf.mBuf_Body, size);
mBigBookAtom_Body[ size ] = 0;
}
else
this->ZeroAidError(ev);
}
else
ev->NilPointerError();
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,337 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKATOM_
#define _MORKATOM_ 1
#ifndef _MORK_
#include "mork.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkAtom_kMaxByteSize 255 /* max for 8-bit integer */
#define morkAtom_kForeverCellUses 0x0FF /* max for 8-bit integer */
#define morkAtom_kMaxCellUses 0x07F /* max for 7-bit integer */
#define morkAtom_kKindWeeAnon 'a' /* means morkWeeAnonAtom subclass */
#define morkAtom_kKindBigAnon 'A' /* means morkBigAnonAtom subclass */
#define morkAtom_kKindWeeBook 'b' /* means morkWeeBookAtom subclass */
#define morkAtom_kKindBigBook 'B' /* means morkBigBookAtom subclass */
#define morkAtom_kKindRowOid 'r' /* means morkOidAtom subclass */
#define morkAtom_kKindTableOid 't' /* means morkOidAtom subclass */
/*| Atom: .
|*/
class morkAtom { //
public:
mork_u1 mAtom_Kind; // identifies a specific atom subclass
mork_u1 mAtom_CellUses; // number of persistent uses in a cell
mork_change mAtom_Change; // how has this atom been changed?
mork_u1 mAtom_Size; // only for atoms smaller than 256 bytes
public:
morkAtom(mork_aid inAid, mork_u1 inKind);
mork_bool IsWeeAnon() const { return mAtom_Kind == morkAtom_kKindWeeAnon; }
mork_bool IsBigAnon() const { return mAtom_Kind == morkAtom_kKindBigAnon; }
mork_bool IsWeeBook() const { return mAtom_Kind == morkAtom_kKindWeeBook; }
mork_bool IsBigBook() const { return mAtom_Kind == morkAtom_kKindBigBook; }
mork_bool IsRowOid() const { return mAtom_Kind == morkAtom_kKindRowOid; }
mork_bool IsTableOid() const { return mAtom_Kind == morkAtom_kKindTableOid; }
mork_bool IsBook() const { return this->IsWeeBook() || this->IsBigBook(); }
public: // clean vs dirty
void SetAtomClean() { mAtom_Change = morkChange_kNil; }
void SetAtomDirty() { mAtom_Change = morkChange_kAdd; }
mork_bool IsAtomClean() const { return mAtom_Change == morkChange_kNil; }
mork_bool IsAtomDirty() const { return mAtom_Change == morkChange_kAdd; }
public: // atom space scope if IsBook() is true, or else zero:
mork_scope GetBookAtomSpaceScope(morkEnv* ev) const;
// zero or book's space's scope
mork_aid GetBookAtomAid() const;
// zero or book atom's ID
public: // empty construction does nothing
morkAtom() { }
public: // one-byte refcounting, freezing at maximum
void MakeCellUseForever(morkEnv* ev);
mork_u1 AddCellUse(morkEnv* ev);
mork_u1 CutCellUse(morkEnv* ev);
mork_bool IsCellUseForever() const
{ return mAtom_CellUses == morkAtom_kForeverCellUses; }
private: // warnings
static void CellUsesUnderflowWarning(morkEnv* ev);
public: // errors
static void BadAtomKindError(morkEnv* ev);
static void ZeroAidError(morkEnv* ev);
static void AtomSizeOverflowError(morkEnv* ev);
public: // yarns
mork_bool AsBuf(morkBuf& outBuf) const;
mork_bool AliasYarn(mdbYarn* outYarn) const;
mork_bool GetYarn(mdbYarn* outYarn) const;
private: // copying is not allowed
morkAtom(const morkAtom& other);
morkAtom& operator=(const morkAtom& other);
};
/*| OidAtom: an atom that references a row or table by identity.
|*/
class morkOidAtom : public morkAtom { //
// mork_u1 mAtom_Kind; // identifies a specific atom subclass
// mork_u1 mAtom_CellUses; // number of persistent uses in a cell
// mork_change mAtom_Change; // how has this atom been changed?
// mork_u1 mAtom_Size; // NOT USED IN "BIG" format atoms
public:
mdbOid mOidAtom_Oid; // identity of referenced object
public: // empty construction does nothing
morkOidAtom() { }
void InitRowOidAtom(morkEnv* ev, const mdbOid& inOid);
void InitTableOidAtom(morkEnv* ev, const mdbOid& inOid);
private: // copying is not allowed
morkOidAtom(const morkOidAtom& other);
morkOidAtom& operator=(const morkOidAtom& other);
};
/*| WeeAnonAtom: an atom whose content immediately follows morkAtom slots
**| in an inline fashion, so that morkWeeAnonAtom contains both leading
**| atom slots and then the content bytes without further overhead. Note
**| that charset encoding is not indicated, so zero is implied for Latin1.
**| (Non-Latin1 content must be stored in a morkBigAnonAtom with a charset.)
**|
**|| An anon (anonymous) atom has no identity, with no associated bookkeeping
**| for lookup needed for sharing like a book atom.
**|
**|| A wee anon atom is immediate but not shared with any other users of this
**| atom, so no bookkeeping for sharing is needed. This means the atom has
**| no ID, because the atom has no identity other than this immediate content,
**| and no hash table is needed to look up this particular atom. This also
**| applies to the larger format morkBigAnonAtom, which has more slots.
|*/
class morkWeeAnonAtom : public morkAtom { //
// mork_u1 mAtom_Kind; // identifies a specific atom subclass
// mork_u1 mAtom_CellUses; // number of persistent uses in a cell
// mork_change mAtom_Change; // how has this atom been changed?
// mork_u1 mAtom_Size; // only for atoms smaller than 256 bytes
public:
mork_u1 mWeeAnonAtom_Body[ 1 ]; // 1st byte of immediate content vector
public: // empty construction does nothing
morkWeeAnonAtom() { }
void InitWeeAnonAtom(morkEnv* ev, const morkBuf& inBuf);
// allow extra trailing byte for a null byte:
static mork_size SizeForFill(mork_fill inFill)
{ return sizeof(morkWeeAnonAtom) + inFill; }
private: // copying is not allowed
morkWeeAnonAtom(const morkWeeAnonAtom& other);
morkWeeAnonAtom& operator=(const morkWeeAnonAtom& other);
};
/*| BigAnonAtom: another immediate atom that cannot be encoded as the smaller
**| morkWeeAnonAtom format because either the size is too great, and/or the
**| charset is not the default zero for Latin1 and must be explicitly noted.
**|
**|| An anon (anonymous) atom has no identity, with no associated bookkeeping
**| for lookup needed for sharing like a book atom.
|*/
class morkBigAnonAtom : public morkAtom { //
// mork_u1 mAtom_Kind; // identifies a specific atom subclass
// mork_u1 mAtom_CellUses; // number of persistent uses in a cell
// mork_change mAtom_Change; // how has this atom been changed?
// mork_u1 mAtom_Size; // NOT USED IN "BIG" format atoms
public:
mork_cscode mBigAnonAtom_Form; // charset format encoding
mork_size mBigAnonAtom_Size; // size of content vector
mork_u1 mBigAnonAtom_Body[ 1 ]; // 1st byte of immed content vector
public: // empty construction does nothing
morkBigAnonAtom() { }
void InitBigAnonAtom(morkEnv* ev, const morkBuf& inBuf, mork_cscode inForm);
// allow extra trailing byte for a null byte:
static mork_size SizeForFill(mork_fill inFill)
{ return sizeof(morkBigAnonAtom) + inFill; }
private: // copying is not allowed
morkBigAnonAtom(const morkBigAnonAtom& other);
morkBigAnonAtom& operator=(const morkBigAnonAtom& other);
};
#define morkBookAtom_kMaxBodySize 1024 /* if larger, cannot be shared */
/*| BookAtom: the common subportion of wee book atoms and big book atoms that
**| includes the atom ID and the pointer to the space referencing this atom
**| through a hash table.
|*/
class morkBookAtom : public morkAtom { //
// mork_u1 mAtom_Kind; // identifies a specific atom subclass
// mork_u1 mAtom_CellUses; // number of persistent uses in a cell
// mork_change mAtom_Change; // how has this atom been changed?
// mork_u1 mAtom_Size; // only for atoms smaller than 256 bytes
public:
morkAtomSpace* mBookAtom_Space; // mBookAtom_Space->mSpace_Scope is atom scope
mork_aid mBookAtom_Id; // identity token for this shared atom
public: // empty construction does nothing
morkBookAtom() { }
static void NonBookAtomTypeError(morkEnv* ev);
public: // Hash() and Equal() for atom ID maps are same for all subclasses:
mork_u4 HashAid() const { return mBookAtom_Id; }
mork_bool EqualAid(const morkBookAtom* inAtom) const
{ return ( mBookAtom_Id == inAtom->mBookAtom_Id); }
public: // Hash() and Equal() for atom body maps know about subclasses:
mork_u4 HashFormAndBody(morkEnv* ev) const;
mork_bool EqualFormAndBody(morkEnv* ev, const morkBookAtom* inAtom) const;
public: // separation from containing space
void CutBookAtomFromSpace(morkEnv* ev);
private: // copying is not allowed
morkBookAtom(const morkBookAtom& other);
morkBookAtom& operator=(const morkBookAtom& other);
};
/*| WeeBookAtom: .
|*/
class morkWeeBookAtom : public morkBookAtom { //
// mork_u1 mAtom_Kind; // identifies a specific atom subclass
// mork_u1 mAtom_CellUses; // number of persistent uses in a cell
// mork_change mAtom_Change; // how has this atom been changed?
// mork_u1 mAtom_Size; // only for atoms smaller than 256 bytes
// morkAtomSpace* mBookAtom_Space; // mBookAtom_Space->mSpace_Scope is scope
// mork_aid mBookAtom_Id; // identity token for this shared atom
public:
mork_u1 mWeeBookAtom_Body[ 1 ]; // 1st byte of immed content vector
public: // empty construction does nothing
morkWeeBookAtom() { }
morkWeeBookAtom(mork_aid inAid);
void InitWeeBookAtom(morkEnv* ev, const morkBuf& inBuf,
morkAtomSpace* ioSpace, mork_aid inAid);
// allow extra trailing byte for a null byte:
static mork_size SizeForFill(mork_fill inFill)
{ return sizeof(morkWeeBookAtom) + inFill; }
private: // copying is not allowed
morkWeeBookAtom(const morkWeeBookAtom& other);
morkWeeBookAtom& operator=(const morkWeeBookAtom& other);
};
/*| BigBookAtom: .
|*/
class morkBigBookAtom : public morkBookAtom { //
// mork_u1 mAtom_Kind; // identifies a specific atom subclass
// mork_u1 mAtom_CellUses; // number of persistent uses in a cell
// mork_change mAtom_Change; // how has this atom been changed?
// mork_u1 mAtom_Size; // NOT USED IN "BIG" format atoms
// morkAtomSpace* mBookAtom_Space; // mBookAtom_Space->mSpace_Scope is scope
// mork_aid mBookAtom_Id; // identity token for this shared atom
public:
mork_cscode mBigBookAtom_Form; // charset format encoding
mork_size mBigBookAtom_Size; // size of content vector
mork_u1 mBigBookAtom_Body[ 1 ]; // 1st byte of immed content vector
public: // empty construction does nothing
morkBigBookAtom() { }
void InitBigBookAtom(morkEnv* ev, const morkBuf& inBuf,
mork_cscode inForm, morkAtomSpace* ioSpace, mork_aid inAid);
// allow extra trailing byte for a null byte:
static mork_size SizeForFill(mork_fill inFill)
{ return sizeof(morkBigBookAtom) + inFill; }
private: // copying is not allowed
morkBigBookAtom(const morkBigBookAtom& other);
morkBigBookAtom& operator=(const morkBigBookAtom& other);
};
/*| MaxBookAtom: .
|*/
class morkMaxBookAtom : public morkBigBookAtom { //
// mork_u1 mAtom_Kind; // identifies a specific atom subclass
// mork_u1 mAtom_CellUses; // number of persistent uses in a cell
// mork_change mAtom_Change; // how has this atom been changed?
// mork_u1 mAtom_Size; // NOT USED IN "BIG" format atoms
// morkAtomSpace* mBookAtom_Space; // mBookAtom_Space->mSpace_Scope is scope
// mork_aid mBookAtom_Id; // identity token for this shared atom
// mork_cscode mBigBookAtom_Form; // charset format encoding
// mork_size mBigBookAtom_Size; // size of content vector
// mork_u1 mBigBookAtom_Body[ 1 ]; // 1st byte of immed content vector
public:
mork_u1 mMaxBookAtom_Body[ morkBookAtom_kMaxBodySize + 3 ]; // max bytes
public: // empty construction does nothing
morkMaxBookAtom() { }
void InitMaxBookAtom(morkEnv* ev, const morkBuf& inBuf,
mork_cscode inForm, morkAtomSpace* ioSpace, mork_aid inAid)
{ this->InitBigBookAtom(ev, inBuf, inForm, ioSpace, inAid); }
private: // copying is not allowed
morkMaxBookAtom(const morkMaxBookAtom& other);
morkMaxBookAtom& operator=(const morkMaxBookAtom& other);
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKATOM_ */

View File

@@ -1,305 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
#ifndef _MORKATOMMAP_
#include "morkAtomMap.h"
#endif
#ifndef _MORKATOM_
#include "morkAtom.h"
#endif
#ifndef _MORKINTMAP_
#include "morkIntMap.h"
#endif
#ifndef _MORKROW_
#include "morkRow.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkAtomAidMap::CloseMorkNode(morkEnv* ev) // CloseAtomAidMap() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseAtomAidMap(ev);
this->MarkShut();
}
}
/*public virtual*/
morkAtomAidMap::~morkAtomAidMap() // assert CloseAtomAidMap() executed earlier
{
MORK_ASSERT(this->IsShutNode());
}
/*public non-poly*/
morkAtomAidMap::morkAtomAidMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
: morkMap(ev, inUsage, ioHeap,
/*inKeySize*/ sizeof(morkBookAtom*), /*inValSize*/ 0,
morkAtomAidMap_kStartSlotCount, ioSlotHeap,
/*inHoldChanges*/ morkBool_kFalse)
{
if ( ev->Good() )
mNode_Derived = morkDerived_kAtomAidMap;
}
/*public non-poly*/ void
morkAtomAidMap::CloseAtomAidMap(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
this->CloseMap(ev);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
// { ===== begin morkMap poly interface =====
/*virtual*/ mork_bool //
morkAtomAidMap::Equal(morkEnv* ev, const void* inKeyA,
const void* inKeyB) const
{
MORK_USED_1(ev);
return (*(const morkBookAtom**) inKeyA)->EqualAid(
*(const morkBookAtom**) inKeyB);
}
/*virtual*/ mork_u4 //
morkAtomAidMap::Hash(morkEnv* ev, const void* inKey) const
{
MORK_USED_1(ev);
return (*(const morkBookAtom**) inKey)->HashAid();
}
// } ===== end morkMap poly interface =====
mork_bool
morkAtomAidMap::AddAtom(morkEnv* ev, morkBookAtom* ioAtom)
{
if ( ev->Good() )
{
this->Put(ev, &ioAtom, /*val*/ (void*) 0,
/*key*/ (void*) 0, /*val*/ (void*) 0, (mork_change**) 0);
}
return ev->Good();
}
morkBookAtom*
morkAtomAidMap::CutAtom(morkEnv* ev, const morkBookAtom* inAtom)
{
morkBookAtom* oldKey = 0;
this->Cut(ev, &inAtom, &oldKey, /*val*/ (void*) 0,
(mork_change**) 0);
return oldKey;
}
morkBookAtom*
morkAtomAidMap::GetAtom(morkEnv* ev, const morkBookAtom* inAtom)
{
morkBookAtom* key = 0; // old val in the map
this->Get(ev, &inAtom, &key, /*val*/ (void*) 0, (mork_change**) 0);
return key;
}
morkBookAtom*
morkAtomAidMap::GetAid(morkEnv* ev, mork_aid inAid)
{
morkWeeBookAtom weeAtom(inAid);
morkBookAtom* key = &weeAtom; // we need a pointer
morkBookAtom* oldKey = 0; // old key in the map
this->Get(ev, &key, &oldKey, /*val*/ (void*) 0, (mork_change**) 0);
return oldKey;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkAtomBodyMap::CloseMorkNode(morkEnv* ev) // CloseAtomBodyMap() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseAtomBodyMap(ev);
this->MarkShut();
}
}
/*public virtual*/
morkAtomBodyMap::~morkAtomBodyMap() // assert CloseAtomBodyMap() executed earlier
{
MORK_ASSERT(this->IsShutNode());
}
/*public non-poly*/
morkAtomBodyMap::morkAtomBodyMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
: morkMap(ev, inUsage, ioHeap,
/*inKeySize*/ sizeof(morkBookAtom*), /*inValSize*/ 0,
morkAtomBodyMap_kStartSlotCount, ioSlotHeap,
/*inHoldChanges*/ morkBool_kFalse)
{
if ( ev->Good() )
mNode_Derived = morkDerived_kAtomBodyMap;
}
/*public non-poly*/ void
morkAtomBodyMap::CloseAtomBodyMap(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
this->CloseMap(ev);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
// { ===== begin morkMap poly interface =====
/*virtual*/ mork_bool //
morkAtomBodyMap::Equal(morkEnv* ev, const void* inKeyA,
const void* inKeyB) const
{
return (*(const morkBookAtom**) inKeyA)->EqualFormAndBody(ev,
*(const morkBookAtom**) inKeyB);
}
/*virtual*/ mork_u4 //
morkAtomBodyMap::Hash(morkEnv* ev, const void* inKey) const
{
return (*(const morkBookAtom**) inKey)->HashFormAndBody(ev);
}
// } ===== end morkMap poly interface =====
mork_bool
morkAtomBodyMap::AddAtom(morkEnv* ev, morkBookAtom* ioAtom)
{
if ( ev->Good() )
{
this->Put(ev, &ioAtom, /*val*/ (void*) 0,
/*key*/ (void*) 0, /*val*/ (void*) 0, (mork_change**) 0);
}
return ev->Good();
}
morkBookAtom*
morkAtomBodyMap::CutAtom(morkEnv* ev, const morkBookAtom* inAtom)
{
morkBookAtom* oldKey = 0;
this->Cut(ev, &inAtom, &oldKey, /*val*/ (void*) 0,
(mork_change**) 0);
return oldKey;
}
morkBookAtom*
morkAtomBodyMap::GetAtom(morkEnv* ev, const morkBookAtom* inAtom)
{
morkBookAtom* key = 0; // old val in the map
this->Get(ev, &inAtom, &key, /*val*/ (void*) 0, (mork_change**) 0);
return key;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
morkAtomRowMap::~morkAtomRowMap()
{
}
morkAtomRowMap::morkAtomRowMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap, mork_column inIndexColumn)
: morkIntMap(ev, inUsage, sizeof(mork_aid), ioHeap, ioSlotHeap,
/*inHoldChanges*/ morkBool_kFalse)
, mAtomRowMap_IndexColumn( inIndexColumn )
{
if ( ev->Good() )
mNode_Derived = morkDerived_kAtomRowMap;
}
void morkAtomRowMap::AddRow(morkEnv* ev, morkRow* ioRow)
// add ioRow only if it contains a cell in mAtomRowMap_IndexColumn.
{
mork_aid aid = ioRow->GetCellAtomAid(ev, mAtomRowMap_IndexColumn);
if ( aid )
this->AddAid(ev, aid, ioRow);
}
void morkAtomRowMap::CutRow(morkEnv* ev, morkRow* ioRow)
// cut ioRow only if it contains a cell in mAtomRowMap_IndexColumn.
{
mork_aid aid = ioRow->GetCellAtomAid(ev, mAtomRowMap_IndexColumn);
if ( aid )
this->CutAid(ev, aid);
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,291 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKATOMMAP_
#define _MORKATOMMAP_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
#ifndef _MORKINTMAP_
#include "morkIntMap.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kAtomAidMap /*i*/ 0x6141 /* ascii 'aA' */
#define morkAtomAidMap_kStartSlotCount 512
/*| morkAtomAidMap: keys of morkBookAtom organized by atom ID
|*/
class morkAtomAidMap : public morkMap { // for mapping tokens to maps
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseAtomAidMap() only if open
virtual ~morkAtomAidMap(); // assert that CloseAtomAidMap() executed earlier
public: // morkMap construction & destruction
morkAtomAidMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap);
void CloseAtomAidMap(morkEnv* ev); // called by CloseMorkNode();
public: // dynamic type identification
mork_bool IsAtomAidMap() const
{ return IsNode() && mNode_Derived == morkDerived_kAtomAidMap; }
// } ===== end morkNode methods =====
// { ===== begin morkMap poly interface =====
virtual mork_bool // note: equal(a,b) implies hash(a) == hash(b)
Equal(morkEnv* ev, const void* inKeyA, const void* inKeyB) const;
// implemented using morkBookAtom::HashAid()
virtual mork_u4 // note: equal(a,b) implies hash(a) == hash(b)
Hash(morkEnv* ev, const void* inKey) const;
// implemented using morkBookAtom::EqualAid()
// } ===== end morkMap poly interface =====
public: // other map methods
mork_bool AddAtom(morkEnv* ev, morkBookAtom* ioAtom);
// AddAtom() returns ev->Good()
morkBookAtom* CutAtom(morkEnv* ev, const morkBookAtom* inAtom);
// CutAtom() returns the atom removed equal to inAtom, if there was one
morkBookAtom* GetAtom(morkEnv* ev, const morkBookAtom* inAtom);
// GetAtom() returns the atom equal to inAtom, or else nil
morkBookAtom* GetAid(morkEnv* ev, mork_aid inAid);
// GetAid() returns the atom equal to inAid, or else nil
// note the atoms are owned elsewhere, usuall by morkAtomSpace
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakAtomAidMap(morkAtomAidMap* me,
morkEnv* ev, morkAtomAidMap** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongAtomAidMap(morkAtomAidMap* me,
morkEnv* ev, morkAtomAidMap** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
class morkAtomAidMapIter: public morkMapIter{ // typesafe wrapper class
public:
morkAtomAidMapIter(morkEnv* ev, morkAtomAidMap* ioMap)
: morkMapIter(ev, ioMap) { }
morkAtomAidMapIter( ) : morkMapIter() { }
void InitAtomAidMapIter(morkEnv* ev, morkAtomAidMap* ioMap)
{ this->InitMapIter(ev, ioMap); }
mork_change* FirstAtom(morkEnv* ev, morkBookAtom** outAtomPtr)
{ return this->First(ev, outAtomPtr, /*val*/ (void*) 0); }
mork_change* NextAtom(morkEnv* ev, morkBookAtom** outAtomPtr)
{ return this->Next(ev, outAtomPtr, /*val*/ (void*) 0); }
mork_change* HereAtom(morkEnv* ev, morkBookAtom** outAtomPtr)
{ return this->Here(ev, outAtomPtr, /*val*/ (void*) 0); }
mork_change* CutHereAtom(morkEnv* ev, morkBookAtom** outAtomPtr)
{ return this->CutHere(ev, outAtomPtr, /*val*/ (void*) 0); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kAtomBodyMap /*i*/ 0x6142 /* ascii 'aB' */
#define morkAtomBodyMap_kStartSlotCount 512
/*| morkAtomBodyMap: keys of morkBookAtom organized by body bytes
|*/
class morkAtomBodyMap : public morkMap { // for mapping tokens to maps
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseAtomBodyMap() only if open
virtual ~morkAtomBodyMap(); // assert CloseAtomBodyMap() executed earlier
public: // morkMap construction & destruction
morkAtomBodyMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap);
void CloseAtomBodyMap(morkEnv* ev); // called by CloseMorkNode();
public: // dynamic type identification
mork_bool IsAtomBodyMap() const
{ return IsNode() && mNode_Derived == morkDerived_kAtomBodyMap; }
// } ===== end morkNode methods =====
// { ===== begin morkMap poly interface =====
virtual mork_bool // note: equal(a,b) implies hash(a) == hash(b)
Equal(morkEnv* ev, const void* inKeyA, const void* inKeyB) const;
// implemented using morkBookAtom::EqualFormAndBody()
virtual mork_u4 // note: equal(a,b) implies hash(a) == hash(b)
Hash(morkEnv* ev, const void* inKey) const;
// implemented using morkBookAtom::HashFormAndBody()
// } ===== end morkMap poly interface =====
public: // other map methods
mork_bool AddAtom(morkEnv* ev, morkBookAtom* ioAtom);
// AddAtom() returns ev->Good()
morkBookAtom* CutAtom(morkEnv* ev, const morkBookAtom* inAtom);
// CutAtom() returns the atom removed equal to inAtom, if there was one
morkBookAtom* GetAtom(morkEnv* ev, const morkBookAtom* inAtom);
// GetAtom() returns the atom equal to inAtom, or else nil
// note the atoms are owned elsewhere, usuall by morkAtomSpace
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakAtomBodyMap(morkAtomBodyMap* me,
morkEnv* ev, morkAtomBodyMap** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongAtomBodyMap(morkAtomBodyMap* me,
morkEnv* ev, morkAtomBodyMap** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
class morkAtomBodyMapIter: public morkMapIter{ // typesafe wrapper class
public:
morkAtomBodyMapIter(morkEnv* ev, morkAtomBodyMap* ioMap)
: morkMapIter(ev, ioMap) { }
morkAtomBodyMapIter( ) : morkMapIter() { }
void InitAtomBodyMapIter(morkEnv* ev, morkAtomBodyMap* ioMap)
{ this->InitMapIter(ev, ioMap); }
mork_change* FirstAtom(morkEnv* ev, morkBookAtom** outAtomPtr)
{ return this->First(ev, outAtomPtr, /*val*/ (void*) 0); }
mork_change* NextAtom(morkEnv* ev, morkBookAtom** outAtomPtr)
{ return this->Next(ev, outAtomPtr, /*val*/ (void*) 0); }
mork_change* HereAtom(morkEnv* ev, morkBookAtom** outAtomPtr)
{ return this->Here(ev, outAtomPtr, /*val*/ (void*) 0); }
mork_change* CutHereAtom(morkEnv* ev, morkBookAtom** outAtomPtr)
{ return this->CutHere(ev, outAtomPtr, /*val*/ (void*) 0); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kAtomRowMap /*i*/ 0x6152 /* ascii 'aR' */
/*| morkAtomRowMap: maps morkAtom* -> morkRow*
|*/
class morkAtomRowMap : public morkIntMap { // for mapping atoms to rows
public:
mork_column mAtomRowMap_IndexColumn; // row column being indexed
public:
virtual ~morkAtomRowMap();
morkAtomRowMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap, mork_column inIndexColumn);
public: // adding and cutting from morkRow instance candidate
void AddRow(morkEnv* ev, morkRow* ioRow);
// add ioRow only if it contains a cell in mAtomRowMap_IndexColumn.
void CutRow(morkEnv* ev, morkRow* ioRow);
// cut ioRow only if it contains a cell in mAtomRowMap_IndexColumn.
public: // other map methods
mork_bool AddAid(morkEnv* ev, mork_aid inAid, morkRow* ioRow)
{ return this->AddInt(ev, inAid, ioRow); }
// the AddAid() boolean return equals ev->Good().
mork_bool CutAid(morkEnv* ev, mork_aid inAid)
{ return this->CutInt(ev, inAid); }
// The CutAid() boolean return indicates whether removal happened.
morkRow* GetAid(morkEnv* ev, mork_aid inAid)
{ return (morkRow*) this->GetInt(ev, inAid); }
// Note the returned space does NOT have an increase in refcount for this.
public: // dynamic type identification
mork_bool IsAtomRowMap() const
{ return IsNode() && mNode_Derived == morkDerived_kAtomRowMap; }
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakAtomRowMap(morkAtomRowMap* me,
morkEnv* ev, morkAtomRowMap** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongAtomRowMap(morkAtomRowMap* me,
morkEnv* ev, morkAtomRowMap** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
class morkAtomRowMapIter: public morkMapIter{ // typesafe wrapper class
public:
morkAtomRowMapIter(morkEnv* ev, morkAtomRowMap* ioMap)
: morkMapIter(ev, ioMap) { }
morkAtomRowMapIter( ) : morkMapIter() { }
void InitAtomRowMapIter(morkEnv* ev, morkAtomRowMap* ioMap)
{ this->InitMapIter(ev, ioMap); }
mork_change*
FirstAtomAndRow(morkEnv* ev, morkAtom** outAtom, morkRow** outRow)
{ return this->First(ev, outAtom, outRow); }
mork_change*
NextAtomAndRow(morkEnv* ev, morkAtom** outAtom, morkRow** outRow)
{ return this->Next(ev, outAtom, outRow); }
mork_change*
HereAtomAndRow(morkEnv* ev, morkAtom** outAtom, morkRow** outRow)
{ return this->Here(ev, outAtom, outRow); }
mork_change*
CutHereAtomAndRow(morkEnv* ev, morkAtom** outAtom, morkRow** outRow)
{ return this->CutHere(ev, outAtom, outRow); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKATOMMAP_ */

View File

@@ -1,275 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
#ifndef _MORKSPACE_
#include "morkSpace.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKSPACE_
#include "morkSpace.h"
#endif
#ifndef _MORKATOMSPACE_
#include "morkAtomSpace.h"
#endif
#ifndef _MORKPOOL_
#include "morkPool.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
#ifndef _MORKATOM_
#include "morkAtom.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkAtomSpace::CloseMorkNode(morkEnv* ev) // CloseAtomSpace() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseAtomSpace(ev);
this->MarkShut();
}
}
/*public virtual*/
morkAtomSpace::~morkAtomSpace() // assert CloseAtomSpace() executed earlier
{
MORK_ASSERT(mAtomSpace_HighUnderId==0);
MORK_ASSERT(mAtomSpace_HighOverId==0);
MORK_ASSERT(this->IsShutNode());
MORK_ASSERT(mAtomSpace_AtomAids.IsShutNode());
MORK_ASSERT(mAtomSpace_AtomBodies.IsShutNode());
}
/*public non-poly*/
morkAtomSpace::morkAtomSpace(morkEnv* ev, const morkUsage& inUsage,
mork_scope inScope, morkStore* ioStore,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
: morkSpace(ev, inUsage, inScope, ioStore, ioHeap, ioSlotHeap)
, mAtomSpace_HighUnderId( morkAtomSpace_kMinUnderId )
, mAtomSpace_HighOverId( morkAtomSpace_kMinOverId )
, mAtomSpace_AtomAids(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioSlotHeap)
, mAtomSpace_AtomBodies(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioSlotHeap)
{
// the morkSpace base constructor handles any dirty propagation
if ( ev->Good() )
mNode_Derived = morkDerived_kAtomSpace;
}
/*public non-poly*/ void
morkAtomSpace::CloseAtomSpace(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
mAtomSpace_AtomBodies.CloseMorkNode(ev);
morkStore* store = mSpace_Store;
if ( store )
this->CutAllAtoms(ev, &store->mStore_Pool);
mAtomSpace_AtomAids.CloseMorkNode(ev);
this->CloseSpace(ev);
mAtomSpace_HighUnderId = 0;
mAtomSpace_HighOverId = 0;
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
/*static*/ void
morkAtomSpace::NonAtomSpaceTypeError(morkEnv* ev)
{
ev->NewError("non morkAtomSpace");
}
mork_num
morkAtomSpace::CutAllAtoms(morkEnv* ev, morkPool* ioPool)
{
if ( this->IsAtomSpaceClean() )
this->MaybeDirtyStoreAndSpace();
mork_num outSlots = mAtomSpace_AtomAids.mMap_Fill;
morkBookAtom* a = 0; // old key atom in the map
mork_change* c = 0;
morkAtomAidMapIter i(ev, &mAtomSpace_AtomAids);
for ( c = i.FirstAtom(ev, &a); c ; c = i.NextAtom(ev, &a) )
{
if ( a )
ioPool->ZapAtom(ev, a);
i.CutHereAtom(ev, /*key*/ (morkBookAtom**) 0);
}
return outSlots;
}
morkBookAtom*
morkAtomSpace::MakeBookAtomCopyWithAid(morkEnv* ev,
const morkBigBookAtom& inAtom, mork_aid inAid)
// Make copy of inAtom and put it in both maps, using specified ID.
{
morkBookAtom* outAtom = 0;
if ( ev->Good() )
{
morkPool* pool = this->GetSpaceStorePool();
outAtom = pool->NewBookAtomCopy(ev, inAtom);
if ( outAtom )
{
if ( mSpace_Store->mStore_CanDirty )
{
outAtom->SetAtomDirty();
if ( this->IsAtomSpaceClean() )
this->MaybeDirtyStoreAndSpace();
}
outAtom->mBookAtom_Id = inAid;
outAtom->mBookAtom_Space = this;
mAtomSpace_AtomAids.AddAtom(ev, outAtom);
mAtomSpace_AtomBodies.AddAtom(ev, outAtom);
if ( mSpace_Scope == morkAtomSpace_kColumnScope )
outAtom->MakeCellUseForever(ev);
if ( mAtomSpace_HighUnderId <= inAid )
mAtomSpace_HighUnderId = inAid + 1;
}
}
return outAtom;
}
morkBookAtom*
morkAtomSpace::MakeBookAtomCopy(morkEnv* ev, const morkBigBookAtom& inAtom)
// make copy of inAtom and put it in both maps, using a new ID as needed.
{
morkBookAtom* outAtom = 0;
morkStore* store = mSpace_Store;
if ( ev->Good() && store )
{
if ( store->mStore_CanAutoAssignAtomIdentity )
{
morkPool* pool = this->GetSpaceStorePool();
morkBookAtom* atom = pool->NewBookAtomCopy(ev, inAtom);
if ( atom )
{
mork_aid id = this->MakeNewAtomId(ev, atom);
if ( id )
{
if ( store->mStore_CanDirty )
{
atom->SetAtomDirty();
if ( this->IsAtomSpaceClean() )
this->MaybeDirtyStoreAndSpace();
}
outAtom = atom;
atom->mBookAtom_Space = this;
mAtomSpace_AtomAids.AddAtom(ev, atom);
mAtomSpace_AtomBodies.AddAtom(ev, atom);
if ( mSpace_Scope == morkAtomSpace_kColumnScope )
outAtom->MakeCellUseForever(ev);
}
else
pool->ZapAtom(ev, atom);
}
}
else
mSpace_Store->CannotAutoAssignAtomIdentityError(ev);
}
return outAtom;
}
mork_aid
morkAtomSpace::MakeNewAtomId(morkEnv* ev, morkBookAtom* ioAtom)
{
mork_aid outAid = 0;
mork_tid id = mAtomSpace_HighUnderId;
mork_num count = 8; // try up to eight times
while ( !outAid && count ) // still trying to find an unused table ID?
{
--count;
ioAtom->mBookAtom_Id = id;
if ( !mAtomSpace_AtomAids.GetAtom(ev, ioAtom) )
outAid = id;
else
{
MORK_ASSERT(morkBool_kFalse); // alert developer about ID problems
++id;
}
}
mAtomSpace_HighUnderId = id + 1;
return outAid;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
morkAtomSpaceMap::~morkAtomSpaceMap()
{
}
morkAtomSpaceMap::morkAtomSpaceMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
: morkNodeMap(ev, inUsage, ioHeap, ioSlotHeap)
{
if ( ev->Good() )
mNode_Derived = morkDerived_kAtomSpaceMap;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,232 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKATOMSPACE_
#define _MORKATOMSPACE_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKSPACE_
#include "morkSpace.h"
#endif
#ifndef _MORKATOMMAP_
#include "morkAtomMap.h"
#endif
#ifndef _MORKNODEMAP_
#include "morkNodeMap.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/*| kMinUnderId: the smallest ID we auto-assign to the 'under' namespace
**| reserved for tokens expected to occur very frequently, such as the names
**| of columns. We reserve single byte ids in the ASCII range to correspond
**| one-to-one to those tokens consisting single ASCII characters (so that
**| this assignment is always known and constant). So we start at 0x80, and
**| then reserve the upper half of two hex digit ids and all the three hex
**| digit IDs for the 'under' namespace for common tokens.
|*/
#define morkAtomSpace_kMinUnderId 0x80 /* low 7 bits mean byte tokens */
#define morkAtomSpace_kMaxSevenBitAid 0x7F /* low seven bit integer ID */
/*| kMinOverId: the smallest ID we auto-assign to the 'over' namespace that
**| might include very large numbers of tokens that are used infrequently,
**| so that we care less whether the shortest hex representation is used.
**| So we start all IDs for 'over' category tokens at a value range that
**| needs at least four hex digits, so we can reserve three hex digits and
**| shorter for more commonly occuring tokens in the 'under' category.
|*/
#define morkAtomSpace_kMinOverId 0x1000 /* using at least four hex bytes */
#define morkDerived_kAtomSpace /*i*/ 0x6153 /* ascii 'aS' */
#define morkAtomSpace_kColumnScope ((mork_scope) 'c') /* column scope is forever */
/*| morkAtomSpace:
|*/
class morkAtomSpace : public morkSpace { //
// public: // slots inherited from morkSpace (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
// morkStore* mSpace_Store; // weak ref to containing store
// mork_scope mSpace_Scope; // the scope for this space
// mork_bool mSpace_DoAutoIDs; // whether db should assign member IDs
// mork_bool mSpace_HaveDoneAutoIDs; // whether actually auto assigned IDs
// mork_u1 mSpace_Pad[ 2 ]; // pad to u4 alignment
public: // state is public because the entire Mork system is private
mork_aid mAtomSpace_HighUnderId; // high ID in 'under' range
mork_aid mAtomSpace_HighOverId; // high ID in 'over' range
morkAtomAidMap mAtomSpace_AtomAids; // all atoms in space by ID
morkAtomBodyMap mAtomSpace_AtomBodies; // all atoms in space by body
public: // more specific dirty methods for atom space:
void SetAtomSpaceDirty() { this->SetNodeDirty(); }
void SetAtomSpaceClean() { this->SetNodeClean(); }
mork_bool IsAtomSpaceClean() const { return this->IsNodeClean(); }
mork_bool IsAtomSpaceDirty() const { return this->IsNodeDirty(); }
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseAtomSpace() only if open
virtual ~morkAtomSpace(); // assert that CloseAtomSpace() executed earlier
public: // morkMap construction & destruction
morkAtomSpace(morkEnv* ev, const morkUsage& inUsage, mork_scope inScope,
morkStore* ioStore, nsIMdbHeap* ioNodeHeap, nsIMdbHeap* ioSlotHeap);
void CloseAtomSpace(morkEnv* ev); // called by CloseMorkNode();
public: // dynamic type identification
mork_bool IsAtomSpace() const
{ return IsNode() && mNode_Derived == morkDerived_kAtomSpace; }
// } ===== end morkNode methods =====
public: // typing
void NonAtomSpaceTypeError(morkEnv* ev);
public: // setup
mork_bool MarkAllAtomSpaceContentDirty(morkEnv* ev);
// MarkAllAtomSpaceContentDirty() visits every space object and marks
// them dirty, including every table, row, cell, and atom. The return
// equals ev->Good(), to show whether any error happened. This method is
// intended for use in the beginning of a "compress commit" which writes
// all store content, whether dirty or not. We dirty everything first so
// that later iterations over content can mark things clean as they are
// written, and organize the process of serialization so that objects are
// written only at need (because of being dirty).
public: // other space methods
// void ReserveColumnAidCount(mork_count inCount)
// {
// mAtomSpace_HighUnderId = morkAtomSpace_kMinUnderId + inCount;
// mAtomSpace_HighOverId = morkAtomSpace_kMinOverId + inCount;
// }
mork_num CutAllAtoms(morkEnv* ev, morkPool* ioPool);
// CutAllAtoms() puts all the atoms back in the pool.
morkBookAtom* MakeBookAtomCopyWithAid(morkEnv* ev,
const morkBigBookAtom& inAtom, mork_aid inAid);
// Make copy of inAtom and put it in both maps, using specified ID.
morkBookAtom* MakeBookAtomCopy(morkEnv* ev, const morkBigBookAtom& inAtom);
// Make copy of inAtom and put it in both maps, using a new ID as needed.
mork_aid MakeNewAtomId(morkEnv* ev, morkBookAtom* ioAtom);
// generate an unused atom id.
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakAtomSpace(morkAtomSpace* me,
morkEnv* ev, morkAtomSpace** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongAtomSpace(morkAtomSpace* me,
morkEnv* ev, morkAtomSpace** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kAtomSpaceMap /*i*/ 0x615A /* ascii 'aZ' */
/*| morkAtomSpaceMap: maps mork_scope -> morkAtomSpace
|*/
class morkAtomSpaceMap : public morkNodeMap { // for mapping tokens to tables
public:
virtual ~morkAtomSpaceMap();
morkAtomSpaceMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap);
public: // other map methods
mork_bool AddAtomSpace(morkEnv* ev, morkAtomSpace* ioAtomSpace)
{ return this->AddNode(ev, ioAtomSpace->mSpace_Scope, ioAtomSpace); }
// the AddAtomSpace() boolean return equals ev->Good().
mork_bool CutAtomSpace(morkEnv* ev, mork_scope inScope)
{ return this->CutNode(ev, inScope); }
// The CutAtomSpace() boolean return indicates whether removal happened.
morkAtomSpace* GetAtomSpace(morkEnv* ev, mork_scope inScope)
{ return (morkAtomSpace*) this->GetNode(ev, inScope); }
// Note the returned space does NOT have an increase in refcount for this.
mork_num CutAllAtomSpaces(morkEnv* ev)
{ return this->CutAllNodes(ev); }
// CutAllAtomSpaces() releases all the referenced table values.
};
class morkAtomSpaceMapIter: public morkMapIter{ // typesafe wrapper class
public:
morkAtomSpaceMapIter(morkEnv* ev, morkAtomSpaceMap* ioMap)
: morkMapIter(ev, ioMap) { }
morkAtomSpaceMapIter( ) : morkMapIter() { }
void InitAtomSpaceMapIter(morkEnv* ev, morkAtomSpaceMap* ioMap)
{ this->InitMapIter(ev, ioMap); }
mork_change*
FirstAtomSpace(morkEnv* ev, mork_scope* outScope, morkAtomSpace** outAtomSpace)
{ return this->First(ev, outScope, outAtomSpace); }
mork_change*
NextAtomSpace(morkEnv* ev, mork_scope* outScope, morkAtomSpace** outAtomSpace)
{ return this->Next(ev, outScope, outAtomSpace); }
mork_change*
HereAtomSpace(morkEnv* ev, mork_scope* outScope, morkAtomSpace** outAtomSpace)
{ return this->Here(ev, outScope, outAtomSpace); }
mork_change*
CutHereAtomSpace(morkEnv* ev, mork_scope* outScope, morkAtomSpace** outAtomSpace)
{ return this->CutHere(ev, outScope, outAtomSpace); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKATOMSPACE_ */

View File

@@ -1,123 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKBLOB_
#include "morkBlob.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/*static*/ void
morkBuf::NilBufBodyError(morkEnv* ev)
{
ev->NewError("nil mBuf_Body");
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/*static*/ void
morkBlob::BlobFillOverSizeError(morkEnv* ev)
{
ev->NewError("mBuf_Fill > mBlob_Size");
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
mork_bool
morkBlob::GrowBlob(morkEnv* ev, nsIMdbHeap* ioHeap, mork_size inNewSize)
{
if ( ioHeap )
{
if ( !mBuf_Body ) // no body? implies zero sized?
mBlob_Size = 0;
if ( mBuf_Fill > mBlob_Size ) // fill more than size?
{
ev->NewWarning("mBuf_Fill > mBlob_Size");
mBuf_Fill = mBlob_Size;
}
if ( inNewSize > mBlob_Size ) // need to allocate larger blob?
{
mork_u1* body = 0;
ioHeap->Alloc(ev->AsMdbEnv(), inNewSize, (void**) &body);
if ( body && ev->Good() )
{
void* oldBody = mBuf_Body;
if ( mBlob_Size ) // any old content to transfer?
MORK_MEMCPY(body, oldBody, mBlob_Size);
mBlob_Size = inNewSize; // install new size
mBuf_Body = body; // install new body
if ( oldBody ) // need to free old buffer body?
ioHeap->Free(ev->AsMdbEnv(), oldBody);
}
}
}
else
ev->NilPointerError();
if ( ev->Good() && mBlob_Size < inNewSize )
ev->NewError("mBlob_Size < inNewSize");
return ev->Good();
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
morkCoil::morkCoil(morkEnv* ev, nsIMdbHeap* ioHeap)
{
mBuf_Body = 0;
mBuf_Fill = 0;
mBlob_Size = 0;
mText_Form = 0;
mCoil_Heap = ioHeap;
if ( !ioHeap )
ev->NilPointerError();
}
void
morkCoil::CloseCoil(morkEnv* ev)
{
void* body = mBuf_Body;
nsIMdbHeap* heap = mCoil_Heap;
mBuf_Body = 0;
mCoil_Heap = 0;
if ( body && heap )
{
heap->Free(ev->AsMdbEnv(), body);
}
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,154 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKBLOB_
#define _MORKBLOB_ 1
#ifndef _MORK_
#include "mork.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/*| Buf: the minimum needed to describe location and content length.
**| This is typically only enough to read from this buffer, since
**| one cannot write effectively without knowing the size of a buf.
|*/
class morkBuf { // subset of nsIMdbYarn slots
public:
void* mBuf_Body; // space for holding any binary content
mork_fill mBuf_Fill; // logical content in Buf in bytes
public:
morkBuf() { }
morkBuf(const void* ioBuf, mork_fill inFill)
: mBuf_Body((void*) ioBuf), mBuf_Fill(inFill) { }
void ClearBufFill() { mBuf_Fill = 0; }
static void NilBufBodyError(morkEnv* ev);
private: // copying is not allowed
morkBuf(const morkBuf& other);
morkBuf& operator=(const morkBuf& other);
};
/*| Blob: a buffer with an associated size, to increase known buf info
**| to include max capacity in addition to buf location and content.
**| This form factor allows us to allocate a vector of such blobs,
**| which can share the same managing heap stored elsewhere, and that
**| is why we don't include a pointer to a heap in this blob class.
|*/
class morkBlob : public morkBuf { // greater subset of nsIMdbYarn slots
// void* mBuf_Body; // space for holding any binary content
// mdb_fill mBuf_Fill; // logical content in Buf in bytes
public:
mork_size mBlob_Size; // physical size of Buf in bytes
public:
morkBlob() { }
morkBlob(const void* ioBuf, mork_fill inFill, mork_size inSize)
: morkBuf(ioBuf, inFill), mBlob_Size(inSize) { }
static void BlobFillOverSizeError(morkEnv* ev);
public:
mork_bool GrowBlob(morkEnv* ev, nsIMdbHeap* ioHeap,
mork_size inNewSize);
private: // copying is not allowed
morkBlob(const morkBlob& other);
morkBlob& operator=(const morkBlob& other);
};
/*| Text: a blob with an associated charset annotation, where the
**| charset actually includes the general notion of typing, and not
**| just a specification of character set alone; we want to permit
**| arbitrary charset annotations for ad hoc binary types as well.
**| (We avoid including a nsIMdbHeap pointer in morkText for the same
**| reason morkBlob does: we want minimal size vectors of morkText.)
|*/
class morkText : public morkBlob { // greater subset of nsIMdbYarn slots
// void* mBuf_Body; // space for holding any binary content
// mdb_fill mBuf_Fill; // logical content in Buf in bytes
// mdb_size mBlob_Size; // physical size of Buf in bytes
public:
mork_cscode mText_Form; // charset format encoding
morkText() { }
private: // copying is not allowed
morkText(const morkText& other);
morkText& operator=(const morkText& other);
};
/*| Coil: a text with an associated nsIMdbHeap instance that provides
**| all memory management for the space pointed to by mBuf_Body. (This
**| was the hardest type to give a name in this small class hierarchy,
**| because it's hard to characterize self-management of one's space.)
**| A coil is a self-contained blob that knows how to grow itself as
**| necessary to hold more content when necessary. Coil descends from
**| morkText to include the mText_Form slot, even though this won't be
**| needed always, because we are not as concerned about the overall
**| size of this particular Coil object (if we were concerned about
**| the size of an array of Coil instances, we would not bother with
**| a separate heap pointer for each of them).
**|
**|| A coil makes a good medium in which to stream content as a sink,
**| so we will have a subclass of morkSink called morkCoil that
**| will stream bytes into this self-contained coil object. The name
**| of this morkCoil class derives more from this intended usage than
**| from anything else. The Mork code to parse db content will use
**| coils with associated sinks to accumulate parsed strings.
**|
**|| Heap: this is the heap used for memory allocation. This instance
**| is NOT refcounted, since this coil always assumes the heap is held
**| through a reference elsewhere (for example, through the same object
**| that contains or holds the coil itself. This lack of refcounting
**| is consistent with the fact that morkCoil itself is not refcounted,
**| and is not intended for use as a standalone object.
|*/
class morkCoil : public morkText { // self-managing text blob object
// void* mBuf_Body; // space for holding any binary content
// mdb_fill mBuf_Fill; // logical content in Buf in bytes
// mdb_size mBlob_Size; // physical size of Buf in bytes
// mdb_cscode mText_Form; // charset format encoding
public:
nsIMdbHeap* mCoil_Heap; // storage manager for mBuf_Body pointer
public:
morkCoil(morkEnv* ev, nsIMdbHeap* ioHeap);
void CloseCoil(morkEnv* ev);
mork_bool GrowCoil(morkEnv* ev, mork_size inNewSize)
{ return this->GrowBlob(ev, mCoil_Heap, inNewSize); }
private: // copying is not allowed
morkCoil(const morkCoil& other);
morkCoil& operator=(const morkCoil& other);
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKBLOB_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,316 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKBUILDER_
#define _MORKBUILDER_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKPARSER_
#include "morkParser.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/*| kCellsVecSize: length of cell vector buffer inside morkBuilder
|*/
#define morkBuilder_kCellsVecSize 64
#define morkBuilder_kDefaultBytesPerParseSegment 512 /* plausible to big */
#define morkDerived_kBuilder /*i*/ 0x4275 /* ascii 'Bu' */
class morkBuilder /*d*/ : public morkParser {
// public: // slots inherited from morkParser (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
// nsIMdbHeap* mParser_Heap; // refcounted heap used for allocation
// morkStream* mParser_Stream; // refcounted input stream
// mork_u4 mParser_Tag; // must equal morkParser_kTag
// mork_count mParser_MoreGranularity; // constructor inBytesPerParseSegment
// mork_u4 mParser_State; // state where parser should resume
// after finding ends of group transactions, we can re-seek the start:
// mork_pos mParser_GroupContentStartPos; // start of this group
// mdbOid mParser_TableOid; // table oid if inside a table
// mdbOid mParser_RowOid; // row oid if inside a row
// mork_gid mParser_GroupId; // group ID if inside a group
// mork_bool mParser_InPort; // called OnNewPort but not OnPortEnd?
// mork_bool mParser_InDict; // called OnNewDict but not OnDictEnd?
// mork_bool mParser_InCell; // called OnNewCell but not OnCellEnd?
// mork_bool mParser_InMeta; // called OnNewMeta but not OnMetaEnd?
// morkMid mParser_Mid; // current alias being parsed
// note that mParser_Mid.mMid_Buf points at mParser_ScopeCoil below:
// blob coils allocated in mParser_Heap
// morkCoil mParser_ScopeCoil; // place to accumulate ID scope blobs
// morkCoil mParser_ValueCoil; // place to accumulate value blobs
// morkCoil mParser_ColumnCoil; // place to accumulate column blobs
// morkCoil mParser_StringCoil; // place to accumulate string blobs
// morkSpool mParser_ScopeSpool; // writes to mParser_ScopeCoil
// morkSpool mParser_ValueSpool; // writes to mParser_ValueCoil
// morkSpool mParser_ColumnSpool; // writes to mParser_ColumnCoil
// morkSpool mParser_StringSpool; // writes to mParser_StringCoil
// yarns allocated in mParser_Heap
// morkYarn mParser_MidYarn; // place to receive from MidToYarn()
// span showing current ongoing file position status:
// morkSpan mParser_PortSpan; // span of current db port file
// various spans denoting nested subspaces inside the file's port span:
// morkSpan mParser_GroupSpan; // span of current transaction group
// morkSpan mParser_DictSpan;
// morkSpan mParser_AliasSpan;
// morkSpan mParser_MetaDictSpan;
// morkSpan mParser_TableSpan;
// morkSpan mParser_MetaTableSpan;
// morkSpan mParser_RowSpan;
// morkSpan mParser_MetaRowSpan;
// morkSpan mParser_CellSpan;
// morkSpan mParser_ColumnSpan;
// morkSpan mParser_SlotSpan;
// ````` ````` ````` ````` ````` ````` ````` `````
protected: // protected morkBuilder members
// weak refs that do not prevent closure of referenced nodes:
morkStore* mBuilder_Store; // weak ref to builder's store
// strong refs that do indeed prevent closure of referenced nodes:
morkTable* mBuilder_Table; // current table being built (or nil)
morkRow* mBuilder_Row; // current row being built (or nil)
morkCell* mBuilder_Cell; // current cell within CellsVec (or nil)
morkRowSpace* mBuilder_RowSpace; // space for mBuilder_CellRowScope
morkAtomSpace* mBuilder_AtomSpace; // space for mBuilder_CellAtomScope
morkAtomSpace* mBuilder_OidAtomSpace; // ground atom space for oids
morkAtomSpace* mBuilder_ScopeAtomSpace; // ground atom space for scopes
// scoped object ids for current objects under construction:
mdbOid mBuilder_TableOid; // full oid for current table
mdbOid mBuilder_RowOid; // full oid for current row
// tokens that become set as the result of meta cells in port rows:
mork_cscode mBuilder_PortForm; // default port charset format
mork_scope mBuilder_PortRowScope; // port row scope
mork_scope mBuilder_PortAtomScope; // port atom scope
// tokens that become set as the result of meta cells in meta tables:
mork_cscode mBuilder_TableForm; // default table charset format
mork_scope mBuilder_TableRowScope; // table row scope
mork_scope mBuilder_TableAtomScope; // table atom scope
mork_kind mBuilder_TableKind; // table kind
mork_token mBuilder_TableStatus; // dummy: priority/unique/verbose
mork_priority mBuilder_TablePriority; // table priority
mork_bool mBuilder_TableIsUnique; // table uniqueness
mork_bool mBuilder_TableIsVerbose; // table verboseness
mork_u1 mBuilder_TablePadByte; // for u4 alignment
// tokens that become set as the result of meta cells in meta rows:
mork_cscode mBuilder_RowForm; // default row charset format
mork_scope mBuilder_RowRowScope; // row scope per row metainfo
mork_scope mBuilder_RowAtomScope; // row atom scope
// meta tokens currently in force, driven by meta info slots above:
mork_cscode mBuilder_CellForm; // cell charset format
mork_scope mBuilder_CellAtomScope; // cell atom scope
mork_cscode mBuilder_DictForm; // dict charset format
mork_scope mBuilder_DictAtomScope; // dict atom scope
mork_token* mBuilder_MetaTokenSlot; // pointer to some slot above
// If any of these 'cut' bools are true, it means a minus was seen in the
// Mork source text to indicate removal of content from some container.
// (Note there is no corresponding 'add' bool, since add is the default.)
// CutRow implies the current row should be cut from the table.
// CutCell implies the current column should be cut from the row.
mork_bool mBuilder_DoCutRow; // row with kCut change
mork_bool mBuilder_DoCutCell; // cell with kCut change
mork_u1 mBuilder_row_pad; // pad to u4 alignment
mork_u1 mBuilder_cell_pad; // pad to u4 alignment
morkCell mBuilder_CellsVec[ morkBuilder_kCellsVecSize + 1 ];
mork_fill mBuilder_CellsVecFill; // count used in CellsVec
// Note when mBuilder_CellsVecFill equals morkBuilder_kCellsVecSize, and
// another cell is added, this means all the cells in the vector above
// must be flushed to the current row being built to create more room.
protected: // protected inlines
mork_bool CellVectorIsFull() const
{ return ( mBuilder_CellsVecFill == morkBuilder_kCellsVecSize ); };
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseBuilder() only if open
virtual ~morkBuilder(); // assert that CloseBuilder() executed earlier
public: // morkYarn construction & destruction
morkBuilder(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap,
morkStream* ioStream, // the readonly stream for input bytes
mdb_count inBytesPerParseSegment, // target for ParseMore()
nsIMdbHeap* ioSlotHeap, morkStore* ioStore
);
void CloseBuilder(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkBuilder(const morkBuilder& other);
morkBuilder& operator=(const morkBuilder& other);
public: // dynamic type identification
mork_bool IsBuilder() const
{ return IsNode() && mNode_Derived == morkDerived_kBuilder; }
// } ===== end morkNode methods =====
public: // errors
static void NonBuilderTypeError(morkEnv* ev);
static void NilBuilderCellError(morkEnv* ev);
static void NilBuilderRowError(morkEnv* ev);
static void NilBuilderTableError(morkEnv* ev);
static void NonColumnSpaceScopeError(morkEnv* ev);
void LogGlitch(morkEnv* ev, const morkGlitch& inGlitch,
const char* inKind);
public: // other builder methods
morkCell* AddBuilderCell(morkEnv* ev,
const morkMid& inMid, mork_change inChange);
void FlushBuilderCells(morkEnv* ev);
// ````` ````` ````` ````` ````` ````` ````` `````
public: // in virtual morkParser methods, data flow subclass to parser
virtual void MidToYarn(morkEnv* ev,
const morkMid& inMid, // typically an alias to concat with strings
mdbYarn* outYarn);
// The parser might ask that some aliases be turned into yarns, so they
// can be concatenated into longer blobs under some circumstances. This
// is an alternative to using a long and complex callback for many parts
// for a single cell value.
// ````` ````` ````` ````` ````` ````` ````` `````
public: // out virtual morkParser methods, data flow parser to subclass
virtual void OnNewPort(morkEnv* ev, const morkPlace& inPlace);
virtual void OnPortGlitch(morkEnv* ev, const morkGlitch& inGlitch);
virtual void OnPortEnd(morkEnv* ev, const morkSpan& inSpan);
virtual void OnNewGroup(morkEnv* ev, const morkPlace& inPlace, mork_gid inGid);
virtual void OnGroupGlitch(morkEnv* ev, const morkGlitch& inGlitch);
virtual void OnGroupCommitEnd(morkEnv* ev, const morkSpan& inSpan);
virtual void OnGroupAbortEnd(morkEnv* ev, const morkSpan& inSpan);
virtual void OnNewPortRow(morkEnv* ev, const morkPlace& inPlace,
const morkMid& inMid, mork_change inChange);
virtual void OnPortRowGlitch(morkEnv* ev, const morkGlitch& inGlitch);
virtual void OnPortRowEnd(morkEnv* ev, const morkSpan& inSpan);
virtual void OnNewTable(morkEnv* ev, const morkPlace& inPlace,
const morkMid& inMid, mork_bool inCutAllRows);
virtual void OnTableGlitch(morkEnv* ev, const morkGlitch& inGlitch);
virtual void OnTableEnd(morkEnv* ev, const morkSpan& inSpan);
virtual void OnNewMeta(morkEnv* ev, const morkPlace& inPlace);
virtual void OnMetaGlitch(morkEnv* ev, const morkGlitch& inGlitch);
virtual void OnMetaEnd(morkEnv* ev, const morkSpan& inSpan);
virtual void OnMinusRow(morkEnv* ev);
virtual void OnNewRow(morkEnv* ev, const morkPlace& inPlace,
const morkMid& inMid, mork_bool inCutAllCols);
virtual void OnRowPos(morkEnv* ev, mork_pos inRowPos);
virtual void OnRowGlitch(morkEnv* ev, const morkGlitch& inGlitch);
virtual void OnRowEnd(morkEnv* ev, const morkSpan& inSpan);
virtual void OnNewDict(morkEnv* ev, const morkPlace& inPlace);
virtual void OnDictGlitch(morkEnv* ev, const morkGlitch& inGlitch);
virtual void OnDictEnd(morkEnv* ev, const morkSpan& inSpan);
virtual void OnAlias(morkEnv* ev, const morkSpan& inSpan,
const morkMid& inMid);
virtual void OnAliasGlitch(morkEnv* ev, const morkGlitch& inGlitch);
virtual void OnMinusCell(morkEnv* ev);
virtual void OnNewCell(morkEnv* ev, const morkPlace& inPlace,
const morkMid* inMid, const morkBuf* inBuf);
// Exactly one of inMid and inBuf is nil, and the other is non-nil.
// When hex ID syntax is used for a column, then inMid is not nil, and
// when a naked string names a column, then inBuf is not nil.
virtual void OnCellGlitch(morkEnv* ev, const morkGlitch& inGlitch);
virtual void OnCellForm(morkEnv* ev, mork_cscode inCharsetFormat);
virtual void OnCellEnd(morkEnv* ev, const morkSpan& inSpan);
virtual void OnValue(morkEnv* ev, const morkSpan& inSpan,
const morkBuf& inBuf);
virtual void OnValueMid(morkEnv* ev, const morkSpan& inSpan,
const morkMid& inMid);
virtual void OnRowMid(morkEnv* ev, const morkSpan& inSpan,
const morkMid& inMid);
virtual void OnTableMid(morkEnv* ev, const morkSpan& inSpan,
const morkMid& inMid);
// ````` ````` ````` ````` ````` ````` ````` `````
public: // public non-poly morkBuilder methods
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakBuilder(morkBuilder* me,
morkEnv* ev, morkBuilder** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongBuilder(morkBuilder* me,
morkEnv* ev, morkBuilder** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKBUILDER_ */

View File

@@ -1,126 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
#ifndef _MORKPOOL_
#include "morkPool.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKCELL_
#include "morkCell.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
void
morkCell::SetYarn(morkEnv* ev, const mdbYarn* inYarn, morkStore* ioStore)
{
morkAtom* atom = ioStore->YarnToAtom(ev, inYarn);
if ( atom )
this->SetAtom(ev, atom, ioStore->StorePool()); // refcounts atom
}
void
morkCell::GetYarn(morkEnv* ev, mdbYarn* outYarn) const
{
MORK_USED_1(ev);
mCell_Atom->GetYarn(outYarn);
}
void
morkCell::AliasYarn(morkEnv* ev, mdbYarn* outYarn) const
{
MORK_USED_1(ev);
mCell_Atom->AliasYarn(outYarn);
}
void
morkCell::SetCellClean()
{
mork_column col = this->GetColumn();
this->SetColumnAndChange(col, morkChange_kNil);
}
void
morkCell::SetCellDirty()
{
mork_column col = this->GetColumn();
this->SetColumnAndChange(col, morkChange_kAdd);
}
void
morkCell::SetAtom(morkEnv* ev, morkAtom* ioAtom, morkPool* ioPool)
// SetAtom() "acquires" the new ioAtom if non-nil, by calling AddCellUse()
// to increase the refcount, and puts ioAtom into mCell_Atom. If the old
// atom in mCell_Atom is non-nil, then it is "released" first by a call to
// CutCellUse(), and if the use count then becomes zero, then the old atom
// is deallocated by returning it to the pool ioPool. (And this is
// why ioPool is a parameter to this method.) Note that ioAtom can be nil
// to cause the cell to refer to nothing, and the old atom in mCell_Atom
// can also be nil, and all the atom refcounting is handled correctly.
//
// Note that if ioAtom was just created, it typically has a zero use count
// before calling SetAtom(). But use count is one higher after SetAtom().
{
morkAtom* oldAtom = mCell_Atom;
if ( oldAtom != ioAtom ) // ioAtom is not already installed in this cell?
{
if ( oldAtom )
{
mCell_Atom = 0;
if ( oldAtom->CutCellUse(ev) == 0 )
{
if ( ioPool )
{
if ( oldAtom->IsBook() )
((morkBookAtom*) oldAtom)->CutBookAtomFromSpace(ev);
ioPool->ZapAtom(ev, oldAtom);
}
else
ev->NilPointerError();
}
}
if ( ioAtom )
ioAtom->AddCellUse(ev);
mCell_Atom = ioAtom;
}
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,102 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKCELL_
#define _MORKCELL_ 1
#ifndef _MORK_
#include "mork.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDelta_kShift 8 /* 8 bit shift */
#define morkDelta_kChangeMask 0x0FF /* low 8 bit mask */
#define morkDelta_kColumnMask (~ (mork_column) morkDelta_kChangeMask)
#define morkDelta_Init(self,cl,ch) ((self) = ((cl)<<morkDelta_kShift) | (ch))
#define morkDelta_Change(self) ((mork_change) ((self) & morkDelta_kChangeMask))
#define morkDelta_Column(self) ((self) >> morkDelta_kShift)
class morkCell { // minimal cell format
public:
mork_delta mCell_Delta; // encoding of both column and change
morkAtom* mCell_Atom; // content in this cell
public:
morkCell() : mCell_Delta( 0 ), mCell_Atom( 0 ) { }
morkCell(const morkCell& c)
: mCell_Delta( c.mCell_Delta ), mCell_Atom( c.mCell_Atom ) { }
// note if ioAtom is non-nil, caller needs to call ioAtom->AddCellUse():
morkCell(mork_column inCol, mork_change inChange, morkAtom* ioAtom)
{
morkDelta_Init(mCell_Delta, inCol,inChange);
mCell_Atom = ioAtom;
}
// note if ioAtom is non-nil, caller needs to call ioAtom->AddCellUse():
void Init(mork_column inCol, mork_change inChange, morkAtom* ioAtom)
{
morkDelta_Init(mCell_Delta,inCol,inChange);
mCell_Atom = ioAtom;
}
mork_column GetColumn() const { return morkDelta_Column(mCell_Delta); }
mork_change GetChange() const { return morkDelta_Change(mCell_Delta); }
mork_bool IsCellClean() const { return GetChange() == morkChange_kNil; }
mork_bool IsCellDirty() const { return GetChange() != morkChange_kNil; }
void SetCellClean(); // set change to kNil
void SetCellDirty(); // set change to kAdd
void SetCellColumnDirty(mork_column inCol)
{ this->SetColumnAndChange(inCol, morkChange_kAdd); }
void SetCellColumnClean(mork_column inCol)
{ this->SetColumnAndChange(inCol, morkChange_kNil); }
void SetColumnAndChange(mork_column inCol, mork_change inChange)
{ morkDelta_Init(mCell_Delta, inCol, inChange); }
morkAtom* GetAtom() { return mCell_Atom; }
void SetAtom(morkEnv* ev, morkAtom* ioAtom, morkPool* ioPool);
// SetAtom() "acquires" the new ioAtom if non-nil, by calling AddCellUse()
// to increase the refcount, and puts ioAtom into mCell_Atom. If the old
// atom in mCell_Atom is non-nil, then it is "released" first by a call to
// CutCellUse(), and if the use count then becomes zero, then the old atom
// is deallocated by returning it to the pool ioPool. (And this is
// why ioPool is a parameter to this method.) Note that ioAtom can be nil
// to cause the cell to refer to nothing, and the old atom in mCell_Atom
// can also be nil, and all the atom refcounting is handled correctly.
//
// Note that if ioAtom was just created, it typically has a zero use count
// before calling SetAtom(). But use count is one higher after SetAtom().
void SetYarn(morkEnv* ev, const mdbYarn* inYarn, morkStore* ioStore);
void AliasYarn(morkEnv* ev, mdbYarn* outYarn) const;
void GetYarn(morkEnv* ev, mdbYarn* outYarn) const;
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKCELL_ */

View File

@@ -1,236 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKOBJECT_
#include "morkObject.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKCELLOBJECT_
#include "morkCellObject.h"
#endif
#ifndef _MORKROWOBJECT_
#include "morkRowObject.h"
#endif
#ifndef _MORKROW_
#include "morkRow.h"
#endif
#ifndef _MORKCELL_
#include "morkCell.h"
#endif
#ifndef _ORKINCELL_
#include "orkinCell.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkCellObject::CloseMorkNode(morkEnv* ev) // CloseCellObject() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseCellObject(ev);
this->MarkShut();
}
}
/*public virtual*/
morkCellObject::~morkCellObject() // assert CloseCellObject() executed earlier
{
MORK_ASSERT(mCellObject_Row==0);
}
/*public non-poly*/
morkCellObject::morkCellObject(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, morkRow* ioRow, morkCell* ioCell,
mork_column inCol, mork_pos inPos)
: morkObject(ev, inUsage, ioHeap, (morkHandle*) 0)
, mCellObject_RowObject( 0 )
, mCellObject_Row( 0 )
, mCellObject_Cell( 0 )
, mCellObject_Col( inCol )
, mCellObject_RowSeed( 0 )
, mCellObject_Pos( (mork_u2) inPos )
{
if ( ev->Good() )
{
if ( ioRow && ioCell )
{
if ( ioRow->IsRow() )
{
morkStore* store = ioRow->GetRowSpaceStore(ev);
if ( store )
{
morkRowObject* rowObj = ioRow->AcquireRowObject(ev, store);
if ( rowObj )
{
mCellObject_Row = ioRow;
mCellObject_Cell = ioCell;
mCellObject_RowSeed = ioRow->mRow_Seed;
// morkRowObject::SlotStrongRowObject(rowObj, ev,
// &mCellObject_RowObject);
mCellObject_RowObject = rowObj; // assume control of strong ref
}
if ( ev->Good() )
mNode_Derived = morkDerived_kCellObject;
}
}
else
ioRow->NonRowTypeError(ev);
}
else
ev->NilPointerError();
}
}
/*public non-poly*/ void
morkCellObject::CloseCellObject(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
morkRowObject::SlotStrongRowObject((morkRowObject*) 0, ev,
&mCellObject_RowObject);
mCellObject_Row = 0;
mCellObject_Cell = 0;
mCellObject_RowSeed = 0;
this->CloseObject(ev);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
mork_bool
morkCellObject::ResyncWithRow(morkEnv* ev)
{
morkRow* row = mCellObject_Row;
mork_pos pos = 0;
morkCell* cell = row->GetCell(ev, mCellObject_Col, &pos);
if ( cell )
{
mCellObject_Pos = (mork_u2) pos;
mCellObject_Cell = cell;
mCellObject_RowSeed = row->mRow_Seed;
}
else
{
mCellObject_Cell = 0;
this->MissingRowColumnError(ev);
}
return ev->Good();
}
morkAtom*
morkCellObject::GetCellAtom(morkEnv* ev) const
{
morkCell* cell = mCellObject_Cell;
if ( cell )
return cell->GetAtom();
else
this->NilCellError(ev);
return (morkAtom*) 0;
}
/*static*/ void
morkCellObject::WrongRowObjectRowError(morkEnv* ev)
{
ev->NewError("mCellObject_Row != mCellObject_RowObject->mRowObject_Row");
}
/*static*/ void
morkCellObject::NilRowError(morkEnv* ev)
{
ev->NewError("nil mCellObject_Row");
}
/*static*/ void
morkCellObject::NilRowObjectError(morkEnv* ev)
{
ev->NewError("nil mCellObject_RowObject");
}
/*static*/ void
morkCellObject::NilCellError(morkEnv* ev)
{
ev->NewError("nil mCellObject_Cell");
}
/*static*/ void
morkCellObject::NonCellObjectTypeError(morkEnv* ev)
{
ev->NewError("non morkCellObject");
}
/*static*/ void
morkCellObject::MissingRowColumnError(morkEnv* ev)
{
ev->NewError("mCellObject_Col not in mCellObject_Row");
}
nsIMdbCell*
morkCellObject::AcquireCellHandle(morkEnv* ev)
{
nsIMdbCell* outCell = 0;
orkinCell* c = (orkinCell*) mObject_Handle;
if ( c ) // have an old handle?
c->AddStrongRef(ev->AsMdbEnv());
else // need new handle?
{
c = orkinCell::MakeCell(ev, this);
mObject_Handle = c;
}
if ( c )
outCell = c;
return outCell;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,107 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKCELLOBJECT_
#define _MORKCELLOBJECT_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKOBJECT_
#include "morkObject.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kCellObject /*i*/ 0x634F /* ascii 'cO' */
class morkCellObject : public morkObject { // blob attribute in column scope
// public: // slots inherited from morkObject (meant to inform only)
// nsIMdbHeap* mNode_Heap;
// mork_able mNode_Mutable; // can this node be modified?
// mork_load mNode_Load; // is this node clean or dirty?
// 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_uses mNode_Uses; // refcount for strong refs
// mork_refs mNode_Refs; // refcount for strong refs + weak refs
// morkFactory* mObject_Factory; // weak ref to suite factory
public: // state is public because the entire Mork system is private
morkRowObject* mCellObject_RowObject; // strong ref to row's object
morkRow* mCellObject_Row; // cell's row if still in row object
morkCell* mCellObject_Cell; // cell in row if rowseed matches
mork_column mCellObject_Col; // col of cell last living in pos
mork_u2 mCellObject_RowSeed; // copy of row's seed
mork_u2 mCellObject_Pos; // position of cell in row
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseCellObject() only if open
virtual ~morkCellObject(); // assert that CloseCellObject() executed earlier
public: // morkCellObject construction & destruction
morkCellObject(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, morkRow* ioRow, morkCell* ioCell,
mork_column inCol, mork_pos inPos);
void CloseCellObject(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkCellObject(const morkCellObject& other);
morkCellObject& operator=(const morkCellObject& other);
public: // dynamic type identification
mork_bool IsCellObject() const
{ return IsNode() && mNode_Derived == morkDerived_kCellObject; }
// } ===== end morkNode methods =====
public: // other cell node methods
mork_bool ResyncWithRow(morkEnv* ev); // return ev->Good()
morkAtom* GetCellAtom(morkEnv* ev) const;
static void MissingRowColumnError(morkEnv* ev);
static void NilRowError(morkEnv* ev);
static void NilCellError(morkEnv* ev);
static void NilRowObjectError(morkEnv* ev);
static void WrongRowObjectRowError(morkEnv* ev);
static void NonCellObjectTypeError(morkEnv* ev);
nsIMdbCell* AcquireCellHandle(morkEnv* ev);
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakCellObject(morkCellObject* me,
morkEnv* ev, morkCellObject** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongCellObject(morkCellObject* me,
morkEnv* ev, morkCellObject** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKCELLOBJECT_ */

View File

@@ -1,214 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKCH_
#include "morkCh.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/* this byte char predicate source file derives from public domain Mithril */
/* (that means much of this has a copyright dedicated to the public domain) */
/*============================================================================*/
/* morkCh_Type */
const mork_flags morkCh_Type[] = /* derives from public domain Mithril table */
{
0, /* 0x0 */
0, /* 0x1 */
0, /* 0x2 */
0, /* 0x3 */
0, /* 0x4 */
0, /* 0x5 */
0, /* 0x6 */
0, /* 0x7 */
morkCh_kW, /* 0x8 backspace */
morkCh_kW, /* 0x9 tab */
morkCh_kW, /* 0xA linefeed */
0, /* 0xB */
morkCh_kW, /* 0xC page */
morkCh_kW, /* 0xD return */
0, /* 0xE */
0, /* 0xF */
0, /* 0x10 */
0, /* 0x11 */
0, /* 0x12 */
0, /* 0x13 */
0, /* 0x14 */
0, /* 0x15 */
0, /* 0x16 */
0, /* 0x17 */
0, /* 0x18 */
0, /* 0x19 */
0, /* 0x1A */
0, /* 0x1B */
0, /* 0x1C */
0, /* 0x1D */
0, /* 0x1E */
0, /* 0x1F */
morkCh_kV|morkCh_kW, /* 0x20 space */
morkCh_kV|morkCh_kM, /* 0x21 ! */
morkCh_kV, /* 0x22 " */
morkCh_kV, /* 0x23 # */
0, /* 0x24 $ cannot be kV because needs escape */
morkCh_kV, /* 0x25 % */
morkCh_kV, /* 0x26 & */
morkCh_kV, /* 0x27 ' */
morkCh_kV, /* 0x28 ( */
0, /* 0x29 ) cannot be kV because needs escape */
morkCh_kV, /* 0x2A * */
morkCh_kV|morkCh_kM, /* 0x2B + */
morkCh_kV, /* 0x2C , */
morkCh_kV|morkCh_kM, /* 0x2D - */
morkCh_kV, /* 0x2E . */
morkCh_kV, /* 0x2F / */
morkCh_kV|morkCh_kD|morkCh_kX, /* 0x30 0 */
morkCh_kV|morkCh_kD|morkCh_kX, /* 0x31 1 */
morkCh_kV|morkCh_kD|morkCh_kX, /* 0x32 2 */
morkCh_kV|morkCh_kD|morkCh_kX, /* 0x33 3 */
morkCh_kV|morkCh_kD|morkCh_kX, /* 0x34 4 */
morkCh_kV|morkCh_kD|morkCh_kX, /* 0x35 5 */
morkCh_kV|morkCh_kD|morkCh_kX, /* 0x36 6 */
morkCh_kV|morkCh_kD|morkCh_kX, /* 0x37 7 */
morkCh_kV|morkCh_kD|morkCh_kX, /* 0x38 8 */
morkCh_kV|morkCh_kD|morkCh_kX, /* 0x39 9 */
morkCh_kV|morkCh_kN|morkCh_kM, /* 0x3A : */
morkCh_kV, /* 0x3B ; */
morkCh_kV, /* 0x3C < */
morkCh_kV, /* 0x3D = */
morkCh_kV, /* 0x3E > */
morkCh_kV|morkCh_kM, /* 0x3F ? */
morkCh_kV, /* 0x40 @ */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU|morkCh_kX, /* 0x41 A */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU|morkCh_kX, /* 0x42 B */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU|morkCh_kX, /* 0x43 C */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU|morkCh_kX, /* 0x44 D */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU|morkCh_kX, /* 0x45 E */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU|morkCh_kX, /* 0x46 F */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x47 G */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x48 H */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x49 I */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x4A J */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x4B K */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x4C L */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x4D M */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x4E N */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x4F O */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x50 P */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x51 Q */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x52 R */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x53 S */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x54 T */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x55 U */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x56 V */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x57 W */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x58 X */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x59 Y */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kU, /* 0x5A Z */
morkCh_kV, /* 0x5B [ */
0, /* 0x5C \ cannot be kV because needs escape */
morkCh_kV, /* 0x5D ] */
morkCh_kV, /* 0x5E ^ */
morkCh_kV|morkCh_kN|morkCh_kM, /* 0x5F _ */
morkCh_kV, /* 0x60 ` */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL|morkCh_kX, /* 0x61 a */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL|morkCh_kX, /* 0x62 b */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL|morkCh_kX, /* 0x63 c */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL|morkCh_kX, /* 0x64 d */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL|morkCh_kX, /* 0x65 e */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL|morkCh_kX, /* 0x66 f */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x67 g */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x68 h */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x69 i */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x6A j */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x6B k */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x6C l */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x6D m */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x6E n */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x6F o */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x70 p */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x71 q */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x72 r */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x73 s */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x74 t */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x75 u */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x76 v */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x77 w */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x78 x */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x79 y */
morkCh_kV|morkCh_kN|morkCh_kM|morkCh_kL, /* 0x7A z */
morkCh_kV, /* 0x7B { */
morkCh_kV, /* 0x7C | */
morkCh_kV, /* 0x7D } */
morkCh_kV, /* 0x7E ~ */
morkCh_kW, /* 0x7F rubout */
/* $"80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F" */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
/* $"90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F" */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
/* $"A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF" */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
/* $"B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF" */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
/* $"C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF" */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
/* $"D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF" */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
/* $"E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF" */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
/* $"F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF" */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,107 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKCH_
#define _MORKCH_ 1
#ifndef _MORK_
#include "mork.h"
#endif
/* this byte char predicate header file derives from public domain Mithril */
/* (that means much of this has a copyright dedicated to the public domain) */
/* Use all 8 pred bits; lose some pred bits only if we need to reuse them. */
/* ch pred bits: W:white D:digit V:value U:upper L:lower N:name M:more */
#define morkCh_kW (1 << 0)
#define morkCh_kD (1 << 1)
#define morkCh_kV (1 << 2)
#define morkCh_kU (1 << 3)
#define morkCh_kL (1 << 4)
#define morkCh_kX (1 << 5)
#define morkCh_kN (1 << 6)
#define morkCh_kM (1 << 7)
extern const mork_flags morkCh_Type[]; /* 256 byte predicate bits ch map */
/* is a numeric decimal digit: (note memory access might be slower) */
/* define morkCh_IsDigit(c) ( morkCh_Type[ (mork_ch)(c) ] & morkCh_kD ) */
#define morkCh_IsDigit(c) ( ((mork_ch) c) >= '0' && ((mork_ch) c) <= '9' )
/* is a numeric octal digit: */
#define morkCh_IsOctal(c) ( ((mork_ch) c) >= '0' && ((mork_ch) c) <= '7' )
/* is a numeric hexadecimal digit: */
#define morkCh_IsHex(c) ( morkCh_Type[ (mork_ch)(c) ] & morkCh_kX )
/* is value (can be printed in Mork value without needing hex or escape): */
#define morkCh_IsValue(c) ( morkCh_Type[ (mork_ch)(c) ] & morkCh_kV )
/* is white space : */
#define morkCh_IsWhite(c) ( morkCh_Type[ (mork_ch)(c) ] & morkCh_kW )
/* is name (can start a Mork name): */
#define morkCh_IsName(c) ( morkCh_Type[ (mork_ch)(c) ] & morkCh_kN )
/* is name (can continue a Mork name): */
#define morkCh_IsMore(c) ( morkCh_Type[ (mork_ch)(c) ] & morkCh_kM )
/* is alphabetic upper or lower case */
#define morkCh_IsAlpha(c) \
( morkCh_Type[ (mork_ch)(c) ] & (morkCh_kL|morkCh_kU) )
/* is alphanumeric, including lower case, upper case, and digits */
#define morkCh_IsAlphaNum(c) \
(morkCh_Type[ (mork_ch)(c) ]&(morkCh_kL|morkCh_kU|morkCh_kD))
/* ````` repeated testing of predicate bits in single flag byte ````` */
#define morkCh_GetFlags(c) ( morkCh_Type[ (mork_ch)(c) ] )
#define morkFlags_IsDigit(f) ( (f) & morkCh_kD )
#define morkFlags_IsHex(f) ( (f) & morkCh_kX )
#define morkFlags_IsValue(f) ( (f) & morkCh_kV )
#define morkFlags_IsWhite(f) ( (f) & morkCh_kW )
#define morkFlags_IsName(f) ( (f) & morkCh_kN )
#define morkFlags_IsMore(f) ( (f) & morkCh_kM )
#define morkFlags_IsAlpha(f) ( (f) & (morkCh_kL|morkCh_kU) )
#define morkFlags_IsAlphaNum(f) ( (f) & (morkCh_kL|morkCh_kU|morkCh_kD) )
#define morkFlags_IsUpper(f) ( (f) & morkCh_kU )
#define morkFlags_IsLower(f) ( (f) & morkCh_kL )
/* ````` character case (e.g. for case insensitive operations) ````` */
#define morkCh_IsAscii(c) ( ((mork_u1) c) <= 0x7F )
#define morkCh_IsSevenBitChar(c) ( ((mork_u1) c) <= 0x7F )
/* ````` character case (e.g. for case insensitive operations) ````` */
#define morkCh_ToLower(c) ((c)-'A'+'a')
#define morkCh_ToUpper(c) ((c)-'a'+'A')
/* extern int morkCh_IsUpper (int c); */
#define morkCh_IsUpper(c) ( morkCh_Type[ (mork_ch)(c) ] & morkCh_kU )
/* extern int morkCh_IsLower (int c); */
#define morkCh_IsLower(c) ( morkCh_Type[ (mork_ch)(c) ] & morkCh_kL )
#endif
/* _MORKCH_ */

View File

@@ -1,252 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKCONFIG_
#include "morkConfig.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/* ----- ----- ----- ----- MORK_OBSOLETE ----- ----- ----- ----- */
#if defined(MORK_OBSOLETE) || defined(MORK_ALONE)
#include <Types.h>
//#include "plstr.h"
static void // copied almost verbatim from the IronDoc debugger sources:
mork_mac_break_string(register const char* inMessage) /*i*/
{
Str255 pascalStr; // to hold Pascal string version of inMessage
mork_u4 length = MORK_STRLEN(inMessage);
// if longer than maximum 255 bytes, just copy 255 bytes worth
pascalStr[ 0 ] = (mork_u1) ((length > 255)? 255 : length);
if ( length ) // anything to copy? */
{
register mork_u1* p = ((mork_u1*) &pascalStr) + 1; // after length byte
register mork_u1* end = p + length; // one past last byte to copy
while ( p < end ) // more bytes to copy?
{
register int c = (mork_u1) *inMessage++;
if ( c == ';' ) // c is the MacsBug ';' metacharacter?
c = ':'; // change to ':', rendering harmless in a MacsBug context
*p++ = (mork_u1) c;
}
}
DebugStr(pascalStr); /* call Mac debugger entry point */
}
#endif /*MORK_OBSOLETE*/
/* ----- ----- ----- ----- MORK_OBSOLETE ----- ----- ----- ----- */
void mork_assertion_signal(const char* inMessage)
{
#if defined(MORK_OBSOLETE) || defined(MORK_ALONE)
mork_mac_break_string(inMessage);
#endif /*MORK_OBSOLETE*/
#if defined(MORK_WIN) || defined(MORK_MAC)
// asm { int 3 }
#ifndef MORK_ALONE
NS_ASSERTION(0, inMessage);
#endif /*MORK_ALONE*/
#endif /*MORK_WIN*/
}
#ifdef MORK_PROVIDE_STDLIB
MORK_LIB_IMPL(mork_i4)
mork_memcmp(const void* inOne, const void* inTwo, mork_size inSize)
{
register const mork_u1* t = (const mork_u1*) inTwo;
register const mork_u1* s = (const mork_u1*) inOne;
const mork_u1* end = s + inSize;
register mork_i4 delta;
while ( s < end )
{
delta = ((mork_i4) *s) - ((mork_i4) *t);
if ( delta )
return delta;
else
{
++t;
++s;
}
}
return 0;
}
MORK_LIB_IMPL(void)
mork_memcpy(void* outDst, const void* inSrc, mork_size inSize)
{
register mork_u1* d = (mork_u1*) outDst;
mork_u1* end = d + inSize;
register const mork_u1* s = ((const mork_u1*) inSrc);
while ( inSize >= 8 )
{
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
inSize -= 8;
}
while ( d < end )
*d++ = *s++;
}
MORK_LIB_IMPL(void)
mork_memmove(void* outDst, const void* inSrc, mork_size inSize)
{
register mork_u1* d = (mork_u1*) outDst;
register const mork_u1* s = (const mork_u1*) inSrc;
if ( d != s && inSize ) // copy is necessary?
{
const mork_u1* srcEnd = s + inSize; // one past last source byte
if ( d > s && d < srcEnd ) // overlap? need to copy backwards?
{
s = srcEnd; // start one past last source byte
d += inSize; // start one past last dest byte
mork_u1* dstBegin = d; // last byte to write is first in dest range
while ( d - dstBegin >= 8 )
{
*--d = *--s;
*--d = *--s;
*--d = *--s;
*--d = *--s;
*--d = *--s;
*--d = *--s;
*--d = *--s;
*--d = *--s;
}
while ( d > dstBegin )
*--d = *--s;
}
else // can copy forwards without any overlap
{
mork_u1* dstEnd = d + inSize;
while ( dstEnd - d >= 8 )
{
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
}
while ( d < dstEnd )
*d++ = *s++;
}
}
}
MORK_LIB_IMPL(void)
mork_memset(void* outDst, int inByte, mork_size inSize)
{
register mork_u1* d = (mork_u1*) outDst;
mork_u1* end = d + inSize;
while ( d < end )
*d++ = (mork_u1) inByte;
}
MORK_LIB_IMPL(void)
mork_strcpy(void* outDst, const void* inSrc)
{
// back up one first to support preincrement
register mork_u1* d = ((mork_u1*) outDst) - 1;
register const mork_u1* s = ((const mork_u1*) inSrc) - 1;
while ( ( *++d = *++s ) != 0 )
/* empty */;
}
MORK_LIB_IMPL(mork_i4)
mork_strcmp(const void* inOne, const void* inTwo)
{
register const mork_u1* t = (const mork_u1*) inTwo;
register const mork_u1* s = ((const mork_u1*) inOne);
register mork_i4 a;
register mork_i4 b;
register mork_i4 delta;
do
{
a = (mork_i4) *s++;
b = (mork_i4) *t++;
delta = a - b;
}
while ( !delta && a && b );
return delta;
}
MORK_LIB_IMPL(mork_i4)
mork_strncmp(const void* inOne, const void* inTwo, mork_size inSize)
{
register const mork_u1* t = (const mork_u1*) inTwo;
register const mork_u1* s = (const mork_u1*) inOne;
const mork_u1* end = s + inSize;
register mork_i4 delta;
register mork_i4 a;
register mork_i4 b;
while ( s < end )
{
a = (mork_i4) *s++;
b = (mork_i4) *t++;
delta = a - b;
if ( delta || !a || !b )
return delta;
}
return 0;
}
MORK_LIB_IMPL(mork_size)
mork_strlen(const void* inString)
{
// back up one first to support preincrement
register const mork_u1* s = ((const mork_u1*) inString) - 1;
while ( *++s ) // preincrement is cheapest
/* empty */;
return s - ((const mork_u1*) inString); // distance from original address
}
#endif /*MORK_PROVIDE_STDLIB*/
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,191 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKCONFIG_
#define _MORKCONFIG_ 1
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// { %%%%% begin debug mode options in Mork %%%%%
#define MORK_DEBUG 1
// } %%%%% end debug mode options in Mork %%%%%
#ifdef MORK_DEBUG
#define MORK_MAX_CODE_COMPILE 1
#endif
// { %%%%% begin platform defs peculiar to Mork %%%%%
//#define XP_MAC 1
//#define MORK_ALONE 1
#ifdef XP_MAC
#define MORK_MAC 1
#endif
#ifdef XP_OS2
#define MORK_OS2 1
#endif
#ifdef XP_PC
#define MORK_WIN 1
#define XP_WIN 1
#endif
#ifdef XP_UNIX
#define MORK_UNIX 1
#endif
#ifdef XP_BEOS
#define MORK_BEOS 1
#endif
#ifdef MORK_OBSOLETE
#undef MORK_MAC
#endif
// } %%%%% end platform defs peculiar to Mork %%%%%
#if defined(MORK_WIN) || defined(MORK_UNIX) || defined(MORK_MAC) || defined(MORK_BEOS)
#include "stdio.h"
#include "ctype.h"
#include "errno.h"
#include "string.h"
#ifdef HAVE_MEMORY_H
#include "memory.h"
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for SEEK_SET, SEEK_END */
#endif
#ifndef MORK_ALONE
#include "nsDebug.h"
#endif /*MORK_ALONE*/
#define MORK_ISPRINT(c) isprint(c)
#define MORK_FILETELL(file) ftell(file)
#define MORK_FILESEEK(file, where, how) fseek(file, where, how)
#define MORK_FILEREAD(outbuf, insize, file) fread(outbuf, 1, insize, file)
#define MORK_FILEFLUSH(file) fflush(file)
#define MORK_FILECLOSE(file) fclose(file)
#endif /*MORK_WIN*/
#ifdef MORK_OBSOLETE
#include "xp_file.h"
#include "ctype.h"
#define MORK_ISPRINT(c) isprint(c)
#define MORK_FILETELL(file) XP_FileTell(file)
#define MORK_FILESEEK(file, where, how) XP_FileSeek(file, where, how)
#define MORK_FILEREAD(outbuf, insize, file) XP_FileRead(outbuf, insize, file)
#define MORK_FILEFLUSH(file) XP_FileFlush(file)
#define MORK_FILECLOSE(file) XP_FileClose(file)
#endif /*MORK_OBSOLETE*/
/* ===== ===== ===== ===== line characters ===== ===== ===== ===== */
#define mork_kCR 0x0D
#define mork_kLF 0x0A
#define mork_kVTAB '\013'
#define mork_kFF '\014'
#define mork_kTAB '\011'
#define mork_kCRLF "\015\012" /* A CR LF equivalent string */
#if defined(MORK_MAC) || defined(MORK_OBSOLETE)
# define mork_kNewline "\015"
# define mork_kNewlineSize 1
#else
# if defined(MORK_WIN) || defined(MORK_OS2)
# define mork_kNewline "\015\012"
# define mork_kNewlineSize 2
# else
# if defined(MORK_UNIX) || defined(MORK_BEOS)
# define mork_kNewline "\012"
# define mork_kNewlineSize 1
# endif /* MORK_UNIX || MORK_BEOS */
# endif /* MORK_WIN */
#endif /* MORK_MAC */
// { %%%%% begin assertion macro %%%%%
extern void mork_assertion_signal(const char* inMessage);
#define MORK_ASSERTION_SIGNAL(Y) mork_assertion_signal(Y)
#define MORK_ASSERT(X) if (!(X)) MORK_ASSERTION_SIGNAL(#X)
// } %%%%% end assertion macro %%%%%
#define MORK_LIB(return) return /*API return declaration*/
#define MORK_LIB_IMPL(return) return /*implementation return declaration*/
// { %%%%% begin standard c utility methods %%%%%
/*define MORK_USE_XP_STDLIB 1*/
#ifdef MORK_OBSOLETE
#define MORK_PROVIDE_STDLIB 1
#endif /*MORK_OBSOLETE*/
#if defined(MORK_WIN) || defined(MORK_UNIX) || defined(MORK_MAC) || defined(MORK_BEOS)
#define MORK_USE_C_STDLIB 1
#endif /*MORK_WIN*/
#ifdef MORK_USE_C_STDLIB
#define MORK_MEMCMP(src1,src2,size) memcmp(src1,src2,size)
#define MORK_MEMCPY(dest,src,size) memcpy(dest,src,size)
#define MORK_MEMMOVE(dest,src,size) memmove(dest,src,size)
#define MORK_MEMSET(dest,byte,size) memset(dest,byte,size)
#define MORK_STRCPY(dest,src) strcpy(dest,src)
#define MORK_STRCMP(one,two) strcmp(one,two)
#define MORK_STRNCMP(one,two,length) strncmp(one,two,length)
#define MORK_STRLEN(string) strlen(string)
#endif /*MORK_USE_C_STDLIB*/
#ifdef MORK_PROVIDE_STDLIB
MORK_LIB(mork_i4) mork_memcmp(const void* a, const void* b, mork_size inSize);
MORK_LIB(void) mork_memcpy(void* dst, const void* src, mork_size inSize);
MORK_LIB(void) mork_memmove(void* dst, const void* src, mork_size inSize);
MORK_LIB(void) mork_memset(void* dst, int inByte, mork_size inSize);
MORK_LIB(void) mork_strcpy(void* dst, const void* src);
MORK_LIB(mork_i4) mork_strcmp(const void* a, const void* b);
MORK_LIB(mork_i4) mork_strncmp(const void* a, const void* b, mork_size inSize);
MORK_LIB(mork_size) mork_strlen(const void* inString);
#define MORK_MEMCMP(src1,src2,size) mork_memcmp(src1,src2,size)
#define MORK_MEMCPY(dest,src,size) mork_memcpy(dest,src,size)
#define MORK_MEMMOVE(dest,src,size) mork_memmove(dest,src,size)
#define MORK_MEMSET(dest,byte,size) mork_memset(dest,byte,size)
#define MORK_STRCPY(dest,src) mork_strcpy(dest,src)
#define MORK_STRCMP(one,two) mork_strcmp(one,two)
#define MORK_STRNCMP(one,two,length) mork_strncmp(one,two,length)
#define MORK_STRLEN(string) mork_strlen(string)
#endif /*MORK_PROVIDE_STDLIB*/
#ifdef MORK_USE_XP_STDLIB
#define MORK_MEMCMP(src1,src2,size) XP_MEMCMP(src1,src2,size)
#define MORK_MEMCPY(dest,src,size) XP_MEMCPY(dest,src,size)
#define MORK_MEMMOVE(dest,src,size) XP_MEMMOVE(dest,src,size)
#define MORK_MEMSET(dest,byte,size) XP_MEMSET(dest,byte,size)
#define MORK_STRCPY(dest,src) XP_STRCPY(dest,src)
#define MORK_STRCMP(one,two) XP_STRCMP(one,two)
#define MORK_STRNCMP(one,two,length) XP_STRNCMP(one,two,length)
#define MORK_STRLEN(string) XP_STRLEN(string)
#endif /*MORK_USE_XP_STDLIB*/
// } %%%%% end standard c utility methods %%%%%
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKCONFIG_ */

View File

@@ -1,98 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKCURSOR_
#include "morkCursor.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkCursor::CloseMorkNode(morkEnv* ev) // CloseCursor() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseCursor(ev);
this->MarkShut();
}
}
/*public virtual*/
morkCursor::~morkCursor() // assert CloseCursor() executed earlier
{
}
/*public non-poly*/
morkCursor::morkCursor(morkEnv* ev,
const morkUsage& inUsage, nsIMdbHeap* ioHeap)
: morkObject(ev, inUsage, ioHeap, (morkHandle*) 0)
, mCursor_Seed( 0 )
, mCursor_Pos( -1 )
, mCursor_DoFailOnSeedOutOfSync( morkBool_kFalse )
{
if ( ev->Good() )
mNode_Derived = morkDerived_kCursor;
}
/*public non-poly*/ void
morkCursor::CloseCursor(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
mCursor_Seed = 0;
mCursor_Pos = -1;
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,88 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKCURSOR_
#define _MORKCURSOR_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKOBJECT_
#include "morkObject.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kCursor /*i*/ 0x4375 /* ascii 'Cu' */
class morkCursor : public morkObject { // collection iterator
// public: // slots inherited from morkObject (meant to inform only)
// nsIMdbHeap* mNode_Heap;
// mork_able mNode_Mutable; // can this node be modified?
// mork_load mNode_Load; // is this node clean or dirty?
// 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_uses mNode_Uses; // refcount for strong refs
// mork_refs mNode_Refs; // refcount for strong refs + weak refs
// morkFactory* mObject_Factory; // weak ref to suite factory
public: // state is public because the entire Mork system is private
mork_seed mCursor_Seed;
mork_pos mCursor_Pos;
mork_bool mCursor_DoFailOnSeedOutOfSync;
mork_u1 mCursor_Pad[ 3 ]; // explicitly pad to u4 alignment
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseCursor() only if open
virtual ~morkCursor(); // assert that CloseCursor() executed earlier
public: // morkCursor construction & destruction
morkCursor(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap);
void CloseCursor(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkCursor(const morkCursor& other);
morkCursor& operator=(const morkCursor& other);
public: // dynamic type identification
mork_bool IsCursor() const
{ return IsNode() && mNode_Derived == morkDerived_kCursor; }
// } ===== end morkNode methods =====
public: // other cursor methods
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakCursor(morkCursor* me,
morkEnv* ev, morkCursor** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongCursor(morkCursor* me,
morkEnv* ev, morkCursor** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKCURSOR_ */

View File

@@ -1,297 +0,0 @@
/*************************************************************************
This software is part of a public domain IronDoc source code distribution,
and is provided on an "AS IS" basis, with all risks borne by the consumers
or users of the IronDoc software. There are no warranties, guarantees, or
promises about quality of any kind; and no remedies for failure exist.
Permission is hereby granted to use this IronDoc software for any purpose
at all, without need for written agreements, without royalty or license
fees, and without fees or obligations of any other kind. Anyone can use,
copy, change and distribute this software for any purpose, and nothing is
required, implicitly or otherwise, in exchange for this usage.
You cannot apply your own copyright to this software, but otherwise you
are encouraged to enjoy the use of this software in any way you see fit.
However, it would be rude to remove names of developers from the code.
(IronDoc is also known by the short name "Fe" and a longer name "Ferrum",
which are used interchangeably with the name IronDoc in the sources.)
*************************************************************************/
/*
* File: morkDeque.cpp
* Contains: Ferrum deque (double ended queue (linked list))
*
* Copied directly from public domain IronDoc, with minor naming tweaks:
* Designed and written by David McCusker, but all this code is public domain.
* There are no warranties, no guarantees, no promises, and no remedies.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKDEQUE_
#include "morkDeque.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
/*=============================================================================
* morkNext: linked list node for very simple, singly-linked list
*/
morkNext::morkNext() : mNext_Link( 0 )
{
}
/*static*/ void*
morkNext::MakeNewNext(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev)
{
void* next = 0;
if ( &ioHeap )
{
ioHeap.Alloc(ev->AsMdbEnv(), inSize, (void**) &next);
if ( !next )
ev->OutOfMemoryError();
}
else
ev->NilPointerError();
return next;
}
/*static*/
void morkNext::ZapOldNext(morkEnv* ev, nsIMdbHeap* ioHeap)
{
if ( &ioHeap )
{
if ( this )
ioHeap->Free(ev->AsMdbEnv(), this);
}
else
ev->NilPointerError();
}
/*=============================================================================
* morkList: simple, singly-linked list
*/
morkList::morkList() : mList_Head( 0 ), mList_Tail( 0 )
{
}
void morkList::CutAndZapAllListMembers(morkEnv* ev, nsIMdbHeap* ioHeap)
// make empty list, zapping every member by calling ZapOldNext()
{
if ( ioHeap )
{
morkNext* next = 0;
while ( (next = this->PopHead()) != 0 )
next->ZapOldNext(ev, ioHeap);
mList_Head = 0;
mList_Tail = 0;
}
else
ev->NilPointerError();
}
void morkList::CutAllListMembers()
// just make list empty, dropping members without zapping
{
while ( this->PopHead() )
/* empty */;
mList_Head = 0;
mList_Tail = 0;
}
morkNext* morkList::PopHead() // cut head of list
{
morkNext* outHead = mList_Head;
if ( outHead ) // anything to cut from list?
{
morkNext* next = outHead->mNext_Link;
mList_Head = next;
if ( !next ) // cut the last member, so tail no longer exists?
mList_Tail = 0;
outHead->mNext_Link = 0; // nil outgoing node link; unnecessary, but tidy
}
return outHead;
}
void morkList::PushHead(morkNext* ioLink) // add to head of list
{
morkNext* head = mList_Head; // old head of list
morkNext* tail = mList_Tail; // old tail of list
MORK_ASSERT( (head && tail) || (!head && !tail));
ioLink->mNext_Link = head; // make old head follow the new link
if ( !head ) // list was previously empty?
mList_Tail = ioLink; // head is also tail for first member added
mList_Head = ioLink; // head of list is the new link
}
void morkList::PushTail(morkNext* ioLink) // add to tail of list
{
morkNext* head = mList_Head; // old head of list
morkNext* tail = mList_Tail; // old tail of list
MORK_ASSERT( (head && tail) || (!head && !tail));
ioLink->mNext_Link = tail; // make old tail follow the new link
if ( !tail ) // list was previously empty?
mList_Head = ioLink; // tail is also head for first member added
mList_Tail = ioLink; // tail of list is the new link
}
/*=============================================================================
* morkLink: linked list node embedded in objs to allow insertion in morkDeques
*/
morkLink::morkLink() : mLink_Next( 0 ), mLink_Prev( 0 )
{
}
/*static*/ void*
morkLink::MakeNewLink(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev)
{
void* link = 0;
if ( &ioHeap )
{
ioHeap.Alloc(ev->AsMdbEnv(), inSize, (void**) &link);
if ( !link )
ev->OutOfMemoryError();
}
else
ev->NilPointerError();
return link;
}
/*static*/
void morkLink::ZapOldLink(morkEnv* ev, nsIMdbHeap* ioHeap)
{
if ( &ioHeap )
{
if ( this )
ioHeap->Free(ev->AsMdbEnv(), this);
}
else
ev->NilPointerError();
}
/*=============================================================================
* morkDeque: doubly linked list modeled after VAX queue instructions
*/
morkDeque::morkDeque()
{
mDeque_Head.SelfRefer();
}
/*| RemoveFirst:
|*/
morkLink*
morkDeque::RemoveFirst() /*i*/
{
morkLink* link = mDeque_Head.mLink_Next;
if ( link != &mDeque_Head )
{
(mDeque_Head.mLink_Next = link->mLink_Next)->mLink_Prev =
&mDeque_Head;
return link;
}
return (morkLink*) 0;
}
/*| RemoveLast:
|*/
morkLink*
morkDeque::RemoveLast() /*i*/
{
morkLink* link = mDeque_Head.mLink_Prev;
if ( link != &mDeque_Head )
{
(mDeque_Head.mLink_Prev = link->mLink_Prev)->mLink_Next =
&mDeque_Head;
return link;
}
return (morkLink*) 0;
}
/*| At:
|*/
morkLink*
morkDeque::At(mork_pos index) const /*i*/
/* indexes are one based (and not zero based) */
{
register mork_num count = 0;
register morkLink* link;
for ( link = this->First(); link; link = this->After(link) )
{
if ( ++count == index )
break;
}
return link;
}
/*| IndexOf:
|*/
mork_pos
morkDeque::IndexOf(const morkLink* member) const /*i*/
/* indexes are one based (and not zero based) */
/* zero means member is not in deque */
{
register mork_num count = 0;
register const morkLink* link;
for ( link = this->First(); link; link = this->After(link) )
{
++count;
if ( member == link )
return (mork_pos) count;
}
return 0;
}
/*| Length:
|*/
mork_num
morkDeque::Length() const /*i*/
{
register mork_num count = 0;
register morkLink* link;
for ( link = this->First(); link; link = this->After(link) )
++count;
return count;
}
/*| LengthCompare:
|*/
int
morkDeque::LengthCompare(mork_num c) const /*i*/
{
register mork_num count = 0;
register const morkLink* link;
for ( link = this->First(); link; link = this->After(link) )
{
if ( ++count > c )
return 1;
}
return ( count == c )? 0 : -1;
}

View File

@@ -1,241 +0,0 @@
/*************************************************************************
This software is part of a public domain IronDoc source code distribution,
and is provided on an "AS IS" basis, with all risks borne by the consumers
or users of the IronDoc software. There are no warranties, guarantees, or
promises about quality of any kind; and no remedies for failure exist.
Permission is hereby granted to use this IronDoc software for any purpose
at all, without need for written agreements, without royalty or license
fees, and without fees or obligations of any other kind. Anyone can use,
copy, change and distribute this software for any purpose, and nothing is
required, implicitly or otherwise, in exchange for this usage.
You cannot apply your own copyright to this software, but otherwise you
are encouraged to enjoy the use of this software in any way you see fit.
However, it would be rude to remove names of developers from the code.
(IronDoc is also known by the short name "Fe" and a longer name "Ferrum",
which are used interchangeably with the name IronDoc in the sources.)
*************************************************************************/
/*
* File: morkDeque.h
* Contains: Ferrum deque (double ended queue (linked list))
*
* Copied directly from public domain IronDoc, with minor naming tweaks:
* Designed and written by David McCusker, but all this code is public domain.
* There are no warranties, no guarantees, no promises, and no remedies.
*/
#ifndef _MORKDEQUE_
#define _MORKDEQUE_ 1
#ifndef _MORK_
#include "mork.h"
#endif
/*=============================================================================
* morkNext: linked list node for very simple, singly-linked list
*/
class morkNext /*d*/ {
public:
morkNext* mNext_Link;
public:
morkNext(int inZero) : mNext_Link( 0 ) { }
morkNext(morkNext* ioLink) : mNext_Link( ioLink ) { }
morkNext(); // mNext_Link( 0 ), { }
public:
morkNext* GetNextLink() const { return mNext_Link; }
public: // link memory management methods
static void* MakeNewNext(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev);
void ZapOldNext(morkEnv* ev, nsIMdbHeap* ioHeap);
public: // link memory management operators
void* operator new(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev)
{ return morkNext::MakeNewNext(inSize, ioHeap, ev); }
void operator delete(void* ioAddress) // DO NOT CALL THIS, hope to crash:
{ ((morkNext*) 0)->ZapOldNext((morkEnv*) 0, (nsIMdbHeap*) 0); } // boom
};
/*=============================================================================
* morkList: simple, singly-linked list
*/
/*| morkList: a list of singly-linked members (instances of morkNext), where
**| the number of list members might be so numerous that we must about cost
**| for two pointer link slots per member (as happens with morkLink).
**|
**|| morkList is intended to support lists of changes in morkTable, where we
**| are worried about the space cost of representing such changes. (Later we
**| can use an array instead, when we get even more worried, to avoid cost
**| of link slots at all, per member).
**|
**|| Do NOT create cycles in links using this list class, since we do not
**| deal with them very nicely.
|*/
class morkList /*d*/ {
public:
morkNext* mList_Head; // first link in the list
morkNext* mList_Tail; // last link in the list
public:
morkNext* GetListHead() const { return mList_Head; }
morkNext* GetListTail() const { return mList_Tail; }
mork_bool IsListEmpty() const { return ( mList_Head == 0 ); }
mork_bool HasListMembers() const { return ( mList_Head != 0 ); }
public:
morkList(); // : mList_Head( 0 ), mList_Tail( 0 ) { }
void CutAndZapAllListMembers(morkEnv* ev, nsIMdbHeap* ioHeap);
// make empty list, zapping every member by calling ZapOldNext()
void CutAllListMembers();
// just make list empty, dropping members without zapping
public:
morkNext* PopHead(); // cut head of list
// Note we don't support PopTail(), so use morkDeque if you need that.
void PushHead(morkNext* ioLink); // add to head of list
void PushTail(morkNext* ioLink); // add to tail of list
};
/*=============================================================================
* morkLink: linked list node embedded in objs to allow insertion in morkDeques
*/
class morkLink /*d*/ {
public:
morkLink* mLink_Next;
morkLink* mLink_Prev;
public:
morkLink(int inZero) : mLink_Next( 0 ), mLink_Prev( 0 ) { }
morkLink(); // mLink_Next( 0 ), mLink_Prev( 0 ) { }
public:
morkLink* Next() const { return mLink_Next; }
morkLink* Prev() const { return mLink_Prev; }
void SelfRefer() { mLink_Next = mLink_Prev = this; }
void Clear() { mLink_Next = mLink_Prev = 0; }
void AddBefore(morkLink* old)
{
((old)->mLink_Prev->mLink_Next = (this))->mLink_Prev = (old)->mLink_Prev;
((this)->mLink_Next = (old))->mLink_Prev = this;
}
void AddAfter(morkLink* old)
{
((old)->mLink_Next->mLink_Prev = (this))->mLink_Next = (old)->mLink_Next;
((this)->mLink_Prev = (old))->mLink_Next = this;
}
void Remove()
{
(mLink_Prev->mLink_Next = mLink_Next)->mLink_Prev = mLink_Prev;
}
public: // link memory management methods
static void* MakeNewLink(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev);
void ZapOldLink(morkEnv* ev, nsIMdbHeap* ioHeap);
public: // link memory management operators
void* operator new(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev)
{ return morkLink::MakeNewLink(inSize, ioHeap, ev); }
void operator delete(void* ioAddress) // DO NOT CALL THIS, hope to crash:
{ ((morkLink*) 0)->ZapOldLink((morkEnv*) 0, (nsIMdbHeap*) 0); } // boom
};
/*=============================================================================
* morkDeque: doubly linked list modeled after VAX queue instructions
*/
class morkDeque /*d*/ {
public:
morkLink mDeque_Head;
public: // construction
morkDeque(); // { mDeque_Head.SelfRefer(); }
public:// methods
morkLink* RemoveFirst();
morkLink* RemoveLast();
morkLink* At(mork_pos index) const ; /* one-based, not zero-based */
mork_pos IndexOf(const morkLink* inMember) const;
/* one-based index ; zero means member is not in deque */
mork_num Length() const;
/* the following method is more efficient for long lists: */
int LengthCompare(mork_num inCount) const;
/* -1: length < count, 0: length == count, 1: length > count */
public: // inlines
mork_bool IsEmpty()const
{ return (mDeque_Head.mLink_Next == (morkLink*) &mDeque_Head); }
morkLink* After(const morkLink* old) const
{ return (((old)->mLink_Next != &mDeque_Head)?
(old)->mLink_Next : (morkLink*) 0); }
morkLink* Before(const morkLink* old) const
{ return (((old)->mLink_Prev != &mDeque_Head)?
(old)->mLink_Prev : (morkLink*) 0); }
morkLink* First() const
{ return ((mDeque_Head.mLink_Next != &mDeque_Head)?
mDeque_Head.mLink_Next : (morkLink*) 0); }
morkLink* Last() const
{ return ((mDeque_Head.mLink_Prev != &mDeque_Head)?
mDeque_Head.mLink_Prev : (morkLink*) 0); }
/*
From IronDoc documentation for AddFirst:
+--------+ +--------+ +--------+ +--------+ +--------+
| h.next |-->| b.next | | h.next |-->| a.next |-->| b.next |
+--------+ +--------+ ==> +--------+ +--------+ +--------+
| h.prev |<--| b.prev | | h.prev |<--| a.prev |<--| b.prev |
+--------+ +--------+ +--------+ +--------+ +--------+
*/
void AddFirst(morkLink* in) /*i*/
{
( (mDeque_Head.mLink_Next->mLink_Prev =
(in))->mLink_Next = mDeque_Head.mLink_Next,
((in)->mLink_Prev = &mDeque_Head)->mLink_Next = (in) );
}
/*
From IronDoc documentation for AddLast:
+--------+ +--------+ +--------+ +--------+ +--------+
| y.next |-->| h.next | | y.next |-->| z.next |-->| h.next |
+--------+ +--------+ ==> +--------+ +--------+ +--------+
| y.prev |<--| h.prev | | y.prev |<--| z.prev |<--| h.prev |
+--------+ +--------+ +--------+ +--------+ +--------+
*/
void AddLast(morkLink* in)
{
( (mDeque_Head.mLink_Prev->mLink_Next =
(in))->mLink_Prev = mDeque_Head.mLink_Prev,
((in)->mLink_Next = &mDeque_Head)->mLink_Prev = (in) );
}
};
#endif /* _MORKDEQUE_ */

View File

@@ -1,492 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#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 _ORKINENV_
#include "orkinEnv.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
{
MORK_ASSERT(mEnv_SelfAsMdbEnv==0);
MORK_ASSERT(mEnv_ErrorHook==0);
}
/*public non-poly*/
morkEnv::morkEnv(const morkUsage& inUsage, nsIMdbHeap* ioHeap,
morkFactory* ioFactory, nsIMdbHeap* ioSlotHeap)
: morkObject(inUsage, ioHeap)
, mEnv_Factory( ioFactory )
, mEnv_Heap( ioSlotHeap )
, mEnv_SelfAsMdbEnv( 0 )
, mEnv_ErrorHook( 0 )
, mEnv_HandlePool( 0 )
, mEnv_ErrorCount( 0 )
, mEnv_WarningCount( 0 )
, mEnv_ErrorCode( 0 )
, mEnv_DoTrace( morkBool_kFalse )
, mEnv_AutoClear( morkAble_kDisabled )
, mEnv_ShouldAbort( morkBool_kFalse )
, mEnv_BeVerbose( 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, (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( 0 )
, mEnv_DoTrace( morkBool_kFalse )
, mEnv_AutoClear( morkAble_kDisabled )
, mEnv_ShouldAbort( morkBool_kFalse )
, mEnv_BeVerbose( 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();
}
/*public non-poly*/ void
morkEnv::CloseEnv(morkEnv* ev) /*i*/ // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
// $$$ release mEnv_SelfAsMdbEnv??
// $$$ release mEnv_ErrorHook??
mEnv_SelfAsMdbEnv = 0;
mEnv_ErrorHook = 0;
morkPool::SlotStrongPool((morkPool*) 0, ev, &mEnv_HandlePool);
// mEnv_Factory is NOT refcounted
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== 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();
}
nsIMdbEnv*
morkEnv::AcquireEnvHandle(morkEnv* ev)
{
nsIMdbEnv* outEnv = 0;
orkinEnv* e = (orkinEnv*) mObject_Handle;
if ( e ) // have an old handle?
e->AddStrongRef(ev->AsMdbEnv());
else // need new handle?
{
e = orkinEnv::MakeEnv(ev, this);
mObject_Handle = e;
}
if ( e )
outEnv = e;
return outEnv;
}
void
morkEnv::NewErrorAndCode(const char* inString, mork_u2 inCode)
{
MORK_ASSERT(morkBool_kFalse); // get developer's attention
++mEnv_ErrorCount;
mEnv_ErrorCode = (mork_u4) ((inCode)? inCode: morkEnv_kGenericError);
if ( mEnv_ErrorHook )
mEnv_ErrorHook->OnErrorString(this->AsMdbEnv(), inString);
}
void
morkEnv::NewError(const char* inString)
{
MORK_ASSERT(morkBool_kFalse); // get developer's attention
++mEnv_ErrorCount;
mEnv_ErrorCode = morkEnv_kGenericError;
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()");
}
void
morkEnv::NilPointerError()
{
this->NewError("nil pointer");
}
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 = 0;
mEnv_ShouldAbort = morkBool_kFalse;
}
void
morkEnv::AutoClearMorkErrorsAndWarnings()
{
if ( this->DoAutoClear() )
{
mEnv_ErrorCount = 0;
mEnv_WarningCount = 0;
mEnv_ErrorCode = 0;
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).
orkinEnv* oenv = (orkinEnv*) ioEnv;
if ( oenv->IsHandle() )
{
if ( oenv->IsOpenNode() )
{
morkEnv* ev = (morkEnv*) oenv->mHandle_Object;
if ( ev && ev->IsEnv() )
{
if ( ev->DoAutoClear() )
{
ev->mEnv_ErrorCount = 0;
ev->mEnv_WarningCount = 0;
ev->mEnv_ErrorCode = 0;
}
outEnv = ev;
}
else
MORK_ASSERT(outEnv);
}
else
MORK_ASSERT(outEnv);
}
else
MORK_ASSERT(outEnv);
}
else
MORK_ASSERT(outEnv);
return outEnv;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,191 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKENV_
#define _MORKENV_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKOBJECT_
#include "morkObject.h"
#endif
#ifndef _MORKPOOL_
#include "morkPool.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kEnv /*i*/ 0x4576 /* ascii 'Ev' */
#define morkEnv_kNoError 0 /* no error has happened */
#define morkEnv_kGenericError 1 /* non-specific error code */
#define morkEnv_kNonEnvTypeError 2 /* morkEnv::IsEnv() is false */
#define morkEnv_kStubMethodOnlyError 3
#define morkEnv_kOutOfMemoryError 4
#define morkEnv_kNilPointerError 5
#define morkEnv_kNewNonEnvError 6
#define morkEnv_kNilEnvSlotError 7
#define morkEnv_kBadFactoryError 8
#define morkEnv_kBadFactoryEnvError 9
#define morkEnv_kBadEnvError 10
#define morkEnv_kNonHandleTypeError 11
#define morkEnv_kNonOpenNodeError 12
#define morkEnv_kWeakRefCountEnvBonus 16 /* try to leak all env instances */
/*| morkEnv:
|*/
class morkEnv : public morkObject {
// 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
// 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;
mork_u4 mEnv_ErrorCode; // simple basis for mdb_err style errors
mork_bool mEnv_DoTrace;
mork_able mEnv_AutoClear;
mork_bool mEnv_ShouldAbort;
mork_bool mEnv_BeVerbose;
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseEnv() only if open
virtual ~morkEnv(); // assert that CloseEnv() executed earlier
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
nsIMdbEnv* AcquireEnvHandle(morkEnv* ev); // mObject_Handle
// alloc and free individual handles in mEnv_HandlePool:
morkHandleFace* NewHandle(mork_size inSize)
{ return mEnv_HandlePool->NewHandle(this, inSize); }
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 NewErrorAndCode(const char* inString, mork_u2 inCode);
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 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 mEnv_SelfAsMdbEnv; }
static morkEnv* FromMdbEnv(nsIMdbEnv* ioEnv); // dynamic type checking
mork_u4 ErrorCode() const { return mEnv_ErrorCode; }
mdb_err AsErr() const { return (mdb_err) mEnv_ErrorCode; }
//mdb_err AsErr() const { return (mdb_err) ( mEnv_ErrorCount != 0 ); }
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); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKENV_ */

View File

@@ -1,159 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKOBJECT_
#include "morkObject.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKFACTORY_
#include "morkFactory.h"
#endif
#ifndef _ORKINFACTORY_
#include "orkinFactory.h"
#endif
#ifndef _ORKINHEAP_
#include "orkinHeap.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkFactory::CloseMorkNode(morkEnv* ev) /*i*/ // CloseFactory() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseFactory(ev);
this->MarkShut();
}
}
/*public virtual*/
morkFactory::~morkFactory() /*i*/ // assert CloseFactory() executed earlier
{
MORK_ASSERT(mFactory_Env.IsShutNode());
MORK_ASSERT(this->IsShutNode());
}
/*public non-poly*/
morkFactory::morkFactory() // uses orkinHeap
: morkObject(morkUsage::kGlobal, (nsIMdbHeap*) 0)
, mFactory_Env(morkUsage::kMember, (nsIMdbHeap*) 0, this,
new orkinHeap())
, mFactory_Heap()
{
if ( mFactory_Env.Good() )
{
mNode_Derived = morkDerived_kFactory;
mNode_Refs += morkFactory_kWeakRefCountBonus;
}
}
/*public non-poly*/
morkFactory::morkFactory(nsIMdbHeap* ioHeap)
: morkObject(morkUsage::kHeap, ioHeap)
, mFactory_Env(morkUsage::kMember, (nsIMdbHeap*) 0, this, ioHeap)
, mFactory_Heap()
{
if ( mFactory_Env.Good() )
{
mNode_Derived = morkDerived_kFactory;
mNode_Refs += morkFactory_kWeakRefCountBonus;
}
}
/*public non-poly*/
morkFactory::morkFactory(morkEnv* ev, /*i*/
const morkUsage& inUsage, nsIMdbHeap* ioHeap)
: morkObject(ev, inUsage, ioHeap, (morkHandle*) 0)
, mFactory_Env(morkUsage::kMember, (nsIMdbHeap*) 0, this, ioHeap)
, mFactory_Heap()
{
if ( ev->Good() )
{
mNode_Derived = morkDerived_kFactory;
mNode_Refs += morkFactory_kWeakRefCountBonus;
}
}
/*public non-poly*/ void
morkFactory::CloseFactory(morkEnv* ev) /*i*/ // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
mFactory_Env.CloseMorkNode(ev);
this->CloseObject(ev);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
nsIMdbFactory*
morkFactory::AcquireFactoryHandle(morkEnv* ev) // mObject_Handle
{
nsIMdbFactory* outFactory = 0;
orkinFactory* f = (orkinFactory*) mObject_Handle;
if ( f ) // have an old handle?
f->AddStrongRef(ev->AsMdbEnv());
else // need new handle?
{
f = orkinFactory::MakeFactory(ev, this);
mObject_Handle = f;
}
if ( f )
outFactory = f;
return outFactory;
}
void
morkFactory::NonFactoryTypeError(morkEnv* ev)
{
ev->NewError("non morkFactory");
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,117 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKFACTORY_
#define _MORKFACTORY_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKOBJECT_
#include "morkObject.h"
#endif
#ifndef _ORKINHEAP_
#include "orkinHeap.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
class nsIMdbFactory;
#define morkDerived_kFactory /*i*/ 0x4663 /* ascii 'Fc' */
#define morkFactory_kWeakRefCountBonus 16 /* try to leak all factories */
/*| morkFactory:
|*/
class morkFactory : public morkObject { // nsIMdbObject
// public: // slots inherited from morkObject (meant to inform only)
// nsIMdbHeap* mNode_Heap;
// mork_able mNode_Mutable; // can this node be modified?
// mork_load mNode_Load; // is this node clean or dirty?
// 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_uses mNode_Uses; // refcount for strong refs
// mork_refs mNode_Refs; // refcount for strong refs + weak refs
// morkHandle* mObject_Handle; // weak ref to handle for this object
public: // state is public because the entire Mork system is private
morkEnv mFactory_Env; // private env instance used internally
orkinHeap mFactory_Heap;
// { ===== begin morkNode interface =====
public: // morkFactory virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseFactory() only if open
virtual ~morkFactory(); // assert that CloseFactory() executed earlier
public: // morkYarn construction & destruction
morkFactory(); // uses orkinHeap
morkFactory(nsIMdbHeap* ioHeap); // caller supplied heap
morkFactory(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap);
void CloseFactory(morkEnv* ev); // called by CloseMorkNode();
public: // morkNode memory management operators
void* operator new(size_t inSize)
{ return ::operator new(inSize); }
void* operator new(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev)
{ return morkNode::MakeNew(inSize, ioHeap, ev); }
void operator delete(void* ioAddress)
{ morkNode::OnDeleteAssert(ioAddress); }
// do NOT call delete on morkNode instances. Call ZapOld() instead.
private: // copying is not allowed
morkFactory(const morkFactory& other);
morkFactory& operator=(const morkFactory& other);
public: // dynamic type identification
mork_bool IsFactory() const
{ return IsNode() && mNode_Derived == morkDerived_kFactory; }
// } ===== end morkNode methods =====
public: // other factory methods
nsIMdbFactory* AcquireFactoryHandle(morkEnv* ev); // mObject_Handle
void NonFactoryTypeError(morkEnv* ev);
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakFactory(morkFactory* me,
morkEnv* ev, morkFactory** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongFactory(morkFactory* me,
morkEnv* ev, morkFactory** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKFACTORY_ */

View File

@@ -1,813 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKFILE_
#include "morkFile.h"
#endif
// #ifndef _ORKINFILE_
// #include "orkinFile.h"
// #endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkFile::CloseMorkNode(morkEnv* ev) // CloseFile() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseFile(ev);
this->MarkShut();
}
}
/*public virtual*/
morkFile::~morkFile() // assert CloseFile() executed earlier
{
MORK_ASSERT(mFile_Frozen==0);
MORK_ASSERT(mFile_DoTrace==0);
MORK_ASSERT(mFile_IoOpen==0);
MORK_ASSERT(mFile_Active==0);
}
/*public non-poly*/
morkFile::morkFile(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
: morkObject(ev, inUsage, ioHeap, (morkHandle*) 0)
, mFile_Frozen( 0 )
, mFile_DoTrace( 0 )
, mFile_IoOpen( 0 )
, mFile_Active( 0 )
, mFile_SlotHeap( 0 )
, mFile_Name( 0 )
, mFile_Thief( 0 )
{
if ( ev->Good() )
{
if ( ioSlotHeap )
{
nsIMdbHeap_SlotStrongHeap(ioSlotHeap, ev, &mFile_SlotHeap);
if ( ev->Good() )
mNode_Derived = morkDerived_kFile;
}
else
ev->NilPointerError();
}
}
/*public non-poly*/ void
morkFile::CloseFile(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
mFile_Frozen = 0;
mFile_DoTrace = 0;
mFile_IoOpen = 0;
mFile_Active = 0;
if ( mFile_Name )
this->SetFileName(ev, (const char*) 0);
nsIMdbHeap_SlotStrongHeap((nsIMdbHeap*) 0, ev, &mFile_SlotHeap);
nsIMdbFile_SlotStrongFile((nsIMdbFile*) 0, ev, &mFile_Thief);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
nsIMdbFile*
morkFile::AcquireFileHandle(morkEnv* ev)
{
nsIMdbFile* outFile = 0;
#ifdef MORK_CONFIG_USE_ORKINFILE
orkinFile* f = (orkinFile*) mObject_Handle;
if ( f ) // have an old handle?
f->AddStrongRef(ev->AsMdbEnv());
else // need new handle?
{
f = orkinFile::MakeFile(ev, this);
mObject_Handle = f;
}
if ( f )
outFile = f;
#endif /*MORK_CONFIG_USE_ORKINFILE*/
MORK_USED_1(ev);
return outFile;
}
/*virtual*/ void
morkFile::BecomeTrunk(morkEnv* ev)
// If this file is a file version branch created by calling AcquireBud(),
// BecomeTrunk() causes this file's content to replace the original
// file's content, typically by assuming the original file's identity.
// This default implementation of BecomeTrunk() does nothing, and this
// is appropriate behavior for files which are not branches, and is
// also the right behavior for files returned from AcquireBud() which are
// in fact the original file that has been truncated down to zero length.
{
this->Flush(ev);
}
/*static*/ morkFile*
morkFile::OpenOldFile(morkEnv* ev, nsIMdbHeap* ioHeap,
const char* inFilePath, mork_bool inFrozen)
// Choose some subclass of morkFile to instantiate, in order to read
// (and write if not frozen) the file known by inFilePath. The file
// returned should be open and ready for use, and presumably positioned
// at the first byte position of the file. The exact manner in which
// files must be opened is considered a subclass specific detail, and
// other portions or Mork source code don't want to know how it's done.
{
return morkStdioFile::OpenOldStdioFile(ev, ioHeap, inFilePath, inFrozen);
}
/*static*/ morkFile*
morkFile::CreateNewFile(morkEnv* ev, nsIMdbHeap* ioHeap,
const char* inFilePath)
// Choose some subclass of morkFile to instantiate, in order to read
// (and write if not frozen) the file known by inFilePath. The file
// returned should be created and ready for use, and presumably positioned
// at the first byte position of the file. The exact manner in which
// files must be opened is considered a subclass specific detail, and
// other portions or Mork source code don't want to know how it's done.
{
return morkStdioFile::CreateNewStdioFile(ev, ioHeap, inFilePath);
}
void
morkFile::NewMissingIoError(morkEnv* ev) const
{
ev->NewError("file missing io");
}
/*static*/ void
morkFile::NonFileTypeError(morkEnv* ev)
{
ev->NewError("non morkFile");
}
/*static*/ void
morkFile::NilSlotHeapError(morkEnv* ev)
{
ev->NewError("nil mFile_SlotHeap");
}
/*static*/ void
morkFile::NilFileNameError(morkEnv* ev)
{
ev->NewError("nil mFile_Name");
}
void
morkFile::SetThief(morkEnv* ev, nsIMdbFile* ioThief)
{
nsIMdbFile_SlotStrongFile(ioThief, ev, &mFile_Thief);
}
void
morkFile::SetFileName(morkEnv* ev, const char* inName) // inName can be nil
{
nsIMdbHeap* heap = mFile_SlotHeap;
if ( heap )
{
char* name = mFile_Name;
if ( name )
{
mFile_Name = 0;
ev->FreeString(heap, name);
}
if ( ev->Good() && inName )
mFile_Name = ev->CopyString(heap, inName);
}
else
this->NilSlotHeapError(ev);
}
void
morkFile::NewFileDownError(morkEnv* ev) const
// call NewFileDownError() when either IsOpenAndActiveFile()
// is false, or when IsOpenActiveAndMutableFile() is false.
{
if ( this->IsOpenNode() )
{
if ( this->FileActive() )
{
if ( this->FileFrozen() )
{
ev->NewError("file frozen");
}
else
ev->NewError("unknown file problem");
}
else
ev->NewError("file not active");
}
else
ev->NewError("file not open");
}
void
morkFile::NewFileErrnoError(morkEnv* ev) const
// call NewFileErrnoError() to convert std C errno into AB fault
{
const char* errnoString = strerror(errno);
ev->NewError(errnoString); // maybe pass value of strerror() instead
}
// ````` ````` ````` ````` newlines ````` ````` ````` `````
#if defined(MORK_MAC) || defined(MORK_OBSOLETE)
static const char* morkFile_kNewlines =
"\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015";
# define morkFile_kNewlinesCount 16
#else
# if defined(MORK_WIN) || defined(MORK_OS2)
static const char* morkFile_kNewlines =
"\015\012\015\012\015\012\015\012\015\012\015\012\015\012\015\012";
# define morkFile_kNewlinesCount 8
# else
# if defined(MORK_UNIX) || defined(MORK_BEOS)
static const char* morkFile_kNewlines =
"\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012";
# define morkFile_kNewlinesCount 16
# endif /* MORK_UNIX || MORK_BEOS */
# endif /* MORK_WIN */
#endif /* MORK_MAC */
mork_size
morkFile::WriteNewlines(morkEnv* ev, mork_count inNewlines)
// WriteNewlines() returns the number of bytes written.
{
mork_size outSize = 0;
while ( inNewlines && ev->Good() ) // more newlines to write?
{
mork_u4 quantum = inNewlines;
if ( quantum > morkFile_kNewlinesCount )
quantum = morkFile_kNewlinesCount;
mork_size quantumSize = quantum * mork_kNewlineSize;
this->Write(ev, morkFile_kNewlines, quantumSize);
outSize += quantumSize;
inNewlines -= quantum;
}
return outSize;
}
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkStdioFile::CloseMorkNode(morkEnv* ev) // CloseStdioFile() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseStdioFile(ev);
this->MarkShut();
}
}
/*public virtual*/
morkStdioFile::~morkStdioFile() // assert CloseStdioFile() executed earlier
{
MORK_ASSERT(mStdioFile_File==0);
}
/*public non-poly*/ void
morkStdioFile::CloseStdioFile(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
if ( mStdioFile_File && this->FileActive() && this->FileIoOpen() )
{
this->CloseStdio(ev);
}
mStdioFile_File = 0;
this->CloseFile(ev);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
// compatible with the morkFile::MakeFile() entry point
/*static*/ morkStdioFile*
morkStdioFile::OpenOldStdioFile(morkEnv* ev, nsIMdbHeap* ioHeap,
const char* inFilePath, mork_bool inFrozen)
{
morkStdioFile* outFile = 0;
if ( ioHeap && inFilePath )
{
const char* mode = (inFrozen)? "rb" : "rb+";
outFile = new(*ioHeap, ev)
morkStdioFile(ev, morkUsage::kHeap, ioHeap, ioHeap, inFilePath, mode);
if ( outFile )
{
outFile->SetFileFrozen(inFrozen);
}
}
else
ev->NilPointerError();
return outFile;
}
/*static*/ morkStdioFile*
morkStdioFile::CreateNewStdioFile(morkEnv* ev, nsIMdbHeap* ioHeap,
const char* inFilePath)
{
morkStdioFile* outFile = 0;
if ( ioHeap && inFilePath )
{
const char* mode = "wb+";
outFile = new(*ioHeap, ev)
morkStdioFile(ev, morkUsage::kHeap, ioHeap, ioHeap, inFilePath, mode);
}
else
ev->NilPointerError();
return outFile;
}
/*public virtual*/ void
morkStdioFile::BecomeTrunk(morkEnv* ev)
// If this file is a file version branch created by calling AcquireBud(),
// BecomeTrunk() causes this file's content to replace the original
// file's content, typically by assuming the original file's identity.
{
this->Flush(ev);
}
/*public virtual*/ morkFile*
morkStdioFile::AcquireBud(morkEnv* ev, nsIMdbHeap* ioHeap)
// AcquireBud() starts a new "branch" version of the file, empty of content,
// so that a new version of the file can be written. This new file
// can later be told to BecomeTrunk() the original file, so the branch
// created by budding the file will replace the original file. Some
// file subclasses might initially take the unsafe but expedient
// approach of simply truncating this file down to zero length, and
// then returning the same morkFile pointer as this, with an extra
// reference count increment. Note that the caller of AcquireBud() is
// expected to eventually call CutStrongRef() on the returned file
// in order to release the strong reference. High quality versions
// of morkFile subclasses will create entirely new files which later
// are renamed to become the old file, so that better transactional
// behavior is exhibited by the file, so crashes protect old files.
// Note that AcquireBud() is an illegal operation on readonly files.
{
MORK_USED_1(ioHeap);
morkFile* outFile = 0;
if ( this->IsOpenAndActiveFile() )
{
FILE* file = (FILE*) mStdioFile_File;
if ( file )
{
//#ifdef MORK_WIN
// truncate(file, /*eof*/ 0);
//#else /*MORK_WIN*/
char* name = mFile_Name;
if ( name )
{
if ( MORK_FILECLOSE(file) >= 0 )
{
this->SetFileActive(morkBool_kFalse);
this->SetFileIoOpen(morkBool_kFalse);
mStdioFile_File = 0;
file = fopen(name, "wb+"); // open for write, discarding old content
if ( file )
{
mStdioFile_File = file;
this->SetFileActive(morkBool_kTrue);
this->SetFileIoOpen(morkBool_kTrue);
this->SetFileFrozen(morkBool_kFalse);
}
else
this->new_stdio_file_fault(ev);
}
else
this->new_stdio_file_fault(ev);
}
else
this->NilFileNameError(ev);
//#endif /*MORK_WIN*/
if ( ev->Good() && this->AddStrongRef(ev) )
outFile = this;
}
else if ( mFile_Thief )
{
nsIMdbFile* outBud = 0;
mFile_Thief->AcquireBud(ev->AsMdbEnv(), ioHeap, &outBud);
if ( outBud )
outBud->CutStrongRef(ev->AsMdbEnv()); // convert to morkFile later
}
else
this->NewMissingIoError(ev);
}
else this->NewFileDownError(ev);
return outFile;
}
/*public virtual*/ mork_pos
morkStdioFile::Length(morkEnv* ev) const
{
mork_pos outPos = 0;
if ( this->IsOpenAndActiveFile() )
{
FILE* file = (FILE*) mStdioFile_File;
if ( file )
{
long start = MORK_FILETELL(file);
if ( start >= 0 )
{
long fore = MORK_FILESEEK(file, 0, SEEK_END);
if ( fore >= 0 )
{
long eof = MORK_FILETELL(file);
if ( eof >= 0 )
{
long back = MORK_FILESEEK(file, start, SEEK_SET);
if ( back >= 0 )
outPos = eof;
else
this->new_stdio_file_fault(ev);
}
else this->new_stdio_file_fault(ev);
}
else this->new_stdio_file_fault(ev);
}
else this->new_stdio_file_fault(ev);
}
else if ( mFile_Thief )
mFile_Thief->Eof(ev->AsMdbEnv(), &outPos);
else
this->NewMissingIoError(ev);
}
else this->NewFileDownError(ev);
return outPos;
}
/*public virtual*/ mork_pos
morkStdioFile::Tell(morkEnv* ev) const
{
mork_pos outPos = 0;
if ( this->IsOpenAndActiveFile() )
{
FILE* file = (FILE*) mStdioFile_File;
if ( file )
{
long where = MORK_FILETELL(file);
if ( where >= 0 )
outPos = where;
else
this->new_stdio_file_fault(ev);
}
else if ( mFile_Thief )
mFile_Thief->Tell(ev->AsMdbEnv(), &outPos);
else
this->NewMissingIoError(ev);
}
else this->NewFileDownError(ev);
return outPos;
}
/*public virtual*/ mork_size
morkStdioFile::Read(morkEnv* ev, void* outBuf, mork_size inSize)
{
mork_num outCount = 0;
if ( this->IsOpenAndActiveFile() )
{
FILE* file = (FILE*) mStdioFile_File;
if ( file )
{
long count = (long) MORK_FILEREAD(outBuf, inSize, file);
if ( count >= 0 )
{
outCount = (mork_num) count;
}
else this->new_stdio_file_fault(ev);
}
else if ( mFile_Thief )
mFile_Thief->Read(ev->AsMdbEnv(), outBuf, inSize, &outCount);
else
this->NewMissingIoError(ev);
}
else this->NewFileDownError(ev);
return outCount;
}
/*public virtual*/ mork_pos
morkStdioFile::Seek(morkEnv* ev, mork_pos inPos)
{
mork_pos outPos = 0;
if ( this->IsOpenOrClosingNode() && this->FileActive() )
{
FILE* file = (FILE*) mStdioFile_File;
if ( file )
{
long where = MORK_FILESEEK(file, inPos, SEEK_SET);
if ( where >= 0 )
outPos = inPos;
else
this->new_stdio_file_fault(ev);
}
else if ( mFile_Thief )
mFile_Thief->Seek(ev->AsMdbEnv(), inPos);
else
this->NewMissingIoError(ev);
}
else this->NewFileDownError(ev);
return outPos;
}
/*public virtual*/ mork_size
morkStdioFile::Write(morkEnv* ev, const void* inBuf, mork_size inSize)
{
mork_num outCount = 0;
if ( this->IsOpenActiveAndMutableFile() )
{
FILE* file = (FILE*) mStdioFile_File;
if ( file )
{
fwrite(inBuf, 1, inSize, file);
if ( !ferror(file) )
outCount = inSize;
else
this->new_stdio_file_fault(ev);
}
else if ( mFile_Thief )
mFile_Thief->Write(ev->AsMdbEnv(), inBuf, inSize, &outCount);
else
this->NewMissingIoError(ev);
}
else this->NewFileDownError(ev);
return outCount;
}
/*public virtual*/ void
morkStdioFile::Flush(morkEnv* ev)
{
if ( this->IsOpenOrClosingNode() && this->FileActive() )
{
FILE* file = (FILE*) mStdioFile_File;
if ( file )
{
MORK_FILEFLUSH(file);
}
else if ( mFile_Thief )
mFile_Thief->Flush(ev->AsMdbEnv());
else
this->NewMissingIoError(ev);
}
else this->NewFileDownError(ev);
}
// ````` ````` ````` ````` ````` ````` ````` `````
//protected: // protected non-poly morkStdioFile methods
void
morkStdioFile::new_stdio_file_fault(morkEnv* ev) const
{
FILE* file = (FILE*) mStdioFile_File;
int copyErrno = errno; // facilitate seeing error in debugger
// bunch of stuff not ported here
if ( !copyErrno && file )
{
copyErrno = ferror(file);
errno = copyErrno;
}
this->NewFileErrnoError(ev);
}
// ````` ````` ````` ````` ````` ````` ````` `````
//public: // public non-poly morkStdioFile methods
/*public non-poly*/
morkStdioFile::morkStdioFile(morkEnv* ev,
const morkUsage& inUsage, nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
: morkFile(ev, inUsage, ioHeap, ioSlotHeap)
, mStdioFile_File( 0 )
{
if ( ev->Good() )
mNode_Derived = morkDerived_kStdioFile;
}
morkStdioFile::morkStdioFile(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap,
const char* inName, const char* inMode)
// calls OpenStdio() after construction
: morkFile(ev, inUsage, ioHeap, ioSlotHeap)
, mStdioFile_File( 0 )
{
if ( ev->Good() )
this->OpenStdio(ev, inName, inMode);
}
morkStdioFile::morkStdioFile(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap,
void* ioFile, const char* inName, mork_bool inFrozen)
// calls UseStdio() after construction
: morkFile(ev, inUsage, ioHeap, ioSlotHeap)
, mStdioFile_File( 0 )
{
if ( ev->Good() )
this->UseStdio(ev, ioFile, inName, inFrozen);
}
void
morkStdioFile::OpenStdio(morkEnv* ev, const char* inName, const char* inMode)
// Open a new FILE with name inName, using mode flags from inMode.
{
if ( ev->Good() )
{
if ( !inMode )
inMode = "";
mork_bool frozen = (*inMode == 'r'); // cursory attempt to note readonly
if ( this->IsOpenNode() )
{
if ( !this->FileActive() )
{
this->SetFileIoOpen(morkBool_kFalse);
if ( inName && *inName )
{
this->SetFileName(ev, inName);
if ( ev->Good() )
{
FILE* file = fopen(inName, inMode);
if ( file )
{
mStdioFile_File = file;
this->SetFileActive(morkBool_kTrue);
this->SetFileIoOpen(morkBool_kTrue);
this->SetFileFrozen(frozen);
}
else
this->new_stdio_file_fault(ev);
}
}
else ev->NewError("no file name");
}
else ev->NewError("file already active");
}
else this->NewFileDownError(ev);
}
}
void
morkStdioFile::UseStdio(morkEnv* ev, void* ioFile, const char* inName,
mork_bool inFrozen)
// Use an existing file, like stdin/stdout/stderr, which should not
// have the io stream closed when the file is closed. The ioFile
// parameter must actually be of type FILE (but we don't want to make
// this header file include the stdio.h header file).
{
if ( ev->Good() )
{
if ( this->IsOpenNode() )
{
if ( !this->FileActive() )
{
if ( ioFile )
{
this->SetFileIoOpen(morkBool_kFalse);
this->SetFileName(ev, inName);
if ( ev->Good() )
{
mStdioFile_File = ioFile;
this->SetFileActive(morkBool_kTrue);
this->SetFileFrozen(inFrozen);
}
}
else
ev->NilPointerError();
}
else ev->NewError("file already active");
}
else this->NewFileDownError(ev);
}
}
void
morkStdioFile::CloseStdio(morkEnv* ev)
// Close the stream io if both and FileActive() and FileIoOpen(), but
// this does not close this instances (like CloseStdioFile() does).
// If stream io was made active by means of calling UseStdio(),
// then this method does little beyond marking the stream inactive
// because FileIoOpen() is false.
{
if ( mStdioFile_File && this->FileActive() && this->FileIoOpen() )
{
FILE* file = (FILE*) mStdioFile_File;
if ( MORK_FILECLOSE(file) < 0 )
this->new_stdio_file_fault(ev);
mStdioFile_File = 0;
this->SetFileActive(morkBool_kFalse);
this->SetFileIoOpen(morkBool_kFalse);
}
}
/*public virtual*/ void
morkStdioFile::Steal(morkEnv* ev, nsIMdbFile* ioThief)
// If this file is a file version branch created by calling AcquireBud(),
// BecomeTrunk() causes this file's content to replace the original
// file's content, typically by assuming the original file's identity.
{
if ( mStdioFile_File && this->FileActive() && this->FileIoOpen() )
{
FILE* file = (FILE*) mStdioFile_File;
if ( MORK_FILECLOSE(file) < 0 )
this->new_stdio_file_fault(ev);
mStdioFile_File = 0;
}
this->SetThief(ev, ioThief);
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,352 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKFILE_
#define _MORKFILE_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKOBJECT_
#include "morkObject.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/*=============================================================================
* morkFile: abstract file interface
*/
#define morkDerived_kFile /*i*/ 0x4669 /* ascii 'Fi' */
class morkFile /*d*/ : public morkObject { /* ````` simple file API ````` */
// public: // slots inherited from morkNode (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
// public: // slots inherited from morkObject (meant to inform only)
// morkHandle* mObject_Handle; // weak ref to handle for this object
// ````` ````` ````` ````` ````` ````` ````` `````
protected: // protected morkFile members (similar to public domain IronDoc)
mork_u1 mFile_Frozen; // 'F' => file allows only read access
mork_u1 mFile_DoTrace; // 'T' trace if ev->DoTrace()
mork_u1 mFile_IoOpen; // 'O' => io stream is open (& needs a close)
mork_u1 mFile_Active; // 'A' => file is active and usable
nsIMdbHeap* mFile_SlotHeap; // heap for Name and other allocated slots
char* mFile_Name; // can be nil if SetFileName() is never called
// mFile_Name convention: managed with morkEnv::CopyString()/FreeString()
nsIMdbFile* mFile_Thief; // from a call to orkinFile::Steal()
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseFile() only if open
virtual ~morkFile(); // assert that CloseFile() executed earlier
public: // morkFile construction & destruction
morkFile(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap,
nsIMdbHeap* ioSlotHeap);
void CloseFile(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkFile(const morkFile& other);
morkFile& operator=(const morkFile& other);
public: // dynamic type identification
mork_bool IsFile() const
{ return IsNode() && mNode_Derived == morkDerived_kFile; }
// } ===== end morkNode methods =====
// ````` ````` ````` ````` ````` ````` ````` `````
public: // public static standard file creation entry point
static morkFile* OpenOldFile(morkEnv* ev, nsIMdbHeap* ioHeap,
const char* inFilePath, mork_bool inFrozen);
// Choose some subclass of morkFile to instantiate, in order to read
// (and write if not frozen) the file known by inFilePath. The file
// returned should be open and ready for use, and presumably positioned
// at the first byte position of the file. The exact manner in which
// files must be opened is considered a subclass specific detail, and
// other portions or Mork source code don't want to know how it's done.
static morkFile* CreateNewFile(morkEnv* ev, nsIMdbHeap* ioHeap,
const char* inFilePath);
// Choose some subclass of morkFile to instantiate, in order to read
// (and write if not frozen) the file known by inFilePath. The file
// returned should be created and ready for use, and presumably positioned
// at the first byte position of the file. The exact manner in which
// files must be opened is considered a subclass specific detail, and
// other portions or Mork source code don't want to know how it's done.
// ````` ````` ````` ````` ````` ````` ````` `````
public: // virtual morkFile methods
virtual void Steal(morkEnv* ev, nsIMdbFile* ioThief) = 0;
// Steal: tell this file to close any associated i/o stream in the file
// system, because the file ioThief intends to reopen the file in order
// to provide the MDB implementation with more exotic file access than is
// offered by the nsIMdbFile alone. Presumably the thief knows enough
// from Path() in order to know which file to reopen. If Steal() is
// successful, this file should probably delegate all future calls to
// the nsIMdbFile interface down to the thief files, so that even after
// the file has been stolen, it can still be read, written, or forcibly
// closed (by a call to CloseMdbObject()).
virtual void BecomeTrunk(morkEnv* ev);
// If this file is a file version branch created by calling AcquireBud(),
// BecomeTrunk() causes this file's content to replace the original
// file's content, typically by assuming the original file's identity.
// This default implementation of BecomeTrunk() does nothing, and this
// is appropriate behavior for files which are not branches, and is
// also the right behavior for files returned from AcquireBud() which are
// in fact the original file that has been truncated down to zero length.
virtual morkFile* AcquireBud(morkEnv* ev, nsIMdbHeap* ioHeap) = 0;
// AcquireBud() starts a new "branch" version of the file, empty of content,
// so that a new version of the file can be written. This new file
// can later be told to BecomeTrunk() the original file, so the branch
// created by budding the file will replace the original file. Some
// file subclasses might initially take the unsafe but expedient
// approach of simply truncating this file down to zero length, and
// then returning the same morkFile pointer as this, with an extra
// reference count increment. Note that the caller of AcquireBud() is
// expected to eventually call CutStrongRef() on the returned file
// in order to release the strong reference. High quality versions
// of morkFile subclasses will create entirely new files which later
// are renamed to become the old file, so that better transactional
// behavior is exhibited by the file, so crashes protect old files.
// Note that AcquireBud() is an illegal operation on readonly files.
virtual mork_pos Length(morkEnv* ev) const = 0; // eof
virtual mork_pos Tell(morkEnv* ev) const = 0;
virtual mork_size Read(morkEnv* ev, void* outBuf, mork_size inSize) = 0;
virtual mork_pos Seek(morkEnv* ev, mork_pos inPos) = 0;
virtual mork_size Write(morkEnv* ev, const void* inBuf, mork_size inSize) = 0;
virtual void Flush(morkEnv* ev) = 0;
// ````` ````` ````` ````` ````` ````` ````` `````
public: // non-poly morkFile methods
nsIMdbFile* AcquireFileHandle(morkEnv* ev); // mObject_Handle
mork_bool FileFrozen() const { return mFile_Frozen == 'F'; }
mork_bool FileDoTrace() const { return mFile_DoTrace == 'T'; }
mork_bool FileIoOpen() const { return mFile_IoOpen == 'O'; }
mork_bool FileActive() const { return mFile_Active == 'A'; }
void SetFileFrozen(mork_bool b) { mFile_Frozen = (mork_u1) ((b)? 'F' : 0); }
void SetFileDoTrace(mork_bool b) { mFile_DoTrace = (mork_u1) ((b)? 'T' : 0); }
void SetFileIoOpen(mork_bool b) { mFile_IoOpen = (mork_u1) ((b)? 'O' : 0); }
void SetFileActive(mork_bool b) { mFile_Active = (mork_u1) ((b)? 'A' : 0); }
mork_bool IsOpenActiveAndMutableFile() const
{ return ( IsOpenNode() && FileActive() && !FileFrozen() ); }
// call IsOpenActiveAndMutableFile() before writing a file
mork_bool IsOpenAndActiveFile() const
{ return ( this->IsOpenNode() && this->FileActive() ); }
// call IsOpenAndActiveFile() before using a file
nsIMdbFile* GetThief() const { return mFile_Thief; }
void SetThief(morkEnv* ev, nsIMdbFile* ioThief); // ioThief can be nil
const char* GetFileNameString() const { return mFile_Name; }
void SetFileName(morkEnv* ev, const char* inName); // inName can be nil
static void NilSlotHeapError(morkEnv* ev);
static void NilFileNameError(morkEnv* ev);
static void NonFileTypeError(morkEnv* ev);
void NewMissingIoError(morkEnv* ev) const;
void NewFileDownError(morkEnv* ev) const;
// call NewFileDownError() when either IsOpenAndActiveFile()
// is false, or when IsOpenActiveAndMutableFile() is false.
void NewFileErrnoError(morkEnv* ev) const;
// call NewFileErrnoError() to convert std C errno into AB fault
mork_size WriteNewlines(morkEnv* ev, mork_count inNewlines);
// WriteNewlines() returns the number of bytes written.
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakFile(morkFile* me,
morkEnv* ev, morkFile** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongFile(morkFile* me,
morkEnv* ev, morkFile** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
/*=============================================================================
* morkStdioFile: concrete file using standard C file io
*/
#define morkDerived_kStdioFile /*i*/ 0x7346 /* ascii 'sF' */
class morkStdioFile /*d*/ : public morkFile { /* `` copied from IronDoc `` */
// ````` ````` ````` ````` ````` ````` ````` `````
protected: // protected morkStdioFile members
void* mStdioFile_File;
// actually type FILE*, but using opaque void* type
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseStdioFile() only if open
virtual ~morkStdioFile(); // assert that CloseStdioFile() executed earlier
public: // morkStdioFile construction & destruction
morkStdioFile(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap);
void CloseStdioFile(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkStdioFile(const morkStdioFile& other);
morkStdioFile& operator=(const morkStdioFile& other);
public: // dynamic type identification
mork_bool IsStdioFile() const
{ return IsNode() && mNode_Derived == morkDerived_kStdioFile; }
// } ===== end morkNode methods =====
public: // typing
static void NonStdioFileTypeError(morkEnv* ev);
// ````` ````` ````` ````` ````` ````` ````` `````
public: // compatible with the morkFile::OpenOldFile() entry point
static morkStdioFile* OpenOldStdioFile(morkEnv* ev, nsIMdbHeap* ioHeap,
const char* inFilePath, mork_bool inFrozen);
static morkStdioFile* CreateNewStdioFile(morkEnv* ev, nsIMdbHeap* ioHeap,
const char* inFilePath);
// ````` ````` ````` ````` ````` ````` ````` `````
public: // virtual ab_File methods
virtual void Steal(morkEnv* ev, nsIMdbFile* ioThief);
// Steal: tell this file to close any associated i/o stream in the file
// system, because the file ioThief intends to reopen the file in order
// to provide the MDB implementation with more exotic file access than is
// offered by the nsIMdbFile alone. Presumably the thief knows enough
// from Path() in order to know which file to reopen. If Steal() is
// successful, this file should probably delegate all future calls to
// the nsIMdbFile interface down to the thief files, so that even after
// the file has been stolen, it can still be read, written, or forcibly
// closed (by a call to CloseMdbObject()).
virtual void BecomeTrunk(morkEnv* ev);
// If this file is a file version branch created by calling AcquireBud(),
// BecomeTrunk() causes this file's content to replace the original
// file's content, typically by assuming the original file's identity.
virtual morkFile* AcquireBud(morkEnv* ev, nsIMdbHeap* ioHeap);
// AcquireBud() starts a new "branch" version of the file, empty of content,
// so that a new version of the file can be written. This new file
// can later be told to BecomeTrunk() the original file, so the branch
// created by budding the file will replace the original file. Some
// file subclasses might initially take the unsafe but expedient
// approach of simply truncating this file down to zero length, and
// then returning the same morkFile pointer as this, with an extra
// reference count increment. Note that the caller of AcquireBud() is
// expected to eventually call CutStrongRef() on the returned file
// in order to release the strong reference. High quality versions
// of morkFile subclasses will create entirely new files which later
// are renamed to become the old file, so that better transactional
// behavior is exhibited by the file, so crashes protect old files.
// Note that AcquireBud() is an illegal operation on readonly files.
virtual mork_pos Length(morkEnv* ev) const; // eof
virtual mork_pos Tell(morkEnv* ev) const;
virtual mork_size Read(morkEnv* ev, void* outBuf, mork_size inSize);
virtual mork_pos Seek(morkEnv* ev, mork_pos inPos);
virtual mork_size Write(morkEnv* ev, const void* inBuf, mork_size inSize);
virtual void Flush(morkEnv* ev);
// ````` ````` ````` ````` ````` ````` ````` `````
protected: // protected non-poly morkStdioFile methods
void new_stdio_file_fault(morkEnv* ev) const;
// ````` ````` ````` ````` ````` ````` ````` `````
public: // public non-poly morkStdioFile methods
morkStdioFile(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap,
const char* inName, const char* inMode);
// calls OpenStdio() after construction
morkStdioFile(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap,
void* ioFile, const char* inName, mork_bool inFrozen);
// calls UseStdio() after construction
void OpenStdio(morkEnv* ev, const char* inName, const char* inMode);
// Open a new FILE with name inName, using mode flags from inMode.
void UseStdio(morkEnv* ev, void* ioFile, const char* inName,
mork_bool inFrozen);
// Use an existing file, like stdin/stdout/stderr, which should not
// have the io stream closed when the file is closed. The ioFile
// parameter must actually be of type FILE (but we don't want to make
// this header file include the stdio.h header file).
void CloseStdio(morkEnv* ev);
// Close the stream io if both and FileActive() and FileIoOpen(), but
// this does not close this instances (like CloseStdioFile() does).
// If stream io was made active by means of calling UseStdio(),
// then this method does little beyond marking the stream inactive
// because FileIoOpen() is false.
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakStdioFile(morkStdioFile* me,
morkEnv* ev, morkStdioFile** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongStdioFile(morkStdioFile* me,
morkEnv* ev, morkStdioFile** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKFILE_ */

View File

@@ -1,414 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKFACTORY_
#include "morkFactory.h"
#endif
#ifndef _MORKPOOL_
#include "morkPool.h"
#endif
#ifndef _MORKHANDLE_
#include "morkHandle.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkHandle::CloseMorkNode(morkEnv* ev) // CloseHandle() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseHandle(ev);
this->MarkShut();
}
}
/*public virtual*/
morkHandle::~morkHandle() // assert CloseHandle() executed earlier
{
MORK_ASSERT(mHandle_Env==0);
MORK_ASSERT(mHandle_Face==0);
MORK_ASSERT(mHandle_Object==0);
MORK_ASSERT(mHandle_Magic==0);
MORK_ASSERT(mHandle_Tag==morkHandle_kTag); // should still have correct tag
}
/*public non-poly*/
morkHandle::morkHandle(morkEnv* ev, // note morkUsage is always morkUsage_kPool
morkHandleFace* ioFace, // must not be nil, cookie for this handle
morkObject* ioObject, // must not be nil, the object for this handle
mork_magic inMagic) // magic sig to denote specific subclass
: morkNode(ev, morkUsage::kPool, (nsIMdbHeap*) 0L)
, mHandle_Tag( 0 )
, mHandle_Env( ev )
, mHandle_Face( ioFace )
, mHandle_Object( 0 )
, mHandle_Magic( 0 )
{
if ( ioFace && ioObject )
{
if ( ev->Good() )
{
mHandle_Tag = morkHandle_kTag;
morkObject::SlotStrongObject(ioObject, ev, &mHandle_Object);
morkHandle::SlotWeakHandle(this, ev, &ioObject->mObject_Handle);
if ( ev->Good() )
{
mHandle_Magic = inMagic;
mNode_Derived = morkDerived_kHandle;
}
}
else
ev->CantMakeWhenBadError();
}
else
ev->NilPointerError();
}
/*public non-poly*/ void
morkHandle::CloseHandle(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
morkObject* obj = mHandle_Object;
mork_bool objDidRefSelf = ( obj && obj->mObject_Handle == this );
if ( objDidRefSelf )
obj->mObject_Handle = 0; // drop the reference
morkObject::SlotStrongObject((morkObject*) 0, ev, &mHandle_Object);
mHandle_Magic = 0;
// note mHandle_Tag MUST stay morkHandle_kTag for morkNode::ZapOld()
this->MarkShut();
if ( objDidRefSelf )
this->CutWeakRef(ev); // do last, because it might self destroy
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
void morkHandle::NilFactoryError(morkEnv* ev) const
{
ev->NewError("nil mHandle_Factory");
}
void morkHandle::NilHandleObjectError(morkEnv* ev) const
{
ev->NewError("nil mHandle_Object");
}
void morkHandle::NonNodeObjectError(morkEnv* ev) const
{
ev->NewError("non-node mHandle_Object");
}
void morkHandle::NonOpenObjectError(morkEnv* ev) const
{
ev->NewError("non-open mHandle_Object");
}
void morkHandle::NewBadMagicHandleError(morkEnv* ev, mork_magic inMagic) const
{
MORK_USED_1(inMagic);
ev->NewError("wrong mHandle_Magic");
}
void morkHandle::NewDownHandleError(morkEnv* ev) const
{
if ( this->IsHandle() )
{
if ( this->GoodHandleTag() )
{
if ( this->IsOpenNode() )
ev->NewError("unknown down morkHandle error");
else
this->NonOpenNodeError(ev);
}
else
ev->NewError("wrong morkHandle tag");
}
else
ev->NewError("non morkHandle");
}
morkObject* morkHandle::GetGoodHandleObject(morkEnv* ev,
mork_bool inMutable, mork_magic inMagicType) const
{
morkObject* outObject = 0;
if ( this->IsHandle() && this->GoodHandleTag() && this->IsOpenNode() )
{
if ( !inMagicType || mHandle_Magic == inMagicType )
{
morkObject* obj = this->mHandle_Object;
if ( obj )
{
if ( obj->IsNode() )
{
if ( obj->IsOpenNode() )
{
if ( this->IsMutable() || !inMutable )
outObject = obj;
else
this->NonMutableNodeError(ev);
}
else
this->NonOpenObjectError(ev);
}
else
this->NonNodeObjectError(ev);
}
else
this->NilHandleObjectError(ev);
}
else
this->NewBadMagicHandleError(ev, inMagicType);
}
else
this->NewDownHandleError(ev);
MORK_ASSERT(outObject);
return outObject;
}
morkEnv*
morkHandle::CanUseHandle(nsIMdbEnv* mev, mork_bool inMutable,
mdb_err* outErr) const
{
morkEnv* outEnv = 0;
morkEnv* ev = morkEnv::FromMdbEnv(mev);
if ( ev )
{
morkObject* obj = this->GetGoodHandleObject(ev, inMutable, /*magic*/ 0);
if ( obj )
{
outEnv = ev;
}
*outErr = ev->AsErr();
}
MORK_ASSERT(outEnv);
return outEnv;
}
// { ===== begin nsIMdbObject methods =====
// { ----- begin attribute methods -----
/*virtual*/ mdb_err
morkHandle::Handle_IsFrozenMdbObject(nsIMdbEnv* mev, mdb_bool* outIsReadonly)
{
mdb_err outErr = 0;
morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
MORK_ASSERT(outIsReadonly);
if ( outIsReadonly )
*outIsReadonly = mHandle_Object->IsFrozen();
outErr = ev->AsErr();
}
return outErr;
}
// same as nsIMdbPort::GetIsPortReadonly() when this object is inside a port.
// } ----- end attribute methods -----
// { ----- begin factory methods -----
/*virtual*/ mdb_err
morkHandle::Handle_GetMdbFactory(nsIMdbEnv* mev, nsIMdbFactory** acqFactory)
{
mdb_err outErr = 0;
morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
morkFactory* factory = ev->mEnv_Factory;
if ( factory )
{
nsIMdbFactory* handle = factory->AcquireFactoryHandle(ev);
MORK_ASSERT(acqFactory);
if ( handle && acqFactory )
*acqFactory = handle;
}
else
this->NilFactoryError(ev);
outErr = ev->AsErr();
}
return outErr;
}
// } ----- end factory methods -----
// { ----- begin ref counting for well-behaved cyclic graphs -----
/*virtual*/ mdb_err
morkHandle::Handle_GetWeakRefCount(nsIMdbEnv* mev, // weak refs
mdb_count* outCount)
{
mdb_err outErr = 0;
morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
MORK_ASSERT(outCount);
if ( outCount )
*outCount = this->WeakRefsOnly();
outErr = ev->AsErr();
}
return outErr;
}
/*virtual*/ mdb_err
morkHandle::Handle_GetStrongRefCount(nsIMdbEnv* mev, // strong refs
mdb_count* outCount)
{
mdb_err outErr = 0;
morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
MORK_ASSERT(outCount);
if ( outCount )
*outCount = this->StrongRefsOnly();
outErr = ev->AsErr();
}
return outErr;
}
/*virtual*/ mdb_err
morkHandle::Handle_AddWeakRef(nsIMdbEnv* mev)
{
mdb_err outErr = 0;
morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
this->AddWeakRef(ev);
outErr = ev->AsErr();
}
return outErr;
}
/*virtual*/ mdb_err
morkHandle::Handle_AddStrongRef(nsIMdbEnv* mev)
{
mdb_err outErr = 0;
morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
this->AddStrongRef(ev);
outErr = ev->AsErr();
}
return outErr;
}
/*virtual*/ mdb_err
morkHandle::Handle_CutWeakRef(nsIMdbEnv* mev)
{
mdb_err outErr = 0;
morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
this->CutWeakRef(ev);
outErr = ev->AsErr();
}
return outErr;
}
/*virtual*/ mdb_err
morkHandle::Handle_CutStrongRef(nsIMdbEnv* mev)
{
mdb_err outErr = 0;
morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
this->CutStrongRef(ev);
outErr = ev->AsErr();
}
return outErr;
}
/*virtual*/ mdb_err
morkHandle::Handle_CloseMdbObject(nsIMdbEnv* mev)
// called at strong refs zero
{
mdb_err outErr = 0;
if ( this->IsNode() && this->IsOpenNode() )
{
morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
morkObject* object = mHandle_Object;
if ( object && object->IsNode() && object->IsOpenNode() )
object->CloseMorkNode(ev);
this->CloseMorkNode(ev);
outErr = ev->AsErr();
}
}
return outErr;
}
/*virtual*/ mdb_err
morkHandle::Handle_IsOpenMdbObject(nsIMdbEnv* mev, mdb_bool* outOpen)
{
MORK_USED_1(mev);
mdb_err outErr = 0;
MORK_ASSERT(outOpen);
if ( outOpen )
*outOpen = this->IsOpenNode();
return outErr;
}
// } ----- end ref counting -----
// } ===== end nsIMdbObject methods =====
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,189 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKHANDLE_
#define _MORKHANDLE_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKDEQUE_
#include "morkDeque.h"
#endif
#ifndef _MORKPOOL_
#include "morkPool.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
class morkPool;
class morkObject;
class morkFactory;
#define morkDerived_kHandle /*i*/ 0x486E /* ascii 'Hn' */
#define morkHandle_kTag 0x68416E44 /* ascii 'hAnD' */
/*| morkHandle:
|*/
class morkHandle : public morkNode {
// public: // slots inherited from morkNode (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
public: // state is public because the entire Mork system is private
mork_u4 mHandle_Tag; // must equal morkHandle_kTag
morkEnv* mHandle_Env; // pool that allocated this handle
morkHandleFace* mHandle_Face; // cookie from pool containing this
morkObject* mHandle_Object; // object this handle wraps for MDB API
mork_magic mHandle_Magic; // magic sig different in each subclass
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseHandle() only if open
virtual ~morkHandle(); // assert that CloseHandle() executed earlier
public: // morkHandle construction & destruction
morkHandle(morkEnv* ev, // note morkUsage is always morkUsage_kPool
morkHandleFace* ioFace, // must not be nil, cookie for this handle
morkObject* ioObject, // must not be nil, the object for this handle
mork_magic inMagic); // magic sig to denote specific subclass
void CloseHandle(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkHandle(const morkHandle& other);
morkHandle& operator=(const morkHandle& other);
protected: // special case empty construction for morkHandleFrame
friend class morkHandleFrame;
morkHandle() { }
public: // dynamic type identification
mork_bool IsHandle() const
{ return IsNode() && mNode_Derived == morkDerived_kHandle; }
// } ===== end morkNode methods =====
public: // morkHandle memory management operators
void* operator new(size_t inSize, morkPool& ioPool, morkEnv* ev)
{ return ioPool.NewHandle(ev, inSize); }
void* operator new(size_t inSize, morkHandleFace* ioFace)
{ MORK_USED_1(inSize); return ioFace; }
void operator delete(void* ioAddress)
{ morkNode::OnDeleteAssert(ioAddress); }
// do NOT call delete on morkHandle instances. They are collected.
public: // other handle methods
mork_bool GoodHandleTag() const
{ return mHandle_Tag == morkHandle_kTag; }
void NewBadMagicHandleError(morkEnv* ev, mork_magic inMagic) const;
void NewDownHandleError(morkEnv* ev) const;
void NilFactoryError(morkEnv* ev) const;
void NilHandleObjectError(morkEnv* ev) const;
void NonNodeObjectError(morkEnv* ev) const;
void NonOpenObjectError(morkEnv* ev) const;
morkObject* GetGoodHandleObject(morkEnv* ev,
mork_bool inMutabl, mork_magic inMagicType) const;
public: // interface supporting mdbObject methods
morkEnv* CanUseHandle(nsIMdbEnv* mev, mork_bool inMutable,
mdb_err* outErr) const;
// { ----- begin mdbObject style methods -----
mdb_err Handle_IsFrozenMdbObject(nsIMdbEnv* ev, mdb_bool* outIsReadonly);
mdb_err Handle_GetMdbFactory(nsIMdbEnv* ev, nsIMdbFactory** acqFactory);
mdb_err Handle_GetWeakRefCount(nsIMdbEnv* ev, mdb_count* outCount);
mdb_err Handle_GetStrongRefCount(nsIMdbEnv* ev, mdb_count* outCount);
mdb_err Handle_AddWeakRef(nsIMdbEnv* ev);
mdb_err Handle_AddStrongRef(nsIMdbEnv* ev);
mdb_err Handle_CutWeakRef(nsIMdbEnv* ev);
mdb_err Handle_CutStrongRef(nsIMdbEnv* ev);
mdb_err Handle_CloseMdbObject(nsIMdbEnv* ev);
mdb_err Handle_IsOpenMdbObject(nsIMdbEnv* ev, mdb_bool* outOpen);
// } ----- end mdbObject style methods -----
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakHandle(morkHandle* me,
morkEnv* ev, morkHandle** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongHandle(morkHandle* me,
morkEnv* ev, morkHandle** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
#define morkHandleFrame_kPadSlotCount 4
/*| morkHandleFrame: an object format used for allocating and maintaining
**| instances of morkHandle, with leading slots used to maintain this in a
**| linked list, and following slots to provide extra footprint that might
**| be needed by any morkHandle subclasses that include very little extra
**| space (by virtue of the fact that each morkHandle subclass is expected
**| to multiply inherit from another base class that has only abstact methods
**| for space overhead related only to some vtable representation).
|*/
class morkHandleFrame {
public:
morkLink mHandleFrame_Link; // list storage without trampling Handle
morkHandle mHandleFrame_Handle;
mork_ip mHandleFrame_Padding[ morkHandleFrame_kPadSlotCount ];
public:
morkHandle* AsHandle() { return &mHandleFrame_Handle; }
morkHandleFrame() {} // actually, morkHandleFrame never gets constructed
private: // copying is not allowed
morkHandleFrame(const morkHandleFrame& other);
morkHandleFrame& operator=(const morkHandleFrame& other);
};
#define morkHandleFrame_kHandleOffset \
mork_OffsetOf(morkHandleFrame,mHandleFrame_Handle)
#define morkHandle_AsHandleFrame(h) ((h)->mHandle_Block , \
((morkHandleFrame*) (((mork_u1*)(h)) - morkHandleFrame_kHandleOffset)))
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKHANDLE_ */

View File

@@ -1,261 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
#ifndef _MORKINTMAP_
#include "morkIntMap.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkIntMap::CloseMorkNode(morkEnv* ev) // CloseIntMap() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseIntMap(ev);
this->MarkShut();
}
}
/*public virtual*/
morkIntMap::~morkIntMap() // assert CloseIntMap() executed earlier
{
MORK_ASSERT(this->IsShutNode());
}
/*public non-poly*/
morkIntMap::morkIntMap(morkEnv* ev,
const morkUsage& inUsage, mork_size inValSize,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap, mork_bool inHoldChanges)
: morkMap(ev, inUsage, ioHeap, sizeof(mork_u4), inValSize,
morkIntMap_kStartSlotCount, ioSlotHeap, inHoldChanges)
{
if ( ev->Good() )
mNode_Derived = morkDerived_kIntMap;
}
/*public non-poly*/ void
morkIntMap::CloseIntMap(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
this->CloseMap(ev);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
// { ===== begin morkMap poly interface =====
/*virtual*/ mork_bool // *((mork_u4*) inKeyA) == *((mork_u4*) inKeyB)
morkIntMap::Equal(morkEnv* ev, const void* inKeyA, const void* inKeyB) const
{
MORK_USED_1(ev);
return *((const mork_u4*) inKeyA) == *((const mork_u4*) inKeyB);
}
/*virtual*/ mork_u4 // some integer function of *((mork_u4*) inKey)
morkIntMap::Hash(morkEnv* ev, const void* inKey) const
{
MORK_USED_1(ev);
return *((const mork_u4*) inKey);
}
// } ===== end morkMap poly interface =====
mork_bool
morkIntMap::AddInt(morkEnv* ev, mork_u4 inKey, void* ioAddress)
// the AddInt() method return value equals ev->Good().
{
if ( ev->Good() )
{
this->Put(ev, &inKey, &ioAddress,
/*key*/ (void*) 0, /*val*/ (void*) 0, (mork_change**) 0);
}
return ev->Good();
}
mork_bool
morkIntMap::CutInt(morkEnv* ev, mork_u4 inKey)
{
return this->Cut(ev, &inKey, /*key*/ (void*) 0, /*val*/ (void*) 0,
(mork_change**) 0);
}
void*
morkIntMap::GetInt(morkEnv* ev, mork_u4 inKey)
// Note the returned val does NOT have an increase in refcount for this.
{
void* val = 0; // old val in the map
this->Get(ev, &inKey, /*key*/ (void*) 0, &val, (mork_change**) 0);
return val;
}
mork_bool
morkIntMap::HasInt(morkEnv* ev, mork_u4 inKey)
// Note the returned val does NOT have an increase in refcount for this.
{
return this->Get(ev, &inKey, /*key*/ (void*) 0, /*val*/ (void*) 0,
(mork_change**) 0);
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#ifdef MORK_POINTER_MAP_IMPL
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkPointerMap::CloseMorkNode(morkEnv* ev) // ClosePointerMap() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->ClosePointerMap(ev);
this->MarkShut();
}
}
/*public virtual*/
morkPointerMap::~morkPointerMap() // assert ClosePointerMap() executed earlier
{
MORK_ASSERT(this->IsShutNode());
}
/*public non-poly*/
morkPointerMap::morkPointerMap(morkEnv* ev,
const morkUsage& inUsage, nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
: morkMap(ev, inUsage, ioHeap, sizeof(void*), sizeof(void*),
morkPointerMap_kStartSlotCount, ioSlotHeap,
/*inHoldChanges*/ morkBool_kFalse)
{
if ( ev->Good() )
mNode_Derived = morkDerived_kPointerMap;
}
/*public non-poly*/ void
morkPointerMap::ClosePointerMap(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
this->CloseMap(ev);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
// { ===== begin morkMap poly interface =====
/*virtual*/ mork_bool // *((void**) inKeyA) == *((void**) inKeyB)
morkPointerMap::Equal(morkEnv* ev, const void* inKeyA, const void* inKeyB) const
{
MORK_USED_1(ev);
return *((const void**) inKeyA) == *((const void**) inKeyB);
}
/*virtual*/ mork_u4 // some integer function of *((mork_u4*) inKey)
morkPointerMap::Hash(morkEnv* ev, const void* inKey) const
{
MORK_USED_1(ev);
return *((const mork_u4*) inKey);
}
// } ===== end morkMap poly interface =====
mork_bool
morkPointerMap::AddPointer(morkEnv* ev, void* inKey, void* ioAddress)
// the AddPointer() method return value equals ev->Good().
{
if ( ev->Good() )
{
this->Put(ev, &inKey, &ioAddress,
/*key*/ (void*) 0, /*val*/ (void*) 0, (mork_change**) 0);
}
return ev->Good();
}
mork_bool
morkPointerMap::CutPointer(morkEnv* ev, void* inKey)
{
return this->Cut(ev, &inKey, /*key*/ (void*) 0, /*val*/ (void*) 0,
(mork_change**) 0);
}
void*
morkPointerMap::GetPointer(morkEnv* ev, void* inKey)
// Note the returned val does NOT have an increase in refcount for this.
{
void* val = 0; // old val in the map
this->Get(ev, &inKey, /*key*/ (void*) 0, &val, (mork_change**) 0);
return val;
}
mork_bool
morkPointerMap::HasPointer(morkEnv* ev, void* inKey)
// Note the returned val does NOT have an increase in refcount for this.
{
return this->Get(ev, &inKey, /*key*/ (void*) 0, /*val*/ (void*) 0,
(mork_change**) 0);
}
#endif /*MORK_POINTER_MAP_IMPL*/
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,158 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKINTMAP_
#define _MORKINTMAP_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kIntMap /*i*/ 0x694D /* ascii 'iM' */
#define morkIntMap_kStartSlotCount 256
/*| morkIntMap: maps mork_token -> morkNode
|*/
class morkIntMap : public morkMap { // for mapping tokens to maps
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseIntMap() only if open
virtual ~morkIntMap(); // assert that CloseIntMap() executed earlier
public: // morkMap construction & destruction
// keySize for morkIntMap equals sizeof(mork_u4)
morkIntMap(morkEnv* ev, const morkUsage& inUsage, mork_size inValSize,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap, mork_bool inHoldChanges);
void CloseIntMap(morkEnv* ev); // called by CloseMorkNode();
public: // dynamic type identification
mork_bool IsIntMap() const
{ return IsNode() && mNode_Derived == morkDerived_kIntMap; }
// } ===== end morkNode methods =====
// { ===== begin morkMap poly interface =====
virtual mork_bool // *((mork_u4*) inKeyA) == *((mork_u4*) inKeyB)
Equal(morkEnv* ev, const void* inKeyA, const void* inKeyB) const;
virtual mork_u4 // some integer function of *((mork_u4*) inKey)
Hash(morkEnv* ev, const void* inKey) const;
// } ===== end morkMap poly interface =====
public: // other map methods
mork_bool AddInt(morkEnv* ev, mork_u4 inKey, void* ioAddress);
// the AddInt() boolean return equals ev->Good().
mork_bool CutInt(morkEnv* ev, mork_u4 inKey);
// The CutInt() boolean return indicates whether removal happened.
void* GetInt(morkEnv* ev, mork_u4 inKey);
// Note the returned node does NOT have an increase in refcount for this.
mork_bool HasInt(morkEnv* ev, mork_u4 inKey);
// Note the returned node does NOT have an increase in refcount for this.
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#ifdef MORK_POINTER_MAP_IMPL
#define morkDerived_kPointerMap /*i*/ 0x704D /* ascii 'pM' */
#define morkPointerMap_kStartSlotCount 256
/*| morkPointerMap: maps void* -> void*
**|
**| This pointer map class is equivalent to morkIntMap when sizeof(mork_u4)
**| equals sizeof(void*). However, when these two sizes are different,
**| then we cannot use the same hash table structure very easily without
**| being very careful about the size and usage assumptions of those
**| clients using the smaller data type. So we just go ahead and use
**| morkPointerMap for hash tables using pointer key types.
|*/
class morkPointerMap : public morkMap { // for mapping tokens to maps
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // ClosePointerMap() only if open
virtual ~morkPointerMap(); // assert that ClosePointerMap() executed earlier
public: // morkMap construction & destruction
// keySize for morkPointerMap equals sizeof(mork_u4)
morkPointerMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap);
void ClosePointerMap(morkEnv* ev); // called by CloseMorkNode();
public: // dynamic type identification
mork_bool IsPointerMap() const
{ return IsNode() && mNode_Derived == morkDerived_kPointerMap; }
// } ===== end morkNode methods =====
// { ===== begin morkMap poly interface =====
virtual mork_bool // *((void**) inKeyA) == *((void**) inKeyB)
Equal(morkEnv* ev, const void* inKeyA, const void* inKeyB) const;
virtual mork_u4 // some integer function of *((mork_u4*) inKey)
Hash(morkEnv* ev, const void* inKey) const;
// } ===== end morkMap poly interface =====
public: // other map methods
mork_bool AddPointer(morkEnv* ev, void* inKey, void* ioAddress);
// the AddPointer() boolean return equals ev->Good().
mork_bool CutPointer(morkEnv* ev, void* inKey);
// The CutPointer() boolean return indicates whether removal happened.
void* GetPointer(morkEnv* ev, void* inKey);
// Note the returned node does NOT have an increase in refcount for this.
mork_bool HasPointer(morkEnv* ev, void* inKey);
// Note the returned node does NOT have an increase in refcount for this.
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakIntMap(morkIntMap* me,
morkEnv* ev, morkIntMap** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongIntMap(morkIntMap* me,
morkEnv* ev, morkIntMap** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
#endif /*MORK_POINTER_MAP_IMPL*/
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKINTMAP_ */

View File

@@ -1,941 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
// This code is mostly a port to C++ from public domain IronDoc C sources.
// Note many code comments here come verbatim from cut-and-pasted IronDoc.
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
class morkHashArrays {
public:
nsIMdbHeap* mHashArrays_Heap; // copy of mMap_Heap
mork_count mHashArrays_Slots; // copy of mMap_Slots
mork_u1* mHashArrays_Keys; // copy of mMap_Keys
mork_u1* mHashArrays_Vals; // copy of mMap_Vals
morkAssoc* mHashArrays_Assocs; // copy of mMap_Assocs
mork_change* mHashArrays_Changes; // copy of mMap_Changes
morkAssoc** mHashArrays_Buckets; // copy of mMap_Buckets
morkAssoc* mHashArrays_FreeList; // copy of mMap_FreeList
public:
void finalize(morkEnv* ev);
};
void morkHashArrays::finalize(morkEnv* ev)
{
nsIMdbEnv* menv = ev->AsMdbEnv();
nsIMdbHeap* heap = mHashArrays_Heap;
if ( heap )
{
if ( mHashArrays_Keys )
heap->Free(menv, mHashArrays_Keys);
if ( mHashArrays_Vals )
heap->Free(menv, mHashArrays_Vals);
if ( mHashArrays_Assocs )
heap->Free(menv, mHashArrays_Assocs);
if ( mHashArrays_Changes )
heap->Free(menv, mHashArrays_Changes);
if ( mHashArrays_Buckets )
heap->Free(menv, mHashArrays_Buckets);
}
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkMap::CloseMorkNode(morkEnv* ev) // CloseMap() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseMap(ev);
this->MarkShut();
}
}
/*public virtual*/
morkMap::~morkMap() // assert CloseMap() executed earlier
{
MORK_ASSERT(mMap_FreeList==0);
MORK_ASSERT(mMap_Buckets==0);
MORK_ASSERT(mMap_Keys==0);
MORK_ASSERT(mMap_Vals==0);
MORK_ASSERT(mMap_Changes==0);
MORK_ASSERT(mMap_Assocs==0);
}
/*public non-poly*/ void
morkMap::CloseMap(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
nsIMdbHeap* heap = mMap_Heap;
if ( heap ) /* need to free the arrays? */
{
nsIMdbEnv* menv = ev->AsMdbEnv();
if ( mMap_Keys )
heap->Free(menv, mMap_Keys);
if ( mMap_Vals )
heap->Free(menv, mMap_Vals);
if ( mMap_Assocs )
heap->Free(menv, mMap_Assocs);
if ( mMap_Buckets )
heap->Free(menv, mMap_Buckets);
if ( mMap_Changes )
heap->Free(menv, mMap_Changes);
}
mMap_Keys = 0;
mMap_Vals = 0;
mMap_Buckets = 0;
mMap_Assocs = 0;
mMap_Changes = 0;
mMap_FreeList = 0;
MORK_MEMSET(&mMap_Form, 0, sizeof(morkMapForm));
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
void
morkMap::clear_map(morkEnv* ev, nsIMdbHeap* ioSlotHeap)
{
mMap_Tag = 0;
mMap_Seed = 0;
mMap_Slots = 0;
mMap_Fill = 0;
mMap_Keys = 0;
mMap_Vals = 0;
mMap_Assocs = 0;
mMap_Changes = 0;
mMap_Buckets = 0;
mMap_FreeList = 0;
MORK_MEMSET(&mMap_Form, 0, sizeof(morkMapForm));
mMap_Heap = 0;
if ( ioSlotHeap )
{
nsIMdbHeap_SlotStrongHeap(ioSlotHeap, ev, &mMap_Heap);
}
else
ev->NilPointerError();
}
morkMap::morkMap(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap,
mork_size inKeySize, mork_size inValSize,
mork_size inSlots, nsIMdbHeap* ioSlotHeap, mork_bool inHoldChanges)
: morkNode(ev, inUsage, ioHeap)
, mMap_Heap( 0 )
{
if ( ev->Good() )
{
this->clear_map(ev, ioSlotHeap);
if ( ev->Good() )
{
mMap_Form.mMapForm_HoldChanges = inHoldChanges;
mMap_Form.mMapForm_KeySize = inKeySize;
mMap_Form.mMapForm_ValSize = inValSize;
mMap_Form.mMapForm_KeyIsIP = ( inKeySize == sizeof(mork_ip) );
mMap_Form.mMapForm_ValIsIP = ( inValSize == sizeof(mork_ip) );
this->InitMap(ev, inSlots);
if ( ev->Good() )
mNode_Derived = morkDerived_kMap;
}
}
}
void
morkMap::NewIterOutOfSyncError(morkEnv* ev)
{
ev->NewError("map iter out of sync");
}
void morkMap::NewBadMapError(morkEnv* ev)
{
ev->NewError("bad morkMap tag");
if ( !this )
ev->NewError("nil morkMap instance");
}
void morkMap::NewSlotsUnderflowWarning(morkEnv* ev)
{
ev->NewWarning("member count underflow");
}
void morkMap::InitMap(morkEnv* ev, mork_size inSlots)
{
if ( ev->Good() )
{
morkHashArrays old;
// MORK_MEMCPY(&mMap_Form, &inForm, sizeof(morkMapForm));
if ( inSlots < 3 ) /* requested capacity absurdly small? */
inSlots = 3; /* bump it up to a minimum practical level */
else if ( inSlots > (128 * 1024) ) /* requested slots absurdly big? */
inSlots = (128 * 1024); /* decrease it to a maximum practical level */
if ( this->new_arrays(ev, &old, inSlots) )
mMap_Tag = morkMap_kTag;
MORK_MEMSET(&old, 0, sizeof(morkHashArrays)); // do NOT finalize
}
}
morkAssoc**
morkMap::find(morkEnv* ev, const void* inKey, mork_u4 inHash) const
{
mork_u1* keys = mMap_Keys;
mork_num keySize = this->FormKeySize();
// morkMap_mEqual equal = this->FormEqual();
morkAssoc** ref = mMap_Buckets + (inHash % mMap_Slots);
morkAssoc* assoc = *ref;
while ( assoc ) /* look at another assoc in the bucket? */
{
mork_pos i = assoc - mMap_Assocs; /* index of this assoc */
if ( this->Equal(ev, keys + (i * keySize), inKey) ) /* found? */
return ref;
ref = &assoc->mAssoc_Next; /* consider next assoc slot in bucket */
assoc = *ref; /* if this is null, then we are done */
}
return 0;
}
/*| get_assoc: read the key and/or value at index inPos
|*/
void
morkMap::get_assoc(void* outKey, void* outVal, mork_pos inPos) const
{
mork_num valSize = this->FormValSize();
if ( valSize && outVal ) /* map holds values? caller wants the value? */
{
const mork_u1* value = mMap_Vals + (valSize * inPos);
if ( valSize == sizeof(mork_ip) && this->FormValIsIP() ) /* ip case? */
*((mork_ip*) outVal) = *((const mork_ip*) value);
else
MORK_MEMCPY(outVal, value, valSize);
}
if ( outKey ) /* caller wants the key? */
{
mork_num keySize = this->FormKeySize();
const mork_u1* key = mMap_Keys + (keySize * inPos);
if ( keySize == sizeof(mork_ip) && this->FormKeyIsIP() ) /* ip case? */
*((mork_ip*) outKey) = *((const mork_ip*) key);
else
MORK_MEMCPY(outKey, key, keySize);
}
}
/*| put_assoc: write the key and/or value at index inPos
|*/
void
morkMap::put_assoc(const void* inKey, const void* inVal, mork_pos inPos) const
{
mork_num valSize = this->FormValSize();
if ( valSize && inVal ) /* map holds values? caller sends a value? */
{
mork_u1* value = mMap_Vals + (valSize * inPos);
if ( valSize == sizeof(mork_ip) && this->FormValIsIP() ) /* ip case? */
*((mork_ip*) value) = *((const mork_ip*) inVal);
else
MORK_MEMCPY(value, inVal, valSize);
}
if ( inKey ) /* caller sends a key? */
{
mork_num keySize = this->FormKeySize();
mork_u1* key = mMap_Keys + (keySize * inPos);
if ( keySize == sizeof(mork_ip) && this->FormKeyIsIP() ) /* ip case? */
*((mork_ip*) key) = *((const mork_ip*) inKey);
else
MORK_MEMCPY(key, inKey, keySize);
}
}
void*
morkMap::clear_alloc(morkEnv* ev, mork_size inSize)
{
void* p = 0;
nsIMdbHeap* heap = mMap_Heap;
if ( heap )
{
if ( heap->Alloc(ev->AsMdbEnv(), inSize, (void**) &p) == 0 && p )
{
MORK_MEMSET(p, 0, inSize);
return p;
}
}
else
ev->NilPointerError();
return (void*) 0;
}
void*
morkMap::alloc(morkEnv* ev, mork_size inSize)
{
void* p = 0;
nsIMdbHeap* heap = mMap_Heap;
if ( heap )
{
if ( heap->Alloc(ev->AsMdbEnv(), inSize, (void**) &p) == 0 && p )
return p;
}
else
ev->NilPointerError();
return (void*) 0;
}
/*| new_keys: allocate an array of inSlots new keys filled with zero.
|*/
mork_u1*
morkMap::new_keys(morkEnv* ev, mork_num inSlots)
{
mork_num size = inSlots * this->FormKeySize();
return (mork_u1*) this->clear_alloc(ev, size);
}
/*| new_values: allocate an array of inSlots new values filled with zero.
**| When values are zero sized, we just return a null pointer.
|*/
mork_u1*
morkMap::new_values(morkEnv* ev, mork_num inSlots)
{
mork_u1* values = 0;
mork_num size = inSlots * this->FormValSize();
if ( size )
values = (mork_u1*) this->clear_alloc(ev, size);
return values;
}
mork_change*
morkMap::new_changes(morkEnv* ev, mork_num inSlots)
{
mork_change* changes = 0;
mork_num size = inSlots * sizeof(mork_change);
if ( size && mMap_Form.mMapForm_HoldChanges )
changes = (mork_change*) this->clear_alloc(ev, size);
return changes;
}
/*| new_buckets: allocate an array of inSlots new buckets filled with zero.
|*/
morkAssoc**
morkMap::new_buckets(morkEnv* ev, mork_num inSlots)
{
mork_num size = inSlots * sizeof(morkAssoc*);
return (morkAssoc**) this->clear_alloc(ev, size);
}
/*| new_assocs: allocate an array of inSlots new assocs, with each assoc
**| linked together in a list with the first array element at the list head
**| and the last element at the list tail. (morkMap::grow() needs this.)
|*/
morkAssoc*
morkMap::new_assocs(morkEnv* ev, mork_num inSlots)
{
mork_num size = inSlots * sizeof(morkAssoc);
morkAssoc* assocs = (morkAssoc*) this->alloc(ev, size);
if ( assocs ) /* able to allocate the array? */
{
morkAssoc* a = assocs + (inSlots - 1); /* the last array element */
a->mAssoc_Next = 0; /* terminate tail element of the list with null */
while ( --a >= assocs ) /* another assoc to link into the list? */
a->mAssoc_Next = a + 1; /* each points to the following assoc */
}
return assocs;
}
mork_bool
morkMap::new_arrays(morkEnv* ev, morkHashArrays* old, mork_num inSlots)
{
mork_bool outNew = morkBool_kFalse;
/* see if we can allocate all the new arrays before we go any further: */
morkAssoc** newBuckets = this->new_buckets(ev, inSlots);
morkAssoc* newAssocs = this->new_assocs(ev, inSlots);
mork_u1* newKeys = this->new_keys(ev, inSlots);
mork_u1* newValues = this->new_values(ev, inSlots);
mork_change* newChanges = this->new_changes(ev, inSlots);
/* it is okay for newChanges to be null when changes are not held: */
mork_bool okayChanges = ( newChanges || !this->FormHoldChanges() );
/* it is okay for newValues to be null when values are zero sized: */
mork_bool okayValues = ( newValues || !this->FormValSize() );
if ( newBuckets && newAssocs && newKeys && okayChanges && okayValues )
{
outNew = morkBool_kTrue; /* yes, we created all the arrays we need */
/* init the old hashArrays with slots from this hash table: */
old->mHashArrays_Heap = mMap_Heap;
old->mHashArrays_Slots = mMap_Slots;
old->mHashArrays_Keys = mMap_Keys;
old->mHashArrays_Vals = mMap_Vals;
old->mHashArrays_Assocs = mMap_Assocs;
old->mHashArrays_Buckets = mMap_Buckets;
old->mHashArrays_Changes = mMap_Changes;
/* now replace all our array slots with the new structures: */
++mMap_Seed; /* note the map is now changed */
mMap_Keys = newKeys;
mMap_Vals = newValues;
mMap_Buckets = newBuckets;
mMap_Assocs = newAssocs;
mMap_FreeList = newAssocs; /* all are free to start with */
mMap_Changes = newChanges;
mMap_Slots = inSlots;
}
else /* free the partial set of arrays that were actually allocated */
{
nsIMdbEnv* menv = ev->AsMdbEnv();
nsIMdbHeap* heap = mMap_Heap;
if ( newBuckets )
heap->Free(menv, newBuckets);
if ( newAssocs )
heap->Free(menv, newAssocs);
if ( newKeys )
heap->Free(menv, newKeys);
if ( newValues )
heap->Free(menv, newValues);
if ( newChanges )
heap->Free(menv, newChanges);
MORK_MEMSET(old, 0, sizeof(morkHashArrays));
}
return outNew;
}
/*| grow: make the map arrays bigger by 33%. The old map is completely
**| full, or else we would not have called grow() to get more space. This
**| means the free list is empty, and also means every old key and value is in
**| use in the old arrays. So every key and value must be copied to the new
**| arrays, and since they are contiguous in the old arrays, we can efficiently
**| bitwise copy them in bulk from the old arrays to the new arrays, without
**| paying any attention to the structure of the old arrays.
**|
**|| The content of the old bucket and assoc arrays need not be copied because
**| this information is going to be completely rebuilt by rehashing all the
**| keys into their new buckets, given the new larger map capacity. The new
**| bucket array from new_arrays() is assumed to contain all zeroes, which is
**| necessary to ensure the lists in each bucket stay null terminated as we
**| build the new linked lists. (Note no old bucket ordering is preserved.)
**|
**|| If the old capacity is N, then in the new arrays the assocs with indexes
**| from zero to N-1 are still allocated and must be rehashed into the map.
**| The new free list contains all the following assocs, starting with the new
**| assoc link at index N. (We call the links in the link array "assocs"
**| because allocating a link is the same as allocating the key/value pair
**| with the same index as the link.)
**|
**|| The new free list is initialized simply by pointing at the first new link
**| in the assoc array after the size of the old assoc array. This assumes
**| that FeHashTable_new_arrays() has already linked all the new assocs into a
**| list with the first at the head of the list and the last at the tail of the
**| list. So by making the free list point to the first of the new uncopied
**| assocs, the list is already well-formed.
|*/
mork_bool morkMap::grow(morkEnv* ev)
{
if ( mMap_Heap ) /* can we grow the map? */
{
mork_num newSlots = ((mMap_Slots * 4) / 3) + 1; /* +33% */
morkHashArrays old; /* a place to temporarily hold all the old arrays */
if ( this->new_arrays(ev, &old, newSlots) ) /* have more? */
{
// morkMap_mHash hash = this->FormHash(); /* for terse loop use */
/* figure out the bulk volume sizes of old keys and values to move: */
mork_num oldSlots = old.mHashArrays_Slots; /* number of old assocs */
mork_num keyBulk = oldSlots * this->FormKeySize(); /* key volume */
mork_num valBulk = oldSlots * this->FormValSize(); /* values */
/* convenient variables for new arrays that need to be rehashed: */
morkAssoc** newBuckets = mMap_Buckets; /* new all zeroes */
morkAssoc* newAssocs = mMap_Assocs; /* hash into buckets */
morkAssoc* newFreeList = newAssocs + oldSlots; /* new room is free */
mork_u1* key = mMap_Keys; /* the first key to rehash */
--newAssocs; /* back up one before preincrement used in while loop */
/* move all old keys and values to the new arrays: */
MORK_MEMCPY(mMap_Keys, old.mHashArrays_Keys, keyBulk);
if ( valBulk ) /* are values nonzero sized? */
MORK_MEMCPY(mMap_Vals, old.mHashArrays_Vals, valBulk);
mMap_FreeList = newFreeList; /* remaining assocs are free */
while ( ++newAssocs < newFreeList ) /* rehash another old assoc? */
{
morkAssoc** top = newBuckets + (this->Hash(ev, key) % newSlots);
key += this->FormKeySize(); /* the next key to rehash */
newAssocs->mAssoc_Next = *top; /* link to prev bucket top */
*top = newAssocs; /* push assoc on top of bucket */
}
++mMap_Seed; /* note the map has changed */
old.finalize(ev); /* remember to free the old arrays */
}
}
else ev->OutOfMemoryError();
return ev->Good();
}
mork_bool
morkMap::Put(morkEnv* ev, const void* inKey, const void* inVal,
void* outKey, void* outVal, mork_change** outChange)
{
mork_bool outPut = morkBool_kFalse;
if ( this->GoodMap() ) /* looks good? */
{
mork_u4 hash = this->Hash(ev, inKey);
morkAssoc** ref = this->find(ev, inKey, hash);
if ( ref ) /* assoc was found? reuse an existing assoc slot? */
{
outPut = morkBool_kTrue; /* inKey was indeed already inside the map */
}
else /* assoc not found -- need to allocate a new assoc slot */
{
morkAssoc* assoc = this->pop_free_assoc();
if ( !assoc ) /* no slots remaining in free list? must grow map? */
{
if ( this->grow(ev) ) /* successfully made map larger? */
assoc = this->pop_free_assoc();
}
if ( assoc ) /* allocated new assoc without error? */
{
ref = mMap_Buckets + (hash % mMap_Slots);
assoc->mAssoc_Next = *ref; /* link to prev bucket top */
*ref = assoc; /* push assoc on top of bucket */
++mMap_Fill; /* one more member in the collection */
++mMap_Seed; /* note the map has changed */
}
}
if ( ref ) /* did not have an error during possible growth? */
{
mork_pos i = (*ref) - mMap_Assocs; /* index of assoc */
if ( outPut && (outKey || outVal) ) /* copy old before cobbering? */
this->get_assoc(outKey, outVal, i);
this->put_assoc(inKey, inVal, i);
++mMap_Seed; /* note the map has changed */
if ( outChange )
{
if ( mMap_Changes )
*outChange = mMap_Changes + i;
else
*outChange = this->FormDummyChange();
}
}
}
else this->NewBadMapError(ev);
return outPut;
}
mork_num
morkMap::CutAll(morkEnv* ev)
{
mork_num outCutAll = 0;
if ( this->GoodMap() ) /* map looks good? */
{
mork_num slots = mMap_Slots;
morkAssoc* before = mMap_Assocs - 1; /* before first member */
morkAssoc* assoc = before + slots; /* the very last member */
++mMap_Seed; /* note the map is changed */
/* make the assoc array a linked list headed by first & tailed by last: */
assoc->mAssoc_Next = 0; /* null terminate the new free list */
while ( --assoc > before ) /* another assoc to link into the list? */
assoc->mAssoc_Next = assoc + 1;
mMap_FreeList = mMap_Assocs; /* all are free */
outCutAll = mMap_Fill; /* we'll cut all of them of course */
mMap_Fill = 0; /* the map is completely empty */
}
else this->NewBadMapError(ev);
return outCutAll;
}
mork_bool
morkMap::Cut(morkEnv* ev, const void* inKey,
void* outKey, void* outVal, mork_change** outChange)
{
mork_bool outCut = morkBool_kFalse;
if ( this->GoodMap() ) /* looks good? */
{
mork_u4 hash = this->Hash(ev, inKey);
morkAssoc** ref = this->find(ev, inKey, hash);
if ( ref ) /* found an assoc for key? */
{
outCut = morkBool_kTrue;
morkAssoc* assoc = *ref;
mork_pos i = assoc - mMap_Assocs; /* index of assoc */
if ( outKey || outVal )
this->get_assoc(outKey, outVal, i);
*ref = assoc->mAssoc_Next; /* unlink the found assoc */
this->push_free_assoc(assoc); /* and put it in free list */
if ( outChange )
{
if ( mMap_Changes )
*outChange = mMap_Changes + i;
else
*outChange = this->FormDummyChange();
}
++mMap_Seed; /* note the map has changed */
if ( mMap_Fill ) /* the count shows nonzero members? */
--mMap_Fill; /* one less member in the collection */
else
this->NewSlotsUnderflowWarning(ev);
}
}
else this->NewBadMapError(ev);
return outCut;
}
mork_bool
morkMap::Get(morkEnv* ev, const void* inKey,
void* outKey, void* outVal, mork_change** outChange)
{
mork_bool outGet = morkBool_kFalse;
if ( this->GoodMap() ) /* looks good? */
{
mork_u4 hash = this->Hash(ev, inKey);
morkAssoc** ref = this->find(ev, inKey, hash);
if ( ref ) /* found an assoc for inKey? */
{
mork_pos i = (*ref) - mMap_Assocs; /* index of assoc */
outGet = morkBool_kTrue;
this->get_assoc(outKey, outVal, i);
if ( outChange )
{
if ( mMap_Changes )
*outChange = mMap_Changes + i;
else
*outChange = this->FormDummyChange();
}
}
}
else this->NewBadMapError(ev);
return outGet;
}
morkMapIter::morkMapIter( )
: mMapIter_Map( 0 )
, mMapIter_Seed( 0 )
, mMapIter_Bucket( 0 )
, mMapIter_AssocRef( 0 )
, mMapIter_Assoc( 0 )
, mMapIter_Next( 0 )
{
}
void
morkMapIter::InitMapIter(morkEnv* ev, morkMap* ioMap)
{
mMapIter_Map = 0;
mMapIter_Seed = 0;
mMapIter_Bucket = 0;
mMapIter_AssocRef = 0;
mMapIter_Assoc = 0;
mMapIter_Next = 0;
if ( ioMap )
{
if ( ioMap->GoodMap() )
{
mMapIter_Map = ioMap;
mMapIter_Seed = ioMap->mMap_Seed;
}
else ioMap->NewBadMapError(ev);
}
else ev->NilPointerError();
}
morkMapIter::morkMapIter(morkEnv* ev, morkMap* ioMap)
: mMapIter_Map( 0 )
, mMapIter_Seed( 0 )
, mMapIter_Bucket( 0 )
, mMapIter_AssocRef( 0 )
, mMapIter_Assoc( 0 )
, mMapIter_Next( 0 )
{
if ( ioMap )
{
if ( ioMap->GoodMap() )
{
mMapIter_Map = ioMap;
mMapIter_Seed = ioMap->mMap_Seed;
}
else ioMap->NewBadMapError(ev);
}
else ev->NilPointerError();
}
void
morkMapIter::CloseMapIter(morkEnv* ev)
{
MORK_USED_1(ev);
mMapIter_Map = 0;
mMapIter_Seed = 0;
mMapIter_Bucket = 0;
mMapIter_AssocRef = 0;
mMapIter_Assoc = 0;
mMapIter_Next = 0;
}
mork_change*
morkMapIter::First(morkEnv* ev, void* outKey, void* outVal)
{
mork_change* outFirst = 0;
morkMap* map = mMapIter_Map;
if ( map && map->GoodMap() ) /* map looks good? */
{
morkAssoc** bucket = map->mMap_Buckets;
morkAssoc** end = bucket + map->mMap_Slots; /* one past last */
mMapIter_Seed = map->mMap_Seed; /* sync the seeds */
while ( bucket < end ) /* another bucket in which to look for assocs? */
{
morkAssoc* assoc = *bucket++;
if ( assoc ) /* found the first map assoc in use? */
{
mork_pos i = assoc - map->mMap_Assocs;
mork_change* c = map->mMap_Changes;
outFirst = ( c )? (c + i) : map->FormDummyChange();
mMapIter_Assoc = assoc; /* current assoc in iteration */
mMapIter_Next = assoc->mAssoc_Next; /* more in bucket */
mMapIter_Bucket = --bucket; /* bucket for this assoc */
mMapIter_AssocRef = bucket; /* slot referencing assoc */
map->get_assoc(outKey, outVal, i);
break; /* end while loop */
}
}
}
else map->NewBadMapError(ev);
return outFirst;
}
mork_change*
morkMapIter::Next(morkEnv* ev, void* outKey, void* outVal)
{
mork_change* outNext = 0;
morkMap* map = mMapIter_Map;
if ( map && map->GoodMap() ) /* map looks good? */
{
if ( mMapIter_Seed == map->mMap_Seed ) /* in sync? */
{
morkAssoc* here = mMapIter_Assoc; /* current assoc */
if ( here ) /* iteration is not yet concluded? */
{
morkAssoc* next = mMapIter_Next;
morkAssoc* assoc = next; /* default new mMapIter_Assoc */
if ( next ) /* there are more assocs in the same bucket after Here? */
{
morkAssoc** ref = mMapIter_AssocRef;
/* (*HereRef) equals Here, except when Here has been cut, after
** which (*HereRef) always equals Next. So if (*HereRef) is not
** equal to Next, then HereRef still needs to be updated to point
** somewhere else other than Here. Otherwise it is fine.
*/
if ( *ref != next ) /* Here was not cut? must update HereRef? */
mMapIter_AssocRef = &here->mAssoc_Next;
mMapIter_Next = next->mAssoc_Next;
}
else /* look for the next assoc in the next nonempty bucket */
{
morkAssoc** bucket = map->mMap_Buckets;
morkAssoc** end = bucket + map->mMap_Slots; /* beyond */
mMapIter_Assoc = 0; /* default to no more assocs */
bucket = mMapIter_Bucket; /* last exhausted bucket */
mMapIter_Assoc = 0; /* default to iteration ended */
while ( ++bucket < end ) /* another bucket to search for assocs? */
{
assoc = *bucket;
if ( assoc ) /* found another map assoc in use? */
{
mMapIter_Bucket = bucket;
mMapIter_AssocRef = bucket; /* ref to assoc */
mMapIter_Next = assoc->mAssoc_Next; /* more */
break; /* end while loop */
}
}
}
if ( assoc ) /* did we find another assoc in the iteration? */
{
mMapIter_Assoc = assoc; /* current assoc */
mork_pos i = assoc - map->mMap_Assocs;
mork_change* c = map->mMap_Changes;
outNext = ( c )? (c + i) : map->FormDummyChange();
map->get_assoc( outKey, outVal, i);
}
}
}
else map->NewIterOutOfSyncError(ev);
}
else map->NewBadMapError(ev);
return outNext;
}
mork_change*
morkMapIter::Here(morkEnv* ev, void* outKey, void* outVal)
{
mork_change* outHere = 0;
morkMap* map = mMapIter_Map;
if ( map && map->GoodMap() ) /* map looks good? */
{
if ( mMapIter_Seed == map->mMap_Seed ) /* in sync? */
{
morkAssoc* here = mMapIter_Assoc; /* current assoc */
if ( here ) /* iteration is not yet concluded? */
{
mork_pos i = here - map->mMap_Assocs;
mork_change* c = map->mMap_Changes;
outHere = ( c )? (c + i) : map->FormDummyChange();
map->get_assoc(outKey, outVal, i);
}
}
else map->NewIterOutOfSyncError(ev);
}
else map->NewBadMapError(ev);
return outHere;
}
mork_change*
morkMapIter::CutHere(morkEnv* ev, void* outKey, void* outVal)
{
mork_change* outCutHere = 0;
morkMap* map = mMapIter_Map;
if ( map && map->GoodMap() ) /* map looks good? */
{
if ( mMapIter_Seed == map->mMap_Seed ) /* in sync? */
{
morkAssoc* here = mMapIter_Assoc; /* current assoc */
if ( here ) /* iteration is not yet concluded? */
{
morkAssoc** ref = mMapIter_AssocRef;
if ( *ref != mMapIter_Next ) /* not already cut? */
{
mork_pos i = here - map->mMap_Assocs;
mork_change* c = map->mMap_Changes;
outCutHere = ( c )? (c + i) : map->FormDummyChange();
if ( outKey || outVal )
map->get_assoc(outKey, outVal, i);
map->push_free_assoc(here); /* add to free list */
*ref = mMapIter_Next; /* unlink here from bucket list */
/* note the map has changed, but we are still in sync: */
mMapIter_Seed = ++map->mMap_Seed; /* sync */
if ( map->mMap_Fill ) /* still has nonzero value? */
--map->mMap_Fill; /* one less member in the collection */
else
map->NewSlotsUnderflowWarning(ev);
}
}
}
else map->NewIterOutOfSyncError(ev);
}
else map->NewBadMapError(ev);
return outCutHere;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,372 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKMAP_
#define _MORKMAP_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/* (These hash methods closely resemble those in public domain IronDoc.) */
/*| Equal: equal for hash table. Note equal(a,b) implies hash(a)==hash(b).
|*/
typedef mork_bool (* morkMap_mEqual)
(const morkMap* self, morkEnv* ev, const void* inKeyA, const void* inKeyB);
/*| Hash: hash for hash table. Note equal(a,b) implies hash(a)==hash(b).
|*/
typedef mork_u4 (* morkMap_mHash)
(const morkMap* self, morkEnv* ev, const void* inKey);
/*| IsNil: whether a key slot contains a "null" value denoting "no such key".
|*/
typedef mork_bool (* morkMap_mIsNil)
(const morkMap* self, morkEnv* ev, const void* inKey);
/*| Note: notify regarding a refcounting change for a key or a value.
|*/
//typedef void (* morkMap_mNote)
//(morkMap* self, morkEnv* ev, void* inKeyOrVal);
/*| morkMapForm: slots need to initialize a new dict. (This is very similar
**| to the config object for public domain IronDoc hash tables.)
|*/
class morkMapForm { // a struct of callback method pointers for morkMap
public:
// const void* mMapForm_NilKey; // externally defined 'nil' bit pattern
// void* mMapForm_NilBuf[ 8 ]; // potential place to put NilKey
// If keys are no larger than 8*sizeof(void*), NilKey can be put in NilBuf.
// Note this should be true for all Mork subclasses, and we plan usage so.
// These three methods must always be provided, so zero will cause errors:
// morkMap_mEqual mMapForm_Equal; // for comparing two keys for identity
// morkMap_mHash mMapForm_Hash; // deterministic key to hash method
// morkMap_mIsNil mMapForm_IsNil; // to query whether a key equals 'nil'
// If any of these method slots are nonzero, then morkMap will call the
// appropriate one to notify dict users when a key or value is added or cut.
// Presumably a caller wants to know this in order to perform refcounting or
// some other kind of memory management. These methods are definitely only
// called when references to keys or values are inserted or removed, and are
// never called when the actual number of references does not change (such
// as when added keys are already present or cut keys are alreading missing).
//
// morkMap_mNote mMapForm_AddKey; // if nonzero, notify about add key
// morkMap_mNote mMapForm_CutKey; // if nonzero, notify about cut key
// morkMap_mNote mMapForm_AddVal; // if nonzero, notify about add val
// morkMap_mNote mMapForm_CutVal; // if nonzero, notify about cut val
//
// These note methods have been removed because it seems difficult to
// guarantee suitable alignment of objects passed to notification methods.
// Note dict clients should pick key and val sizes that provide whatever
// alignment will be required for an array of such keys and values.
mork_size mMapForm_KeySize; // size of every key (cannot be zero)
mork_size mMapForm_ValSize; // size of every val (can indeed be zero)
mork_bool mMapForm_HoldChanges; // support changes array in the map
mork_change mMapForm_DummyChange; // change used for false HoldChanges
mork_bool mMapForm_KeyIsIP; // key is mork_ip sized
mork_bool mMapForm_ValIsIP; // key is mork_ip sized
};
/*| morkAssoc: a canonical association slot in a morkMap. A single assoc
**| instance does nothing except point to the next assoc in the same bucket
**| of a hash table. Each assoc has only two interesting attributes: 1) the
**| address of the assoc, and 2) the next assoc in a bucket's list. The assoc
**| address is interesting because in the context of an array of such assocs,
**| one can determine the index of a particular assoc in the array by address
**| arithmetic, subtracting the array address from the assoc address. And the
**| index of each assoc is the same index as the associated key and val slots
**| in the associated arrays
**|
**|| Think of an assoc instance as really also containing a key slot and a val
**| slot, where each key is mMap_Form.mMapForm_KeySize bytes in size, and
**| each val is mMap_Form.mMapForm_ValSize in size. But the key and val
**| slots are stored in separate arrays with indexes that are parallel to the
**| indexes in the array of morkAssoc instances. We have taken the variable
**| sized slots out of the morkAssoc structure, and put them into parallel
**| arrays associated with each morkAssoc by array index. And this leaves us
**| with only the link field to the next assoc in each assoc instance.
|*/
class morkAssoc {
public:
morkAssoc* mAssoc_Next;
};
#define morkDerived_kMap /*i*/ 0x4D70 /* ascii 'Mp' */
#define morkMap_kTag /*i*/ 0x6D4D6150 /* ascii 'mMaP' */
/*| morkMap: a hash table based on the public domain IronDoc hash table
**| (which is in turn rather like a similar OpenDoc hash table).
|*/
class morkMap : public morkNode {
// public: // slots inherited from morkNode (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
public: // state is public because the entire Mork system is private
nsIMdbHeap* mMap_Heap; // strong ref to heap allocating all space
mork_u4 mMap_Tag; // must equal morkMap_kTag
// When a morkMap instance is constructed, the dict form slots must be
// provided in order to properly configure a dict with all runtime needs:
morkMapForm mMap_Form; // construction time parameterization
// Whenever the dict changes structure in a way that would affect any
// iteration of the dict associations, the seed increments to show this:
mork_seed mMap_Seed; // counter for member and structural changes
// The current total assoc capacity of the dict is mMap_Slots, where
// mMap_Fill of these slots are actually holding content, so mMap_Fill
// is the actual membership count, and mMap_Slots is how larger membership
// can become before the hash table must grow the buffers being used.
mork_count mMap_Slots; // count of slots in the hash table
mork_fill mMap_Fill; // number of used slots in the hash table
// Key and value slots are bound to corresponding mMap_Assocs array slots.
// Instead of having a single array like this: {key,val,next}[ mMap_Slots ]
// we have instead three parallel arrays with essentially the same meaning:
// {key}[ mMap_Slots ], {val}[ mMap_Slots ], {assocs}[ mMap_Slots ]
mork_u1* mMap_Keys; // mMap_Slots * mMapForm_KeySize buffer
mork_u1* mMap_Vals; // mMap_Slots * mMapForm_ValSize buffer
// An assoc is "used" when it appears in a bucket's linked list of assocs.
// Until an assoc is used, it appears in the FreeList linked list. Every
// assoc that becomes used goes into the bucket determined by hashing the
// key associated with a new assoc. The key associated with a new assoc
// goes in to the slot in mMap_Keys which occupies exactly the same array
// index as the array index of the used assoc in the mMap_Assocs array.
morkAssoc* mMap_Assocs; // mMap_Slots * sizeof(morkAssoc) buffer
// The changes array is only needed when the
mork_change* mMap_Changes; // mMap_Slots * sizeof(mork_change) buffer
// The Buckets array need not be the same length as the Assocs array, but we
// usually do it that way so the average bucket depth is no more than one.
// (We could pick a different policy, or make it parameterizable, but that's
// tuning we can do some other time.)
morkAssoc** mMap_Buckets; // mMap_Slots * sizeof(morkAssoc*) buffer
// The length of the mMap_FreeList should equal (mMap_Slots - mMap_Fill).
// We need a free list instead of a simpler representation because assocs
// can be cut and returned to availability in any kind of unknown pattern.
// (However, when assocs are first allocated, or when the dict is grown, we
// know all new assocs are contiguous and can chain together adjacently.)
morkAssoc* mMap_FreeList; // list of unused mMap_Assocs array slots
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseMap() only if open
virtual ~morkMap(); // assert that CloseMap() executed earlier
public: // morkMap construction & destruction
morkMap(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioNodeHeap,
mork_size inKeySize, mork_size inValSize,
mork_size inSlots, nsIMdbHeap* ioSlotHeap, mork_bool inHoldChanges);
void CloseMap(morkEnv* ev); // called by
public: // dynamic type identification
mork_bool IsMap() const
{ return IsNode() && mNode_Derived == morkDerived_kMap; }
// } ===== end morkNode methods =====
public: // poly map hash table methods
// { ===== begin morkMap poly interface =====
virtual mork_bool // note: equal(a,b) implies hash(a) == hash(b)
Equal(morkEnv* ev, const void* inKeyA, const void* inKeyB) const = 0;
virtual mork_u4 // note: equal(a,b) implies hash(a) == hash(b)
Hash(morkEnv* ev, const void* inKey) const = 0;
// } ===== end morkMap poly interface =====
public: // open utitity methods
mork_bool GoodMapTag() const { return mMap_Tag == morkMap_kTag; }
mork_bool GoodMap() const
{ return ( IsNode() && GoodMapTag() ); }
void NewIterOutOfSyncError(morkEnv* ev);
void NewBadMapError(morkEnv* ev);
void NewSlotsUnderflowWarning(morkEnv* ev);
void InitMap(morkEnv* ev, mork_size inSlots);
protected: // internal utitity methods
friend class morkMapIter;
void clear_map(morkEnv* ev, nsIMdbHeap* ioHeap);
void* alloc(morkEnv* ev, mork_size inSize);
void* clear_alloc(morkEnv* ev, mork_size inSize);
void push_free_assoc(morkAssoc* ioAssoc)
{
ioAssoc->mAssoc_Next = mMap_FreeList;
mMap_FreeList = ioAssoc;
}
morkAssoc* pop_free_assoc()
{
morkAssoc* assoc = mMap_FreeList;
if ( assoc )
mMap_FreeList = assoc->mAssoc_Next;
return assoc;
}
morkAssoc** find(morkEnv* ev, const void* inKey, mork_u4 inHash) const;
mork_u1* new_keys(morkEnv* ev, mork_num inSlots);
mork_u1* new_values(morkEnv* ev, mork_num inSlots);
mork_change* new_changes(morkEnv* ev, mork_num inSlots);
morkAssoc** new_buckets(morkEnv* ev, mork_num inSlots);
morkAssoc* new_assocs(morkEnv* ev, mork_num inSlots);
mork_bool new_arrays(morkEnv* ev, morkHashArrays* old, mork_num inSlots);
mork_bool grow(morkEnv* ev);
void get_assoc(void* outKey, void* outVal, mork_pos inPos) const;
void put_assoc(const void* inKey, const void* inVal, mork_pos inPos) const;
public: // inlines to form slots
// const void* FormNilKey() const { return mMap_Form.mMapForm_NilKey; }
// morkMap_mEqual FormEqual() const { return mMap_Form.mMapForm_Equal; }
// morkMap_mHash FormHash() const { return mMap_Form.mMapForm_Hash; }
// orkMap_mIsNil FormIsNil() const { return mMap_Form.mMapForm_IsNil; }
// morkMap_mNote FormAddKey() const { return mMap_Form.mMapForm_AddKey; }
// morkMap_mNote FormCutKey() const { return mMap_Form.mMapForm_CutKey; }
// morkMap_mNote FormAddVal() const { return mMap_Form.mMapForm_AddVal; }
// morkMap_mNote FormCutVal() const { return mMap_Form.mMapForm_CutVal; }
mork_size FormKeySize() const { return mMap_Form.mMapForm_KeySize; }
mork_size FormValSize() const { return mMap_Form.mMapForm_ValSize; }
mork_bool FormKeyIsIP() const { return mMap_Form.mMapForm_KeyIsIP; }
mork_bool FormValIsIP() const { return mMap_Form.mMapForm_ValIsIP; }
mork_bool FormHoldChanges() const
{ return mMap_Form.mMapForm_HoldChanges; }
mork_change* FormDummyChange()
{ return &mMap_Form.mMapForm_DummyChange; }
public: // other map methods
mork_bool Put(morkEnv* ev, const void* inKey, const void* inVal,
void* outKey, void* outVal, mork_change** outChange);
mork_bool Cut(morkEnv* ev, const void* inKey,
void* outKey, void* outVal, mork_change** outChange);
mork_bool Get(morkEnv* ev, const void* inKey,
void* outKey, void* outVal, mork_change** outChange);
mork_num CutAll(morkEnv* ev);
private: // copying is not allowed
morkMap(const morkMap& other);
morkMap& operator=(const morkMap& other);
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakMap(morkMap* me,
morkEnv* ev, morkMap** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongMap(morkMap* me,
morkEnv* ev, morkMap** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
/*| morkMapIter: an iterator for morkMap and subclasses. This is not a node,
**| and expected usage is as a member of some other node subclass, such as in
**| a cursor subclass or a thumb subclass. Also, iters might be as temp stack
**| objects when scanning the content of a map.
|*/
class morkMapIter{ // iterator for hash table map
protected:
morkMap* mMapIter_Map; // map to iterate, NOT refcounted
mork_seed mMapIter_Seed; // cached copy of map's seed
morkAssoc** mMapIter_Bucket; // one bucket in mMap_Buckets array
morkAssoc** mMapIter_AssocRef; // usually *AtRef equals Here
morkAssoc* mMapIter_Assoc; // the current assoc in an iteration
morkAssoc* mMapIter_Next; // mMapIter_Assoc->mAssoc_Next */
public:
morkMapIter(morkEnv* ev, morkMap* ioMap);
void CloseMapIter(morkEnv* ev);
morkMapIter( ); // everything set to zero -- need to call InitMapIter()
protected: // we want all subclasses to provide typesafe wrappers:
void InitMapIter(morkEnv* ev, morkMap* ioMap);
// The morkAssoc returned below is always either mork_change* or
// else nil (when there is no such assoc). We return a pointer to
// the change rather than a simple bool, because callers might
// want to access change info associated with an assoc.
mork_change* First(morkEnv* ev, void* outKey, void* outVal);
mork_change* Next(morkEnv* ev, void* outKey, void* outVal);
mork_change* Here(morkEnv* ev, void* outKey, void* outVal);
mork_change* CutHere(morkEnv* ev, void* outKey, void* outVal);
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKMAP_ */

View File

@@ -1,603 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKPOOL_
#include "morkPool.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKHANDLE_
#include "morkHandle.h"
#endif
/*3456789_123456789_123456789_123456789_123456789_123456789_123456789_12345678*/
/* ===== ===== ===== ===== morkUsage ===== ===== ===== ===== */
static morkUsage morkUsage_gHeap; // ensure EnsureReadyStaticUsage()
const morkUsage& morkUsage::kHeap = morkUsage_gHeap;
static morkUsage morkUsage_gStack; // ensure EnsureReadyStaticUsage()
const morkUsage& morkUsage::kStack = morkUsage_gStack;
static morkUsage morkUsage_gMember; // ensure EnsureReadyStaticUsage()
const morkUsage& morkUsage::kMember = morkUsage_gMember;
static morkUsage morkUsage_gGlobal; // ensure EnsureReadyStaticUsage()
const morkUsage& morkUsage::kGlobal = morkUsage_gGlobal;
static morkUsage morkUsage_gPool; // ensure EnsureReadyStaticUsage()
const morkUsage& morkUsage::kPool = morkUsage_gPool;
static morkUsage morkUsage_gNone; // ensure EnsureReadyStaticUsage()
const morkUsage& morkUsage::kNone = morkUsage_gNone;
// This must be structured to allow for non-zero values in global variables
// just before static init time. We can only safely check for whether a
// global has the address of some other global. Please, do not initialize
// either of the variables below to zero, because this could break when a zero
// is assigned at static init time, but after EnsureReadyStaticUsage() runs.
static mork_u4 morkUsage_g_static_init_target; // only address of this matters
static mork_u4* morkUsage_g_static_init_done; // is address of target above?
#define morkUsage_do_static_init() \
( morkUsage_g_static_init_done = &morkUsage_g_static_init_target )
#define morkUsage_need_static_init() \
( morkUsage_g_static_init_done != &morkUsage_g_static_init_target )
/*static*/
void morkUsage::EnsureReadyStaticUsage()
{
if ( morkUsage_need_static_init() )
{
morkUsage_do_static_init();
morkUsage_gHeap.InitUsage(morkUsage_kHeap);
morkUsage_gStack.InitUsage(morkUsage_kStack);
morkUsage_gMember.InitUsage(morkUsage_kMember);
morkUsage_gGlobal.InitUsage(morkUsage_kGlobal);
morkUsage_gPool.InitUsage(morkUsage_kPool);
morkUsage_gNone.InitUsage(morkUsage_kNone);
}
}
/*static*/
const morkUsage& morkUsage::GetHeap() // kHeap safe at static init time
{
EnsureReadyStaticUsage();
return morkUsage_gHeap;
}
/*static*/
const morkUsage& morkUsage::GetStack() // kStack safe at static init time
{
EnsureReadyStaticUsage();
return morkUsage_gStack;
}
/*static*/
const morkUsage& morkUsage::GetMember() // kMember safe at static init time
{
EnsureReadyStaticUsage();
return morkUsage_gMember;
}
/*static*/
const morkUsage& morkUsage::GetGlobal() // kGlobal safe at static init time
{
EnsureReadyStaticUsage();
return morkUsage_gGlobal;
}
/*static*/
const morkUsage& morkUsage::GetPool() // kPool safe at static init time
{
EnsureReadyStaticUsage();
return morkUsage_gPool;
}
/*static*/
const morkUsage& morkUsage::GetNone() // kNone safe at static init time
{
EnsureReadyStaticUsage();
return morkUsage_gNone;
}
morkUsage::morkUsage()
{
if ( morkUsage_need_static_init() )
{
morkUsage::EnsureReadyStaticUsage();
}
}
morkUsage::morkUsage(mork_usage code)
: mUsage_Code(code)
{
if ( morkUsage_need_static_init() )
{
morkUsage::EnsureReadyStaticUsage();
}
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/*static*/ void*
morkNode::MakeNew(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev)
{
void* node = 0;
if ( &ioHeap )
{
ioHeap.Alloc(ev->AsMdbEnv(), inSize, (void **) &node);
if ( !node )
ev->OutOfMemoryError();
}
else
ev->NilPointerError();
return node;
}
/*static*/ void
morkNode::OnDeleteAssert(void* ioAddress) // cannot operator delete()
{
MORK_USED_1(ioAddress);
MORK_ASSERT(morkBool_kFalse); // tell developer: must not delete nodes
}
/*public non-poly*/ void
morkNode::ZapOld(morkEnv* ev, nsIMdbHeap* ioHeap)
{
if ( this )
{
if ( this->IsNode() )
{
mork_usage usage = mNode_Usage; // mNode_Usage before ~morkNode
this->morkNode::~morkNode(); // first call polymorphic destructor
if ( ioHeap ) // was this node heap allocated?
ioHeap->Free(ev->AsMdbEnv(), this);
else if ( usage == morkUsage_kPool ) // mNode_Usage before ~morkNode
{
morkHandle* h = (morkHandle*) this;
if ( h->IsHandle() && h->GoodHandleTag() )
{
if ( h->mHandle_Face )
{
ev->mEnv_HandlePool->ZapHandle(ev, h->mHandle_Face);
}
else
ev->NilPointerError();
}
}
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
/*public virtual*/ void
morkNode::CloseMorkNode(morkEnv* ev) // CloseNode() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseNode(ev);
this->MarkShut();
}
}
/*public virtual*/
morkNode::~morkNode() // assert that CloseNode() executed earlier
{
MORK_ASSERT(this->IsShutNode());
mNode_Access = morkAccess_kDead;
mNode_Usage = morkUsage_kNone;
}
/*public virtual*/
// void CloseMorkNode(morkEnv* ev) = 0; // CloseNode() only if open
// CloseMorkNode() is the polymorphic close method called when uses==0,
// which must do NOTHING at all when IsOpenNode() is not true. Otherwise,
// CloseMorkNode() should call a static close method specific to an object.
// Each such static close method should either call inherited static close
// methods, or else perform the consolidated effect of calling them, where
// subclasses should closely track any changes in base classes with care.
/*public non-poly*/
morkNode::morkNode(const morkUsage& inUsage, nsIMdbHeap* ioHeap)
: mNode_Heap( ioHeap )
, mNode_Base( morkBase_kNode )
, mNode_Derived ( 0 ) // until subclass sets appropriately
, mNode_Access( morkAccess_kOpen )
, mNode_Usage( inUsage.Code() )
, mNode_Mutable( morkAble_kEnabled )
, mNode_Load( morkLoad_kClean )
, mNode_Uses( 1 )
, mNode_Refs( 1 )
{
if ( !ioHeap && mNode_Usage == morkUsage_kHeap )
MORK_ASSERT(ioHeap);
}
/*public non-poly*/
morkNode::morkNode(morkEnv* ev,
const morkUsage& inUsage, nsIMdbHeap* ioHeap)
: mNode_Heap( ioHeap )
, mNode_Base( morkBase_kNode )
, mNode_Derived ( 0 ) // until subclass sets appropriately
, mNode_Access( morkAccess_kOpen )
, mNode_Usage( inUsage.Code() )
, mNode_Mutable( morkAble_kEnabled )
, mNode_Load( morkLoad_kClean )
, mNode_Uses( 1 )
, mNode_Refs( 1 )
{
if ( !ioHeap && mNode_Usage == morkUsage_kHeap )
{
this->NilHeapError(ev);
}
}
/*protected non-poly*/ void
morkNode::RefsUnderUsesWarning(morkEnv* ev) const
{
ev->NewError("mNode_Refs < mNode_Uses");
}
/*protected non-poly*/ void
morkNode::NonNodeError(morkEnv* ev) const // called when IsNode() is false
{
ev->NewError("non-morkNode");
}
/*protected non-poly*/ void
morkNode::NonOpenNodeError(morkEnv* ev) const // when IsOpenNode() is false
{
ev->NewError("non-open-morkNode");
}
/*protected non-poly*/ void
morkNode::NonMutableNodeError(morkEnv* ev) const // when IsMutable() is false
{
ev->NewError("non-mutable-morkNode");
}
/*protected non-poly*/ void
morkNode::NilHeapError(morkEnv* ev) const // zero mNode_Heap w/ kHeap usage
{
ev->NewError("nil mNode_Heap");
}
/*protected non-poly*/ void
morkNode::RefsOverflowWarning(morkEnv* ev) const // mNode_Refs overflow
{
ev->NewWarning("mNode_Refs overflow");
}
/*protected non-poly*/ void
morkNode::UsesOverflowWarning(morkEnv* ev) const // mNode_Uses overflow
{
ev->NewWarning("mNode_Uses overflow");
}
/*protected non-poly*/ void
morkNode::RefsUnderflowWarning(morkEnv* ev) const // mNode_Refs underflow
{
ev->NewWarning("mNode_Refs underflow");
}
/*protected non-poly*/ void
morkNode::UsesUnderflowWarning(morkEnv* ev) const // mNode_Uses underflow
{
ev->NewWarning("mNode_Uses underflow");
}
/*public non-poly*/ void
morkNode::CloseNode(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
this->MarkShut();
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
extern void // utility method very similar to morkNode::SlotStrongNode():
nsIMdbFile_SlotStrongFile(nsIMdbFile* self, morkEnv* ev, nsIMdbFile** ioSlot)
// If *ioSlot is non-nil, that file is released by CutStrongRef() and
// then zeroed out. Then if self is non-nil, this is acquired by
// calling AddStrongRef(), and if the return value shows success,
// then self is put into slot *ioSlot. Note self can be nil, so we take
// expression 'nsIMdbFile_SlotStrongFile(0, ev, &slot)'.
{
nsIMdbEnv* menv = ev->AsMdbEnv();
nsIMdbFile* file = *ioSlot;
if ( file )
{
*ioSlot = 0;
file->CutStrongRef(menv);
}
if ( self && ev->Good() && (self->AddStrongRef(menv)==0) && ev->Good() )
*ioSlot = self;
}
void // utility method very similar to morkNode::SlotStrongNode():
nsIMdbHeap_SlotStrongHeap(nsIMdbHeap* self, morkEnv* ev, nsIMdbHeap** ioSlot)
// If *ioSlot is non-nil, that heap is released by CutStrongRef() and
// then zeroed out. Then if self is non-nil, self is acquired by
// calling AddStrongRef(), and if the return value shows success,
// then self is put into slot *ioSlot. Note self can be nil, so we
// permit expression 'nsIMdbHeap_SlotStrongHeap(0, ev, &slot)'.
{
nsIMdbEnv* menv = ev->AsMdbEnv();
nsIMdbHeap* heap = *ioSlot;
if ( heap )
{
*ioSlot = 0;
heap->CutStrongRef(menv);
}
if ( self && ev->Good() && (self->AddStrongRef(menv)==0) && ev->Good() )
*ioSlot = self;
}
/*public static*/ void
morkNode::SlotStrongNode(morkNode* me, morkEnv* ev, morkNode** ioSlot)
// If *ioSlot is non-nil, that node is released by CutStrongRef() and
// then zeroed out. Then if me is non-nil, this is acquired by
// calling AddStrongRef(), and if positive is returned to show success,
// then me is put into slot *ioSlot. Note me can be nil, so we take
// expression 'morkNode::SlotStrongNode((morkNode*) 0, ev, &slot)'.
{
morkNode* node = *ioSlot;
if ( me != node )
{
if ( node )
{
*ioSlot = 0;
node->CutStrongRef(ev);
}
if ( me && me->AddStrongRef(ev) )
*ioSlot = me;
}
}
/*public static*/ void
morkNode::SlotWeakNode(morkNode* me, morkEnv* ev, morkNode** ioSlot)
// If *ioSlot is non-nil, that node is released by CutWeakRef() and
// then zeroed out. Then if me is non-nil, this is acquired by
// calling AddWeakRef(), and if positive is returned to show success,
// then me is put into slot *ioSlot. Note me can be nil, so we
// expression 'morkNode::SlotWeakNode((morkNode*) 0, ev, &slot)'.
{
morkNode* node = *ioSlot;
if ( me != node )
{
if ( node )
{
*ioSlot = 0;
node->CutWeakRef(ev);
}
if ( me && me->AddWeakRef(ev) )
*ioSlot = me;
}
}
/*public non-poly*/ mork_uses
morkNode::AddStrongRef(morkEnv* ev)
{
mork_uses outUses = 0;
if ( this )
{
if ( this->IsNode() )
{
mork_uses uses = mNode_Uses;
mork_refs refs = mNode_Refs;
if ( refs < uses ) // need to fix broken refs/uses relation?
{
this->RefsUnderUsesWarning(ev);
mNode_Refs = mNode_Uses = refs = uses;
}
if ( refs < morkNode_kMaxRefCount ) // not too great?
{
mNode_Refs = ++refs;
mNode_Uses = ++uses;
}
else
this->RefsOverflowWarning(ev);
outUses = uses;
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
return outUses;
}
/*private non-poly*/ mork_bool
morkNode::cut_use_count(morkEnv* ev) // just one part of CutStrongRef()
{
mork_bool didCut = morkBool_kFalse;
if ( this )
{
if ( this->IsNode() )
{
mork_uses uses = mNode_Uses;
if ( uses ) // not yet zero?
mNode_Uses = --uses;
else
this->UsesUnderflowWarning(ev);
didCut = morkBool_kTrue;
if ( !mNode_Uses ) // last use gone? time to close node?
{
if ( this->IsOpenNode() )
{
if ( !mNode_Refs ) // no outstanding reference?
{
this->RefsUnderflowWarning(ev);
++mNode_Refs; // prevent potential crash during close
}
this->CloseMorkNode(ev); // polymorphic self close
// (Note CutNode() is not polymorphic -- so don't call that.)
}
}
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
return didCut;
}
/*public non-poly*/ mork_uses
morkNode::CutStrongRef(morkEnv* ev)
{
mork_refs outRefs = 0;
if ( this )
{
if ( this->IsNode() )
{
if ( this->cut_use_count(ev) )
outRefs = this->CutWeakRef(ev);
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
return outRefs;
}
/*public non-poly*/ mork_refs
morkNode::AddWeakRef(morkEnv* ev)
{
mork_refs outRefs = 0;
if ( this )
{
if ( this->IsNode() )
{
mork_refs refs = mNode_Refs;
if ( refs < morkNode_kMaxRefCount ) // not too great?
mNode_Refs = ++refs;
else
this->RefsOverflowWarning(ev);
outRefs = refs;
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
return outRefs;
}
/*public non-poly*/ mork_refs
morkNode::CutWeakRef(morkEnv* ev)
{
mork_refs outRefs = 0;
if ( this )
{
if ( this->IsNode() )
{
mork_uses uses = mNode_Uses;
mork_refs refs = mNode_Refs;
if ( refs ) // not yet zero?
mNode_Refs = --refs;
else
this->RefsUnderflowWarning(ev);
if ( refs < uses ) // need to fix broken refs/uses relation?
{
this->RefsUnderUsesWarning(ev);
mNode_Refs = mNode_Uses = refs = uses;
}
outRefs = refs;
if ( !refs ) // last reference gone? time to destroy node?
this->ZapOld(ev, mNode_Heap); // self destroy, use this no longer
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
return outRefs;
}
static const char* morkNode_kBroken = "broken";
/*public non-poly*/ const char*
morkNode::GetNodeAccessAsString() const // e.g. "open", "shut", etc.
{
const char* outString = morkNode_kBroken;
switch( mNode_Access )
{
case morkAccess_kOpen: outString = "open"; break;
case morkAccess_kClosing: outString = "closing"; break;
case morkAccess_kShut: outString = "shut"; break;
case morkAccess_kDead: outString = "dead"; break;
}
return outString;
}
/*public non-poly*/ const char*
morkNode::GetNodeUsageAsString() const // e.g. "heap", "stack", etc.
{
const char* outString = morkNode_kBroken;
switch( mNode_Usage )
{
case morkUsage_kHeap: outString = "heap"; break;
case morkUsage_kStack: outString = "stack"; break;
case morkUsage_kMember: outString = "member"; break;
case morkUsage_kGlobal: outString = "global"; break;
case morkUsage_kPool: outString = "pool"; break;
case morkUsage_kNone: outString = "none"; break;
}
return outString;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,282 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKNODE_
#define _MORKNODE_ 1
#ifndef _MORK_
#include "mork.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkUsage_kHeap 'h'
#define morkUsage_kStack 's'
#define morkUsage_kMember 'm'
#define morkUsage_kGlobal 'g'
#define morkUsage_kPool 'p'
#define morkUsage_kNone 'n'
class morkUsage {
public:
mork_usage mUsage_Code; // kHeap, kStack, kMember, or kGhost
public:
morkUsage(mork_usage inCode);
morkUsage(); // does nothing except maybe call EnsureReadyStaticUsage()
void InitUsage( mork_usage inCode)
{ mUsage_Code = inCode; }
~morkUsage() { }
mork_usage Code() const { return mUsage_Code; }
static void EnsureReadyStaticUsage();
public:
static const morkUsage& kHeap; // morkUsage_kHeap
static const morkUsage& kStack; // morkUsage_kStack
static const morkUsage& kMember; // morkUsage_kMember
static const morkUsage& kGlobal; // morkUsage_kGlobal
static const morkUsage& kPool; // morkUsage_kPool
static const morkUsage& kNone; // morkUsage_kNone
static const morkUsage& GetHeap(); // kHeap, safe at static init time
static const morkUsage& GetStack(); // kStack, safe at static init time
static const morkUsage& GetMember(); // kMember, safe at static init time
static const morkUsage& GetGlobal(); // kGlobal, safe at static init time
static const morkUsage& GetPool(); // kPool, safe at static init time
static const morkUsage& GetNone(); // kNone, safe at static init time
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkNode_kMaxRefCount 0x0FFFF /* count sticks if it hits this */
#define morkBase_kNode /*i*/ 0x4E64 /* ascii 'Nd' */
/*| morkNode: several groups of two-byte integers that track the basic
**| status of an object that can be used to compose in-memory graphs.
**| This is the base class for nsIMdbObject (which adds members that fit
**| the needs of an nsIMdbObject subclass). The morkNode class is also used
**| as the base class for other Mork db classes with no strong relation to
**| the MDB class hierarchy.
**|
**|| Heap: the heap in which this node was allocated, when the usage equals
**| morkUsage_kHeap to show dynamic allocation. Note this heap is NOT ref-
**| counted, because that would be too great and complex a burden for all
**| the nodes allocated in that heap. So heap users should take care to
**| understand that nodes allocated in that heap are considered protected
**| by some inclusive context in which all those nodes are allocated, and
**| that context must maintain at least one strong refcount for the heap.
**| Occasionally a node subclass will indeed wish to hold a refcounted
**| reference to a heap, and possibly the same heap that is in mNode_Heap,
**| but this is always done in a separate slot that explicitly refcounts,
**| so we avoid confusing what is meant by the mNode_Heap slot.
|*/
class morkNode { // base class for constructing Mork object graphs
public: // state is public because the entire Mork system is private
nsIMdbHeap* mNode_Heap; // NON-refcounted heap pointer
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
protected: // special case empty construction for morkHandleFrame
friend class morkHandleFrame;
morkNode() { }
public: // inlines for weird mNode_Mutable and mNode_Load constants
void SetFrozen() { mNode_Mutable = morkAble_kDisabled; }
void SetMutable() { mNode_Mutable = morkAble_kEnabled; }
void SetAsleep() { mNode_Mutable = morkAble_kAsleep; }
mork_bool IsFrozen() const { return mNode_Mutable == morkAble_kDisabled; }
mork_bool IsMutable() const { return mNode_Mutable == morkAble_kEnabled; }
mork_bool IsAsleep() const { return mNode_Mutable == morkAble_kAsleep; }
void SetNodeClean() { mNode_Load = morkLoad_kClean; }
void SetNodeDirty() { mNode_Load = morkLoad_kDirty; }
mork_bool IsNodeClean() const { return mNode_Load == morkLoad_kClean; }
mork_bool IsNodeDirty() const { return mNode_Load == morkLoad_kDirty; }
public: // morkNode memory management methods
static void* MakeNew(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev);
static void OnDeleteAssert(void* ioAddress); // cannot operator delete()
void ZapOld(morkEnv* ev, nsIMdbHeap* ioHeap); // replaces operator delete()
// this->morkNode::~morkNode(); // first call polymorphic destructor
// if ( ioHeap ) // was this node heap allocated?
// ioHeap->Free(ev->AsMdbEnv(), this);
public: // morkNode memory management operators
void* operator new(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev)
{ return morkNode::MakeNew(inSize, ioHeap, ev); }
void operator delete(void* ioAddress)
{ morkNode::OnDeleteAssert(ioAddress); }
// do NOT call delete on morkNode instances. Call ZapOld() instead.
protected: // construction without an anv needed for first env constructed:
morkNode(const morkUsage& inUsage, nsIMdbHeap* ioHeap);
// { ===== begin basic node interface =====
public: // morkNode virtual methods
// virtual FlushMorkNode(morkEnv* ev, morkStream* ioStream);
// virtual WriteMorkNode(morkEnv* ev, morkStream* ioStream);
virtual ~morkNode(); // assert that CloseNode() executed earlier
virtual void CloseMorkNode(morkEnv* ev); // CloseNode() only if open
// CloseMorkNode() is the polymorphic close method called when uses==0,
// which must do NOTHING at all when IsOpenNode() is not true. Otherwise,
// CloseMorkNode() should call a static close method specific to an object.
// Each such static close method should either call inherited static close
// methods, or else perform the consolidated effect of calling them, where
// subclasses should closely track any changes in base classes with care.
public: // morkNode construction
morkNode(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap);
void CloseNode(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkNode(const morkNode& other);
morkNode& operator=(const morkNode& other);
public: // dynamic type identification
mork_bool IsNode() const
{ return mNode_Base == morkBase_kNode; }
// } ===== end basic node methods =====
public: // public error & warning methods
void RefsUnderUsesWarning(morkEnv* ev) const; // call if mNode_Refs < mNode_Uses
void NonNodeError(morkEnv* ev) const; // call when IsNode() is false
void NilHeapError(morkEnv* ev) const; // zero mNode_Heap when usage is kHeap
void NonOpenNodeError(morkEnv* ev) const; // call when IsOpenNode() is false
void NonMutableNodeError(morkEnv* ev) const; // when IsMutable() is false
void RefsOverflowWarning(morkEnv* ev) const; // call on mNode_Refs overflow
void UsesOverflowWarning(morkEnv* ev) const; // call on mNode_Uses overflow
void RefsUnderflowWarning(morkEnv* ev) const; // call on mNode_Refs underflow
void UsesUnderflowWarning(morkEnv* ev) const; // call on mNode_Uses underflow
private: // private refcounting methods
mork_bool cut_use_count(morkEnv* ev); // just one part of CutStrongRef()
public: // other morkNode methods
mork_bool GoodRefs() const { return mNode_Refs >= mNode_Uses; }
mork_bool BadRefs() const { return mNode_Refs < mNode_Uses; }
mork_uses StrongRefsOnly() const { return mNode_Uses; }
mork_refs WeakRefsOnly() const { return (mork_refs) ( mNode_Refs - mNode_Uses ); }
// (this refcounting derives from public domain IronDoc node refcounts)
mork_refs AddStrongRef(morkEnv* ev);
mork_refs CutStrongRef(morkEnv* ev);
mork_refs AddWeakRef(morkEnv* ev);
mork_refs CutWeakRef(morkEnv* ev);
const char* GetNodeAccessAsString() const; // e.g. "open", "shut", etc.
const char* GetNodeUsageAsString() const; // e.g. "heap", "stack", etc.
mork_usage NodeUsage() const { return mNode_Usage; }
mork_bool IsHeapNode() const
{ return mNode_Usage == morkUsage_kHeap; }
mork_bool IsStackNode() const
{ return mNode_Usage == morkUsage_kStack; }
mork_bool IsGlobalNode() const
{ return mNode_Usage == morkUsage_kGlobal; }
mork_bool IsMemberNode() const
{ return mNode_Usage == morkUsage_kMember; }
mork_bool IsOpenNode() const
{ return mNode_Access == morkAccess_kOpen; }
mork_bool IsShutNode() const
{ return mNode_Access == morkAccess_kShut; }
mork_bool IsDeadNode() const
{ return mNode_Access == morkAccess_kDead; }
mork_bool IsClosingNode() const
{ return mNode_Access == morkAccess_kClosing; }
mork_bool IsOpenOrClosingNode() const
{ return IsOpenNode() || IsClosingNode(); }
mork_bool HasNodeAccess() const
{ return ( IsOpenNode() || IsShutNode() || IsClosingNode() ); }
void MarkShut() { mNode_Access = morkAccess_kShut; }
void MarkClosing() { mNode_Access = morkAccess_kClosing; }
void MarkDead() { mNode_Access = morkAccess_kDead; }
public: // refcounting for typesafe subclass inline methods
static void SlotWeakNode(morkNode* me, morkEnv* ev, morkNode** ioSlot);
// If *ioSlot is non-nil, that node is released by CutWeakRef() and
// then zeroed out. Then if me is non-nil, this is acquired by
// calling AddWeakRef(), and if positive is returned to show success,
// then this is put into slot *ioSlot. Note me can be nil, so we
// permit expression '((morkNode*) 0L)->SlotWeakNode(ev, &slot)'.
static void SlotStrongNode(morkNode* me, morkEnv* ev, morkNode** ioSlot);
// If *ioSlot is non-nil, that node is released by CutStrongRef() and
// then zeroed out. Then if me is non-nil, this is acquired by
// calling AddStrongRef(), and if positive is returned to show success,
// then me is put into slot *ioSlot. Note me can be nil, so we take
// expression 'morkNode::SlotStrongNode((morkNode*) 0, ev, &slot)'.
};
extern void // utility method very similar to morkNode::SlotStrongNode():
nsIMdbHeap_SlotStrongHeap(nsIMdbHeap* self, morkEnv* ev, nsIMdbHeap** ioSlot);
// If *ioSlot is non-nil, that heap is released by CutStrongRef() and
// then zeroed out. Then if self is non-nil, this is acquired by
// calling AddStrongRef(), and if the return value shows success,
// then self is put into slot *ioSlot. Note self can be nil, so we take
// expression 'nsIMdbHeap_SlotStrongHeap(0, ev, &slot)'.
extern void // utility method very similar to morkNode::SlotStrongNode():
nsIMdbFile_SlotStrongFile(nsIMdbFile* self, morkEnv* ev, nsIMdbFile** ioSlot);
// If *ioSlot is non-nil, that file is released by CutStrongRef() and
// then zeroed out. Then if self is non-nil, this is acquired by
// calling AddStrongRef(), and if the return value shows success,
// then self is put into slot *ioSlot. Note self can be nil, so we take
// expression 'nsIMdbHeap_SlotStrongFile(0, ev, &slot)'.
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKNODE_ */

View File

@@ -1,173 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
#ifndef _MORKINTMAP_
#include "morkIntMap.h"
#endif
#ifndef _MORKNODEMAP_
#include "morkNodeMap.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkNodeMap::CloseMorkNode(morkEnv* ev) // CloseNodeMap() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseNodeMap(ev);
this->MarkShut();
}
}
/*public virtual*/
morkNodeMap::~morkNodeMap() // assert CloseNodeMap() executed earlier
{
MORK_ASSERT(this->IsShutNode());
}
/*public non-poly*/
morkNodeMap::morkNodeMap(morkEnv* ev,
const morkUsage& inUsage, nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
: morkIntMap(ev, inUsage, /*valsize*/ sizeof(morkNode*), ioHeap, ioSlotHeap,
/*inHoldChanges*/ morkBool_kTrue)
{
if ( ev->Good() )
mNode_Derived = morkDerived_kNodeMap;
}
/*public non-poly*/ void
morkNodeMap::CloseNodeMap(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
this->CutAllNodes(ev);
this->CloseMap(ev);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
mork_bool
morkNodeMap::AddNode(morkEnv* ev, mork_token inToken, morkNode* ioNode)
// the AddNode() method return value equals ev->Good().
{
if ( ioNode && ev->Good() )
{
morkNode* node = 0; // old val in the map
mork_bool put = this->Put(ev, &inToken, &ioNode,
/*key*/ (void*) 0, &node, (mork_change**) 0);
if ( put ) // replaced an existing value for key inToken?
{
if ( node && node != ioNode ) // need to release old node?
node->CutStrongRef(ev);
}
if ( ev->Bad() || !ioNode->AddStrongRef(ev) )
{
// problems adding node or increasing refcount?
this->Cut(ev, &inToken, // make sure not in map
/*key*/ (void*) 0, /*val*/ (void*) 0, (mork_change**) 0);
}
}
else if ( !ioNode )
ev->NilPointerError();
return ev->Good();
}
mork_bool
morkNodeMap::CutNode(morkEnv* ev, mork_token inToken)
{
morkNode* node = 0; // old val in the map
mork_bool outCutNode = this->Cut(ev, &inToken,
/*key*/ (void*) 0, &node, (mork_change**) 0);
if ( node )
node->CutStrongRef(ev);
return outCutNode;
}
morkNode*
morkNodeMap::GetNode(morkEnv* ev, mork_token inToken)
// Note the returned node does NOT have an increase in refcount for this.
{
morkNode* node = 0; // old val in the map
this->Get(ev, &inToken, /*key*/ (void*) 0, &node, (mork_change**) 0);
return node;
}
mork_num
morkNodeMap::CutAllNodes(morkEnv* ev)
// CutAllNodes() releases all the reference node values.
{
mork_num outSlots = mMap_Slots;
mork_token key = 0; // old key token in the map
morkNode* val = 0; // old val node in the map
mork_change* c = 0;
morkNodeMapIter i(ev, this);
for ( c = i.FirstNode(ev, &key, &val); c ; c = i.NextNode(ev, &key, &val) )
{
if ( val )
val->CutStrongRef(ev);
i.CutHereNode(ev, /*key*/ (mork_token*) 0, /*val*/ (morkNode**) 0);
}
return outSlots;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,111 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKNODEMAP_
#define _MORKNODEMAP_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
#ifndef _MORKINTMAP_
#include "morkIntMap.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kNodeMap /*i*/ 0x6E4D /* ascii 'nM' */
#define morkNodeMap_kStartSlotCount 512
/*| morkNodeMap: maps mork_token -> morkNode
|*/
class morkNodeMap : public morkIntMap { // for mapping tokens to nodes
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseNodeMap() only if open
virtual ~morkNodeMap(); // assert that CloseNodeMap() executed earlier
public: // morkMap construction & destruction
morkNodeMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap);
void CloseNodeMap(morkEnv* ev); // called by CloseMorkNode();
public: // dynamic type identification
mork_bool IsNodeMap() const
{ return IsNode() && mNode_Derived == morkDerived_kNodeMap; }
// } ===== end morkNode methods =====
// { ===== begin morkMap poly interface =====
// use the Equal() and Hash() for mork_u4 inherited from morkIntMap
// } ===== end morkMap poly interface =====
protected: // we want all subclasses to provide typesafe wrappers:
mork_bool AddNode(morkEnv* ev, mork_token inToken, morkNode* ioNode);
// the AddNode() boolean return equals ev->Good().
mork_bool CutNode(morkEnv* ev, mork_token inToken);
// The CutNode() boolean return indicates whether removal happened.
morkNode* GetNode(morkEnv* ev, mork_token inToken);
// Note the returned node does NOT have an increase in refcount for this.
mork_num CutAllNodes(morkEnv* ev);
// CutAllNodes() releases all the reference node values.
};
class morkNodeMapIter: public morkMapIter{ // typesafe wrapper class
public:
morkNodeMapIter(morkEnv* ev, morkNodeMap* ioMap)
: morkMapIter(ev, ioMap) { }
morkNodeMapIter( ) : morkMapIter() { }
void InitNodeMapIter(morkEnv* ev, morkNodeMap* ioMap)
{ this->InitMapIter(ev, ioMap); }
mork_change*
FirstNode(morkEnv* ev, mork_token* outToken, morkNode** outNode)
{ return this->First(ev, outToken, outNode); }
mork_change*
NextNode(morkEnv* ev, mork_token* outToken, morkNode** outNode)
{ return this->Next(ev, outToken, outNode); }
mork_change*
HereNode(morkEnv* ev, mork_token* outToken, morkNode** outNode)
{ return this->Here(ev, outToken, outNode); }
mork_change*
CutHereNode(morkEnv* ev, mork_token* outToken, morkNode** outNode)
{ return this->CutHere(ev, outToken, outNode); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKNODEMAP_ */

View File

@@ -1,119 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKOBJECT_
#include "morkObject.h"
#endif
#ifndef _MORKHANDLE_
#include "morkHandle.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkObject::CloseMorkNode(morkEnv* ev) // CloseObject() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseObject(ev);
this->MarkShut();
}
}
/*public virtual*/
morkObject::~morkObject() // assert CloseObject() executed earlier
{
MORK_ASSERT(mObject_Handle==0);
}
/*public non-poly*/
morkObject::morkObject(const morkUsage& inUsage, nsIMdbHeap* ioHeap)
: morkNode(inUsage, ioHeap)
, mObject_Handle( 0 )
{
}
/*public non-poly*/
morkObject::morkObject(morkEnv* ev,
const morkUsage& inUsage, nsIMdbHeap* ioHeap, morkHandle* ioHandle)
: morkNode(ev, inUsage, ioHeap)
, mObject_Handle( 0 )
{
if ( ev->Good() )
{
if ( ioHandle )
morkHandle::SlotWeakHandle(ioHandle, ev, &mObject_Handle);
if ( ev->Good() )
mNode_Derived = morkDerived_kObject;
}
}
/*public non-poly*/ void
morkObject::CloseObject(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
if ( !this->IsShutNode() )
{
if ( mObject_Handle )
morkHandle::SlotWeakHandle((morkHandle*) 0L, ev, &mObject_Handle);
this->MarkShut();
}
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
//void morkObject::NewNilHandleError(morkEnv* ev) // mObject_Handle is nil
//{
// ev->NewError("nil mObject_Handle");
//}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,94 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKOBJECT_
#define _MORKOBJECT_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kObject /*i*/ 0x6F42 /* ascii 'oB' */
/*| morkObject: subclass of morkNode that adds knowledge of db suite factory
**| and containing port to those objects that are exposed as instances of
**| nsIMdbObject in the public interface.
|*/
class morkObject : public morkNode {
// public: // slots inherited from morkNode (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
public: // state is public because the entire Mork system is private
morkHandle* mObject_Handle; // weak ref to handle for this object
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseObject() only if open
virtual ~morkObject(); // assert that CloseObject() executed earlier
protected: // special case construction of first env without preceding env
morkObject(const morkUsage& inUsage, nsIMdbHeap* ioHeap);
public: // morkEnv construction & destruction
morkObject(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap,
morkHandle* ioHandle); // ioHandle can be nil
void CloseObject(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkObject(const morkObject& other);
morkObject& operator=(const morkObject& other);
public: // dynamic type identification
mork_bool IsObject() const
{ return IsNode() && mNode_Derived == morkDerived_kObject; }
// } ===== end morkNode methods =====
// void NewNilHandleError(morkEnv* ev); // mObject_Handle is nil
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakObject(morkObject* me,
morkEnv* ev, morkObject** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongObject(morkObject* me,
morkEnv* ev, morkObject** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKOBJECT_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,530 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKPARSER_
#define _MORKPARSER_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKBLOB_
#include "morkBlob.h"
#endif
#ifndef _MORKSINK_
#include "morkSink.h"
#endif
#ifndef _MORKYARN_
#include "morkYarn.h"
#endif
#ifndef _MORKCELL_
#include "morkCell.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/*=============================================================================
* morkPlace: stream byte position and stream line count
*/
class morkPlace {
public:
mork_pos mPlace_Pos; // byte offset in an input stream
mork_line mPlace_Line; // line count in an input stream
void ClearPlace()
{
mPlace_Pos = 0; mPlace_Line = 0;
}
void SetPlace(mork_pos inPos, mork_line inLine)
{
mPlace_Pos = inPos; mPlace_Line = inLine;
}
morkPlace() { mPlace_Pos = 0; mPlace_Line = 0; }
morkPlace(mork_pos inPos, mork_line inLine)
{ mPlace_Pos = inPos; mPlace_Line = inLine; }
morkPlace(const morkPlace& inPlace)
: mPlace_Pos(inPlace.mPlace_Pos), mPlace_Line(inPlace.mPlace_Line) { }
};
/*=============================================================================
* morkGlitch: stream place and error comment describing a parsing error
*/
class morkGlitch {
public:
morkPlace mGlitch_Place; // place in stream where problem happened
const char* mGlitch_Comment; // null-terminated ASCII C string
morkGlitch() { mGlitch_Comment = 0; }
morkGlitch(const morkPlace& inPlace, const char* inComment)
: mGlitch_Place(inPlace), mGlitch_Comment(inComment) { }
};
/*=============================================================================
* morkMid: all possible ways needed to express an alias ID in Mork syntax
*/
/*| morkMid: an abstraction of all the variations we might need to support
**| in order to present an ID through the parser interface most cheaply and
**| with minimum transformation away from the original text format.
**|
**|| An ID can have one of four forms:
**| 1) idHex (mMid_Oid.mOid_Id <- idHex)
**| 2) idHex:^scopeHex (mMid_Oid.mOid_Id <- idHex, mOid_Scope <- scopeHex)
**| 3) idHex:scopeName (mMid_Oid.mOid_Id <- idHex, mMid_Buf <- scopeName)
**| 4) columnName (mMid_Buf <- columnName, for columns in cells only)
**|
**|| Typically, mMid_Oid.mOid_Id will hold a nonzero integer value for
**| an ID, but we might have an optional scope specified by either an integer
**| in hex format, or a string name. (Note that while the first ID can be
**| scoped variably, any integer ID for a scope is assumed always located in
**| the same scope, so the second ID need not be disambiguated.)
**|
**|| The only time mMid_Oid.mOid_Id is ever zero is when mMid_Buf alone
**| is nonzero, to indicate an explicit string instead of an alias appeared.
**| This case happens to make the representation of columns in cells somewhat
**| easier to represent, since columns can just appear as a string name; and
**| this unifies those interfaces with row and table APIs expecting IDs.
**|
**|| So when the parser passes an instance of morkMid to a subclass, the
**| mMid_Oid.mOid_Id slot should usually be nonzero. And the other two
**| slots, mMid_Oid.mOid_Scope and mMid_Buf, might both be zero, or at
**| most one of them will be nonzero to indicate an explicit scope; the
**| parser is responsible for ensuring at most one of these is nonzero.
|*/
class morkMid {
public:
mdbOid mMid_Oid; // mOid_Scope is zero when not specified
const morkBuf* mMid_Buf; // points to some specific buf subclass
morkMid()
{ mMid_Oid.mOid_Scope = 0; mMid_Oid.mOid_Id = morkId_kMinusOne;
mMid_Buf = 0; }
void InitMidWithCoil(morkCoil* ioCoil)
{ mMid_Oid.mOid_Scope = 0; mMid_Oid.mOid_Id = morkId_kMinusOne;
mMid_Buf = ioCoil; }
void ClearMid()
{ mMid_Oid.mOid_Scope = 0; mMid_Oid.mOid_Id = morkId_kMinusOne;
mMid_Buf = 0; }
morkMid(const morkMid& other)
: mMid_Oid(other.mMid_Oid), mMid_Buf(other.mMid_Buf) { }
mork_bool HasNoId() const // ID is unspecified?
{ return ( mMid_Oid.mOid_Id == morkId_kMinusOne ); }
mork_bool HasSomeId() const // ID is specified?
{ return ( mMid_Oid.mOid_Id != morkId_kMinusOne ); }
};
/*=============================================================================
* morkSpan: start and end stream byte position and stream line count
*/
class morkSpan {
public:
morkPlace mSpan_Start;
morkPlace mSpan_End;
public: // methods
public: // inlines
morkSpan() { } // use inline empty constructor for each place
morkPlace* AsPlace() { return &mSpan_Start; }
const morkPlace* AsConstPlace() const { return &mSpan_Start; }
void SetSpan(mork_pos inFromPos, mork_line inFromLine,
mork_pos inToPos, mork_line inToLine)
{
mSpan_Start.SetPlace(inFromPos, inFromLine);
mSpan_End.SetPlace(inToPos,inToLine);
}
// setting end, useful to terminate a span using current port span end:
void SetEndWithEnd(const morkSpan& inSpan) // end <- span.end
{ mSpan_End = inSpan.mSpan_End; }
// setting start, useful to initiate a span using current port span end:
void SetStartWithEnd(const morkSpan& inSpan) // start <- span.end
{ mSpan_Start = inSpan.mSpan_End; }
void ClearSpan()
{
mSpan_Start.mPlace_Pos = 0; mSpan_Start.mPlace_Line = 0;
mSpan_End.mPlace_Pos = 0; mSpan_End.mPlace_Line = 0;
}
morkSpan(mork_pos inFromPos, mork_line inFromLine,
mork_pos inToPos, mork_line inToLine)
: mSpan_Start(inFromPos, inFromLine), mSpan_End(inToPos, inToLine)
{ /* empty implementation */ }
};
/*=============================================================================
* morkParser: for parsing Mork text syntax
*/
#define morkParser_kMinGranularity 512 /* parse at least half 0.5K at once */
#define morkParser_kMaxGranularity (64 * 1024) /* parse at most 64 K at once */
#define morkDerived_kParser /*i*/ 0x5073 /* ascii 'Ps' */
#define morkParser_kTag /*i*/ 0x70417253 /* ascii 'pArS' */
// These are states for the simple parsing virtual machine. Needless to say,
// these must be distinct, and preferrably in a contiguous integer range.
// Don't change these constants without looking at switch statements in code.
#define morkParser_kCellState 0 /* cell is tightest scope */
#define morkParser_kMetaState 1 /* meta is tightest scope */
#define morkParser_kRowState 2 /* row is tightest scope */
#define morkParser_kTableState 3 /* table is tightest scope */
#define morkParser_kDictState 4 /* dict is tightest scope */
#define morkParser_kPortState 5 /* port is tightest scope */
#define morkParser_kStartState 6 /* parsing has not yet begun */
#define morkParser_kDoneState 7 /* parsing is complete */
#define morkParser_kBrokenState 8 /* parsing is to broken to work */
class morkParser /*d*/ : public morkNode {
// public: // slots inherited from morkNode (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
// ````` ````` ````` ````` ````` ````` ````` `````
protected: // protected morkParser members
nsIMdbHeap* mParser_Heap; // refcounted heap used for allocation
morkStream* mParser_Stream; // refcounted input stream
mork_u4 mParser_Tag; // must equal morkParser_kTag
mork_count mParser_MoreGranularity; // constructor inBytesPerParseSegment
mork_u4 mParser_State; // state where parser should resume
// after finding ends of group transactions, we can re-seek the start:
mork_pos mParser_GroupContentStartPos; // start of this group
morkMid mParser_TableMid; // table mid if inside a table
morkMid mParser_RowMid; // row mid if inside a row
morkMid mParser_CellMid; // cell mid if inside a row
mork_gid mParser_GroupId; // group ID if inside a group
mork_bool mParser_InPort; // called OnNewPort but not OnPortEnd?
mork_bool mParser_InDict; // called OnNewDict but not OnDictEnd?
mork_bool mParser_InCell; // called OnNewCell but not OnCellEnd?
mork_bool mParser_InMeta; // called OnNewMeta but not OnMetaEnd?
mork_bool mParser_InPortRow; // called OnNewPortRow but not OnPortRowEnd?
mork_bool mParser_InRow; // called OnNewRow but not OnNewRowEnd?
mork_bool mParser_InTable; // called OnNewMeta but not OnMetaEnd?
mork_bool mParser_InGroup; // called OnNewGroup but not OnGroupEnd?
mork_change mParser_AtomChange; // driven by mParser_Change
mork_change mParser_CellChange; // driven by mParser_Change
mork_change mParser_RowChange; // driven by mParser_Change
mork_change mParser_TableChange; // driven by mParser_Change
mork_change mParser_Change; // driven by modifier in text
mork_bool mParser_IsBroken; // has the parse become broken?
mork_bool mParser_IsDone; // has the parse finished?
mork_bool mParser_DoMore; // mParser_MoreGranularity not exhausted?
morkMid mParser_Mid; // current alias being parsed
// note that mParser_Mid.mMid_Buf points at mParser_ScopeCoil below:
// blob coils allocated in mParser_Heap
morkCoil mParser_ScopeCoil; // place to accumulate ID scope blobs
morkCoil mParser_ValueCoil; // place to accumulate value blobs
morkCoil mParser_ColumnCoil; // place to accumulate column blobs
morkCoil mParser_StringCoil; // place to accumulate string blobs
morkSpool mParser_ScopeSpool; // writes to mParser_ScopeCoil
morkSpool mParser_ValueSpool; // writes to mParser_ValueCoil
morkSpool mParser_ColumnSpool; // writes to mParser_ColumnCoil
morkSpool mParser_StringSpool; // writes to mParser_StringCoil
// yarns allocated in mParser_Heap
morkYarn mParser_MidYarn; // place to receive from MidToYarn()
// span showing current ongoing file position status:
morkSpan mParser_PortSpan; // span of current db port file
// various spans denoting nested subspaces inside the file's port span:
morkSpan mParser_GroupSpan; // span of current transaction group
morkSpan mParser_DictSpan;
morkSpan mParser_AliasSpan;
morkSpan mParser_MetaSpan;
morkSpan mParser_TableSpan;
morkSpan mParser_RowSpan;
morkSpan mParser_CellSpan;
morkSpan mParser_ColumnSpan;
morkSpan mParser_SlotSpan;
private: // convenience inlines
mork_pos HerePos() const
{ return mParser_PortSpan.mSpan_End.mPlace_Pos; }
void SetHerePos(mork_pos inPos)
{ mParser_PortSpan.mSpan_End.mPlace_Pos = inPos; }
void CountLineBreak()
{ ++mParser_PortSpan.mSpan_End.mPlace_Line; }
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseParser() only if open
virtual ~morkParser(); // assert that CloseParser() executed earlier
public: // morkYarn construction & destruction
morkParser(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap,
morkStream* ioStream, // the readonly stream for input bytes
mdb_count inBytesPerParseSegment, // target for ParseMore()
nsIMdbHeap* ioSlotHeap);
void CloseParser(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkParser(const morkParser& other);
morkParser& operator=(const morkParser& other);
public: // dynamic type identification
mork_bool IsParser() const
{ return IsNode() && mNode_Derived == morkDerived_kParser; }
// } ===== end morkNode methods =====
public: // errors and warnings
static void UnexpectedEofError(morkEnv* ev);
static void EofInsteadOfHexError(morkEnv* ev);
static void ExpectedEqualError(morkEnv* ev);
static void ExpectedHexDigitError(morkEnv* ev, int c);
static void NonParserTypeError(morkEnv* ev);
static void UnexpectedByteInMetaWarning(morkEnv* ev);
public: // other type methods
mork_bool GoodParserTag() const { return mParser_Tag == morkParser_kTag; }
void NonGoodParserError(morkEnv* ev);
void NonUsableParserError(morkEnv* ev);
// call when IsNode() or GoodParserTag() is false
// ````` ````` ````` ````` ````` ````` ````` `````
public: // in virtual morkParser methods, data flow subclass to parser
virtual void MidToYarn(morkEnv* ev,
const morkMid& inMid, // typically an alias to concat with strings
mdbYarn* outYarn) = 0;
// The parser might ask that some aliases be turned into yarns, so they
// can be concatenated into longer blobs under some circumstances. This
// is an alternative to using a long and complex callback for many parts
// for a single cell value.
// ````` ````` ````` ````` ````` ````` ````` `````
public: // out virtual morkParser methods, data flow parser to subclass
// The virtual methods below will be called in a pattern corresponding
// to the following grammar isomorphic to the Mork grammar. There should
// be no exceptions, so subclasses can rely on seeing an appropriate "end"
// method whenever some "new" method has been seen earlier. In the event
// that some error occurs that causes content to be flushed, or sudden early
// termination of a larger containing entity, we will always call a more
// enclosed "end" method before we call an "end" method with greater scope.
// Note the "mp" prefix stands for "Mork Parser":
// mp:Start ::= OnNewPort mp:PortItem* OnPortEnd
// mp:PortItem ::= mp:Content | mp:Group | OnPortGlitch
// mp:Group ::= OnNewGroup mp:GroupItem* mp:GroupEnd
// mp:GroupItem ::= mp:Content | OnGroupGlitch
// mp:GroupEnd ::= OnGroupCommitEnd | OnGroupAbortEnd
// mp:Content ::= mp:PortRow | mp:Dict | mp:Table | mp:Row
// mp:PortRow ::= OnNewPortRow mp:RowItem* OnPortRowEnd
// mp:Dict ::= OnNewDict mp:DictItem* OnDictEnd
// mp:DictItem ::= OnAlias | OnAliasGlitch | mp:Meta | OnDictGlitch
// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
// mp:TableItem ::= mp:Row | mp:MetaTable | OnTableGlitch
// mp:MetaTable ::= OnNewMeta mp:MetaItem* mp:Row OnMetaEnd
// mp:Meta ::= OnNewMeta mp:MetaItem* OnMetaEnd
// mp:MetaItem ::= mp:Cell | OnMetaGlitch
// mp:Row ::= OnMinusRow? OnNewRow mp:RowItem* OnRowEnd
// mp:RowItem ::= mp:Cell | mp:Meta | OnRowGlitch
// mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
// Note that in interfaces below, mork_change parameters kAdd and kNil
// both mean about the same thing by default. Only kCut is interesting,
// because this usually means to remove members instead of adding them.
virtual void OnNewPort(morkEnv* ev, const morkPlace& inPlace) = 0;
virtual void OnPortGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0;
virtual void OnPortEnd(morkEnv* ev, const morkSpan& inSpan) = 0;
virtual void OnNewGroup(morkEnv* ev, const morkPlace& inPlace, mork_gid inGid) = 0;
virtual void OnGroupGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0;
virtual void OnGroupCommitEnd(morkEnv* ev, const morkSpan& inSpan) = 0;
virtual void OnGroupAbortEnd(morkEnv* ev, const morkSpan& inSpan) = 0;
virtual void OnNewPortRow(morkEnv* ev, const morkPlace& inPlace,
const morkMid& inMid, mork_change inChange) = 0;
virtual void OnPortRowGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0;
virtual void OnPortRowEnd(morkEnv* ev, const morkSpan& inSpan) = 0;
virtual void OnNewTable(morkEnv* ev, const morkPlace& inPlace,
const morkMid& inMid, mork_bool inCutAllRows) = 0;
virtual void OnTableGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0;
virtual void OnTableEnd(morkEnv* ev, const morkSpan& inSpan) = 0;
virtual void OnNewMeta(morkEnv* ev, const morkPlace& inPlace) = 0;
virtual void OnMetaGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0;
virtual void OnMetaEnd(morkEnv* ev, const morkSpan& inSpan) = 0;
virtual void OnMinusRow(morkEnv* ev) = 0;
virtual void OnNewRow(morkEnv* ev, const morkPlace& inPlace,
const morkMid& inMid, mork_bool inCutAllCols) = 0;
virtual void OnRowPos(morkEnv* ev, mork_pos inRowPos) = 0;
virtual void OnRowGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0;
virtual void OnRowEnd(morkEnv* ev, const morkSpan& inSpan) = 0;
virtual void OnNewDict(morkEnv* ev, const morkPlace& inPlace) = 0;
virtual void OnDictGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0;
virtual void OnDictEnd(morkEnv* ev, const morkSpan& inSpan) = 0;
virtual void OnAlias(morkEnv* ev, const morkSpan& inSpan,
const morkMid& inMid) = 0;
virtual void OnAliasGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0;
virtual void OnMinusCell(morkEnv* ev) = 0;
virtual void OnNewCell(morkEnv* ev, const morkPlace& inPlace,
const morkMid* inMid, const morkBuf* inBuf) = 0;
// Exactly one of inMid and inBuf is nil, and the other is non-nil.
// When hex ID syntax is used for a column, then inMid is not nil, and
// when a naked string names a column, then inBuf is not nil.
virtual void OnCellGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0;
virtual void OnCellForm(morkEnv* ev, mork_cscode inCharsetFormat) = 0;
virtual void OnCellEnd(morkEnv* ev, const morkSpan& inSpan) = 0;
virtual void OnValue(morkEnv* ev, const morkSpan& inSpan,
const morkBuf& inBuf) = 0;
virtual void OnValueMid(morkEnv* ev, const morkSpan& inSpan,
const morkMid& inMid) = 0;
virtual void OnRowMid(morkEnv* ev, const morkSpan& inSpan,
const morkMid& inMid) = 0;
virtual void OnTableMid(morkEnv* ev, const morkSpan& inSpan,
const morkMid& inMid) = 0;
// ````` ````` ````` ````` ````` ````` ````` `````
protected: // protected parser helper methods
void ParseLoop(morkEnv* ev); // find parse continuation and resume
void StartParse(morkEnv* ev); // prepare for parsing
void StopParse(morkEnv* ev); // terminate parsing & call needed methods
int NextChar(morkEnv* ev); // next non-white content
void OnCellState(morkEnv* ev);
void OnMetaState(morkEnv* ev);
void OnRowState(morkEnv* ev);
void OnTableState(morkEnv* ev);
void OnDictState(morkEnv* ev);
void OnPortState(morkEnv* ev);
void OnStartState(morkEnv* ev);
void ReadCell(morkEnv* ev);
void ReadRow(morkEnv* ev, int c);
void ReadRowPos(morkEnv* ev);
void ReadTable(morkEnv* ev);
void ReadTableMeta(morkEnv* ev);
void ReadDict(morkEnv* ev);
mork_bool ReadContent(morkEnv* ev, mork_bool inInsideGroup);
void ReadGroup(morkEnv* ev);
mork_bool ReadEndGroupId(morkEnv* ev);
mork_bool ReadAt(morkEnv* ev, mork_bool inInsideGroup);
mork_bool FindGroupEnd(morkEnv* ev);
void ReadMeta(morkEnv* ev, int inEndMeta);
void ReadAlias(morkEnv* ev);
mork_id ReadHex(morkEnv* ev, int* outNextChar);
morkBuf* ReadValue(morkEnv* ev);
morkBuf* ReadName(morkEnv* ev, int c);
mork_bool ReadMid(morkEnv* ev, morkMid* outMid);
mork_bool MatchPattern(morkEnv* ev, const char* inPattern);
void EndSpanOnThisByte(morkEnv* ev, morkSpan* ioSpan);
void EndSpanOnLastByte(morkEnv* ev, morkSpan* ioSpan);
void StartSpanOnLastByte(morkEnv* ev, morkSpan* ioSpan);
void StartSpanOnThisByte(morkEnv* ev, morkSpan* ioSpan);
int eat_line_break(morkEnv* ev, int inLast);
int eat_line_continue(morkEnv* ev); // last char was '\\'
int eat_comment(morkEnv* ev); // last char was '/'
// ````` ````` ````` ````` ````` ````` ````` `````
public: // public non-poly morkParser methods
mdb_count ParseMore( // return count of bytes consumed now
morkEnv* ev, // context
mork_pos* outPos, // current byte pos in the stream afterwards
mork_bool* outDone, // is parsing finished?
mork_bool* outBroken // is parsing irreparably dead and broken?
);
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakParser(morkParser* me,
morkEnv* ev, morkParser** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongParser(morkParser* me,
morkEnv* ev, morkParser** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKPARSER_ */

View File

@@ -1,382 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKPOOL_
#include "morkPool.h"
#endif
#ifndef _MORKATOM_
#include "morkAtom.h"
#endif
#ifndef _MORKHANDLE_
#include "morkHandle.h"
#endif
#ifndef _MORKCELL_
#include "morkCell.h"
#endif
#ifndef _MORKROW_
#include "morkRow.h"
#endif
#ifndef _MORKBLOB_
#include "morkBlob.h"
#endif
#ifndef _MORKDEQUE_
#include "morkDeque.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkPool::CloseMorkNode(morkEnv* ev) // ClosePool() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->ClosePool(ev);
this->MarkShut();
}
}
/*public virtual*/
morkPool::~morkPool() // assert ClosePool() executed earlier
{
MORK_ASSERT(this->IsShutNode());
}
/*public non-poly*/
morkPool::morkPool(const morkUsage& inUsage, nsIMdbHeap* ioHeap,
nsIMdbHeap* ioSlotHeap)
: morkNode(inUsage, ioHeap)
, mPool_Heap( ioSlotHeap )
{
// mPool_Heap is NOT refcounted
MORK_ASSERT(ioSlotHeap);
if ( ioSlotHeap )
mNode_Derived = morkDerived_kPool;
}
/*public non-poly*/
morkPool::morkPool(morkEnv* ev,
const morkUsage& inUsage, nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
: morkNode(ev, inUsage, ioHeap)
, mPool_Heap( ioSlotHeap )
{
if ( ioSlotHeap )
{
// mPool_Heap is NOT refcounted:
// nsIMdbHeap_SlotStrongHeap(ioSlotHeap, ev, &mPool_Heap);
if ( ev->Good() )
mNode_Derived = morkDerived_kPool;
}
else
ev->NilPointerError();
}
/*public non-poly*/ void
morkPool::ClosePool(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
// mPool_Heap is NOT refcounted:
// nsIMdbHeap_SlotStrongHeap((nsIMdbHeap*) 0, ev, &mPool_Heap);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
// alloc and free individual instances of handles (inside hand frames):
morkHandleFace*
morkPool::NewHandle(morkEnv* ev, mork_size inSize)
{
void* newBlock = 0;
mPool_Heap->Alloc(ev->AsMdbEnv(), inSize, (void**) &newBlock);
return (morkHandleFace*) newBlock;
}
void
morkPool::ZapHandle(morkEnv* ev, morkHandleFace* ioHandle)
{
if ( ioHandle )
mPool_Heap->Free(ev->AsMdbEnv(), ioHandle);
}
// alloc and free individual instances of rows:
morkRow*
morkPool::NewRow(morkEnv* ev) // allocate a new row instance
{
morkRow* newRow = 0;
mPool_Heap->Alloc(ev->AsMdbEnv(), sizeof(morkRow), (void**) &newRow);
if ( newRow )
MORK_MEMSET(newRow, 0, sizeof(morkRow));
if ( newRow )
{
}
return newRow;
}
void
morkPool::ZapRow(morkEnv* ev, morkRow* ioRow) // free old row instance
{
if ( ioRow )
mPool_Heap->Free(ev->AsMdbEnv(), ioRow);
}
// alloc and free entire vectors of cells (not just one cell at a time)
morkCell*
morkPool::NewCells(morkEnv* ev, mork_size inSize)
{
morkCell* newCells = 0;
mork_size size = inSize * sizeof(morkCell);
if ( size )
mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newCells);
// note morkAtom depends on having nil stored in all new mCell_Atom slots:
if ( newCells )
MORK_MEMSET(newCells, 0, size);
return newCells;
}
void
morkPool::ZapCells(morkEnv* ev, morkCell* ioVector, mork_size inSize)
{
MORK_USED_1(inSize);
if ( ioVector )
mPool_Heap->Free(ev->AsMdbEnv(), ioVector);
}
// resize (grow or trim) cell vectors inside a containing row instance
mork_bool
morkPool::AddRowCells(morkEnv* ev, morkRow* ioRow, mork_size inNewSize)
{
// note strong implementation similarity to morkArray::Grow()
mork_fill fill = ioRow->mRow_Length;
if ( ev->Good() && fill < inNewSize ) // need more cells?
{
morkCell* newCells = this->NewCells(ev, inNewSize);
if ( newCells )
{
morkCell* c = newCells; // for iterating during copy
morkCell* oldCells = ioRow->mRow_Cells;
morkCell* end = oldCells + fill; // copy all the old cells
while ( oldCells < end )
{
*c++ = *oldCells++; // bitwise copy each old cell struct
}
oldCells = ioRow->mRow_Cells;
ioRow->mRow_Cells = newCells;
ioRow->mRow_Length = (mork_u2) inNewSize;
++ioRow->mRow_Seed;
if ( oldCells )
this->ZapCells(ev, oldCells, fill);
}
}
return ( ev->Good() && ioRow->mRow_Length >= inNewSize );
}
mork_bool
morkPool::CutRowCells(morkEnv* ev, morkRow* ioRow,
mork_size inNewSize)
{
mork_fill fill = ioRow->mRow_Length;
if ( ev->Good() && fill > inNewSize ) // need fewer cells?
{
if ( inNewSize ) // want any row cells at all?
{
morkCell* newCells = this->NewCells(ev, inNewSize);
if ( newCells )
{
morkCell* oldCells = ioRow->mRow_Cells;
morkCell* oldEnd = oldCells + fill; // one past all old cells
morkCell* newEnd = oldCells + inNewSize; // copy only kept old cells
while ( oldCells < newEnd )
{
*newCells++ = *oldCells++; // bitwise copy each old cell struct
}
while ( oldCells < oldEnd )
{
if ( oldCells->mCell_Atom ) // need to unref old cell atom?
oldCells->SetAtom(ev, (morkAtom*) 0, this); // unref cell atom
++oldCells;
}
oldCells = ioRow->mRow_Cells;
ioRow->mRow_Cells = newCells;
ioRow->mRow_Length = (mork_u2) inNewSize;
++ioRow->mRow_Seed;
if ( oldCells )
this->ZapCells(ev, oldCells, fill);
}
}
else // get rid of all row cells
{
morkCell* oldCells = ioRow->mRow_Cells;
ioRow->mRow_Cells = 0;
ioRow->mRow_Length = 0;
++ioRow->mRow_Seed;
if ( oldCells )
this->ZapCells(ev, oldCells, fill);
}
}
return ( ev->Good() && ioRow->mRow_Length <= inNewSize );
}
// alloc & free individual instances of atoms (lots of atom subclasses):
void
morkPool::ZapAtom(morkEnv* ev, morkAtom* ioAtom) // any subclass (by kind)
{
if ( ioAtom )
mPool_Heap->Free(ev->AsMdbEnv(), ioAtom);
}
morkOidAtom*
morkPool::NewRowOidAtom(morkEnv* ev, const mdbOid& inOid)
{
morkOidAtom* newAtom = 0;
mPool_Heap->Alloc(ev->AsMdbEnv(), sizeof(morkOidAtom),(void**) &newAtom);
if ( newAtom )
newAtom->InitRowOidAtom(ev, inOid);
return newAtom;
}
morkOidAtom*
morkPool::NewTableOidAtom(morkEnv* ev, const mdbOid& inOid)
{
morkOidAtom* newAtom = 0;
mPool_Heap->Alloc(ev->AsMdbEnv(), sizeof(morkOidAtom), (void**) &newAtom);
if ( newAtom )
newAtom->InitTableOidAtom(ev, inOid);
return newAtom;
}
morkAtom*
morkPool::NewAnonAtom(morkEnv* ev, const morkBuf& inBuf,
mork_cscode inForm)
// if inForm is zero, and inBuf.mBuf_Fill is less than 256, then a 'wee'
// anon atom will be created, and otherwise a 'big' anon atom.
{
morkAtom* newAtom = 0;
mork_bool needBig = ( inForm || inBuf.mBuf_Fill > 255 );
mork_size size = ( needBig )?
morkBigAnonAtom::SizeForFill(inBuf.mBuf_Fill) :
morkWeeAnonAtom::SizeForFill(inBuf.mBuf_Fill);
mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newAtom);
if ( newAtom )
{
if ( needBig )
((morkBigAnonAtom*) newAtom)->InitBigAnonAtom(ev, inBuf, inForm);
else
((morkWeeAnonAtom*) newAtom)->InitWeeAnonAtom(ev, inBuf);
}
return newAtom;
}
morkBookAtom*
morkPool::NewBookAtom(morkEnv* ev, const morkBuf& inBuf,
mork_cscode inForm, morkAtomSpace* ioSpace, mork_aid inAid)
// if inForm is zero, and inBuf.mBuf_Fill is less than 256, then a 'wee'
// book atom will be created, and otherwise a 'big' book atom.
{
morkBookAtom* newAtom = 0;
mork_bool needBig = ( inForm || inBuf.mBuf_Fill > 255 );
mork_size size = ( needBig )?
morkBigBookAtom::SizeForFill(inBuf.mBuf_Fill) :
morkWeeBookAtom::SizeForFill(inBuf.mBuf_Fill);
mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newAtom);
if ( newAtom )
{
if ( needBig )
((morkBigBookAtom*) newAtom)->InitBigBookAtom(ev,
inBuf, inForm, ioSpace, inAid);
else
((morkWeeBookAtom*) newAtom)->InitWeeBookAtom(ev,
inBuf, ioSpace, inAid);
}
return newAtom;
}
morkBookAtom*
morkPool::NewBookAtomCopy(morkEnv* ev, const morkBigBookAtom& inAtom)
// make the smallest kind of book atom that can hold content in inAtom.
// The inAtom parameter is often expected to be a staged book atom in
// the store, which was used to search an atom space for existing atoms.
{
morkBookAtom* newAtom = 0;
mork_cscode form = inAtom.mBigBookAtom_Form;
mork_fill fill = inAtom.mBigBookAtom_Size;
mork_bool needBig = ( form || fill > 255 );
mork_size size = ( needBig )?
morkBigBookAtom::SizeForFill(fill) :
morkWeeBookAtom::SizeForFill(fill);
mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newAtom);
if ( newAtom )
{
morkBuf buf(inAtom.mBigBookAtom_Body, fill);
if ( needBig )
((morkBigBookAtom*) newAtom)->InitBigBookAtom(ev,
buf, form, inAtom.mBookAtom_Space, inAtom.mBookAtom_Id);
else
((morkWeeBookAtom*) newAtom)->InitWeeBookAtom(ev,
buf, inAtom.mBookAtom_Space, inAtom.mBookAtom_Id);
}
return newAtom;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,158 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKPOOL_
#define _MORKPOOL_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKDEQUE_
#include "morkDeque.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
class morkHandle;
class morkHandleFrame;
class morkHandleFace; // just an opaque cookie type
class morkBigBookAtom;
#define morkDerived_kPool /*i*/ 0x706C /* ascii 'pl' */
/*| morkPool: a place to manage pools of non-node objects that are memory
**| managed out of large chunks of space, so that per-object management
**| space overhead has no signficant cost.
|*/
class morkPool : public morkNode {
// public: // slots inherited from morkNode (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
public: // state is public because the entire Mork system is private
nsIMdbHeap* mPool_Heap; // NON-refcounted heap instance
morkDeque mPool_Blocks; // linked list of large blocks from heap
// These two lists contain instances of morkHandleFrame:
morkDeque mPool_UsedHandleFrames; // handle frames currently being used
morkDeque mPool_FreeHandleFrames; // handle frames currently in free list
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // ClosePool() only if open
virtual ~morkPool(); // assert that ClosePool() executed earlier
public: // morkPool construction & destruction
morkPool(const morkUsage& inUsage, nsIMdbHeap* ioHeap,
nsIMdbHeap* ioSlotHeap);
morkPool(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap,
nsIMdbHeap* ioSlotHeap);
void ClosePool(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkPool(const morkPool& other);
morkPool& operator=(const morkPool& other);
public: // dynamic type identification
mork_bool IsPool() const
{ return IsNode() && mNode_Derived == morkDerived_kPool; }
// } ===== end morkNode methods =====
public: // typing
void NonPoolTypeError(morkEnv* ev);
public: // morkNode memory management operators
void* operator new(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev)
{ return morkNode::MakeNew(inSize, ioHeap, ev); }
void* operator new(size_t inSize)
{ return ::operator new(inSize); }
void operator delete(void* ioAddress)
{ morkNode::OnDeleteAssert(ioAddress); }
// do NOT call delete on morkNode instances. Call ZapOld() instead.
public: // other pool methods
// alloc and free individual instances of handles (inside hand frames):
morkHandleFace* NewHandle(morkEnv* ev, mork_size inSize);
void ZapHandle(morkEnv* ev, morkHandleFace* ioHandle);
// alloc and free individual instances of rows:
morkRow* NewRow(morkEnv* ev); // allocate a new row instance
void ZapRow(morkEnv* ev, morkRow* ioRow); // free old row instance
// alloc and free entire vectors of cells (not just one cell at a time)
morkCell* NewCells(morkEnv* ev, mork_size inSize);
void ZapCells(morkEnv* ev, morkCell* ioVector, mork_size inSize);
// resize (grow or trim) cell vectors inside a containing row instance
mork_bool AddRowCells(morkEnv* ev, morkRow* ioRow, mork_size inNewSize);
mork_bool CutRowCells(morkEnv* ev, morkRow* ioRow, mork_size inNewSize);
// alloc & free individual instances of atoms (lots of atom subclasses):
void ZapAtom(morkEnv* ev, morkAtom* ioAtom); // any subclass (by kind)
morkOidAtom* NewRowOidAtom(morkEnv* ev, const mdbOid& inOid);
morkOidAtom* NewTableOidAtom(morkEnv* ev, const mdbOid& inOid);
morkAtom* NewAnonAtom(morkEnv* ev, const morkBuf& inBuf,
mork_cscode inForm);
// if inForm is zero, and inBuf.mBuf_Fill is less than 256, then a 'wee'
// anon atom will be created, and otherwise a 'big' anon atom.
morkBookAtom* NewBookAtom(morkEnv* ev, const morkBuf& inBuf,
mork_cscode inForm, morkAtomSpace* ioSpace, mork_aid inAid);
// if inForm is zero, and inBuf.mBuf_Fill is less than 256, then a 'wee'
// book atom will be created, and otherwise a 'big' book atom.
morkBookAtom* NewBookAtomCopy(morkEnv* ev, const morkBigBookAtom& inAtom);
// make the smallest kind of book atom that can hold content in inAtom.
// The inAtom parameter is often expected to be a staged book atom in
// the store, which was used to search an atom space for existing atoms.
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakPool(morkPool* me,
morkEnv* ev, morkPool** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongPool(morkPool* me,
morkEnv* ev, morkPool** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKPOOL_ */

View File

@@ -1,317 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKCURSOR_
#include "morkCursor.h"
#endif
#ifndef _MORKPORTTABLECURSOR_
#include "morkPortTableCursor.h"
#endif
#ifndef _ORKINPORTTABLECURSOR_
#include "orkinPortTableCursor.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkPortTableCursor::CloseMorkNode(morkEnv* ev) // ClosePortTableCursor() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->ClosePortTableCursor(ev);
this->MarkShut();
}
}
/*public virtual*/
morkPortTableCursor::~morkPortTableCursor() // ClosePortTableCursor() executed earlier
{
MORK_ASSERT(this->IsShutNode());
}
/*public non-poly*/
morkPortTableCursor::morkPortTableCursor(morkEnv* ev,
const morkUsage& inUsage,
nsIMdbHeap* ioHeap, morkStore* ioStore, mdb_scope inRowScope,
mdb_kind inTableKind, nsIMdbHeap* ioSlotHeap)
: morkCursor(ev, inUsage, ioHeap)
, mPortTableCursor_Store( 0 )
, mPortTableCursor_RowScope( (mdb_scope) -1 ) // we want != inRowScope
, mPortTableCursor_TableKind( (mdb_kind) -1 ) // we want != inTableKind
, mPortTableCursor_LastTable ( 0 ) // not refcounted
, mPortTableCursor_RowSpace( 0 ) // strong ref to row space
, mPortTableCursor_TablesDidEnd( morkBool_kFalse )
, mPortTableCursor_SpacesDidEnd( morkBool_kFalse )
{
if ( ev->Good() )
{
if ( ioStore && ioSlotHeap )
{
mCursor_Pos = -1;
mCursor_Seed = 0; // let the iterator do it's own seed handling
morkStore::SlotWeakStore(ioStore, ev, &mPortTableCursor_Store);
if ( this->SetRowScope(ev, inRowScope) )
this->SetTableKind(ev, inTableKind);
if ( ev->Good() )
mNode_Derived = morkDerived_kPortTableCursor;
}
else
ev->NilPointerError();
}
}
/*public non-poly*/ void
morkPortTableCursor::ClosePortTableCursor(morkEnv* ev)
{
if ( this )
{
if ( this->IsNode() )
{
mCursor_Pos = -1;
mCursor_Seed = 0;
mPortTableCursor_LastTable = 0;
morkStore::SlotWeakStore((morkStore*) 0, ev, &mPortTableCursor_Store);
morkRowSpace::SlotStrongRowSpace((morkRowSpace*) 0, ev,
&mPortTableCursor_RowSpace);
this->CloseCursor(ev);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
/*static*/ void
morkPortTableCursor::NilCursorStoreError(morkEnv* ev)
{
ev->NewError("nil mPortTableCursor_Store");
}
/*static*/ void
morkPortTableCursor::NonPortTableCursorTypeError(morkEnv* ev)
{
ev->NewError("non morkPortTableCursor");
}
orkinPortTableCursor*
morkPortTableCursor::AcquirePortTableCursorHandle(morkEnv* ev)
{
orkinPortTableCursor* outCursor = 0;
orkinPortTableCursor* c = (orkinPortTableCursor*) mObject_Handle;
if ( c ) // have an old handle?
c->AddStrongRef(ev->AsMdbEnv());
else // need new handle?
{
c = orkinPortTableCursor::MakePortTableCursor(ev, this);
mObject_Handle = c;
}
if ( c )
outCursor = c;
return outCursor;
}
mork_bool
morkPortTableCursor::SetRowScope(morkEnv* ev, mork_scope inRowScope)
{
mPortTableCursor_RowScope = inRowScope;
mPortTableCursor_LastTable = 0; // restart iteration of space
mPortTableCursor_TableIter.CloseMapIter(ev);
mPortTableCursor_TablesDidEnd = morkBool_kTrue;
mPortTableCursor_SpacesDidEnd = morkBool_kTrue;
morkStore* store = mPortTableCursor_Store;
if ( store )
{
morkRowSpace* space = mPortTableCursor_RowSpace;
if ( inRowScope ) // intend to cover a specific scope only?
{
space = store->LazyGetRowSpace(ev, inRowScope);
morkRowSpace::SlotStrongRowSpace(space, ev,
&mPortTableCursor_RowSpace);
// We want mPortTableCursor_SpacesDidEnd == morkBool_kTrue
// to show this is the only space to be covered.
}
else // prepare space map iter to cover all space scopes
{
morkRowSpaceMapIter* rsi = &mPortTableCursor_SpaceIter;
rsi->InitRowSpaceMapIter(ev, &store->mStore_RowSpaces);
space = 0;
(void) rsi->FirstRowSpace(ev, (mork_scope*) 0, &space);
morkRowSpace::SlotStrongRowSpace(space, ev,
&mPortTableCursor_RowSpace);
if ( space ) // found first space in store
mPortTableCursor_SpacesDidEnd = morkBool_kFalse;
}
this->init_space_tables_map(ev);
}
else
this->NilCursorStoreError(ev);
return ev->Good();
}
void
morkPortTableCursor::init_space_tables_map(morkEnv* ev)
{
morkRowSpace* space = mPortTableCursor_RowSpace;
if ( space && ev->Good() )
{
morkTableMapIter* ti = &mPortTableCursor_TableIter;
ti->InitTableMapIter(ev, &space->mRowSpace_Tables);
if ( ev->Good() )
mPortTableCursor_TablesDidEnd = morkBool_kFalse;
}
}
mork_bool
morkPortTableCursor::SetTableKind(morkEnv* ev, mork_kind inTableKind)
{
mPortTableCursor_TableKind = inTableKind;
mPortTableCursor_LastTable = 0; // restart iteration of space
mPortTableCursor_TablesDidEnd = morkBool_kTrue;
morkRowSpace* space = mPortTableCursor_RowSpace;
if ( !space && mPortTableCursor_RowScope == 0 )
{
this->SetRowScope(ev, 0);
space = mPortTableCursor_RowSpace;
}
this->init_space_tables_map(ev);
return ev->Good();
}
morkRowSpace*
morkPortTableCursor::NextSpace(morkEnv* ev)
{
morkRowSpace* outSpace = 0;
mPortTableCursor_LastTable = 0;
mPortTableCursor_SpacesDidEnd = morkBool_kTrue;
mPortTableCursor_TablesDidEnd = morkBool_kTrue;
if ( !mPortTableCursor_RowScope ) // not just one scope?
{
morkStore* store = mPortTableCursor_Store;
if ( store )
{
morkRowSpaceMapIter* rsi = &mPortTableCursor_SpaceIter;
(void) rsi->NextRowSpace(ev, (mork_scope*) 0, &outSpace);
morkRowSpace::SlotStrongRowSpace(outSpace, ev,
&mPortTableCursor_RowSpace);
if ( outSpace ) // found next space in store
{
mPortTableCursor_SpacesDidEnd = morkBool_kFalse;
this->init_space_tables_map(ev);
if ( ev->Bad() )
outSpace = 0;
}
}
else
this->NilCursorStoreError(ev);
}
return outSpace;
}
morkTable *
morkPortTableCursor::NextTable(morkEnv* ev)
{
mork_kind kind = mPortTableCursor_TableKind;
do // until spaces end, or until we find a table in a space
{
morkRowSpace* space = mPortTableCursor_RowSpace;
if ( mPortTableCursor_TablesDidEnd ) // current space exhausted?
space = this->NextSpace(ev); // go on to the next space
if ( space ) // have a space remaining that might hold tables?
{
mork_tid* key = 0; // ignore keys in table map
morkTable* table = 0; // old value table in the map
morkTableMapIter* ti = &mPortTableCursor_TableIter;
mork_change* c = ( mPortTableCursor_LastTable )?
ti->NextTable(ev, key, &table) : ti->FirstTable(ev, key, &table);
for ( ; c && ev->Good(); c = ti->NextTable(ev, key, &table) )
{
if ( table && table->IsTable() )
{
if ( !kind || kind == table->mTable_Kind )
{
mPortTableCursor_LastTable = table; // ti->NextTable() hence
return table;
}
}
else
table->NonTableTypeWarning(ev);
}
mPortTableCursor_TablesDidEnd = morkBool_kTrue; // space is done
mPortTableCursor_LastTable = 0; // make sure next space starts fresh
}
} while ( ev->Good() && !mPortTableCursor_SpacesDidEnd );
return (morkTable*) 0;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,130 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKPORTTABLECURSOR_
#define _MORKPORTTABLECURSOR_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKCURSOR_
#include "morkCursor.h"
#endif
#ifndef _MORKROWSPACE_
#include "morkRowSpace.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
class orkinPortTableCursor;
#define morkDerived_kPortTableCursor /*i*/ 0x7443 /* ascii 'tC' */
class morkPortTableCursor : public morkCursor { // row iterator
// public: // slots inherited from morkObject (meant to inform only)
// nsIMdbHeap* mNode_Heap;
// mork_able mNode_Mutable; // can this node be modified?
// mork_load mNode_Load; // is this node clean or dirty?
// 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_uses mNode_Uses; // refcount for strong refs
// mork_refs mNode_Refs; // refcount for strong refs + weak refs
// morkFactory* mObject_Factory; // weak ref to suite factory
// mork_seed mCursor_Seed;
// mork_pos mCursor_Pos;
// mork_bool mCursor_DoFailOnSeedOutOfSync;
// mork_u1 mCursor_Pad[ 3 ]; // explicitly pad to u4 alignment
public: // state is public because the entire Mork system is private
morkStore* mPortTableCursor_Store; // weak ref to store
mdb_scope mPortTableCursor_RowScope;
mdb_kind mPortTableCursor_TableKind;
// We only care if LastTablle is non-nil, so it is not refcounted;
// so you must never access table state or methods using LastTable:
morkTable* mPortTableCursor_LastTable; // nil or last table (no refcount)
morkRowSpace* mPortTableCursor_RowSpace; // current space (strong ref)
morkRowSpaceMapIter mPortTableCursor_SpaceIter; // iter over spaces
morkTableMapIter mPortTableCursor_TableIter; // iter over tables
// these booleans indicate when the table or space iterator is exhausted:
mork_bool mPortTableCursor_TablesDidEnd; // no more tables?
mork_bool mPortTableCursor_SpacesDidEnd; // no more spaces?
mork_u1 mPortTableCursor_Pad[ 2 ]; // for u4 alignment
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // ClosePortTableCursor()
virtual ~morkPortTableCursor(); // assert that close executed earlier
public: // morkPortTableCursor construction & destruction
morkPortTableCursor(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, morkStore* ioStore, mdb_scope inRowScope,
mdb_kind inTableKind, nsIMdbHeap* ioSlotHeap);
void ClosePortTableCursor(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkPortTableCursor(const morkPortTableCursor& other);
morkPortTableCursor& operator=(const morkPortTableCursor& other);
public: // dynamic type identification
mork_bool IsPortTableCursor() const
{ return IsNode() && mNode_Derived == morkDerived_kPortTableCursor; }
// } ===== end morkNode methods =====
protected: // utilities
void init_space_tables_map(morkEnv* ev);
public: // other cursor methods
static void NilCursorStoreError(morkEnv* ev);
static void NonPortTableCursorTypeError(morkEnv* ev);
orkinPortTableCursor* AcquirePortTableCursorHandle(morkEnv* ev);
morkRowSpace* NextSpace(morkEnv* ev);
morkTable* NextTable(morkEnv* ev);
mork_bool SetRowScope(morkEnv* ev, mork_scope inRowScope);
mork_bool SetTableKind(morkEnv* ev, mork_kind inTableKind);
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakPortTableCursor(morkPortTableCursor* me,
morkEnv* ev, morkPortTableCursor** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongPortTableCursor(morkPortTableCursor* me,
morkEnv* ev, morkPortTableCursor** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKPORTTABLECURSOR_ */

View File

@@ -1,879 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKROW_
#include "morkRow.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKROWSPACE_
#include "morkRowSpace.h"
#endif
#ifndef _MORKPOOL_
#include "morkPool.h"
#endif
#ifndef _MORKROWOBJECT_
#include "morkRowObject.h"
#endif
#ifndef _MORKCELLOBJECT_
#include "morkCellObject.h"
#endif
#ifndef _MORKCELL_
#include "morkCell.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
#ifndef _MORKROWCELLCURSOR_
#include "morkRowCellCursor.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// notifications regarding row changes:
void morkRow::NoteRowAddCol(morkEnv* ev, mork_column inColumn)
{
if ( !this->IsRowRewrite() )
{
mork_delta newDelta;
morkDelta_Init(newDelta, inColumn, morkChange_kAdd);
if ( newDelta != mRow_Delta ) // not repeating existing data?
{
if ( this->HasRowDelta() ) // already have one change recorded?
this->SetRowRewrite(); // just plan to write all row cells
else
this->SetRowDelta(inColumn, morkChange_kAdd);
}
}
else
this->ClearRowDelta();
}
void morkRow::NoteRowCutCol(morkEnv* ev, mork_column inColumn)
{
if ( !this->IsRowRewrite() )
{
mork_delta newDelta;
morkDelta_Init(newDelta, inColumn, morkChange_kCut);
if ( newDelta != mRow_Delta ) // not repeating existing data?
{
if ( this->HasRowDelta() ) // already have one change recorded?
this->SetRowRewrite(); // just plan to write all row cells
else
this->SetRowDelta(inColumn, morkChange_kCut);
}
}
else
this->ClearRowDelta();
}
void morkRow::NoteRowSetCol(morkEnv* ev, mork_column inColumn)
{
if ( !this->IsRowRewrite() )
{
if ( this->HasRowDelta() ) // already have one change recorded?
this->SetRowRewrite(); // just plan to write all row cells
else
this->SetRowDelta(inColumn, morkChange_kSet);
}
else
this->ClearRowDelta();
}
void morkRow::NoteRowSetAll(morkEnv* ev)
{
this->SetRowRewrite(); // just plan to write all row cells
this->ClearRowDelta();
}
mork_u2
morkRow::AddRowGcUse(morkEnv* ev)
{
if ( this->IsRow() )
{
if ( mRow_GcUses < morkRow_kMaxGcUses ) // not already maxed out?
++mRow_GcUses;
}
else
this->NonRowTypeError(ev);
return mRow_GcUses;
}
mork_u2
morkRow::CutRowGcUse(morkEnv* ev)
{
if ( this->IsRow() )
{
if ( mRow_GcUses ) // any outstanding uses to cut?
{
if ( mRow_GcUses < morkRow_kMaxGcUses ) // not frozen at max?
--mRow_GcUses;
}
else
this->GcUsesUnderflowWarning(ev);
}
else
this->NonRowTypeError(ev);
return mRow_GcUses;
}
/*static*/ void
morkRow::GcUsesUnderflowWarning(morkEnv* ev)
{
ev->NewWarning("mRow_GcUses underflow");
}
/*static*/ void
morkRow::NonRowTypeError(morkEnv* ev)
{
ev->NewError("non morkRow");
}
/*static*/ void
morkRow::NonRowTypeWarning(morkEnv* ev)
{
ev->NewWarning("non morkRow");
}
/*static*/ void
morkRow::LengthBeyondMaxError(morkEnv* ev)
{
ev->NewError("mRow_Length over max");
}
/*static*/ void
morkRow::ZeroColumnError(morkEnv* ev)
{
ev->NewError(" zero mork_column");
}
/*static*/ void
morkRow::NilCellsError(morkEnv* ev)
{
ev->NewError("nil mRow_Cells");
}
void
morkRow::InitRow(morkEnv* ev, const mdbOid* inOid, morkRowSpace* ioSpace,
mork_size inLength, morkPool* ioPool)
// if inLength is nonzero, cells will be allocated from ioPool
{
if ( ioSpace && ioPool && inOid )
{
if ( inLength <= morkRow_kMaxLength )
{
if ( inOid->mOid_Id != morkRow_kMinusOneRid )
{
mRow_Space = ioSpace;
mRow_Object = 0;
mRow_Cells = 0;
mRow_Oid = *inOid;
mRow_Length = (mork_u2) inLength;
mRow_Seed = (mork_u2) (mork_ip) this; // "random" assignment
mRow_GcUses = 0;
mRow_Pad = 0;
mRow_Flags = 0;
mRow_Tag = morkRow_kTag;
if ( inLength )
mRow_Cells = ioPool->NewCells(ev, inLength);
if ( this->MaybeDirtySpaceStoreAndRow() ) // new row might dirty store
{
this->SetRowRewrite();
this->NoteRowSetAll(ev);
}
}
else
ioSpace->MinusOneRidError(ev);
}
else
this->LengthBeyondMaxError(ev);
}
else
ev->NilPointerError();
}
morkRowObject*
morkRow::AcquireRowObject(morkEnv* ev, morkStore* ioStore)
{
morkRowObject* ro = mRow_Object;
if ( ro ) // need new row object?
ro->AddStrongRef(ev);
else
{
nsIMdbHeap* heap = ioStore->mPort_Heap;
ro = new(*heap, ev)
morkRowObject(ev, morkUsage::kHeap, heap, this, ioStore);
morkRowObject::SlotWeakRowObject(ro, ev, &mRow_Object);
}
return ro;
}
nsIMdbRow*
morkRow::AcquireRowHandle(morkEnv* ev, morkStore* ioStore)
{
morkRowObject* object = this->AcquireRowObject(ev, ioStore);
if ( object )
{
nsIMdbRow* rowHandle = object->AcquireRowHandle(ev);
object->CutStrongRef(ev);
return rowHandle;
}
return (nsIMdbRow*) 0;
}
nsIMdbCell*
morkRow::AcquireCellHandle(morkEnv* ev, morkCell* ioCell,
mdb_column inCol, mork_pos inPos)
{
nsIMdbHeap* heap = ev->mEnv_Heap;
morkCellObject* cellObj = new(*heap, ev)
morkCellObject(ev, morkUsage::kHeap, heap, this, ioCell, inCol, inPos);
if ( cellObj )
{
nsIMdbCell* cellHandle = cellObj->AcquireCellHandle(ev);
cellObj->CutStrongRef(ev);
return cellHandle;
}
return (nsIMdbCell*) 0;
}
mork_count
morkRow::CountOverlap(morkEnv* ev, morkCell* ioVector, mork_fill inFill)
// Count cells in ioVector that change existing cells in this row when
// ioVector is added to the row (as in TakeCells()). This is the set
// of cells with the same columns in ioVector and mRow_Cells, which do
// not have exactly the same value in mCell_Atom, and which do not both
// have change status equal to morkChange_kCut (because cutting a cut
// cell still yields a cell that has been cut). CountOverlap() also
// modifies the change attribute of any cell in ioVector to kDup when
// the change was previously kCut and the same column cell was found
// in this row with change also equal to kCut; this tells callers later
// they need not look for that cell in the row again on a second pass.
{
mork_count outCount = 0;
mork_pos pos = 0; // needed by GetCell()
morkCell* cells = ioVector;
morkCell* end = cells + inFill;
--cells; // prepare for preincrement
while ( ++cells < end && ev->Good() )
{
mork_column col = cells->GetColumn();
morkCell* old = this->GetCell(ev, col, &pos);
if ( old ) // same column?
{
mork_change newChg = cells->GetChange();
mork_change oldChg = old->GetChange();
if ( newChg != morkChange_kCut || oldChg != newChg ) // not cut+cut?
{
if ( cells->mCell_Atom != old->mCell_Atom ) // not same atom?
++outCount; // cells will replace old significantly when added
}
else
cells->SetColumnAndChange(col, morkChange_kDup); // note dup status
}
}
return outCount;
}
void
morkRow::MergeCells(morkEnv* ev, morkCell* ioVector,
mork_fill inVecLength, mork_fill inOldRowFill, mork_fill inOverlap)
// MergeCells() is the part of TakeCells() that does the insertion.
// inOldRowFill is the old value of mRow_Length, and inOverlap is the
// number of cells in the intersection that must be updated.
{
morkCell* newCells = mRow_Cells + inOldRowFill; // 1st new cell in row
morkCell* newEnd = newCells + mRow_Length; // one past last cell
morkCell* srcCells = ioVector;
morkCell* srcEnd = srcCells + inVecLength;
--srcCells; // prepare for preincrement
while ( ++srcCells < srcEnd && ev->Good() )
{
mork_change srcChg = srcCells->GetChange();
if ( srcChg != morkChange_kDup ) // anything to be done?
{
morkCell* dstCell = 0;
if ( inOverlap )
{
mork_pos pos = 0; // needed by GetCell()
dstCell = this->GetCell(ev, srcCells->GetColumn(), &pos);
}
if ( dstCell )
{
--inOverlap; // one fewer intersections to resolve
// swap the atoms in the cells to avoid ref counting here:
morkAtom* dstAtom = dstCell->mCell_Atom;
*dstCell = *srcCells; // bitwise copy, taking src atom
srcCells->mCell_Atom = dstAtom; // forget cell ref, if any
}
else if ( newCells < newEnd ) // another new cell exists?
{
dstCell = newCells++; // alloc another new cell
// take atom from source cell, transferring ref to this row:
*dstCell = *srcCells; // bitwise copy, taking src atom
srcCells->mCell_Atom = 0; // forget cell ref, if any
}
else // oops, we ran out...
ev->NewError("out of new cells");
}
}
}
void
morkRow::TakeCells(morkEnv* ev, morkCell* ioVector, mork_fill inVecLength,
morkStore* ioStore)
{
if ( ioVector && inVecLength && ev->Good() )
{
++mRow_Seed; // intend to change structure of mRow_Cells
mork_size length = (mork_size) mRow_Length;
mork_count overlap = this->CountOverlap(ev, ioVector, inVecLength);
mork_size growth = inVecLength - overlap; // cells to add
mork_size newLength = length + growth;
if ( growth && ev->Good() ) // need to add any cells?
{
morkPool* pool = ioStore->StorePool();
if ( !pool->AddRowCells(ev, this, length + growth) )
ev->NewError("cannot take cells");
}
if ( ev->Good() )
{
if ( mRow_Length >= newLength )
this->MergeCells(ev, ioVector, inVecLength, length, overlap);
else
ev->NewError("not enough new cells");
}
}
}
mork_bool morkRow::MaybeDirtySpaceStoreAndRow()
{
morkRowSpace* rowSpace = mRow_Space;
if ( rowSpace )
{
morkStore* store = rowSpace->mSpace_Store;
if ( store && store->mStore_CanDirty )
{
store->SetStoreDirty();
rowSpace->mSpace_CanDirty = morkBool_kTrue;
}
if ( rowSpace->mSpace_CanDirty )
{
this->SetRowDirty();
rowSpace->SetRowSpaceDirty();
return morkBool_kTrue;
}
}
return morkBool_kFalse;
}
morkCell*
morkRow::NewCell(morkEnv* ev, mdb_column inColumn,
mork_pos* outPos, morkStore* ioStore)
{
++mRow_Seed; // intend to change structure of mRow_Cells
mork_size length = (mork_size) mRow_Length;
*outPos = (mork_pos) length;
morkPool* pool = ioStore->StorePool();
mork_bool canDirty = this->MaybeDirtySpaceStoreAndRow();
if ( pool->AddRowCells(ev, this, length + 1) )
{
morkCell* cell = mRow_Cells + length;
// next line equivalent to inline morkCell::SetCellDirty():
if ( canDirty )
cell->SetCellColumnDirty(inColumn);
else
cell->SetCellColumnClean(inColumn);
if ( canDirty && !this->IsRowRewrite() )
this->NoteRowAddCol(ev, inColumn);
return cell;
}
return (morkCell*) 0;
}
morkCell*
morkRow::CellAt(morkEnv* ev, mork_pos inPos) const
{
MORK_USED_1(ev);
morkCell* cells = mRow_Cells;
if ( cells && inPos < mRow_Length && inPos >= 0 )
{
return cells + inPos;
}
return (morkCell*) 0;
}
morkCell*
morkRow::GetCell(morkEnv* ev, mdb_column inColumn, mork_pos* outPos) const
{
MORK_USED_1(ev);
morkCell* cells = mRow_Cells;
if ( cells )
{
morkCell* end = cells + mRow_Length;
while ( cells < end )
{
mork_column col = cells->GetColumn();
if ( col == inColumn ) // found the desired column?
{
*outPos = cells - mRow_Cells;
return cells;
}
else
++cells;
}
}
*outPos = -1;
return (morkCell*) 0;
}
mork_aid
morkRow::GetCellAtomAid(morkEnv* ev, mdb_column inColumn) const
// GetCellAtomAid() finds the cell with column inColumn, and sees if the
// atom has a token ID, and returns the atom's ID if there is one. Or
// else zero is returned if there is no such column, or no atom, or if
// the atom has no ID to return. This method is intended to support
// efficient updating of column indexes for rows in a row space.
{
if ( this && this->IsRow() )
{
morkCell* cells = mRow_Cells;
if ( cells )
{
morkCell* end = cells + mRow_Length;
while ( cells < end )
{
mork_column col = cells->GetColumn();
if ( col == inColumn ) // found desired column?
{
morkAtom* atom = cells->mCell_Atom;
if ( atom && atom->IsBook() )
return ((morkBookAtom*) atom)->mBookAtom_Id;
else
return 0;
}
else
++cells;
}
}
}
else
this->NonRowTypeError(ev);
return 0;
}
void
morkRow::EmptyAllCells(morkEnv* ev)
{
morkCell* cells = mRow_Cells;
if ( cells )
{
morkStore* store = this->GetRowSpaceStore(ev);
if ( store )
{
if ( this->MaybeDirtySpaceStoreAndRow() )
{
this->SetRowRewrite();
this->NoteRowSetAll(ev);
}
morkPool* pool = store->StorePool();
morkCell* end = cells + mRow_Length;
--cells; // prepare for preincrement:
while ( ++cells < end )
{
if ( cells->mCell_Atom )
cells->SetAtom(ev, (morkAtom*) 0, pool);
}
}
}
}
void
morkRow::cut_all_index_entries(morkEnv* ev)
{
morkRowSpace* rowSpace = mRow_Space;
if ( rowSpace->mRowSpace_IndexCount ) // any indexes?
{
morkCell* cells = mRow_Cells;
if ( cells )
{
morkCell* end = cells + mRow_Length;
--cells; // prepare for preincrement:
while ( ++cells < end )
{
morkAtom* atom = cells->mCell_Atom;
if ( atom )
{
mork_aid atomAid = atom->GetBookAtomAid();
if ( atomAid )
{
mork_column col = cells->GetColumn();
morkAtomRowMap* map = rowSpace->FindMap(ev, col);
if ( map ) // cut row from index for this column?
map->CutAid(ev, atomAid);
}
}
}
}
}
}
void
morkRow::CutAllColumns(morkEnv* ev)
{
morkStore* store = this->GetRowSpaceStore(ev);
if ( store )
{
if ( this->MaybeDirtySpaceStoreAndRow() )
{
this->SetRowRewrite();
this->NoteRowSetAll(ev);
}
morkRowSpace* rowSpace = mRow_Space;
if ( rowSpace->mRowSpace_IndexCount ) // any indexes?
this->cut_all_index_entries(ev);
morkPool* pool = store->StorePool();
pool->CutRowCells(ev, this, /*newSize*/ 0);
}
}
void
morkRow::SetRow(morkEnv* ev, const morkRow* inSourceRow)
{
// note inSourceRow might be in another DB, with a different store...
morkStore* store = this->GetRowSpaceStore(ev);
morkStore* srcStore = inSourceRow->GetRowSpaceStore(ev);
if ( store && srcStore )
{
if ( this->MaybeDirtySpaceStoreAndRow() )
{
this->SetRowRewrite();
this->NoteRowSetAll(ev);
}
morkRowSpace* rowSpace = mRow_Space;
mork_count indexes = rowSpace->mRowSpace_IndexCount; // any indexes?
mork_bool sameStore = ( store == srcStore ); // identical stores?
morkPool* pool = store->StorePool();
if ( pool->CutRowCells(ev, this, /*newSize*/ 0) )
{
mork_fill fill = inSourceRow->mRow_Length;
if ( pool->AddRowCells(ev, this, fill) )
{
morkCell* dst = mRow_Cells;
morkCell* dstEnd = dst + mRow_Length;
const morkCell* src = inSourceRow->mRow_Cells;
const morkCell* srcEnd = src + fill;
--dst; --src; // prepare both for preincrement:
while ( ++dst < dstEnd && ++src < srcEnd && ev->Good() )
{
morkAtom* atom = src->mCell_Atom;
mork_column dstCol = src->GetColumn();
// Note we modify the mCell_Atom slot directly instead of using
// morkCell::SetAtom(), because we know it starts equal to nil.
if ( sameStore ) // source and dest in same store?
{
// next line equivalent to inline morkCell::SetCellDirty():
dst->SetCellColumnDirty(dstCol);
dst->mCell_Atom = atom;
if ( atom ) // another ref to non-nil atom?
atom->AddCellUse(ev);
}
else // need to dup items from src store in a dest store
{
dstCol = store->CopyToken(ev, dstCol, srcStore);
if ( dstCol )
{
// next line equivalent to inline morkCell::SetCellDirty():
dst->SetCellColumnDirty(dstCol);
atom = store->CopyAtom(ev, atom);
dst->mCell_Atom = atom;
if ( atom ) // another ref?
atom->AddCellUse(ev);
}
}
if ( indexes && atom )
{
mork_aid atomAid = atom->GetBookAtomAid();
if ( atomAid )
{
morkAtomRowMap* map = rowSpace->FindMap(ev, dstCol);
if ( map )
map->AddAid(ev, atomAid, this);
}
}
}
}
}
}
}
void
morkRow::AddRow(morkEnv* ev, const morkRow* inSourceRow)
{
if ( mRow_Length ) // any existing cells we might need to keep?
{
ev->StubMethodOnlyError();
}
else
this->SetRow(ev, inSourceRow); // just exactly duplicate inSourceRow
}
void
morkRow::OnZeroRowGcUse(morkEnv* ev)
// OnZeroRowGcUse() is called when CutRowGcUse() returns zero.
{
MORK_USED_1(ev);
// ev->NewWarning("need to implement OnZeroRowGcUse");
}
void
morkRow::DirtyAllRowContent(morkEnv* ev)
{
MORK_USED_1(ev);
if ( this->MaybeDirtySpaceStoreAndRow() )
{
this->SetRowRewrite();
this->NoteRowSetAll(ev);
}
morkCell* cells = mRow_Cells;
if ( cells )
{
morkCell* end = cells + mRow_Length;
--cells; // prepare for preincrement:
while ( ++cells < end )
{
cells->SetCellDirty();
}
}
}
morkStore*
morkRow::GetRowSpaceStore(morkEnv* ev) const
{
morkRowSpace* rowSpace = mRow_Space;
if ( rowSpace )
{
morkStore* store = rowSpace->mSpace_Store;
if ( store )
{
if ( store->IsStore() )
{
return store;
}
else
store->NonStoreTypeError(ev);
}
else
ev->NilPointerError();
}
else
ev->NilPointerError();
return (morkStore*) 0;
}
void morkRow::CutColumn(morkEnv* ev, mdb_column inColumn)
{
mork_pos pos = -1;
morkCell* cell = this->GetCell(ev, inColumn, &pos);
if ( cell )
{
morkStore* store = this->GetRowSpaceStore(ev);
if ( store )
{
if ( this->MaybeDirtySpaceStoreAndRow() && !this->IsRowRewrite() )
this->NoteRowCutCol(ev, inColumn);
morkRowSpace* rowSpace = mRow_Space;
morkAtomRowMap* map = ( rowSpace->mRowSpace_IndexCount )?
rowSpace->FindMap(ev, inColumn) : (morkAtomRowMap*) 0;
if ( map ) // this row attribute is indexed by row space?
{
morkAtom* oldAtom = cell->mCell_Atom;
if ( oldAtom ) // need to cut an entry from the index?
{
mork_aid oldAid = oldAtom->GetBookAtomAid();
if ( oldAid ) // cut old row attribute from row index in space?
map->CutAid(ev, oldAid);
}
}
morkPool* pool = store->StorePool();
cell->SetAtom(ev, (morkAtom*) 0, pool);
mork_fill fill = mRow_Length; // should not be zero
MORK_ASSERT(fill);
if ( fill ) // index < fill for last cell exists?
{
mork_fill last = fill - 1; // index of last cell in row
if ( pos < last ) // need to move cells following cut cell?
{
morkCell* lastCell = mRow_Cells + last;
mork_count after = last - pos; // cell count after cut cell
morkCell* next = cell + 1; // next cell after cut cell
MORK_MEMMOVE(cell, next, after * sizeof(morkCell));
lastCell->SetColumnAndChange(0, 0);
lastCell->mCell_Atom = 0;
}
if ( ev->Good() )
pool->CutRowCells(ev, this, fill - 1);
}
}
}
}
void morkRow::AddColumn(morkEnv* ev, mdb_column inColumn,
const mdbYarn* inYarn, morkStore* ioStore)
{
if ( ev->Good() )
{
mork_pos pos = -1;
morkCell* cell = this->GetCell(ev, inColumn, &pos);
morkCell* oldCell = cell; // need to know later whether new
if ( !cell ) // column does not yet exist?
cell = this->NewCell(ev, inColumn, &pos, ioStore);
if ( cell )
{
morkAtom* oldAtom = cell->mCell_Atom;
morkAtom* atom = ioStore->YarnToAtom(ev, inYarn);
if ( atom && atom != oldAtom )
{
morkRowSpace* rowSpace = mRow_Space;
morkAtomRowMap* map = ( rowSpace->mRowSpace_IndexCount )?
rowSpace->FindMap(ev, inColumn) : (morkAtomRowMap*) 0;
if ( map ) // inColumn is indexed by row space?
{
if ( oldAtom && oldAtom != atom ) // cut old cell from index?
{
mork_aid oldAid = oldAtom->GetBookAtomAid();
if ( oldAid ) // cut old row attribute from row index in space?
map->CutAid(ev, oldAid);
}
}
cell->SetAtom(ev, atom, ioStore->StorePool()); // refcounts atom
if ( oldCell ) // we changed a pre-existing cell in the row?
{
++mRow_Seed;
if ( this->MaybeDirtySpaceStoreAndRow() && !this->IsRowRewrite() )
this->NoteRowAddCol(ev, inColumn);
}
if ( map ) // inColumn is indexed by row space?
{
mork_aid newAid = atom->GetBookAtomAid();
if ( newAid ) // add new row attribute to row index in space?
map->AddAid(ev, newAid, this);
}
}
}
}
}
morkRowCellCursor*
morkRow::NewRowCellCursor(morkEnv* ev, mdb_pos inPos)
{
morkRowCellCursor* outCursor = 0;
if ( ev->Good() )
{
morkStore* store = this->GetRowSpaceStore(ev);
if ( store )
{
morkRowObject* rowObj = this->AcquireRowObject(ev, store);
if ( rowObj )
{
nsIMdbHeap* heap = store->mPort_Heap;
morkRowCellCursor* cursor = new(*heap, ev)
morkRowCellCursor(ev, morkUsage::kHeap, heap, rowObj);
if ( cursor )
{
if ( ev->Good() )
{
cursor->mCursor_Pos = inPos;
outCursor = cursor;
}
else
cursor->CutStrongRef(ev);
}
rowObj->CutStrongRef(ev); // always cut ref (cursor has its own)
}
}
}
return outCursor;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,227 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKROW_
#define _MORKROW_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKCELL_
#include "morkCell.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
class nsIMdbRow;
class nsIMdbCell;
#define morkDerived_kRow /*i*/ 0x5277 /* ascii 'Rw' */
#define morkRow_kMaxGcUses 0x0FF /* max for 8-bit unsigned int */
#define morkRow_kMaxLength 0x0FFFF /* max for 16-bit unsigned int */
#define morkRow_kMinusOneRid ((mork_rid) -1)
#define morkRow_kTag 'r' /* magic signature for mRow_Tag */
#define morkRow_kNotedBit ((mork_u1) (1 << 0)) /* space has change notes */
#define morkRow_kRewriteBit ((mork_u1) (1 << 1)) /* must rewrite all cells */
#define morkRow_kDirtyBit ((mork_u1) (1 << 2)) /* row has been changed */
class morkRow { // row of cells
public: // state is public because the entire Mork system is private
morkRowSpace* mRow_Space; // mRow_Space->mSpace_Scope is the row scope
morkRowObject* mRow_Object; // refcount & other state for object sharing
morkCell* mRow_Cells;
mdbOid mRow_Oid;
mork_delta mRow_Delta; // space to note a single column change
mork_u2 mRow_Length; // physical count of cells in mRow_Cells
mork_u2 mRow_Seed; // count changes in mRow_Cells structure
mork_u1 mRow_GcUses; // persistent references from tables
mork_u1 mRow_Pad; // for u1 alignment
mork_u1 mRow_Flags; // one-byte flags slot
mork_u1 mRow_Tag; // one-byte tag (need u4 alignment pad)
public: // interpreting mRow_Delta
mork_bool HasRowDelta() const { return ( mRow_Delta != 0 ); }
void ClearRowDelta() { mRow_Delta = 0; }
void SetRowDelta(mork_column inCol, mork_change inChange)
{ morkDelta_Init(mRow_Delta, inCol, inChange); }
mork_column GetDeltaColumn() const { return morkDelta_Column(mRow_Delta); }
mork_change GetDeltaChange() const { return morkDelta_Change(mRow_Delta); }
public: // noting row changes
void NoteRowSetAll(morkEnv* ev);
void NoteRowSetCol(morkEnv* ev, mork_column inCol);
void NoteRowAddCol(morkEnv* ev, mork_column inCol);
void NoteRowCutCol(morkEnv* ev, mork_column inCol);
public: // flags bit twiddling
void SetRowNoted() { mRow_Flags |= morkRow_kNotedBit; }
void SetRowRewrite() { mRow_Flags |= morkRow_kRewriteBit; }
void SetRowDirty() { mRow_Flags |= morkRow_kDirtyBit; }
void ClearRowNoted() { mRow_Flags &= (mork_u1) ~morkRow_kNotedBit; }
void ClearRowRewrite() { mRow_Flags &= (mork_u1) ~morkRow_kRewriteBit; }
void SetRowClean() { mRow_Flags = 0; mRow_Delta = 0; }
mork_bool IsRowNoted() const
{ return ( mRow_Flags & morkRow_kNotedBit ) != 0; }
mork_bool IsRowRewrite() const
{ return ( mRow_Flags & morkRow_kRewriteBit ) != 0; }
mork_bool IsRowClean() const
{ return ( mRow_Flags & morkRow_kDirtyBit ) == 0; }
mork_bool IsRowDirty() const
{ return ( mRow_Flags & morkRow_kDirtyBit ) != 0; }
public: // other row methods
morkRow( ) { }
morkRow(const mdbOid* inOid) :mRow_Oid(*inOid) { }
void InitRow(morkEnv* ev, const mdbOid* inOid, morkRowSpace* ioSpace,
mork_size inLength, morkPool* ioPool);
// if inLength is nonzero, cells will be allocated from ioPool
morkRowObject* AcquireRowObject(morkEnv* ev, morkStore* ioStore);
nsIMdbRow* AcquireRowHandle(morkEnv* ev, morkStore* ioStore);
nsIMdbCell* AcquireCellHandle(morkEnv* ev, morkCell* ioCell,
mdb_column inColumn, mork_pos inPos);
mork_u2 AddRowGcUse(morkEnv* ev);
mork_u2 CutRowGcUse(morkEnv* ev);
mork_bool MaybeDirtySpaceStoreAndRow();
public: // internal row methods
void cut_all_index_entries(morkEnv* ev);
// void cut_cell_from_space_index(morkEnv* ev, morkCell* ioCell);
mork_count CountOverlap(morkEnv* ev, morkCell* ioVector, mork_fill inFill);
// Count cells in ioVector that change existing cells in this row when
// ioVector is added to the row (as in TakeCells()). This is the set
// of cells with the same columns in ioVector and mRow_Cells, which do
// not have exactly the same value in mCell_Atom, and which do not both
// have change status equal to morkChange_kCut (because cutting a cut
// cell still yields a cell that has been cut). CountOverlap() also
// modifies the change attribute of any cell in ioVector to kDup when
// the change was previously kCut and the same column cell was found
// in this row with change also equal to kCut; this tells callers later
// they need not look for that cell in the row again on a second pass.
void MergeCells(morkEnv* ev, morkCell* ioVector,
mork_fill inVecLength, mork_fill inOldRowFill, mork_fill inOverlap);
// MergeCells() is the part of TakeCells() that does the insertion.
// inOldRowFill is the old value of mRow_Length, and inOverlap is the
// number of cells in the intersection that must be updated.
void TakeCells(morkEnv* ev, morkCell* ioVector, mork_fill inVecLength,
morkStore* ioStore);
morkCell* NewCell(morkEnv* ev, mdb_column inColumn, mork_pos* outPos,
morkStore* ioStore);
morkCell* GetCell(morkEnv* ev, mdb_column inColumn, mork_pos* outPos) const;
morkCell* CellAt(morkEnv* ev, mork_pos inPos) const;
mork_aid GetCellAtomAid(morkEnv* ev, mdb_column inColumn) const;
// GetCellAtomAid() finds the cell with column inColumn, and sees if the
// atom has a token ID, and returns the atom's ID if there is one. Or
// else zero is returned if there is no such column, or no atom, or if
// the atom has no ID to return. This method is intended to support
// efficient updating of column indexes for rows in a row space.
public: // external row methods
void DirtyAllRowContent(morkEnv* ev);
morkStore* GetRowSpaceStore(morkEnv* ev) const;
void AddColumn(morkEnv* ev, mdb_column inColumn,
const mdbYarn* inYarn, morkStore* ioStore);
void CutColumn(morkEnv* ev, mdb_column inColumn);
morkRowCellCursor* NewRowCellCursor(morkEnv* ev, mdb_pos inPos);
void EmptyAllCells(morkEnv* ev);
void AddRow(morkEnv* ev, const morkRow* inSourceRow);
void SetRow(morkEnv* ev, const morkRow* inSourceRow);
void CutAllColumns(morkEnv* ev);
void OnZeroRowGcUse(morkEnv* ev);
// OnZeroRowGcUse() is called when CutRowGcUse() returns zero.
public: // dynamic typing
mork_bool IsRow() const { return mRow_Tag == morkRow_kTag; }
public: // hash and equal
mork_u4 HashRow() const
{
return (mRow_Oid.mOid_Scope << 16) ^ mRow_Oid.mOid_Id;
}
mork_bool EqualRow(const morkRow* ioRow) const
{
return
(
( mRow_Oid.mOid_Scope == ioRow->mRow_Oid.mOid_Scope )
&& ( mRow_Oid.mOid_Id == ioRow->mRow_Oid.mOid_Id )
);
}
mork_bool EqualOid(const mdbOid* ioOid) const
{
return
(
( mRow_Oid.mOid_Scope == ioOid->mOid_Scope )
&& ( mRow_Oid.mOid_Id == ioOid->mOid_Id )
);
}
public: // errors
static void ZeroColumnError(morkEnv* ev);
static void LengthBeyondMaxError(morkEnv* ev);
static void NilCellsError(morkEnv* ev);
static void NonRowTypeError(morkEnv* ev);
static void NonRowTypeWarning(morkEnv* ev);
static void GcUsesUnderflowWarning(morkEnv* ev);
private: // copying is not allowed
morkRow(const morkRow& other);
morkRow& operator=(const morkRow& other);
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKROW_ */

View File

@@ -1,171 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKCURSOR_
#include "morkCursor.h"
#endif
#ifndef _MORKROWCELLCURSOR_
#include "morkRowCellCursor.h"
#endif
#ifndef _ORKINROWCELLCURSOR_
#include "orkinRowCellCursor.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
#ifndef _MORKROWOBJECT_
#include "morkRowObject.h"
#endif
#ifndef _MORKROW_
#include "morkRow.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkRowCellCursor::CloseMorkNode(morkEnv* ev) // CloseRowCellCursor() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseRowCellCursor(ev);
this->MarkShut();
}
}
/*public virtual*/
morkRowCellCursor::~morkRowCellCursor() // CloseRowCellCursor() executed earlier
{
MORK_ASSERT(this->IsShutNode());
}
/*public non-poly*/
morkRowCellCursor::morkRowCellCursor(morkEnv* ev,
const morkUsage& inUsage,
nsIMdbHeap* ioHeap, morkRowObject* ioRowObject)
: morkCursor(ev, inUsage, ioHeap)
, mRowCellCursor_RowObject( 0 )
, mRowCellCursor_Col( 0 )
{
if ( ev->Good() )
{
if ( ioRowObject )
{
morkRow* row = ioRowObject->mRowObject_Row;
if ( row )
{
if ( row->IsRow() )
{
mCursor_Pos = -1;
mCursor_Seed = row->mRow_Seed;
morkRowObject::SlotStrongRowObject(ioRowObject, ev,
&mRowCellCursor_RowObject);
if ( ev->Good() )
mNode_Derived = morkDerived_kRowCellCursor;
}
else
row->NonRowTypeError(ev);
}
else
ioRowObject->NilRowError(ev);
}
else
ev->NilPointerError();
}
}
/*public non-poly*/ void
morkRowCellCursor::CloseRowCellCursor(morkEnv* ev)
{
if ( this )
{
if ( this->IsNode() )
{
mCursor_Pos = -1;
mCursor_Seed = 0;
morkRowObject::SlotStrongRowObject((morkRowObject*) 0, ev,
&mRowCellCursor_RowObject);
this->CloseCursor(ev);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
/*static*/ void
morkRowCellCursor::NilRowObjectError(morkEnv* ev)
{
ev->NewError("nil mRowCellCursor_RowObject");
}
/*static*/ void
morkRowCellCursor::NonRowCellCursorTypeError(morkEnv* ev)
{
ev->NewError("non morkRowCellCursor");
}
orkinRowCellCursor*
morkRowCellCursor::AcquireRowCellCursorHandle(morkEnv* ev)
{
orkinRowCellCursor* outCursor = 0;
orkinRowCellCursor* c = (orkinRowCellCursor*) mObject_Handle;
if ( c ) // have an old handle?
c->AddStrongRef(ev->AsMdbEnv());
else // need new handle?
{
c = orkinRowCellCursor::MakeRowCellCursor(ev, this);
mObject_Handle = c;
}
if ( c )
outCursor = c;
return outCursor;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,98 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKROWCELLCURSOR_
#define _MORKROWCELLCURSOR_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKCURSOR_
#include "morkCursor.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
class orkinRowCellCursor;
#define morkDerived_kRowCellCursor /*i*/ 0x6343 /* ascii 'cC' */
class morkRowCellCursor : public morkCursor { // row iterator
// public: // slots inherited from morkObject (meant to inform only)
// nsIMdbHeap* mNode_Heap;
// mork_able mNode_Mutable; // can this node be modified?
// mork_load mNode_Load; // is this node clean or dirty?
// 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_uses mNode_Uses; // refcount for strong refs
// mork_refs mNode_Refs; // refcount for strong refs + weak refs
// morkFactory* mObject_Factory; // weak ref to suite factory
// mork_seed mCursor_Seed;
// mork_pos mCursor_Pos;
// mork_bool mCursor_DoFailOnSeedOutOfSync;
// mork_u1 mCursor_Pad[ 3 ]; // explicitly pad to u4 alignment
public: // state is public because the entire Mork system is private
morkRowObject* mRowCellCursor_RowObject; // strong ref to row
mork_column mRowCellCursor_Col; // col of cell last at mCursor_Pos
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseRowCellCursor()
virtual ~morkRowCellCursor(); // assert that close executed earlier
public: // morkRowCellCursor construction & destruction
morkRowCellCursor(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, morkRowObject* ioRowObject);
void CloseRowCellCursor(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkRowCellCursor(const morkRowCellCursor& other);
morkRowCellCursor& operator=(const morkRowCellCursor& other);
public: // dynamic type identification
mork_bool IsRowCellCursor() const
{ return IsNode() && mNode_Derived == morkDerived_kRowCellCursor; }
// } ===== end morkNode methods =====
public: // errors
static void NilRowObjectError(morkEnv* ev);
static void NonRowCellCursorTypeError(morkEnv* ev);
public: // other cell cursor methods
orkinRowCellCursor* AcquireRowCellCursorHandle(morkEnv* ev);
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakRowCellCursor(morkRowCellCursor* me,
morkEnv* ev, morkRowCellCursor** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongRowCellCursor(morkRowCellCursor* me,
morkEnv* ev, morkRowCellCursor** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKROWCELLCURSOR_ */

View File

@@ -1,173 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
#ifndef _MORKROWMAP_
#include "morkRowMap.h"
#endif
#ifndef _MORKROW_
#include "morkRow.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkRowMap::CloseMorkNode(morkEnv* ev) // CloseRowMap() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseRowMap(ev);
this->MarkShut();
}
}
/*public virtual*/
morkRowMap::~morkRowMap() // assert CloseRowMap() executed earlier
{
MORK_ASSERT(this->IsShutNode());
}
/*public non-poly*/
morkRowMap::morkRowMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap, mork_size inSlots)
: morkMap(ev, inUsage, ioHeap,
/*inKeySize*/ sizeof(morkRow*), /*inValSize*/ 0,
inSlots, ioSlotHeap, /*inHoldChanges*/ morkBool_kFalse)
{
if ( ev->Good() )
mNode_Derived = morkDerived_kRowMap;
}
/*public non-poly*/ void
morkRowMap::CloseRowMap(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
this->CloseMap(ev);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
// { ===== begin morkMap poly interface =====
/*virtual*/ mork_bool //
morkRowMap::Equal(morkEnv* ev, const void* inKeyA,
const void* inKeyB) const
{
MORK_USED_1(ev);
return (*(const morkRow**) inKeyA)->EqualRow(*(const morkRow**) inKeyB);
}
/*virtual*/ mork_u4 //
morkRowMap::Hash(morkEnv* ev, const void* inKey) const
{
MORK_USED_1(ev);
return (*(const morkRow**) inKey)->HashRow();
}
// } ===== end morkMap poly interface =====
mork_bool
morkRowMap::AddRow(morkEnv* ev, morkRow* ioRow)
{
if ( ev->Good() )
{
this->Put(ev, &ioRow, /*val*/ (void*) 0,
/*key*/ (void*) 0, /*val*/ (void*) 0, (mork_change**) 0);
}
return ev->Good();
}
morkRow*
morkRowMap::CutOid(morkEnv* ev, const mdbOid* inOid)
{
morkRow row(inOid);
morkRow* key = &row;
morkRow* oldKey = 0;
this->Cut(ev, &key, &oldKey, /*val*/ (void*) 0,
(mork_change**) 0);
return oldKey;
}
morkRow*
morkRowMap::CutRow(morkEnv* ev, const morkRow* ioRow)
{
morkRow* oldKey = 0;
this->Cut(ev, &ioRow, &oldKey, /*val*/ (void*) 0,
(mork_change**) 0);
return oldKey;
}
morkRow*
morkRowMap::GetOid(morkEnv* ev, const mdbOid* inOid)
{
morkRow row(inOid);
morkRow* key = &row;
morkRow* oldKey = 0;
this->Get(ev, &key, &oldKey, /*val*/ (void*) 0, (mork_change**) 0);
return oldKey;
}
morkRow*
morkRowMap::GetRow(morkEnv* ev, const morkRow* ioRow)
{
morkRow* oldKey = 0;
this->Get(ev, &ioRow, &oldKey, /*val*/ (void*) 0, (mork_change**) 0);
return oldKey;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,121 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKROWMAP_
#define _MORKROWMAP_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kRowMap /*i*/ 0x724D /* ascii 'rM' */
/*| morkRowMap: maps a set of morkRow by contained Oid
|*/
class morkRowMap : public morkMap { // for mapping row IDs to rows
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseRowMap() only if open
virtual ~morkRowMap(); // assert that CloseRowMap() executed earlier
public: // morkMap construction & destruction
morkRowMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap, mork_size inSlots);
void CloseRowMap(morkEnv* ev); // called by CloseMorkNode();
public: // dynamic type identification
mork_bool IsRowMap() const
{ return IsNode() && mNode_Derived == morkDerived_kRowMap; }
// } ===== end morkNode methods =====
// { ===== begin morkMap poly interface =====
virtual mork_bool // note: equal(a,b) implies hash(a) == hash(b)
Equal(morkEnv* ev, const void* inKeyA, const void* inKeyB) const;
// implemented using morkRow::EqualRow()
virtual mork_u4 // note: equal(a,b) implies hash(a) == hash(b)
Hash(morkEnv* ev, const void* inKey) const;
// implemented using morkRow::HashRow()
// } ===== end morkMap poly interface =====
public: // other map methods
mork_bool AddRow(morkEnv* ev, morkRow* ioRow);
// AddRow() returns ev->Good()
morkRow* CutOid(morkEnv* ev, const mdbOid* inOid);
// CutRid() returns the row removed equal to inRid, if there was one
morkRow* CutRow(morkEnv* ev, const morkRow* ioRow);
// CutRow() returns the row removed equal to ioRow, if there was one
morkRow* GetOid(morkEnv* ev, const mdbOid* inOid);
// GetOid() returns the row equal to inRid, or else nil
morkRow* GetRow(morkEnv* ev, const morkRow* ioRow);
// GetRow() returns the row equal to ioRow, or else nil
// note the rows are owned elsewhere, usuall by morkRowSpace
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakRowMap(morkMap* me,
morkEnv* ev, morkRowMap** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongRowMap(morkMap* me,
morkEnv* ev, morkRowMap** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
class morkRowMapIter: public morkMapIter{ // typesafe wrapper class
public:
morkRowMapIter(morkEnv* ev, morkRowMap* ioMap)
: morkMapIter(ev, ioMap) { }
morkRowMapIter( ) : morkMapIter() { }
void InitRowMapIter(morkEnv* ev, morkRowMap* ioMap)
{ this->InitMapIter(ev, ioMap); }
mork_change* FirstRow(morkEnv* ev, morkRow** outRowPtr)
{ return this->First(ev, outRowPtr, /*val*/ (void*) 0); }
mork_change* NextRow(morkEnv* ev, morkRow** outRowPtr)
{ return this->Next(ev, outRowPtr, /*val*/ (void*) 0); }
mork_change* HereRow(morkEnv* ev, morkRow** outRowPtr)
{ return this->Here(ev, outRowPtr, /*val*/ (void*) 0); }
mork_change* CutHereRow(morkEnv* ev, morkRow** outRowPtr)
{ return this->CutHere(ev, outRowPtr, /*val*/ (void*) 0); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKROWMAP_ */

View File

@@ -1,171 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKROWOBJECT_
#include "morkRowObject.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _ORKINROW_
#include "orkinRow.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkRowObject::CloseMorkNode(morkEnv* ev) // CloseRowObject() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseRowObject(ev);
this->MarkShut();
}
}
/*public virtual*/
morkRowObject::~morkRowObject() // assert CloseRowObject() executed earlier
{
MORK_ASSERT(this->IsShutNode());
}
/*public non-poly*/
morkRowObject::morkRowObject(morkEnv* ev,
const morkUsage& inUsage, nsIMdbHeap* ioHeap,
morkRow* ioRow, morkStore* ioStore)
: morkObject(ev, inUsage, ioHeap, (morkHandle*) 0)
, mRowObject_Row( 0 )
, mRowObject_Store( 0 )
{
if ( ev->Good() )
{
if ( ioRow && ioStore )
{
mRowObject_Row = ioRow;
morkStore::SlotWeakStore(ioStore, ev, &mRowObject_Store);
if ( ev->Good() )
mNode_Derived = morkDerived_kRowObject;
}
else
ev->NilPointerError();
}
}
/*public non-poly*/ void
morkRowObject::CloseRowObject(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
morkRow* row = mRowObject_Row;
mRowObject_Row = 0;
this->CloseObject(ev);
this->MarkShut();
if ( row )
{
MORK_ASSERT(row->mRow_Object == this);
if ( row->mRow_Object == this )
{
row->mRow_Object = 0; // just nil this slot -- cut ref down below
morkStore::SlotWeakStore((morkStore*) 0, ev,
&mRowObject_Store);
this->CutWeakRef(ev); // do last, because it might self destroy
}
}
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
/*static*/ void
morkRowObject::NonRowObjectTypeError(morkEnv* ev)
{
ev->NewError("non morkRowObject");
}
/*static*/ void
morkRowObject::NilRowError(morkEnv* ev)
{
ev->NewError("nil mRowObject_Row");
}
/*static*/ void
morkRowObject::NilStoreError(morkEnv* ev)
{
ev->NewError("nil mRowObject_Store");
}
/*static*/ void
morkRowObject::RowObjectRowNotSelfError(morkEnv* ev)
{
ev->NewError("mRowObject_Row->mRow_Object != self");
}
nsIMdbRow*
morkRowObject::AcquireRowHandle(morkEnv* ev) // mObject_Handle
{
nsIMdbRow* outRow = 0;
orkinRow* r = (orkinRow*) mObject_Handle;
if ( r ) // have an old handle?
r->AddStrongRef(ev->AsMdbEnv());
else // need new handle?
{
r = orkinRow::MakeRow(ev, this);
mObject_Handle = r;
}
if ( r )
outRow = r;
return outRow;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,82 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKROWOBJECT_
#define _MORKROWOBJECT_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKOBJECT_
#include "morkObject.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
class nsIMdbRow;
#define morkDerived_kRowObject /*i*/ 0x724F /* ascii 'rO' */
class morkRowObject : public morkObject { //
public: // state is public because the entire Mork system is private
morkRow* mRowObject_Row; // non-refcounted alias to morkRow
morkStore* mRowObject_Store; // weak ref to store containing row
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseRowObject() only if open
virtual ~morkRowObject(); // assert that CloseRowObject() executed earlier
public: // morkRowObject construction & destruction
morkRowObject(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, morkRow* ioRow, morkStore* ioStore);
void CloseRowObject(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkRowObject(const morkRowObject& other);
morkRowObject& operator=(const morkRowObject& other);
public: // dynamic type identification
mork_bool IsRowObject() const
{ return IsNode() && mNode_Derived == morkDerived_kRowObject; }
// } ===== end morkNode methods =====
public: // typing
static void NonRowObjectTypeError(morkEnv* ev);
static void NilRowError(morkEnv* ev);
static void NilStoreError(morkEnv* ev);
static void RowObjectRowNotSelfError(morkEnv* ev);
public: // other row node methods
nsIMdbRow* AcquireRowHandle(morkEnv* ev); // mObject_Handle
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakRowObject(morkRowObject* me,
morkEnv* ev, morkRowObject** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongRowObject(morkRowObject* me,
morkEnv* ev, morkRowObject** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKROWOBJECT_ */

View File

@@ -1,618 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
#ifndef _MORKSPACE_
#include "morkSpace.h"
#endif
#ifndef _MORKNODEMAP_
#include "morkNodeMap.h"
#endif
#ifndef _MORKROWMAP_
#include "morkRowMap.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKROWSPACE_
#include "morkRowSpace.h"
#endif
#ifndef _MORKPOOL_
#include "morkPool.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
#ifndef _MORKTABLE_
#include "morkTable.h"
#endif
#ifndef _MORKROW_
#include "morkRow.h"
#endif
#ifndef _MORKATOMMAP_
#include "morkAtomMap.h"
#endif
#ifndef _MORKROWOBJECT_
#include "morkRowObject.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkRowSpace::CloseMorkNode(morkEnv* ev) // CloseRowSpace() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseRowSpace(ev);
this->MarkShut();
}
}
/*public virtual*/
morkRowSpace::~morkRowSpace() // assert CloseRowSpace() executed earlier
{
MORK_ASSERT(this->IsShutNode());
}
/*public non-poly*/
morkRowSpace::morkRowSpace(morkEnv* ev,
const morkUsage& inUsage, mork_scope inScope, morkStore* ioStore,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
: morkSpace(ev, inUsage, inScope, ioStore, ioHeap, ioSlotHeap)
, mRowSpace_SlotHeap( ioSlotHeap )
, mRowSpace_Rows(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioSlotHeap,
morkRowSpace_kStartRowMapSlotCount)
, mRowSpace_Tables(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioSlotHeap)
, mRowSpace_NextTableId( 1 )
, mRowSpace_NextRowId( 1 )
, mRowSpace_IndexCount( 0 )
{
morkAtomRowMap** cache = mRowSpace_IndexCache;
morkAtomRowMap** cacheEnd = cache + morkRowSpace_kPrimeCacheSize;
while ( cache < cacheEnd )
*cache++ = 0; // put nil into every slot of cache table
if ( ev->Good() )
{
if ( ioSlotHeap )
{
mNode_Derived = morkDerived_kRowSpace;
// the morkSpace base constructor handles any dirty propagation
}
else
ev->NilPointerError();
}
}
/*public non-poly*/ void
morkRowSpace::CloseRowSpace(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
morkAtomRowMap** cache = mRowSpace_IndexCache;
morkAtomRowMap** cacheEnd = cache + morkRowSpace_kPrimeCacheSize;
--cache; // prepare for preincrement:
while ( ++cache < cacheEnd )
{
if ( *cache )
morkAtomRowMap::SlotStrongAtomRowMap(0, ev, cache);
}
mRowSpace_Tables.CloseMorkNode(ev);
morkStore* store = mSpace_Store;
if ( store )
this->CutAllRows(ev, &store->mStore_Pool);
mRowSpace_Rows.CloseMorkNode(ev);
this->CloseSpace(ev);
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
/*static*/ void
morkRowSpace::NonRowSpaceTypeError(morkEnv* ev)
{
ev->NewError("non morkRowSpace");
}
/*static*/ void
morkRowSpace::ZeroKindError(morkEnv* ev)
{
ev->NewError("zero table kind");
}
/*static*/ void
morkRowSpace::ZeroScopeError(morkEnv* ev)
{
ev->NewError("zero row scope");
}
/*static*/ void
morkRowSpace::ZeroTidError(morkEnv* ev)
{
ev->NewError("zero table ID");
}
/*static*/ void
morkRowSpace::MinusOneRidError(morkEnv* ev)
{
ev->NewError("row ID is -1");
}
///*static*/ void
//morkRowSpace::ExpectAutoIdOnlyError(morkEnv* ev)
//{
// ev->NewError("zero row ID");
//}
///*static*/ void
//morkRowSpace::ExpectAutoIdNeverError(morkEnv* ev)
//{
//}
mork_num
morkRowSpace::CutAllRows(morkEnv* ev, morkPool* ioPool)
{
if ( this->IsRowSpaceClean() )
this->MaybeDirtyStoreAndSpace();
mork_num outSlots = mRowSpace_Rows.mMap_Fill;
morkRow* r = 0; // old key row in the map
mork_change* c = 0;
morkRowMapIter i(ev, &mRowSpace_Rows);
for ( c = i.FirstRow(ev, &r); c && ev->Good();
c = i.NextRow(ev, &r) )
{
if ( r )
{
if ( r->IsRow() )
{
if ( r->mRow_Object )
{
morkRowObject::SlotWeakRowObject((morkRowObject*) 0, ev,
&r->mRow_Object);
}
ioPool->ZapRow(ev, r);
}
else
r->NonRowTypeWarning(ev);
}
else
ev->NilPointerError();
i.CutHereRow(ev, /*key*/ (morkRow**) 0);
}
return outSlots;
}
morkTable*
morkRowSpace::FindTableByKind(morkEnv* ev, mork_kind inTableKind)
{
if ( inTableKind )
{
mork_tid* key = 0; // nil pointer to suppress key access
morkTable* table = 0; // old table in the map
mork_change* c = 0;
morkTableMapIter i(ev, &mRowSpace_Tables);
for ( c = i.FirstTable(ev, key, &table); c && ev->Good();
c = i.NextTable(ev, key, &table) )
{
if ( table->mTable_Kind == inTableKind )
return table;
}
}
else
this->ZeroKindError(ev);
return (morkTable*) 0;
}
morkTable*
morkRowSpace::NewTableWithTid(morkEnv* ev, mork_tid inTid,
mork_kind inTableKind,
const mdbOid* inOptionalMetaRowOid) // can be nil to avoid specifying
{
morkTable* outTable = 0;
morkStore* store = mSpace_Store;
if ( inTableKind && store )
{
mdb_bool mustBeUnique = morkBool_kFalse;
nsIMdbHeap* heap = store->mPort_Heap;
morkTable* table = new(*heap, ev)
morkTable(ev, morkUsage::kHeap, heap, store, heap, this,
inOptionalMetaRowOid, inTid, inTableKind, mustBeUnique);
if ( table )
{
if ( mRowSpace_Tables.AddTable(ev, table) )
{
outTable = table;
if ( mRowSpace_NextTableId <= inTid )
mRowSpace_NextTableId = inTid + 1;
}
table->CutStrongRef(ev); // always cut ref; AddTable() adds its own
if ( this->IsRowSpaceClean() && store->mStore_CanDirty )
this->MaybeDirtyStoreAndSpace(); // morkTable does already
}
}
else if ( store )
this->ZeroKindError(ev);
else
this->NilSpaceStoreError(ev);
return outTable;
}
morkTable*
morkRowSpace::NewTable(morkEnv* ev, mork_kind inTableKind,
mdb_bool inMustBeUnique,
const mdbOid* inOptionalMetaRowOid) // can be nil to avoid specifying
{
morkTable* outTable = 0;
morkStore* store = mSpace_Store;
if ( inTableKind && store )
{
if ( inMustBeUnique ) // need to look for existing table first?
outTable = this->FindTableByKind(ev, inTableKind);
if ( !outTable && ev->Good() )
{
mork_tid id = this->MakeNewTableId(ev);
if ( id )
{
nsIMdbHeap* heap = mSpace_Store->mPort_Heap;
morkTable* table = new(*heap, ev)
morkTable(ev, morkUsage::kHeap, heap, mSpace_Store, heap, this,
inOptionalMetaRowOid, id, inTableKind, inMustBeUnique);
if ( table )
{
if ( mRowSpace_Tables.AddTable(ev, table) )
outTable = table;
else
table->CutStrongRef(ev);
if ( this->IsRowSpaceClean() && store->mStore_CanDirty )
this->MaybeDirtyStoreAndSpace(); // morkTable does already
}
}
}
}
else if ( store )
this->ZeroKindError(ev);
else
this->NilSpaceStoreError(ev);
return outTable;
}
mork_tid
morkRowSpace::MakeNewTableId(morkEnv* ev)
{
mork_tid outTid = 0;
mork_tid id = mRowSpace_NextTableId;
mork_num count = 9; // try up to eight times
while ( !outTid && --count ) // still trying to find an unused table ID?
{
if ( !mRowSpace_Tables.GetTable(ev, id) )
outTid = id;
else
{
MORK_ASSERT(morkBool_kFalse); // alert developer about ID problems
++id;
}
}
mRowSpace_NextTableId = id + 1;
return outTid;
}
mork_rid
morkRowSpace::MakeNewRowId(morkEnv* ev)
{
mork_rid outRid = 0;
mork_rid id = mRowSpace_NextRowId;
mork_num count = 9; // try up to eight times
mdbOid oid;
oid.mOid_Scope = mSpace_Scope;
while ( !outRid && --count ) // still trying to find an unused row ID?
{
oid.mOid_Id = id;
if ( !mRowSpace_Rows.GetOid(ev, &oid) )
outRid = id;
else
{
MORK_ASSERT(morkBool_kFalse); // alert developer about ID problems
++id;
}
}
mRowSpace_NextRowId = id + 1;
return outRid;
}
morkAtomRowMap*
morkRowSpace::make_index(morkEnv* ev, mork_column inCol)
{
morkAtomRowMap* outMap = 0;
nsIMdbHeap* heap = mRowSpace_SlotHeap;
if ( heap ) // have expected heap for allocations?
{
morkAtomRowMap* map = new(*heap, ev)
morkAtomRowMap(ev, morkUsage::kHeap, heap, heap, inCol);
if ( map ) // able to create new map index?
{
if ( ev->Good() ) // no errors during construction?
{
morkRowMapIter i(ev, &mRowSpace_Rows);
mork_change* c = 0;
morkRow* row = 0;
mork_aid aidKey = 0;
for ( c = i.FirstRow(ev, &row); c && ev->Good();
c = i.NextRow(ev, &row) ) // another row in space?
{
aidKey = row->GetCellAtomAid(ev, inCol);
if ( aidKey ) // row has indexed attribute?
map->AddAid(ev, aidKey, row); // include in map
}
}
if ( ev->Good() ) // no errors constructing index?
outMap = map; // return from function
else
map->CutStrongRef(ev); // discard map on error
}
}
else
ev->NilPointerError();
return outMap;
}
morkAtomRowMap*
morkRowSpace::ForceMap(morkEnv* ev, mork_column inCol)
{
morkAtomRowMap* outMap = this->FindMap(ev, inCol);
if ( !outMap && ev->Good() ) // no such existing index?
{
if ( mRowSpace_IndexCount < morkRowSpace_kMaxIndexCount )
{
morkAtomRowMap* map = this->make_index(ev, inCol);
if ( map ) // created a new index for col?
{
mork_count wrap = 0; // count times wrap-around occurs
morkAtomRowMap** slot = mRowSpace_IndexCache; // table
morkAtomRowMap** end = slot + morkRowSpace_kPrimeCacheSize;
slot += ( inCol % morkRowSpace_kPrimeCacheSize ); // hash
while ( *slot ) // empty slot not yet found?
{
if ( ++slot >= end ) // wrap around?
{
slot = mRowSpace_IndexCache; // back to table start
if ( ++wrap > 1 ) // wrapped more than once?
{
ev->NewError("no free cache slots"); // disaster
break; // end while loop
}
}
}
if ( ev->Good() ) // everything went just fine?
{
++mRowSpace_IndexCount; // note another new map
*slot = map; // install map in the hash table
outMap = map; // return the new map from function
}
else
map->CutStrongRef(ev); // discard map on error
}
}
else
ev->NewError("too many indexes"); // why so many indexes?
}
return outMap;
}
morkAtomRowMap*
morkRowSpace::FindMap(morkEnv* ev, mork_column inCol)
{
if ( mRowSpace_IndexCount && ev->Good() )
{
mork_count wrap = 0; // count times wrap-around occurs
morkAtomRowMap** slot = mRowSpace_IndexCache; // table
morkAtomRowMap** end = slot + morkRowSpace_kPrimeCacheSize;
slot += ( inCol % morkRowSpace_kPrimeCacheSize ); // hash
morkAtomRowMap* map = *slot;
while ( map ) // another used slot to examine?
{
if ( inCol == map->mAtomRowMap_IndexColumn ) // found col?
return map;
if ( ++slot >= end ) // wrap around?
{
slot = mRowSpace_IndexCache;
if ( ++wrap > 1 ) // wrapped more than once?
return (morkAtomRowMap*) 0; // stop searching
}
map = *slot;
}
}
return (morkAtomRowMap*) 0;
}
morkRow*
morkRowSpace::FindRow(morkEnv* ev, mork_column inCol, const mdbYarn* inYarn)
{
morkRow* outRow = 0;
morkAtom* atom = mSpace_Store->YarnToAtom(ev, inYarn);
if ( atom ) // have or created an atom corresponding to input yarn?
{
mork_aid atomAid = atom->GetBookAtomAid();
if ( atomAid ) // atom has an identity for use in hash table?
{
morkAtomRowMap* map = this->ForceMap(ev, inCol);
if ( map ) // able to find or create index for col?
{
outRow = map->GetAid(ev, atomAid); // search for row
}
}
}
return outRow;
}
morkRow*
morkRowSpace::NewRowWithOid(morkEnv* ev, const mdbOid* inOid)
{
morkRow* outRow = mRowSpace_Rows.GetOid(ev, inOid);
MORK_ASSERT(outRow==0);
if ( !outRow && ev->Good() )
{
morkStore* store = mSpace_Store;
if ( store )
{
morkPool* pool = this->GetSpaceStorePool();
morkRow* row = pool->NewRow(ev);
if ( row )
{
row->InitRow(ev, inOid, this, /*length*/ 0, pool);
if ( ev->Good() && mRowSpace_Rows.AddRow(ev, row) )
{
outRow = row;
mork_rid rid = inOid->mOid_Id;
if ( mRowSpace_NextRowId <= rid )
mRowSpace_NextRowId = rid + 1;
}
else
pool->ZapRow(ev, row);
if ( this->IsRowSpaceClean() && store->mStore_CanDirty )
this->MaybeDirtyStoreAndSpace(); // InitRow() does already
}
}
else
this->NilSpaceStoreError(ev);
}
return outRow;
}
morkRow*
morkRowSpace::NewRow(morkEnv* ev)
{
morkRow* outRow = 0;
if ( ev->Good() )
{
mork_rid id = this->MakeNewRowId(ev);
if ( id )
{
morkStore* store = mSpace_Store;
if ( store )
{
mdbOid oid;
oid.mOid_Scope = mSpace_Scope;
oid.mOid_Id = id;
morkPool* pool = this->GetSpaceStorePool();
morkRow* row = pool->NewRow(ev);
if ( row )
{
row->InitRow(ev, &oid, this, /*length*/ 0, pool);
if ( ev->Good() && mRowSpace_Rows.AddRow(ev, row) )
outRow = row;
else
pool->ZapRow(ev, row);
if ( this->IsRowSpaceClean() && store->mStore_CanDirty )
this->MaybeDirtyStoreAndSpace(); // InitRow() does already
}
}
else
this->NilSpaceStoreError(ev);
}
}
return outRow;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
morkRowSpaceMap::~morkRowSpaceMap()
{
}
morkRowSpaceMap::morkRowSpaceMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
: morkNodeMap(ev, inUsage, ioHeap, ioSlotHeap)
{
if ( ev->Good() )
mNode_Derived = morkDerived_kRowSpaceMap;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,243 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKROWSPACE_
#define _MORKROWSPACE_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKSPACE_
#include "morkSpace.h"
#endif
#ifndef _MORKNODEMAP_
#include "morkNodeMap.h"
#endif
#ifndef _MORKROWMAP_
#include "morkRowMap.h"
#endif
#ifndef _MORKTABLE_
#include "morkTable.h"
#endif
#ifndef _MORKARRAY_
#include "morkArray.h"
#endif
#ifndef _MORKDEQUE_
#include "morkDeque.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kRowSpace /*i*/ 0x7253 /* ascii 'rS' */
#define morkRowSpace_kStartRowMapSlotCount 512
#define morkRowSpace_kMaxIndexCount 8 /* no more indexes than this */
#define morkRowSpace_kPrimeCacheSize 17 /* should be prime number */
class morkAtomRowMap;
/*| morkRowSpace:
|*/
class morkRowSpace : public morkSpace { //
// public: // slots inherited from morkSpace (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
// morkStore* mSpace_Store; // weak ref to containing store
// mork_scope mSpace_Scope; // the scope for this space
// mork_bool mSpace_DoAutoIDs; // whether db should assign member IDs
// mork_bool mSpace_HaveDoneAutoIDs; // whether actually auto assigned IDs
// mork_u1 mSpace_Pad[ 2 ]; // pad to u4 alignment
public: // state is public because the entire Mork system is private
nsIMdbHeap* mRowSpace_SlotHeap;
morkRowMap mRowSpace_Rows; // hash table of morkRow instances
morkTableMap mRowSpace_Tables; // all the tables in this row scope
mork_tid mRowSpace_NextTableId; // for auto-assigning table IDs
mork_rid mRowSpace_NextRowId; // for auto-assigning row IDs
mork_count mRowSpace_IndexCount; // if nonzero, row indexes exist
// every nonzero slot in IndexCache is a strong ref to a morkAtomRowMap:
morkAtomRowMap* mRowSpace_IndexCache[ morkRowSpace_kPrimeCacheSize ];
morkDeque mRowSpace_TablesByPriority[ morkPriority_kCount ];
public: // more specific dirty methods for row space:
void SetRowSpaceDirty() { this->SetNodeDirty(); }
void SetRowSpaceClean() { this->SetNodeClean(); }
mork_bool IsRowSpaceClean() const { return this->IsNodeClean(); }
mork_bool IsRowSpaceDirty() const { return this->IsNodeDirty(); }
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseRowSpace() only if open
virtual ~morkRowSpace(); // assert that CloseRowSpace() executed earlier
public: // morkMap construction & destruction
morkRowSpace(morkEnv* ev, const morkUsage& inUsage, mork_scope inScope,
morkStore* ioStore, nsIMdbHeap* ioNodeHeap, nsIMdbHeap* ioSlotHeap);
void CloseRowSpace(morkEnv* ev); // called by CloseMorkNode();
public: // dynamic type identification
mork_bool IsRowSpace() const
{ return IsNode() && mNode_Derived == morkDerived_kRowSpace; }
// } ===== end morkNode methods =====
public: // typing
static void NonRowSpaceTypeError(morkEnv* ev);
static void ZeroScopeError(morkEnv* ev);
static void ZeroKindError(morkEnv* ev);
static void ZeroTidError(morkEnv* ev);
static void MinusOneRidError(morkEnv* ev);
//static void ExpectAutoIdOnlyError(morkEnv* ev);
//static void ExpectAutoIdNeverError(morkEnv* ev);
public: // other space methods
mork_num CutAllRows(morkEnv* ev, morkPool* ioPool);
// CutAllRows() puts all rows and cells back into the pool.
morkTable* NewTable(morkEnv* ev, mork_kind inTableKind,
mdb_bool inMustBeUnique, const mdbOid* inOptionalMetaRowOid);
morkTable* NewTableWithTid(morkEnv* ev, mork_tid inTid,
mork_kind inTableKind, const mdbOid* inOptionalMetaRowOid);
morkTable* FindTableByKind(morkEnv* ev, mork_kind inTableKind);
morkTable* FindTableByTid(morkEnv* ev, mork_tid inTid)
{ return mRowSpace_Tables.GetTable(ev, inTid); }
mork_tid MakeNewTableId(morkEnv* ev);
mork_rid MakeNewRowId(morkEnv* ev);
// morkRow* FindRowByRid(morkEnv* ev, mork_rid inRid)
// { return (morkRow*) mRowSpace_Rows.GetRow(ev, inRid); }
morkRow* NewRowWithOid(morkEnv* ev, const mdbOid* inOid);
morkRow* NewRow(morkEnv* ev);
morkRow* FindRow(morkEnv* ev, mork_column inColumn, const mdbYarn* inYarn);
morkAtomRowMap* ForceMap(morkEnv* ev, mork_column inColumn);
morkAtomRowMap* FindMap(morkEnv* ev, mork_column inColumn);
protected: // internal utilities
morkAtomRowMap* make_index(morkEnv* ev, mork_column inColumn);
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakRowSpace(morkRowSpace* me,
morkEnv* ev, morkRowSpace** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongRowSpace(morkRowSpace* me,
morkEnv* ev, morkRowSpace** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kRowSpaceMap /*i*/ 0x725A /* ascii 'rZ' */
/*| morkRowSpaceMap: maps mork_scope -> morkRowSpace
|*/
class morkRowSpaceMap : public morkNodeMap { // for mapping tokens to tables
public:
virtual ~morkRowSpaceMap();
morkRowSpaceMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap);
public: // other map methods
mork_bool AddRowSpace(morkEnv* ev, morkRowSpace* ioRowSpace)
{ return this->AddNode(ev, ioRowSpace->mSpace_Scope, ioRowSpace); }
// the AddRowSpace() boolean return equals ev->Good().
mork_bool CutRowSpace(morkEnv* ev, mork_scope inScope)
{ return this->CutNode(ev, inScope); }
// The CutRowSpace() boolean return indicates whether removal happened.
morkRowSpace* GetRowSpace(morkEnv* ev, mork_scope inScope)
{ return (morkRowSpace*) this->GetNode(ev, inScope); }
// Note the returned space does NOT have an increase in refcount for this.
mork_num CutAllRowSpaces(morkEnv* ev)
{ return this->CutAllNodes(ev); }
// CutAllRowSpaces() releases all the referenced table values.
};
class morkRowSpaceMapIter: public morkMapIter{ // typesafe wrapper class
public:
morkRowSpaceMapIter(morkEnv* ev, morkRowSpaceMap* ioMap)
: morkMapIter(ev, ioMap) { }
morkRowSpaceMapIter( ) : morkMapIter() { }
void InitRowSpaceMapIter(morkEnv* ev, morkRowSpaceMap* ioMap)
{ this->InitMapIter(ev, ioMap); }
mork_change*
FirstRowSpace(morkEnv* ev, mork_scope* outScope, morkRowSpace** outRowSpace)
{ return this->First(ev, outScope, outRowSpace); }
mork_change*
NextRowSpace(morkEnv* ev, mork_scope* outScope, morkRowSpace** outRowSpace)
{ return this->Next(ev, outScope, outRowSpace); }
mork_change*
HereRowSpace(morkEnv* ev, mork_scope* outScope, morkRowSpace** outRowSpace)
{ return this->Here(ev, outScope, outRowSpace); }
mork_change*
CutHereRowSpace(morkEnv* ev, mork_scope* outScope, morkRowSpace** outRowSpace)
{ return this->CutHere(ev, outScope, outRowSpace); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKROWSPACE_ */

View File

@@ -1,305 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKSINK_
#include "morkSink.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKBLOB_
#include "morkBlob.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/*virtual*/ morkSink::~morkSink()
{
mSink_At = 0;
mSink_End = 0;
}
/*virtual*/ void
morkSpool::FlushSink(morkEnv* ev) // sync mSpool_Coil->mBuf_Fill
{
morkCoil* coil = mSpool_Coil;
if ( coil )
{
mork_u1* body = (mork_u1*) coil->mBuf_Body;
if ( body )
{
mork_u1* at = mSink_At;
mork_u1* end = mSink_End;
if ( at >= body && at <= end ) // expected cursor order?
{
mork_fill fill = (mork_fill) (at - body); // current content size
if ( fill <= coil->mBlob_Size )
coil->mBuf_Fill = fill;
else
{
coil->BlobFillOverSizeError(ev);
coil->mBuf_Fill = coil->mBlob_Size; // make it safe
}
}
else
this->BadSpoolCursorOrderError(ev);
}
else
coil->NilBufBodyError(ev);
}
else
this->NilSpoolCoilError(ev);
}
/*virtual*/ void
morkSpool::SpillPutc(morkEnv* ev, int c) // grow coil and write byte
{
morkCoil* coil = mSpool_Coil;
if ( coil )
{
mork_u1* body = (mork_u1*) coil->mBuf_Body;
if ( body )
{
mork_u1* at = mSink_At;
mork_u1* end = mSink_End;
if ( at >= body && at <= end ) // expected cursor order?
{
mork_size size = coil->mBlob_Size;
mork_fill fill = (mork_fill) (at - body); // current content size
if ( fill <= size ) // less content than medium size?
{
coil->mBuf_Fill = fill;
if ( at >= end ) // need to grow the coil?
{
if ( size > 2048 ) // grow slower over 2K?
size += 512;
else
{
mork_size growth = ( size * 4 ) / 3; // grow by 33%
if ( growth < 64 ) // grow faster under (64 * 3)?
growth = 64;
size += growth;
}
if ( coil->GrowCoil(ev, size) ) // made coil bigger?
{
body = (mork_u1*) coil->mBuf_Body;
if ( body ) // have a coil body?
{
mSink_At = at = body + fill;
mSink_End = end = body + coil->mBlob_Size;
}
else
coil->NilBufBodyError(ev);
}
}
if ( ev->Good() ) // seem ready to write byte c?
{
if ( at < end ) // morkSink::Putc() would succeed?
{
*at++ = (mork_u1) c;
mSink_At = at;
coil->mBuf_Fill = fill + 1;
}
else
this->BadSpoolCursorOrderError(ev);
}
}
else // fill exceeds size
{
coil->BlobFillOverSizeError(ev);
coil->mBuf_Fill = coil->mBlob_Size; // make it safe
}
}
else
this->BadSpoolCursorOrderError(ev);
}
else
coil->NilBufBodyError(ev);
}
else
this->NilSpoolCoilError(ev);
}
// ````` ````` ````` ````` ````` ````` ````` `````
// public: // public non-poly morkSink methods
/*virtual*/
morkSpool::~morkSpool()
// Zero all slots to show this sink is disabled, but destroy no memory.
// Note it is typically unnecessary to flush this coil sink, since all
// content is written directly to the coil without any buffering.
{
mSink_At = 0;
mSink_End = 0;
mSpool_Coil = 0;
}
morkSpool::morkSpool(morkEnv* ev, morkCoil* ioCoil)
// After installing the coil, calls Seek(ev, 0) to prepare for writing.
: morkSink()
, mSpool_Coil( 0 )
{
mSink_At = 0; // set correctly later in Seek()
mSink_End = 0; // set correctly later in Seek()
if ( ev->Good() )
{
if ( ioCoil )
{
mSpool_Coil = ioCoil;
this->Seek(ev, /*pos*/ 0);
}
else
ev->NilPointerError();
}
}
// ----- All boolean return values below are equal to ev->Good(): -----
/*static*/ void
morkSpool::BadSpoolCursorOrderError(morkEnv* ev)
{
ev->NewError("bad morkSpool cursor order");
}
/*static*/ void
morkSpool::NilSpoolCoilError(morkEnv* ev)
{
ev->NewError("nil mSpool_Coil");
}
mork_bool
morkSpool::Seek(morkEnv* ev, mork_pos inPos)
// Changed the current write position in coil's buffer to inPos.
// For example, to start writing the coil from scratch, use inPos==0.
{
morkCoil* coil = mSpool_Coil;
if ( coil )
{
mork_size minSize = (mork_size) (inPos + 64);
if ( coil->mBlob_Size < minSize )
coil->GrowCoil(ev, minSize);
if ( ev->Good() )
{
coil->mBuf_Fill = (mork_fill) inPos;
mork_u1* body = (mork_u1*) coil->mBuf_Body;
if ( body )
{
mSink_At = body + inPos;
mSink_End = body + coil->mBlob_Size;
}
else
coil->NilBufBodyError(ev);
}
}
else
this->NilSpoolCoilError(ev);
return ev->Good();
}
mork_bool
morkSpool::Write(morkEnv* ev, const void* inBuf, mork_size inSize)
// write inSize bytes of inBuf to current position inside coil's buffer
{
// This method is conceptually very similar to morkStream::Write(),
// and this code was written while looking at that method for clues.
morkCoil* coil = mSpool_Coil;
if ( coil )
{
mork_u1* body = (mork_u1*) coil->mBuf_Body;
if ( body )
{
if ( inBuf && inSize ) // anything to write?
{
mork_u1* at = mSink_At;
mork_u1* end = mSink_End;
if ( at >= body && at <= end ) // expected cursor order?
{
// note coil->mBuf_Fill can be stale after morkSink::Putc():
mork_pos fill = at - body; // current content size
mork_num space = (mork_num) (end - at); // space left in body
if ( space < inSize ) // not enough to hold write?
{
mork_size minGrowth = space + 16;
mork_size minSize = coil->mBlob_Size + minGrowth;
if ( coil->GrowCoil(ev, minSize) )
{
body = (mork_u1*) coil->mBuf_Body;
if ( body )
{
mSink_At = at = body + fill;
mSink_End = end = body + coil->mBlob_Size;
space = (mork_num) (end - at); // space left in body
}
else
coil->NilBufBodyError(ev);
}
}
if ( ev->Good() )
{
if ( space >= inSize ) // enough room to hold write?
{
MORK_MEMCPY(at, inBuf, inSize); // into body
mSink_At = at + inSize; // advance past written bytes
coil->mBuf_Fill = fill + inSize; // "flush" to fix fill
}
else
ev->NewError("insufficient morkSpool space");
}
}
else
this->BadSpoolCursorOrderError(ev);
}
}
else
coil->NilBufBodyError(ev);
}
else
this->NilSpoolCoilError(ev);
return ev->Good();
}
mork_bool
morkSpool::PutString(morkEnv* ev, const char* inString)
// call Write() with inBuf=inString and inSize=strlen(inString),
// unless inString is null, in which case we then do nothing at all.
{
if ( inString )
{
mork_size size = MORK_STRLEN(inString);
this->Write(ev, inString, size);
}
return ev->Good();
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,174 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKSINK_
#define _MORKSINK_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKBLOB_
#include "morkBlob.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/*| morkSink is intended to be a very cheap buffered i/o sink which
**| writes to bufs and other strings a single byte at a time. The
**| basic idea is that writing a single byte has a very cheap average
**| cost, because a polymophic function call need only occur when the
**| space between At and End is exhausted. The rest of the time a
**| very cheap inline method will write a byte, and then bump a pointer.
**|
**|| At: the current position in some sequence of bytes at which to
**| write the next byte put into the sink. Presumably At points into
**| the private storage of some space which is not yet filled (except
**| when At reaches End, and the overflow must then spill). Note both
**| At and End are zeroed in the destructor to help show that a sink
**| is no longer usable; this is safe because At==End causes the case
**| where SpillPutc() is called to handled an exhausted buffer space.
**|
**|| End: an address one byte past the last byte which can be written
**| without needing to make a buffer larger than previously. When At
**| and End are equal, this means there is no space to write a byte,
**| and that some underlying buffer space must be grown before another
**| byte can be written. Note At must always be less than or equal to
**| End, and otherwise an important invariant has failed severely.
**|
**|| Buf: this original class slot has been commented out in the new
**| and more abstract version of this sink class, but the general idea
**| behind this slot should be explained to help design subclasses.
**| Each subclass should provide space into which At and End can point,
**| where End is beyond the last writable byte, and At is less than or
**| equal to this point inside the same buffer. With some kinds of
**| medium, such as writing to an instance of morkBlob, it is feasible
**| to point directly into the final resting place for all the content
**| written to the medium. Other mediums such as files, which write
**| only through function calls, will typically need a local buffer
**| to efficiently accumulate many bytes between such function calls.
**|
**|| FlushSink: this flush method should move any buffered content to
**| it's final destination. For example, for buffered writes to a
**| string medium, where string methods are function calls and not just
**| inline macros, it is faster to accumulate many bytes in a small
**| local buffer and then move these en masse later in a single call.
**|
**|| SpillPutc: when At is greater than or equal to End, this means an
**| underlying buffer has become full, so the buffer must be flushed
**| before a new byte can be written. The intention is that SpillPutc()
**| will be equivalent to calling FlushSink() followed by another call
**| to Putc(), where the flush is expected to make At less then End once
**| again. Except that FlushSink() need not make the underlying buffer
**| any larger, and SpillPutc() typically must make room for more bytes.
**| Note subclasses might want to guard against the case that both At
**| and End are null, which happens when a sink is destroyed, which sets
**| both these pointers to null as an indication the sink is disabled.
|*/
class morkSink {
// ````` ````` ````` ````` ````` ````` ````` `````
public: // public sink virtual methods
virtual void FlushSink(morkEnv* ev) = 0;
virtual void SpillPutc(morkEnv* ev, int c) = 0;
// ````` ````` ````` ````` ````` ````` ````` `````
public: // member variables
mork_u1* mSink_At; // pointer into mSink_Buf
mork_u1* mSink_End; // one byte past last content byte
// define morkSink_kBufSize 256 /* small enough to go on stack */
// mork_u1 mSink_Buf[ morkSink_kBufSize + 4 ];
// want plus one for any needed end null byte; use plus 4 for alignment
// ````` ````` ````` ````` ````` ````` ````` `````
public: // public non-poly morkSink methods
virtual ~morkSink(); // zero both At and End; virtual for subclasses
morkSink() { } // does nothing; subclasses must set At and End suitably
void Putc(morkEnv* ev, int c)
{
if ( mSink_At < mSink_End )
*mSink_At++ = (mork_u1) c;
else
this->SpillPutc(ev, c);
}
};
/*| morkSpool: an output sink that efficiently writes individual bytes
**| or entire byte sequences to a coil instance, which grows as needed by
**| using the heap instance in the coil to grow the internal buffer.
**|
**|| Note we do not "own" the coil referenced by mSpool_Coil, and
**| the lifetime of the coil is expected to equal or exceed that of this
**| sink by some external means. Typical usage might involve keeping an
**| instance of morkCoil and an instance of morkSpool in the same
**| owning parent object, which uses the spool with the associated coil.
|*/
class morkSpool : public morkSink { // for buffered i/o to a morkCoil
// ````` ````` ````` ````` ````` ````` ````` `````
public: // public sink virtual methods
// when morkSink::Putc() moves mSink_At, mSpool_Coil->mBuf_Fill is wrong:
virtual void FlushSink(morkEnv* ev); // sync mSpool_Coil->mBuf_Fill
virtual void SpillPutc(morkEnv* ev, int c); // grow coil and write byte
// ````` ````` ````` ````` ````` ````` ````` `````
public: // member variables
morkCoil* mSpool_Coil; // destination medium for written bytes
// ````` ````` ````` ````` ````` ````` ````` `````
public: // public non-poly morkSink methods
static void BadSpoolCursorOrderError(morkEnv* ev);
static void NilSpoolCoilError(morkEnv* ev);
virtual ~morkSpool();
// Zero all slots to show this sink is disabled, but destroy no memory.
// Note it is typically unnecessary to flush this coil sink, since all
// content is written directly to the coil without any buffering.
morkSpool(morkEnv* ev, morkCoil* ioCoil);
// After installing the coil, calls Seek(ev, 0) to prepare for writing.
// ----- All boolean return values below are equal to ev->Good(): -----
mork_bool Seek(morkEnv* ev, mork_pos inPos);
// Changed the current write position in coil's buffer to inPos.
// For example, to start writing the coil from scratch, use inPos==0.
mork_bool Write(morkEnv* ev, const void* inBuf, mork_size inSize);
// write inSize bytes of inBuf to current position inside coil's buffer
mork_bool PutBuf(morkEnv* ev, const morkBuf& inBuffer)
{ return this->Write(ev, inBuffer.mBuf_Body, inBuffer.mBuf_Fill); }
mork_bool PutString(morkEnv* ev, const char* inString);
// call Write() with inBuf=inString and inSize=strlen(inString),
// unless inString is null, in which case we then do nothing at all.
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKSINK_ */

View File

@@ -1,171 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
#ifndef _MORKSPACE_
#include "morkSpace.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkSpace::CloseMorkNode(morkEnv* ev) // CloseSpace() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseSpace(ev);
this->MarkShut();
}
}
/*public virtual*/
morkSpace::~morkSpace() // assert CloseSpace() executed earlier
{
MORK_ASSERT(mSpace_Scope==0);
MORK_ASSERT(mSpace_Store==0);
MORK_ASSERT(this->IsShutNode());
}
/*public non-poly*/
//morkSpace::morkSpace(morkEnv* ev, const morkUsage& inUsage,
// nsIMdbHeap* ioNodeHeap, const morkMapForm& inForm,
// nsIMdbHeap* ioSlotHeap)
//: morkNode(ev, inUsage, ioNodeHeap)
//, mSpace_Map(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioSlotHeap)
//{
// ev->StubMethodOnlyError();
//}
/*public non-poly*/
morkSpace::morkSpace(morkEnv* ev,
const morkUsage& inUsage, mork_scope inScope, morkStore* ioStore,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
: morkNode(ev, inUsage, ioHeap)
, mSpace_Store( 0 )
, mSpace_Scope( inScope )
, mSpace_DoAutoIDs( morkBool_kFalse )
, mSpace_HaveDoneAutoIDs( morkBool_kFalse )
, mSpace_CanDirty( morkBool_kFalse ) // only when store can be dirtied
{
if ( ev->Good() )
{
if ( ioStore && ioSlotHeap )
{
morkStore::SlotWeakStore(ioStore, ev, &mSpace_Store);
mSpace_CanDirty = ioStore->mStore_CanDirty;
if ( mSpace_CanDirty ) // this new space dirties the store?
this->MaybeDirtyStoreAndSpace();
if ( ev->Good() )
mNode_Derived = morkDerived_kSpace;
}
else
ev->NilPointerError();
}
}
/*public non-poly*/ void
morkSpace::CloseSpace(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
morkStore::SlotWeakStore((morkStore*) 0, ev, &mSpace_Store);
mSpace_Scope = 0;
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
/*static*/ void
morkSpace::NonAsciiSpaceScopeName(morkEnv* ev)
{
ev->NewError("mSpace_Scope > 0x7F");
}
/*static*/ void
morkSpace::NilSpaceStoreError(morkEnv* ev)
{
ev->NewError("nil mSpace_Store");
}
morkPool* morkSpace::GetSpaceStorePool() const
{
return &mSpace_Store->mStore_Pool;
}
mork_bool morkSpace::MaybeDirtyStoreAndSpace()
{
morkStore* store = mSpace_Store;
if ( store && store->mStore_CanDirty )
{
store->SetStoreDirty();
mSpace_CanDirty = morkBool_kTrue;
}
if ( mSpace_CanDirty )
{
this->SetSpaceDirty();
return morkBool_kTrue;
}
return morkBool_kFalse;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,114 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKSPACE_
#define _MORKSPACE_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkSpace_kInitialSpaceSlots /*i*/ 1024 /* default */
#define morkDerived_kSpace /*i*/ 0x5370 /* ascii 'Sp' */
/*| morkSpace:
|*/
class morkSpace : public morkNode { //
// public: // slots inherited from morkNode (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
public: // state is public because the entire Mork system is private
morkStore* mSpace_Store; // weak ref to containing store
mork_scope mSpace_Scope; // the scope for this space
mork_bool mSpace_DoAutoIDs; // whether db should assign member IDs
mork_bool mSpace_HaveDoneAutoIDs; // whether actually auto assigned IDs
mork_bool mSpace_CanDirty; // changes imply the store becomes dirty?
mork_u1 mSpace_Pad; // pad to u4 alignment
public: // more specific dirty methods for space:
void SetSpaceDirty() { this->SetNodeDirty(); }
void SetSpaceClean() { this->SetNodeClean(); }
mork_bool IsSpaceClean() const { return this->IsNodeClean(); }
mork_bool IsSpaceDirty() const { return this->IsNodeDirty(); }
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseSpace() only if open
virtual ~morkSpace(); // assert that CloseSpace() executed earlier
public: // morkMap construction & destruction
//morkSpace(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioNodeHeap,
// const morkMapForm& inForm, nsIMdbHeap* ioSlotHeap);
morkSpace(morkEnv* ev, const morkUsage& inUsage,mork_scope inScope,
morkStore* ioStore, nsIMdbHeap* ioNodeHeap, nsIMdbHeap* ioSlotHeap);
void CloseSpace(morkEnv* ev); // called by CloseMorkNode();
public: // dynamic type identification
mork_bool IsSpace() const
{ return IsNode() && mNode_Derived == morkDerived_kSpace; }
// } ===== end morkNode methods =====
public: // other space methods
mork_bool MaybeDirtyStoreAndSpace();
static void NonAsciiSpaceScopeName(morkEnv* ev);
static void NilSpaceStoreError(morkEnv* ev);
morkPool* GetSpaceStorePool() const;
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakSpace(morkSpace* me,
morkEnv* ev, morkSpace** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongSpace(morkSpace* me,
morkEnv* ev, morkSpace** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKSPACE_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,394 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKSTORE_
#define _MORKSTORE_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKOBJECT_
#include "morkObject.h"
#endif
#ifndef _MORKNODEMAP_
#include "morkNodeMap.h"
#endif
#ifndef _MORKPOOL_
#include "morkPool.h"
#endif
#ifndef _MORKATOM_
#include "morkAtom.h"
#endif
#ifndef _MORKROWSPACE_
#include "morkRowSpace.h"
#endif
#ifndef _MORKATOMSPACE_
#include "morkAtomSpace.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kPort /*i*/ 0x7054 /* ascii 'pT' */
/*| morkPort:
|*/
class morkPort : public morkObject { // private mork port
// public: // slots inherited from morkObject (meant to inform only)
// nsIMdbHeap* mNode_Heap;
// mork_able mNode_Mutable; // can this node be modified?
// mork_load mNode_Load; // is this node clean or dirty?
// 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_uses mNode_Uses; // refcount for strong refs
// mork_refs mNode_Refs; // refcount for strong refs + weak refs
// morkHandle* mObject_Handle; // weak ref to handle for this object
public: // state is public because the entire Mork system is private
morkEnv* mPort_Env; // non-refcounted env which created port
morkFactory* mPort_Factory; // weak ref to suite factory
nsIMdbHeap* mPort_Heap; // heap in which this port allocs objects
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // ClosePort() only if open
virtual ~morkPort(); // assert that ClosePort() executed earlier
public: // morkPort construction & destruction
morkPort(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioNodeHeap, // the heap (if any) for this node instance
morkFactory* inFactory, // the factory for this
nsIMdbHeap* ioPortHeap // the heap to hold all content in the port
);
void ClosePort(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkPort(const morkPort& other);
morkPort& operator=(const morkPort& other);
public: // dynamic type identification
mork_bool IsPort() const
{ return IsNode() && mNode_Derived == morkDerived_kPort; }
// } ===== end morkNode methods =====
public: // other port methods
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakPort(morkPort* me,
morkEnv* ev, morkPort** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongPort(morkPort* me,
morkEnv* ev, morkPort** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
#define morkDerived_kStore /*i*/ 0x7354 /* ascii 'sT' */
/*| kGroundColumnSpace: we use the 'column space' as the default scope
**| for grounding column name IDs, and this is also the default scope for
**| all other explicitly tokenized strings.
|*/
#define morkStore_kGroundColumnSpace 'c' /* for mStore_GroundColumnSpace*/
#define morkStore_kColumnSpaceScope ((mork_scope) 'c') /*kGroundColumnSpace*/
#define morkStore_kValueSpaceScope ((mork_scope) 'v')
#define morkStore_kStreamBufSize (8 * 1024) /* okay buffer size */
#define morkStore_kReservedColumnCount 0x20 /* for well-known columns */
#define morkStore_kNoneToken ((mork_token) 'n')
#define morkStore_kFormColumn ((mork_column) 'f')
#define morkStore_kAtomScopeColumn ((mork_column) 'a')
#define morkStore_kRowScopeColumn ((mork_column) 'r')
#define morkStore_kMetaScope ((mork_scope) 'm')
#define morkStore_kKindColumn ((mork_column) 'k')
#define morkStore_kStatusColumn ((mork_column) 's')
/*| morkStore:
|*/
class morkStore : public morkPort {
// public: // slots inherited from morkPort (meant to inform only)
// nsIMdbHeap* mNode_Heap;
// mork_able mNode_Mutable; // can this node be modified?
// mork_load mNode_Load; // is this node clean or dirty?
// 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_uses mNode_Uses; // refcount for strong refs
// mork_refs mNode_Refs; // refcount for strong refs + weak refs
// morkEnv* mPort_Env; // non-refcounted env which created port
// morkFactory* mPort_Factory; // weak ref to suite factory
// nsIMdbHeap* mPort_Heap; // heap in which this port allocs objects
public: // state is public because the entire Mork system is private
// mStore_OidAtomSpace might be unnecessary; I don't remember why I wanted it.
morkAtomSpace* mStore_OidAtomSpace; // ground atom space for oids
morkAtomSpace* mStore_GroundAtomSpace; // ground atom space for scopes
morkAtomSpace* mStore_GroundColumnSpace; // ground column space for scopes
morkFile* mStore_File; // the file containing Mork text
morkStream* mStore_InStream; // stream using file used by the builder
morkBuilder* mStore_Builder; // to parse Mork text and build structures
morkStream* mStore_OutStream; // stream using file used by the writer
morkRowSpaceMap mStore_RowSpaces; // maps mork_scope -> morkSpace
morkAtomSpaceMap mStore_AtomSpaces; // maps mork_scope -> morkSpace
morkPool mStore_Pool;
// we alloc a max size book atom to reuse space for atom map key searches:
morkMaxBookAtom mStore_BookAtom; // staging area for atom map searches
// GroupIdentity should be one more than largest seen in a parsed db file:
mork_gid mStore_CommitGroupIdentity; // transaction ID number
// group positions are used to help compute PercentOfStoreWasted():
mork_pos mStore_FirstCommitGroupPos; // start of first group
mork_pos mStore_SecondCommitGroupPos; // start of second group
// If the first commit group is very near the start of the file (say less
// than 512 bytes), then we might assume the file started nearly empty and
// that most of the first group is not wasted. In that case, the pos of
// the second commit group might make a better estimate of the start of
// transaction space that might represent wasted file space. That's why
// we support fields for both first and second commit group positions.
//
// We assume that a zero in either group pos means that the slot has not
// yet been given a valid value, since the file will always start with a
// tag, and a commit group cannot actually start at position zero.
//
// Either or both the first or second commit group positions might be
// supplied by either morkWriter (while committing) or morkBuilder (while
// parsing), since either reading or writing the file might encounter the
// first transaction groups which came into existence either in the past
// or in the very recent present.
mork_bool mStore_CanAutoAssignAtomIdentity;
mork_bool mStore_CanDirty; // changes imply the store becomes dirty?
mork_u1 mStore_CanWriteIncremental; // compress not required?
mork_u1 mStore_Pad; // for u4 alignment
// mStore_CanDirty should be FALSE when parsing a file while building the
// content going into the store, because such data structure modifications
// are actuallly in sync with the file. So content read from a file must
// be clean with respect to the file. After a file is finished parsing,
// the mStore_CanDirty slot should become TRUE, so that any additional
// changes at runtime cause structures to be marked dirty with respect to
// the file which must later be updated with changes during a commit.
//
// It might also make sense to set mStore_CanDirty to FALSE while a commit
// is in progress, lest some internal transformations make more content
// appear dirty when it should not. So anyone modifying content during a
// commit should think about the intended significance regarding dirty.
public: // more specific dirty methods for store:
void SetStoreDirty() { this->SetNodeDirty(); }
void SetStoreClean() { this->SetNodeClean(); }
mork_bool IsStoreClean() const { return this->IsNodeClean(); }
mork_bool IsStoreDirty() const { return this->IsNodeDirty(); }
public: // setting dirty based on CanDirty:
void MaybeDirtyStore()
{ if ( mStore_CanDirty ) this->SetStoreDirty(); }
public: // space waste analysis
mork_percent PercentOfStoreWasted(morkEnv* ev);
public: // setting store and all subspaces canDirty:
void SetStoreAndAllSpacesCanDirty(morkEnv* ev, mork_bool inCanDirty);
public: // building an atom inside mStore_BookAtom from a char* string
morkMaxBookAtom* StageAliasAsBookAtom(morkEnv* ev,
const morkMid* inMid, morkAtomSpace* ioSpace, mork_cscode inForm);
morkMaxBookAtom* StageYarnAsBookAtom(morkEnv* ev,
const mdbYarn* inYarn, morkAtomSpace* ioSpace);
morkMaxBookAtom* StageStringAsBookAtom(morkEnv* ev,
const char* inString, mork_cscode inForm, morkAtomSpace* ioSpace);
// StageStringAsBookAtom() returns &mStore_BookAtom if inString is small
// enough, such that strlen(inString) < morkBookAtom_kMaxBodySize. And
// content inside mStore_BookAtom will be the valid atom format for
// inString. This method is the standard way to stage a string as an
// atom for searching or adding new atoms into an atom space hash table.
public: // lazy creation of members and nested row or atom spaces
morkAtomSpace* LazyGetOidAtomSpace(morkEnv* ev);
morkAtomSpace* LazyGetGroundAtomSpace(morkEnv* ev);
morkAtomSpace* LazyGetGroundColumnSpace(morkEnv* ev);
morkStream* LazyGetInStream(morkEnv* ev);
morkBuilder* LazyGetBuilder(morkEnv* ev);
void ForgetBuilder(morkEnv* ev);
morkStream* LazyGetOutStream(morkEnv* ev);
morkRowSpace* LazyGetRowSpace(morkEnv* ev, mdb_scope inRowScope);
morkAtomSpace* LazyGetAtomSpace(morkEnv* ev, mdb_scope inAtomScope);
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseStore() only if open
virtual ~morkStore(); // assert that CloseStore() executed earlier
public: // morkStore construction & destruction
morkStore(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioNodeHeap, // the heap (if any) for this node instance
morkFactory* inFactory, // the factory for this
nsIMdbHeap* ioPortHeap // the heap to hold all content in the port
);
void CloseStore(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkStore(const morkStore& other);
morkStore& operator=(const morkStore& other);
public: // dynamic type identification
mork_bool IsStore() const
{ return IsNode() && mNode_Derived == morkDerived_kStore; }
// } ===== end morkNode methods =====
public: // typing
static void NonStoreTypeError(morkEnv* ev);
static void NilStoreFileError(morkEnv* ev);
static void CannotAutoAssignAtomIdentityError(morkEnv* ev);
public: // store utilties
morkAtom* YarnToAtom(morkEnv* ev, const mdbYarn* inYarn);
morkAtom* AddAlias(morkEnv* ev, const morkMid& inMid,
mork_cscode inForm);
public: // other store methods
void RenumberAllCollectableContent(morkEnv* ev);
nsIMdbStore* AcquireStoreHandle(morkEnv* ev); // mObject_Handle
morkPool* StorePool() { return &mStore_Pool; }
mork_bool OpenStoreFile(morkEnv* ev, // return value equals ev->Good()
mork_bool inFrozen,
const char* inFilePath,
const mdbOpenPolicy* inOpenPolicy);
mork_bool CreateStoreFile(morkEnv* ev, // return value equals ev->Good()
const char* inFilePath,
const mdbOpenPolicy* inOpenPolicy);
morkAtom* CopyAtom(morkEnv* ev, const morkAtom* inAtom);
// copy inAtom (from some other store) over to this store
mork_token CopyToken(morkEnv* ev, mdb_token inToken, morkStore* inStore);
// copy inToken from inStore over to this store
mork_token BufToToken(morkEnv* ev, const morkBuf* inBuf);
mork_token StringToToken(morkEnv* ev, const char* inTokenName);
mork_token QueryToken(morkEnv* ev, const char* inTokenName);
void TokenToString(morkEnv* ev, mdb_token inToken, mdbYarn* outTokenName);
mork_bool MidToOid(morkEnv* ev, const morkMid& inMid,
mdbOid* outOid);
mork_bool OidToYarn(morkEnv* ev, const mdbOid& inOid, mdbYarn* outYarn);
mork_bool MidToYarn(morkEnv* ev, const morkMid& inMid,
mdbYarn* outYarn);
morkBookAtom* MidToAtom(morkEnv* ev, const morkMid& inMid);
morkRow* MidToRow(morkEnv* ev, const morkMid& inMid);
morkTable* MidToTable(morkEnv* ev, const morkMid& inMid);
morkRow* OidToRow(morkEnv* ev, const mdbOid* inOid);
// OidToRow() finds old row with oid, or makes new one if not found.
morkTable* OidToTable(morkEnv* ev, const mdbOid* inOid,
const mdbOid* inOptionalMetaRowOid);
// OidToTable() finds old table with oid, or makes new one if not found.
static void SmallTokenToOneByteYarn(morkEnv* ev, mdb_token inToken,
mdbYarn* outYarn);
mork_bool HasTableKind(morkEnv* ev, mdb_scope inRowScope,
mdb_kind inTableKind, mdb_count* outTableCount);
morkTable* GetTableKind(morkEnv* ev, mdb_scope inRowScope,
mdb_kind inTableKind, mdb_count* outTableCount,
mdb_bool* outMustBeUnique);
morkRow* FindRow(morkEnv* ev, mdb_scope inScope, mdb_column inColumn,
const mdbYarn* inTargetCellValue);
morkRow* GetRow(morkEnv* ev, const mdbOid* inOid);
morkTable* GetTable(morkEnv* ev, const mdbOid* inOid);
morkTable* NewTable(morkEnv* ev, mdb_scope inRowScope,
mdb_kind inTableKind, mdb_bool inMustBeUnique,
const mdbOid* inOptionalMetaRowOid);
morkPortTableCursor* GetPortTableCursor(morkEnv* ev, mdb_scope inRowScope,
mdb_kind inTableKind) ;
morkRow* NewRowWithOid(morkEnv* ev, const mdbOid* inOid);
morkRow* NewRow(morkEnv* ev, mdb_scope inRowScope);
morkThumb* MakeCompressCommitThumb(morkEnv* ev, mork_bool inDoCollect);
public: // commit related methods
mork_bool MarkAllStoreContentDirty(morkEnv* ev);
// MarkAllStoreContentDirty() visits every object in the store and marks
// them dirty, including every table, row, cell, and atom. The return
// equals ev->Good(), to show whether any error happened. This method is
// intended for use in the beginning of a "compress commit" which writes
// all store content, whether dirty or not. We dirty everything first so
// that later iterations over content can mark things clean as they are
// written, and organize the process of serialization so that objects are
// written only at need (because of being dirty).
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakStore(morkStore* me,
morkEnv* ev, morkStore** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongStore(morkStore* me,
morkEnv* ev, morkStore** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKSTORE_ */

View File

@@ -1,878 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKFILE_
#include "morkFile.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKSTREAM_
#include "morkStream.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkStream::CloseMorkNode(morkEnv* ev) // CloseStream() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseStream(ev);
this->MarkShut();
}
}
/*public virtual*/
morkStream::~morkStream() // assert CloseStream() executed earlier
{
MORK_ASSERT(mStream_ContentFile==0);
MORK_ASSERT(mStream_Buf==0);
}
/*public non-poly*/
morkStream::morkStream(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap,
morkFile* ioContentFile, mork_size inBufSize, mork_bool inFrozen)
: morkFile(ev, inUsage, ioHeap, ioHeap)
, mStream_At( 0 )
, mStream_ReadEnd( 0 )
, mStream_WriteEnd( 0 )
, mStream_ContentFile( 0 )
, mStream_Buf( 0 )
, mStream_BufSize( inBufSize )
, mStream_BufPos( 0 )
, mStream_Dirty( morkBool_kFalse )
, mStream_HitEof( morkBool_kFalse )
{
if ( ev->Good() )
{
if ( inBufSize < morkStream_kMinBufSize )
mStream_BufSize = inBufSize = morkStream_kMinBufSize;
else if ( inBufSize > morkStream_kMaxBufSize )
mStream_BufSize = inBufSize = morkStream_kMaxBufSize;
if ( ioContentFile && ioHeap )
{
if ( ioContentFile->FileFrozen() ) // forced to be readonly?
inFrozen = morkBool_kTrue; // override the input value
mork_pos fileEnd = ioContentFile->Length(ev);
morkFile::SlotStrongFile(ioContentFile, ev, &mStream_ContentFile);
if ( ev->Good() )
{
mork_u1* buf = 0;
ioHeap->Alloc(ev->AsMdbEnv(), inBufSize, (void**) &buf);
if ( buf )
{
mStream_At = mStream_Buf = buf;
if ( !inFrozen )
{
// physical buffer end never moves:
mStream_WriteEnd = buf + inBufSize;
}
else
mStream_WriteEnd = 0; // no writing is allowed
if ( inFrozen )
{
// logical buffer end starts at Buf with no content:
mStream_ReadEnd = buf;
this->SetFileFrozen(inFrozen);
}
else
mStream_ReadEnd = 0; // no reading is allowed
this->SetFileActive(morkBool_kTrue);
this->SetFileIoOpen(morkBool_kTrue);
}
if ( ev->Good() )
mNode_Derived = morkDerived_kStream;
}
}
else ev->NilPointerError();
}
}
/*public non-poly*/ void
morkStream::CloseStream(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
morkFile::SlotStrongFile((morkFile*) 0, ev, &mStream_ContentFile);
nsIMdbHeap* heap = mFile_SlotHeap;
mork_u1* buf = mStream_Buf;
mStream_Buf = 0;
if ( heap && buf )
heap->Free(ev->AsMdbEnv(), buf);
this->CloseFile(ev);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
#define morkStream_kSpacesPerIndent 1 /* one space per indent */
#define morkStream_kMaxIndentDepth 70 /* max indent of 70 space bytes */
static const char* morkStream_kSpaces // next line to ease length perception
= " ";
// 123456789_123456789_123456789_123456789_123456789_123456789_123456789_
// morkStream_kSpaces above must contain (at least) 70 spaces (ASCII 0x20)
mork_size
morkStream::PutIndent(morkEnv* ev, mork_count inDepth)
// PutIndent() puts a linebreak, and then
// "indents" by inDepth, and returns the line length after indentation.
{
mork_size outLength = 0;
if ( ev->Good() )
{
this->PutLineBreak(ev);
if ( ev->Good() )
{
outLength = inDepth;
if ( inDepth )
this->Write(ev, morkStream_kSpaces, inDepth);
}
}
return outLength;
}
mork_size
morkStream::PutByteThenIndent(morkEnv* ev, int inByte, mork_count inDepth)
// PutByteThenIndent() puts the byte, then a linebreak, and then
// "indents" by inDepth, and returns the line length after indentation.
{
mork_size outLength = 0;
if ( inDepth > morkStream_kMaxIndentDepth )
inDepth = morkStream_kMaxIndentDepth;
this->Putc(ev, inByte);
if ( ev->Good() )
{
this->PutLineBreak(ev);
if ( ev->Good() )
{
outLength = inDepth;
if ( inDepth )
this->Write(ev, morkStream_kSpaces, inDepth);
}
}
return outLength;
}
mork_size
morkStream::PutStringThenIndent(morkEnv* ev,
const char* inString, mork_count inDepth)
// PutStringThenIndent() puts the string, then a linebreak, and then
// "indents" by inDepth, and returns the line length after indentation.
{
mork_size outLength = 0;
if ( inDepth > morkStream_kMaxIndentDepth )
inDepth = morkStream_kMaxIndentDepth;
if ( inString )
{
mork_size length = MORK_STRLEN(inString);
if ( length && ev->Good() ) // any bytes to write?
this->Write(ev, inString, length);
}
if ( ev->Good() )
{
this->PutLineBreak(ev);
if ( ev->Good() )
{
outLength = inDepth;
if ( inDepth )
this->Write(ev, morkStream_kSpaces, inDepth);
}
}
return outLength;
}
mork_size
morkStream::PutString(morkEnv* ev, const char* inString)
{
mork_size outSize = 0;
if ( inString )
{
outSize = MORK_STRLEN(inString);
if ( outSize && ev->Good() ) // any bytes to write?
{
this->Write(ev, inString, outSize);
}
}
return outSize;
}
mork_size
morkStream::PutStringThenNewline(morkEnv* ev, const char* inString)
// PutStringThenNewline() returns total number of bytes written.
{
mork_size outSize = 0;
if ( inString )
{
outSize = MORK_STRLEN(inString);
if ( outSize && ev->Good() ) // any bytes to write?
{
this->Write(ev, inString, outSize);
if ( ev->Good() )
outSize += this->PutLineBreak(ev);
}
}
return outSize;
}
mork_size
morkStream::PutStringThenNewlineThenSpace(morkEnv* ev, const char* inString)
// PutStringThenNewlineThenSpace() returns total number of bytes written.
{
mork_size outSize = 0;
if ( inString )
{
outSize = MORK_STRLEN(inString);
if ( outSize && ev->Good() ) // any bytes to write?
{
this->Write(ev, inString, outSize);
if ( ev->Good() )
{
outSize += this->PutLineBreak(ev);
if ( ev->Good() )
{
this->Putc(ev, ' ');
++outSize;
}
}
}
}
return outSize;
}
mork_size
morkStream::PutByteThenNewline(morkEnv* ev, int inByte)
// PutByteThenNewline() returns total number of bytes written.
{
mork_size outSize = 1; // one for the following byte
this->Putc(ev, inByte);
if ( ev->Good() )
outSize += this->PutLineBreak(ev);
return outSize;
}
mork_size
morkStream::PutByteThenNewlineThenSpace(morkEnv* ev, int inByte)
// PutByteThenNewlineThenSpace() returns total number of bytes written.
{
mork_size outSize = 1; // one for the following byte
this->Putc(ev, inByte);
if ( ev->Good() )
{
outSize += this->PutLineBreak(ev);
if ( ev->Good() )
{
this->Putc(ev, ' ');
++outSize;
}
}
return outSize;
}
mork_size
morkStream::PutLineBreak(morkEnv* ev)
{
#if defined(MORK_MAC) || defined(MORK_OBSOLETE)
this->Putc(ev, mork_kCR);
return 1;
#else
# if defined(MORK_WIN) || defined(MORK_OS2)
this->Putc(ev, mork_kCR);
this->Putc(ev, mork_kLF);
return 2;
# else
# ifdef MORK_UNIX
this->Putc(ev, mork_kLF);
return 1;
# endif /* MORK_UNIX */
# endif /* MORK_WIN */
#endif /* MORK_MAC */
}
// ````` ````` ````` ````` ````` ````` ````` `````
// public: // virtual morkFile methods
/*public virtual*/ void
morkStream::Steal(morkEnv* ev, nsIMdbFile* ioThief)
// Steal: tell this file to close any associated i/o stream in the file
// system, because the file ioThief intends to reopen the file in order
// to provide the MDB implementation with more exotic file access than is
// offered by the nsIMdbFile alone. Presumably the thief knows enough
// from Path() in order to know which file to reopen. If Steal() is
// successful, this file should probably delegate all future calls to
// the nsIMdbFile interface down to the thief files, so that even after
// the file has been stolen, it can still be read, written, or forcibly
// closed (by a call to CloseMdbObject()).
{
MORK_USED_1(ioThief);
ev->StubMethodOnlyError();
}
/*public virtual*/ void
morkStream::BecomeTrunk(morkEnv* ev)
// If this file is a file version branch created by calling AcquireBud(),
// BecomeTrunk() causes this file's content to replace the original
// file's content, typically by assuming the original file's identity.
{
ev->StubMethodOnlyError();
}
/*public virtual*/ morkFile*
morkStream::AcquireBud(morkEnv* ev, nsIMdbHeap* ioHeap)
// AcquireBud() starts a new "branch" version of the file, empty of content,
// so that a new version of the file can be written. This new file
// can later be told to BecomeTrunk() the original file, so the branch
// created by budding the file will replace the original file. Some
// file subclasses might initially take the unsafe but expedient
// approach of simply truncating this file down to zero length, and
// then returning the same morkFile pointer as this, with an extra
// reference count increment. Note that the caller of AcquireBud() is
// expected to eventually call CutStrongRef() on the returned file
// in order to release the strong reference. High quality versions
// of morkFile subclasses will create entirely new files which later
// are renamed to become the old file, so that better transactional
// behavior is exhibited by the file, so crashes protect old files.
// Note that AcquireBud() is an illegal operation on readonly files.
{
MORK_USED_1(ioHeap);
morkFile* outFile = 0;
morkFile* file = mStream_ContentFile;
if ( this->IsOpenAndActiveFile() && file )
{
// figure out how this interacts with buffering and mStream_WriteEnd:
ev->StubMethodOnlyError();
}
else this->NewFileDownError(ev);
return outFile;
}
/*public virtual*/ mork_pos
morkStream::Length(morkEnv* ev) const // eof
{
mork_pos outPos = 0;
morkFile* file = mStream_ContentFile;
if ( this->IsOpenAndActiveFile() && file )
{
mork_pos contentEof = file->Length(ev);
if ( mStream_WriteEnd ) // this stream supports writing?
{
// the local buffer might have buffered content past content eof
if ( ev->Good() ) // no error happened during Length() above?
{
mork_u1* at = mStream_At;
mork_u1* buf = mStream_Buf;
if ( at >= buf ) // expected cursor order?
{
mork_pos localContent = mStream_BufPos + (at - buf);
if ( localContent > contentEof ) // buffered past eof?
contentEof = localContent; // return new logical eof
outPos = contentEof;
}
else this->NewBadCursorOrderError(ev);
}
}
else
outPos = contentEof; // frozen files get length from content file
}
else this->NewFileDownError(ev);
return outPos;
}
void morkStream::NewBadCursorSlotsError(morkEnv* ev) const
{ ev->NewError("bad stream cursor slots"); }
void morkStream::NewNullStreamBufferError(morkEnv* ev) const
{ ev->NewError("null stream buffer"); }
void morkStream::NewCantReadSinkError(morkEnv* ev) const
{ ev->NewError("cant read stream sink"); }
void morkStream::NewCantWriteSourceError(morkEnv* ev) const
{ ev->NewError("cant write stream source"); }
void morkStream::NewPosBeyondEofError(morkEnv* ev) const
{ ev->NewError("stream pos beyond eof"); }
void morkStream::NewBadCursorOrderError(morkEnv* ev) const
{ ev->NewError("bad stream cursor order"); }
/*public virtual*/ mork_pos
morkStream::Tell(morkEnv* ev) const
{
mork_pos outPos = 0;
morkFile* file = mStream_ContentFile;
if ( this->IsOpenAndActiveFile() && file )
{
mork_u1* buf = mStream_Buf;
mork_u1* at = mStream_At;
mork_u1* readEnd = mStream_ReadEnd; // nonzero only if readonly
mork_u1* writeEnd = mStream_WriteEnd; // nonzero only if writeonly
if ( writeEnd )
{
if ( buf && at >= buf && at <= writeEnd )
{
outPos = mStream_BufPos + (at - buf);
}
else this->NewBadCursorOrderError(ev);
}
else if ( readEnd )
{
if ( buf && at >= buf && at <= readEnd )
{
outPos = mStream_BufPos + (at - buf);
}
else this->NewBadCursorOrderError(ev);
}
}
else this->NewFileDownError(ev);
return outPos;
}
/*public virtual*/ mork_size
morkStream::Read(morkEnv* ev, void* outBuf, mork_size inSize)
{
// First we satisfy the request from buffered bytes, if any. Then
// if additional bytes are needed, we satisfy these by direct reads
// from the content file without any local buffering (but we still need
// to adjust the buffer position to reflect the current i/o point).
mork_pos outActual = 0;
morkFile* file = mStream_ContentFile;
if ( this->IsOpenAndActiveFile() && file )
{
mork_u1* end = mStream_ReadEnd; // byte after last buffered byte
if ( end ) // file is open for read access?
{
if ( inSize ) // caller wants any output?
{
mork_u1* sink = (mork_u1*) outBuf; // where we plan to write bytes
if ( sink ) // caller passed good buffer address?
{
mork_u1* at = mStream_At;
mork_u1* buf = mStream_Buf;
if ( at >= buf && at <= end ) // expected cursor order?
{
mork_num remaining = (mork_num) (end - at); // bytes left in buffer
mork_num quantum = inSize; // number of bytes to copy
if ( quantum > remaining ) // more than buffer content?
quantum = remaining; // restrict to buffered bytes
if ( quantum ) // any bytes left in the buffer?
{
MORK_MEMCPY(sink, at, quantum); // from buffer bytes
at += quantum; // advance past read bytes
mStream_At = at;
outActual += quantum; // this much copied so far
sink += quantum; // in case we need to copy more
inSize -= quantum; // filled this much of request
mStream_HitEof = morkBool_kFalse;
}
if ( inSize ) // we still need to read more content?
{
// We need to read more bytes directly from the
// content file, without local buffering. We have
// exhausted the local buffer, so we need to show
// it is now empty, and adjust the current buf pos.
mork_num posDelta = (mork_num) (at - buf); // old buf content
mStream_BufPos += posDelta; // past now empty buf
mStream_At = mStream_ReadEnd = buf; // empty buffer
file->Seek(ev, mStream_BufPos); // set file pos
if ( ev->Good() ) // no seek error?
{
mork_num actual = file->Read(ev, sink, inSize);
if ( ev->Good() ) // no read error?
{
if ( actual )
{
outActual += actual;
mStream_BufPos += actual;
mStream_HitEof = morkBool_kFalse;
}
else if ( !outActual )
mStream_HitEof = morkBool_kTrue;
}
}
}
}
else this->NewBadCursorOrderError(ev);
}
else this->NewNullStreamBufferError(ev);
}
}
else this->NewCantReadSinkError(ev);
}
else this->NewFileDownError(ev);
if ( ev->Bad() )
outActual = 0;
return (mork_size) outActual;
}
/*public virtual*/ mork_pos
morkStream::Seek(morkEnv* ev, mork_pos inPos)
{
mork_pos outPos = 0;
morkFile* file = mStream_ContentFile;
if ( this->IsOpenOrClosingNode() && this->FileActive() && file )
{
mork_u1* at = mStream_At; // current position in buffer
mork_u1* buf = mStream_Buf; // beginning of buffer
mork_u1* readEnd = mStream_ReadEnd; // nonzero only if readonly
mork_u1* writeEnd = mStream_WriteEnd; // nonzero only if writeonly
if ( writeEnd ) // file is mutable/writeonly?
{
if ( mStream_Dirty ) // need to commit buffer changes?
this->Flush(ev);
if ( ev->Good() ) // no errors during flush or earlier?
{
if ( at == buf ) // expected post flush cursor value?
{
if ( mStream_BufPos != inPos ) // need to change pos?
{
mork_pos eof = file->Length(ev);
if ( ev->Good() ) // no errors getting length?
{
if ( inPos <= eof ) // acceptable new position?
{
mStream_BufPos = inPos; // new stream position
outPos = inPos;
}
else this->NewPosBeyondEofError(ev);
}
}
}
else this->NewBadCursorOrderError(ev);
}
}
else if ( readEnd ) // file is frozen/readonly?
{
if ( at >= buf && at <= readEnd ) // expected cursor order?
{
mork_pos eof = file->Length(ev);
if ( ev->Good() ) // no errors getting length?
{
if ( inPos <= eof ) // acceptable new position?
{
outPos = inPos;
mStream_BufPos = inPos; // new stream position
mStream_At = mStream_ReadEnd = buf; // empty buffer
if ( inPos == eof ) // notice eof reached?
mStream_HitEof = morkBool_kTrue;
}
else this->NewPosBeyondEofError(ev);
}
}
else this->NewBadCursorOrderError(ev);
}
}
else this->NewFileDownError(ev);
return outPos;
}
/*public virtual*/ mork_size
morkStream::Write(morkEnv* ev, const void* inBuf, mork_size inSize)
{
mork_num outActual = 0;
morkFile* file = mStream_ContentFile;
if ( this->IsOpenActiveAndMutableFile() && file )
{
mork_u1* end = mStream_WriteEnd; // byte after last buffered byte
if ( end ) // file is open for write access?
{
if ( inSize ) // caller provided any input?
{
const mork_u1* source = (const mork_u1*) inBuf; // from where
if ( source ) // caller passed good buffer address?
{
mork_u1* at = mStream_At;
mork_u1* buf = mStream_Buf;
if ( at >= buf && at <= end ) // expected cursor order?
{
mork_num space = (mork_num) (end - at); // space left in buffer
mork_num quantum = inSize; // number of bytes to write
if ( quantum > space ) // more than buffer size?
quantum = space; // restrict to avail space
if ( quantum ) // any space left in the buffer?
{
mStream_Dirty = morkBool_kTrue; // to ensure later flush
MORK_MEMCPY(at, source, quantum); // into buffer
mStream_At += quantum; // advance past written bytes
outActual += quantum; // this much written so far
source += quantum; // in case we need to write more
inSize -= quantum; // filled this much of request
}
if ( inSize ) // we still need to write more content?
{
// We need to write more bytes directly to the
// content file, without local buffering. We have
// exhausted the local buffer, so we need to flush
// it and empty it, and adjust the current buf pos.
// After flushing, if the rest of the write fits
// inside the buffer, we will put bytes into the
// buffer rather than write them to content file.
if ( mStream_Dirty )
this->Flush(ev); // will update mStream_BufPos
at = mStream_At;
if ( at < buf || at > end ) // bad cursor?
this->NewBadCursorOrderError(ev);
if ( ev->Good() ) // no errors?
{
space = (mork_num) (end - at); // space left in buffer
if ( space > inSize ) // write to buffer?
{
mStream_Dirty = morkBool_kTrue; // ensure flush
MORK_MEMCPY(at, source, inSize); // copy
mStream_At += inSize; // past written bytes
outActual += inSize; // this much written
}
else // directly to content file instead
{
file->Seek(ev, mStream_BufPos); // set pos
if ( ev->Good() ) // no seek error?
{
mork_num actual =
file->Write(ev, source, inSize);
if ( ev->Good() ) // no write error?
{
outActual += actual;
mStream_BufPos += actual;
}
}
}
}
}
}
else this->NewBadCursorOrderError(ev);
}
else this->NewNullStreamBufferError(ev);
}
}
else this->NewCantWriteSourceError(ev);
}
else this->NewFileDownError(ev);
if ( ev->Bad() )
outActual = 0;
return outActual;
}
/*public virtual*/ void
morkStream::Flush(morkEnv* ev)
{
morkFile* file = mStream_ContentFile;
if ( this->IsOpenOrClosingNode() && this->FileActive() && file )
{
if ( mStream_Dirty )
this->spill_buf(ev);
file->Flush(ev);
}
else this->NewFileDownError(ev);
}
// ````` ````` ````` ````` ````` ````` ````` `````
// protected: // protected non-poly morkStream methods (for char io)
int
morkStream::fill_getc(morkEnv* ev)
{
int c = EOF;
morkFile* file = mStream_ContentFile;
if ( this->IsOpenAndActiveFile() && file )
{
mork_u1* buf = mStream_Buf;
mork_u1* end = mStream_ReadEnd; // beyond buf after earlier read
if ( end > buf ) // any earlier read bytes buffered?
{
mStream_BufPos += ( end - buf ); // advance past old read
}
if ( ev->Good() ) // no errors yet?
{
file->Seek(ev, mStream_BufPos); // set file pos
if ( ev->Good() ) // no seek error?
{
mork_num actual = file->Read(ev, buf, mStream_BufSize);
if ( ev->Good() ) // no read errors?
{
if ( actual > mStream_BufSize ) // more than asked for??
actual = mStream_BufSize;
mStream_At = buf;
mStream_ReadEnd = buf + actual;
if ( actual ) // any bytes actually read?
{
c = *mStream_At++; // return first byte from buffer
mStream_HitEof = morkBool_kFalse;
}
else
mStream_HitEof = morkBool_kTrue;
}
}
}
}
else this->NewFileDownError(ev);
return c;
}
void
morkStream::spill_putc(morkEnv* ev, int c)
{
this->spill_buf(ev);
if ( ev->Good() && mStream_At < mStream_WriteEnd )
this->Putc(ev, c);
}
void
morkStream::spill_buf(morkEnv* ev) // spill/flush from buffer to file
{
morkFile* file = mStream_ContentFile;
if ( this->IsOpenOrClosingNode() && this->FileActive() && file )
{
mork_u1* buf = mStream_Buf;
if ( mStream_Dirty )
{
mork_u1* at = mStream_At;
if ( at >= buf && at <= mStream_WriteEnd ) // order?
{
mork_num count = (mork_num) (at - buf); // bytes buffered
if ( count ) // anything to write to the string?
{
if ( count > mStream_BufSize ) // no more than max?
{
count = mStream_BufSize;
mStream_WriteEnd = buf + mStream_BufSize;
this->NewBadCursorSlotsError(ev);
}
if ( ev->Good() )
{
file->Seek(ev, mStream_BufPos);
if ( ev->Good() )
{
file->Write(ev, buf, count);
if ( ev->Good() )
{
mStream_BufPos += count; // past bytes written
mStream_At = buf; // reset buffer cursor
mStream_Dirty = morkBool_kFalse;
}
}
}
}
}
else this->NewBadCursorOrderError(ev);
}
else
{
#ifdef MORK_DEBUG
ev->NewWarning("stream:spill:not:dirty");
#endif /*MORK_DEBUG*/
}
}
else this->NewFileDownError(ev);
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,254 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKSTREAM_
#define _MORKSTREAM_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKFILE_
#include "morkFile.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/*=============================================================================
* morkStream: buffered file i/o
*/
/*| morkStream exists to define an morkFile subclass that provides buffered
**| i/o for an underlying content file. Naturally this arrangement only makes
**| sense when the underlying content file is itself not efficiently buffered
**| (especially for character by character i/o).
**|
**|| morkStream is intended for either reading use or writing use, but not
**| both simultaneously or interleaved. Pick one when the stream is created
**| and don't change your mind. This restriction is intended to avoid obscure
**| and complex bugs that might arise from interleaved reads and writes -- so
**| just don't do it. A stream is either a sink or a source, but not both.
**|
**|| (When the underlying content file is intended to support both reading and
**| writing, a developer might use two instances of morkStream where one is for
**| reading and the other is for writing. In this case, a developer must take
**| care to keep the two streams in sync because each will maintain a separate
**| buffer representing a cache consistency problem for the other. A simple
**| approach is to invalidate the buffer of one when one uses the other, with
**| the assumption that closely mixed reading and writing is not expected, so
**| that little cost is associated with changing read/write streaming modes.)
**|
**|| Exactly one of mStream_ReadEnd or mStream_WriteEnd must be a null pointer,
**| and this will cause the right thing to occur when inlines use them, because
**| mStream_At < mStream_WriteEnd (for example) will always be false and the
**| else branch of the statement calls a function that raises an appropriate
**| error to complain about either reading a sink or writing a source.
**|
**|| morkStream is a direct clone of ab_Stream from Communicator 4.5's
**| address book code, which in turn was based on the stream class in the
**| public domain Mithril programming language.
|*/
#define morkStream_kPrintBufSize /*i*/ 512 /* buffer size used by printf() */
#define morkStream_kMinBufSize /*i*/ 512 /* buffer no fewer bytes */
#define morkStream_kMaxBufSize /*i*/ (32 * 1024) /* buffer no more bytes */
#define morkDerived_kStream /*i*/ 0x7A74 /* ascii 'zt' */
class morkStream /*d*/ : public morkFile { /* from Mithril's AgStream class */
// ````` ````` ````` ````` ````` ````` ````` `````
protected: // protected morkStream members
mork_u1* mStream_At; // pointer into mStream_Buf
mork_u1* mStream_ReadEnd; // null or one byte past last readable byte
mork_u1* mStream_WriteEnd; // null or mStream_Buf + mStream_BufSize
morkFile* mStream_ContentFile; // where content is read and written
mork_u1* mStream_Buf; // dynamically allocated memory to buffer io
mork_size mStream_BufSize; // requested buf size (fixed by min and max)
mork_pos mStream_BufPos; // logical position of byte at mStream_Buf
mork_bool mStream_Dirty; // does the buffer need to be flushed?
mork_bool mStream_HitEof; // has eof been reached? (only frozen streams)
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseStream() only if open
virtual ~morkStream(); // assert that CloseStream() executed earlier
public: // morkStream construction & destruction
morkStream(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap,
morkFile* ioContentFile, mork_size inBufSize, mork_bool inFrozen);
void CloseStream(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkStream(const morkStream& other);
morkStream& operator=(const morkStream& other);
public: // dynamic type identification
mork_bool IsStream() const
{ return IsNode() && mNode_Derived == morkDerived_kStream; }
// } ===== end morkNode methods =====
public: // typing
void NonStreamTypeError(morkEnv* ev);
// ````` ````` ````` ````` ````` ````` ````` `````
public: // virtual morkFile methods
virtual void Steal(morkEnv* ev, nsIMdbFile* ioThief);
// Steal: tell this file to close any associated i/o stream in the file
// system, because the file ioThief intends to reopen the file in order
// to provide the MDB implementation with more exotic file access than is
// offered by the nsIMdbFile alone. Presumably the thief knows enough
// from Path() in order to know which file to reopen. If Steal() is
// successful, this file should probably delegate all future calls to
// the nsIMdbFile interface down to the thief files, so that even after
// the file has been stolen, it can still be read, written, or forcibly
// closed (by a call to CloseMdbObject()).
virtual void BecomeTrunk(morkEnv* ev);
// If this file is a file version branch created by calling AcquireBud(),
// BecomeTrunk() causes this file's content to replace the original
// file's content, typically by assuming the original file's identity.
virtual morkFile* AcquireBud(morkEnv* ev, nsIMdbHeap* ioHeap);
// AcquireBud() starts a new "branch" version of the file, empty of content,
// so that a new version of the file can be written. This new file
// can later be told to BecomeTrunk() the original file, so the branch
// created by budding the file will replace the original file. Some
// file subclasses might initially take the unsafe but expedient
// approach of simply truncating this file down to zero length, and
// then returning the same morkFile pointer as this, with an extra
// reference count increment. Note that the caller of AcquireBud() is
// expected to eventually call CutStrongRef() on the returned file
// in order to release the strong reference. High quality versions
// of morkFile subclasses will create entirely new files which later
// are renamed to become the old file, so that better transactional
// behavior is exhibited by the file, so crashes protect old files.
// Note that AcquireBud() is an illegal operation on readonly files.
virtual mork_pos Length(morkEnv* ev) const; // eof
virtual mork_pos Tell(morkEnv* ev) const;
virtual mork_size Read(morkEnv* ev, void* outBuf, mork_size inSize);
virtual mork_pos Seek(morkEnv* ev, mork_pos inPos);
virtual mork_size Write(morkEnv* ev, const void* inBuf, mork_size inSize);
virtual void Flush(morkEnv* ev);
// ````` ````` ````` ````` ````` ````` ````` `````
protected: // protected non-poly morkStream methods (for char io)
int fill_getc(morkEnv* ev);
void spill_putc(morkEnv* ev, int c);
void spill_buf(morkEnv* ev); // spill/flush from buffer to file
// ````` ````` ````` ````` ````` ````` ````` `````
public: // public non-poly morkStream methods
void NewBadCursorSlotsError(morkEnv* ev) const;
void NewBadCursorOrderError(morkEnv* ev) const;
void NewNullStreamBufferError(morkEnv* ev) const;
void NewCantReadSinkError(morkEnv* ev) const;
void NewCantWriteSourceError(morkEnv* ev) const;
void NewPosBeyondEofError(morkEnv* ev) const;
morkFile* GetStreamContentFile() const { return mStream_ContentFile; }
mork_size GetStreamBufferSize() const { return mStream_BufSize; }
mork_size PutIndent(morkEnv* ev, mork_count inDepth);
// PutIndent() puts a linebreak, and then
// "indents" by inDepth, and returns the line length after indentation.
mork_size PutByteThenIndent(morkEnv* ev, int inByte, mork_count inDepth);
// PutByteThenIndent() puts the byte, then a linebreak, and then
// "indents" by inDepth, and returns the line length after indentation.
mork_size PutStringThenIndent(morkEnv* ev,
const char* inString, mork_count inDepth);
// PutStringThenIndent() puts the string, then a linebreak, and then
// "indents" by inDepth, and returns the line length after indentation.
mork_size PutString(morkEnv* ev, const char* inString);
// PutString() returns the length of the string written.
mork_size PutStringThenNewline(morkEnv* ev, const char* inString);
// PutStringThenNewline() returns total number of bytes written.
mork_size PutStringThenNewlineThenSpace(morkEnv* ev, const char* inString);
// PutStringThenNewlineThenSpace() returns total number of bytes written.
mork_size PutByteThenNewline(morkEnv* ev, int inByte);
// PutByteThenNewline() returns total number of bytes written.
mork_size PutByteThenNewlineThenSpace(morkEnv* ev, int inByte);
// PutByteThenNewlineThenSpace() returns total number of bytes written.
// ````` ````` stdio type methods ````` `````
void Printf(morkEnv* ev, const char* inFormat, ...);
mork_pos Ftell(morkEnv* ev) /*i*/ { return this->Tell(ev); }
void Fsetpos(morkEnv* ev, mork_pos inPos) /*i*/ { this->Seek(ev, inPos); }
void Rewind(morkEnv* ev) /*i*/ { this->Fsetpos(ev, 0); }
void Fflush(morkEnv* ev) /*i*/ { this->Flush(ev); }
mork_bool Feof() /*i*/ { return mStream_HitEof; }
// Feof() is never true for writable stream output sinks
void Puts(morkEnv* ev, const char* inString) /*i*/
{ this->PutString(ev, inString); }
void Ungetc(int c) /*i*/
{ if ( mStream_At > mStream_Buf && c > 0 ) *--mStream_At = (mork_u1) c; }
// Note Getc() returns EOF consistently after any fill_getc() error occurs.
int Getc(morkEnv* ev) /*i*/
{ return ( mStream_At < mStream_ReadEnd )? *mStream_At++ : fill_getc(ev); }
void Putc(morkEnv* ev, int c) /*i*/
{
mStream_Dirty = morkBool_kTrue;
if ( mStream_At < mStream_WriteEnd )
*mStream_At++ = (mork_u1) c;
else
spill_putc(ev, c);
}
mork_size PutLineBreak(morkEnv* ev);
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakStream(morkStream* me,
morkEnv* ev, morkStream** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongStream(morkStream* me,
morkEnv* ev, morkStream** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKSTREAM_ */

View File

@@ -1,822 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKTABLE_
#include "morkTable.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
#ifndef _MORKROWSPACE_
#include "morkRowSpace.h"
#endif
#ifndef _MORKARRAY_
#include "morkArray.h"
#endif
#ifndef _MORKROW_
#include "morkRow.h"
#endif
#ifndef _ORKINTABLE_
#include "orkinTable.h"
#endif
#ifndef _MORKTABLEROWCURSOR_
#include "morkTableRowCursor.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkTable::CloseMorkNode(morkEnv* ev) /*i*/ // CloseTable() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseTable(ev);
this->MarkShut();
}
}
/*public virtual*/
morkTable::~morkTable() /*i*/ // assert CloseTable() executed earlier
{
MORK_ASSERT(this->IsShutNode());
MORK_ASSERT(mTable_Store==0);
MORK_ASSERT(mTable_RowSpace==0);
}
/*public non-poly*/
morkTable::morkTable(morkEnv* ev, /*i*/
const morkUsage& inUsage, nsIMdbHeap* ioHeap,
morkStore* ioStore, nsIMdbHeap* ioSlotHeap, morkRowSpace* ioRowSpace,
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
mork_tid inTid, mork_kind inKind, mork_bool inMustBeUnique)
: morkObject(ev, inUsage, ioHeap, (morkHandle*) 0)
, mTable_Store( 0 )
, mTable_RowSpace( 0 )
, mTable_MetaRow( 0 )
, mTable_RowMap( 0 )
// , mTable_RowMap(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioSlotHeap,
// morkTable_kStartRowMapSlotCount)
, mTable_RowArray(ev, morkUsage::kMember, (nsIMdbHeap*) 0,
morkTable_kStartRowArraySize, ioSlotHeap)
, mTable_ChangeList()
, mTable_ChangesCount( 0 )
, mTable_ChangesMax( 3 ) // any very small number greater than zero
, mTable_Id( inTid )
, mTable_Kind( inKind )
, mTable_Flags( 0 )
, mTable_Priority( morkPriority_kLo ) // NOT high priority
, mTable_GcUses( 0 )
, mTable_Pad( 0 )
{
this->mLink_Next = 0;
this->mLink_Prev = 0;
if ( ev->Good() )
{
if ( ioStore && ioSlotHeap && ioRowSpace )
{
if ( inKind )
{
if ( inMustBeUnique )
this->SetTableUnique();
morkStore::SlotWeakStore(ioStore, ev, &mTable_Store);
morkRowSpace::SlotWeakRowSpace(ioRowSpace, ev, &mTable_RowSpace);
if ( inOptionalMetaRowOid )
mTable_MetaRowOid = *inOptionalMetaRowOid;
else
{
mTable_MetaRowOid.mOid_Scope = 0;
mTable_MetaRowOid.mOid_Id = morkRow_kMinusOneRid;
}
if ( ev->Good() )
{
if ( this->MaybeDirtySpaceStoreAndTable() )
this->SetTableRewrite(); // everything is dirty
mNode_Derived = morkDerived_kTable;
}
this->MaybeDirtySpaceStoreAndTable(); // new table might dirty store
}
else
ioRowSpace->ZeroKindError(ev);
}
else
ev->NilPointerError();
}
}
/*public non-poly*/ void
morkTable::CloseTable(morkEnv* ev) /*i*/ // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
morkRowMap::SlotStrongRowMap((morkRowMap*) 0, ev, &mTable_RowMap);
// mTable_RowMap.CloseMorkNode(ev);
mTable_RowArray.CloseMorkNode(ev);
morkStore::SlotWeakStore((morkStore*) 0, ev, &mTable_Store);
morkRowSpace::SlotWeakRowSpace((morkRowSpace*) 0,
ev, &mTable_RowSpace);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
mork_u2
morkTable::AddTableGcUse(morkEnv* ev)
{
MORK_USED_1(ev);
if ( mTable_GcUses < morkTable_kMaxTableGcUses ) // not already maxed out?
++mTable_GcUses;
return mTable_GcUses;
}
mork_u2
morkTable::CutTableGcUse(morkEnv* ev)
{
if ( mTable_GcUses ) // any outstanding uses to cut?
{
if ( mTable_GcUses < morkTable_kMaxTableGcUses ) // not frozen at max?
--mTable_GcUses;
}
else
this->TableGcUsesUnderflowWarning(ev);
return mTable_GcUses;
}
// table dirty handling more complex thatn morkNode::SetNodeDirty() etc.
void morkTable::SetTableClean(morkEnv* ev)
{
if ( mTable_ChangeList.HasListMembers() )
{
nsIMdbHeap* heap = mTable_Store->mPort_Heap;
mTable_ChangeList.CutAndZapAllListMembers(ev, heap); // forget changes
}
mTable_ChangesCount = 0;
mTable_Flags = 0;
this->SetNodeClean();
}
// notifications regarding table changes:
void morkTable::NoteTableMoveRow(morkEnv* ev, morkRow* ioRow, mork_pos inPos)
{
nsIMdbHeap* heap = mTable_Store->mPort_Heap;
if ( this->IsTableRewrite() || this->HasChangeOverflow() )
this->NoteTableSetAll(ev);
else
{
morkTableChange* tableChange = new(*heap, ev)
morkTableChange(ev, ioRow, inPos);
if ( tableChange )
{
if ( ev->Good() )
{
mTable_ChangeList.PushTail(tableChange);
++mTable_ChangesCount;
}
else
{
tableChange->ZapOldNext(ev, heap);
this->SetTableRewrite(); // just plan to write all table rows
}
}
}
}
void morkTable::note_row_move(morkEnv* ev, morkRow* ioRow, mork_pos inNewPos)
{
if ( this->IsTableRewrite() || this->HasChangeOverflow() )
this->NoteTableSetAll(ev);
else
{
nsIMdbHeap* heap = mTable_Store->mPort_Heap;
morkTableChange* tableChange = new(*heap, ev)
morkTableChange(ev, ioRow, inNewPos);
if ( tableChange )
{
if ( ev->Good() )
{
mTable_ChangeList.PushTail(tableChange);
++mTable_ChangesCount;
}
else
{
tableChange->ZapOldNext(ev, heap);
this->NoteTableSetAll(ev);
}
}
}
}
void morkTable::note_row_change(morkEnv* ev, mork_change inChange,
morkRow* ioRow)
{
if ( this->IsTableRewrite() || this->HasChangeOverflow() )
this->NoteTableSetAll(ev);
else
{
nsIMdbHeap* heap = mTable_Store->mPort_Heap;
morkTableChange* tableChange = new(*heap, ev)
morkTableChange(ev, inChange, ioRow);
if ( tableChange )
{
if ( ev->Good() )
{
mTable_ChangeList.PushTail(tableChange);
++mTable_ChangesCount;
}
else
{
tableChange->ZapOldNext(ev, heap);
this->NoteTableSetAll(ev);
}
}
}
}
void morkTable::NoteTableSetAll(morkEnv* ev)
{
if ( mTable_ChangeList.HasListMembers() )
{
nsIMdbHeap* heap = mTable_Store->mPort_Heap;
mTable_ChangeList.CutAndZapAllListMembers(ev, heap); // forget changes
}
mTable_ChangesCount = 0;
this->SetTableRewrite();
}
/*static*/ void
morkTable::TableGcUsesUnderflowWarning(morkEnv* ev)
{
ev->NewWarning("mTable_GcUses underflow");
}
/*static*/ void
morkTable::NonTableTypeError(morkEnv* ev)
{
ev->NewError("non morkTable");
}
/*static*/ void
morkTable::NonTableTypeWarning(morkEnv* ev)
{
ev->NewWarning("non morkTable");
}
/*static*/ void
morkTable::NilRowSpaceError(morkEnv* ev)
{
ev->NewError("nil mTable_RowSpace");
}
mork_bool morkTable::MaybeDirtySpaceStoreAndTable()
{
morkRowSpace* rowSpace = mTable_RowSpace;
if ( rowSpace )
{
morkStore* store = rowSpace->mSpace_Store;
if ( store && store->mStore_CanDirty )
{
store->SetStoreDirty();
rowSpace->mSpace_CanDirty = morkBool_kTrue;
}
if ( rowSpace->mSpace_CanDirty ) // first time being dirtied?
{
if ( this->IsTableClean() )
{
mork_count rowCount = this->GetRowCount();
mork_count oneThird = rowCount / 4; // one third of rows
if ( oneThird > 0x07FFF ) // more than half max u2?
oneThird = 0x07FFF;
mTable_ChangesMax = (mork_u2) oneThird;
}
this->SetTableDirty();
rowSpace->SetRowSpaceDirty();
return morkBool_kTrue;
}
}
return morkBool_kFalse;
}
morkRow*
morkTable::GetMetaRow(morkEnv* ev, const mdbOid* inOptionalMetaRowOid)
{
morkRow* outRow = mTable_MetaRow;
if ( !outRow )
{
morkStore* store = mTable_Store;
mdbOid* oid = &mTable_MetaRowOid;
if ( inOptionalMetaRowOid && !oid->mOid_Scope )
*oid = *inOptionalMetaRowOid;
if ( oid->mOid_Scope ) // oid already recorded in table?
outRow = store->OidToRow(ev, oid);
else
{
outRow = store->NewRow(ev, morkStore_kMetaScope);
if ( outRow ) // need to record new oid in table?
*oid = outRow->mRow_Oid;
}
mTable_MetaRow = outRow;
if ( outRow ) // need to note another use of this row?
{
outRow->AddRowGcUse(ev);
this->SetTableNewMeta();
if ( this->IsTableClean() ) // catch dirty status of meta row?
this->MaybeDirtySpaceStoreAndTable();
}
}
return outRow;
}
void
morkTable::GetTableOid(morkEnv* ev, mdbOid* outOid)
{
morkRowSpace* space = mTable_RowSpace;
if ( space )
{
outOid->mOid_Scope = space->mSpace_Scope;
outOid->mOid_Id = mTable_Id;
}
else
this->NilRowSpaceError(ev);
}
nsIMdbTable*
morkTable::AcquireTableHandle(morkEnv* ev)
{
nsIMdbTable* outTable = 0;
orkinTable* t = (orkinTable*) mObject_Handle;
if ( t ) // have an old handle?
t->AddStrongRef(ev->AsMdbEnv());
else // need new handle?
{
t = orkinTable::MakeTable(ev, this);
mObject_Handle = t;
}
if ( t )
outTable = t;
return outTable;
}
mork_pos
morkTable::ArrayHasOid(morkEnv* ev, const mdbOid* inOid)
{
MORK_USED_1(ev);
mork_count count = mTable_RowArray.mArray_Fill;
mork_pos pos = -1;
while ( ++pos < count )
{
morkRow* row = (morkRow*) mTable_RowArray.At(pos);
MORK_ASSERT(row);
if ( row && row->EqualOid(inOid) )
{
return pos;
}
}
return -1;
}
mork_bool
morkTable::MapHasOid(morkEnv* ev, const mdbOid* inOid)
{
if ( mTable_RowMap )
return ( mTable_RowMap->GetOid(ev, inOid) != 0 );
else
return ( ArrayHasOid(ev, inOid) >= 0 );
}
void morkTable::build_row_map(morkEnv* ev)
{
morkRowMap* map = mTable_RowMap;
if ( !map )
{
mork_count count = mTable_RowArray.mArray_Fill + 3;
nsIMdbHeap* heap = mTable_Store->mPort_Heap;
map = new(*heap, ev) morkRowMap(ev, morkUsage::kHeap, heap, heap, count);
if ( map )
{
if ( ev->Good() )
{
mTable_RowMap = map; // put strong ref here
mork_count count = mTable_RowArray.mArray_Fill;
mork_pos pos = -1;
while ( ++pos < count )
{
morkRow* row = (morkRow*) mTable_RowArray.At(pos);
if ( row && row->IsRow() )
map->AddRow(ev, row);
else
row->NonRowTypeError(ev);
}
}
else
map->CutStrongRef(ev);
}
}
}
morkRow* morkTable::find_member_row(morkEnv* ev, morkRow* ioRow)
{
if ( mTable_RowMap )
return mTable_RowMap->GetRow(ev, ioRow);
else
{
mork_count count = mTable_RowArray.mArray_Fill;
mork_pos pos = -1;
while ( ++pos < count )
{
morkRow* row = (morkRow*) mTable_RowArray.At(pos);
if ( row == ioRow )
return row;
}
}
return (morkRow*) 0;
}
mork_pos
morkTable::MoveRow(morkEnv* ev, morkRow* ioRow, // change row position
mork_pos inHintFromPos, // suggested hint regarding start position
mork_pos inToPos) // desired new position for row ioRow
// MoveRow() returns the actual position of ioRow afterwards; this
// position is -1 if and only if ioRow was not found as a member.
{
mork_pos outPos = -1; // means ioRow was not a table member
mork_bool canDirty = ( this->IsTableClean() )?
this->MaybeDirtySpaceStoreAndTable() : morkBool_kTrue;
morkRow** rows = (morkRow**) mTable_RowArray.mArray_Slots;
mork_count count = mTable_RowArray.mArray_Fill;
if ( count && rows && ev->Good() ) // any members at all? no errors?
{
mork_pos lastPos = count - 1; // index of last row slot
if ( inToPos > lastPos ) // beyond last used array slot?
inToPos = lastPos; // put row into last available slot
else if ( inToPos < 0 ) // before first usable slot?
inToPos = 0; // put row in very first slow
if ( inHintFromPos > lastPos ) // beyond last used array slot?
inHintFromPos = lastPos; // seek row in last available slot
else if ( inHintFromPos < 0 ) // before first usable slot?
inHintFromPos = 0; // seek row in very first slow
morkRow** fromSlot = 0; // becomes nonzero of ioRow is ever found
morkRow** rowsEnd = rows + count; // one past last used array slot
if ( inHintFromPos <= 0 ) // start of table? just scan for row?
{
morkRow** cursor = rows - 1; // before first array slot
while ( ++cursor < rowsEnd )
{
if ( *cursor == ioRow )
{
fromSlot = cursor;
break; // end while loop
}
}
}
else // search near the start position and work outwards
{
morkRow** lo = rows + inHintFromPos; // lowest search point
morkRow** hi = lo; // highest search point starts at lowest point
// Seek ioRow in spiral widening search below and above inHintFromPos.
// This is faster when inHintFromPos is at all accurate, but is slower
// than a straightforward scan when inHintFromPos is nearly random.
while ( lo >= rows || hi < rowsEnd ) // keep searching?
{
if ( lo >= rows ) // low direction search still feasible?
{
if ( *lo == ioRow ) // actually found the row?
{
fromSlot = lo;
break; // end while loop
}
--lo; // advance further lower
}
if ( hi < rowsEnd ) // high direction search still feasible?
{
if ( *hi == ioRow ) // actually found the row?
{
fromSlot = hi;
break; // end while loop
}
++hi; // advance further higher
}
}
}
if ( fromSlot ) // ioRow was found as a table member?
{
outPos = fromSlot - rows; // actual position where row was found
if ( outPos != inToPos ) // actually need to move this row?
{
morkRow** toSlot = rows + inToPos; // slot where row must go
++mTable_RowArray.mArray_Seed; // we modify the array now:
if ( fromSlot < toSlot ) // row is moving upwards?
{
morkRow** up = fromSlot; // leading pointer going upward
while ( ++up <= toSlot ) // have not gone above destination?
{
*fromSlot = *up; // shift down one
fromSlot = up; // shift trailing pointer up
}
}
else // ( fromSlot > toSlot ) // row is moving downwards
{
morkRow** down = fromSlot; // leading pointer going downward
while ( --down >= toSlot ) // have not gone below destination?
{
*fromSlot = *down; // shift up one
fromSlot = down; // shift trailing pointer
}
}
*toSlot = ioRow;
outPos = inToPos; // okay, we actually moved the row here
if ( canDirty )
this->note_row_move(ev, ioRow, inToPos);
}
}
}
return outPos;
}
mork_bool
morkTable::AddRow(morkEnv* ev, morkRow* ioRow)
{
morkRow* row = this->find_member_row(ev, ioRow);
if ( !row && ev->Good() )
{
mork_bool canDirty = ( this->IsTableClean() )?
this->MaybeDirtySpaceStoreAndTable() : morkBool_kTrue;
mork_pos pos = mTable_RowArray.AppendSlot(ev, ioRow);
if ( ev->Good() && pos >= 0 )
{
ioRow->AddRowGcUse(ev);
if ( mTable_RowMap )
{
if ( mTable_RowMap->AddRow(ev, ioRow) )
{
// okay, anything else?
}
else
mTable_RowArray.CutSlot(ev, pos);
}
else if ( mTable_RowArray.mArray_Fill >= morkTable_kMakeRowMapThreshold )
this->build_row_map(ev);
if ( canDirty && ev->Good() )
this->NoteTableAddRow(ev, ioRow);
}
}
return ev->Good();
}
mork_bool
morkTable::CutRow(morkEnv* ev, morkRow* ioRow)
{
morkRow* row = this->find_member_row(ev, ioRow);
if ( row )
{
mork_bool canDirty = ( this->IsTableClean() )?
this->MaybeDirtySpaceStoreAndTable() : morkBool_kTrue;
mork_count count = mTable_RowArray.mArray_Fill;
morkRow** rowSlots = (morkRow**) mTable_RowArray.mArray_Slots;
if ( rowSlots ) // array has vector as expected?
{
mork_pos pos = -1;
morkRow** end = rowSlots + count;
morkRow** slot = rowSlots - 1; // prepare for preincrement:
while ( ++slot < end ) // another slot to check?
{
if ( *slot == row ) // found the slot containing row?
{
pos = slot - rowSlots; // record absolute position
break; // end while loop
}
}
if ( pos >= 0 ) // need to cut if from the array?
mTable_RowArray.CutSlot(ev, pos);
else
ev->NewWarning("row not found in array");
}
else
mTable_RowArray.NilSlotsAddressError(ev);
if ( mTable_RowMap )
mTable_RowMap->CutRow(ev, ioRow);
if ( canDirty )
this->NoteTableCutRow(ev, ioRow);
if ( ioRow->CutRowGcUse(ev) == 0 )
ioRow->OnZeroRowGcUse(ev);
}
return ev->Good();
}
mork_bool
morkTable::CutAllRows(morkEnv* ev)
{
if ( this->MaybeDirtySpaceStoreAndTable() )
{
this->SetTableRewrite(); // everything is dirty
this->NoteTableSetAll(ev);
}
if ( ev->Good() )
{
mTable_RowArray.CutAllSlots(ev);
if ( mTable_RowMap )
{
morkRowMapIter i(ev, mTable_RowMap);
mork_change* c = 0;
morkRow* r = 0;
for ( c = i.FirstRow(ev, &r); c; c = i.NextRow(ev, &r) )
{
if ( r )
{
if ( r->CutRowGcUse(ev) == 0 )
r->OnZeroRowGcUse(ev);
i.CutHereRow(ev, (morkRow**) 0);
}
else
ev->NewWarning("nil row in table map");
}
}
}
return ev->Good();
}
morkTableRowCursor*
morkTable::NewTableRowCursor(morkEnv* ev, mork_pos inRowPos)
{
morkTableRowCursor* outCursor = 0;
if ( ev->Good() )
{
nsIMdbHeap* heap = mTable_Store->mPort_Heap;
morkTableRowCursor* cursor = new(*heap, ev)
morkTableRowCursor(ev, morkUsage::kHeap, heap, this, inRowPos);
if ( cursor )
{
if ( ev->Good() )
outCursor = cursor;
else
cursor->CutStrongRef(ev);
}
}
return outCursor;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
morkTableChange::morkTableChange(morkEnv* ev, mork_change inChange,
morkRow* ioRow)
// use this constructor for inChange == morkChange_kAdd or morkChange_kCut
: morkNext()
, mTableChange_Row( ioRow )
, mTableChange_Pos( morkTableChange_kNone )
{
if ( ioRow )
{
if ( ioRow->IsRow() )
{
if ( inChange == morkChange_kAdd )
mTableChange_Pos = morkTableChange_kAdd;
else if ( inChange == morkChange_kCut )
mTableChange_Pos = morkTableChange_kCut;
else
this->UnknownChangeError(ev);
}
else
ioRow->NonRowTypeError(ev);
}
else
ev->NilPointerError();
}
morkTableChange::morkTableChange(morkEnv* ev, morkRow* ioRow, mork_pos inPos)
// use this constructor when the row is moved
: morkNext()
, mTableChange_Row( ioRow )
, mTableChange_Pos( inPos )
{
if ( ioRow )
{
if ( ioRow->IsRow() )
{
if ( inPos < 0 )
this->NegativeMovePosError(ev);
}
else
ioRow->NonRowTypeError(ev);
}
else
ev->NilPointerError();
}
void morkTableChange::UnknownChangeError(morkEnv* ev) const
// morkChange_kAdd or morkChange_kCut
{
ev->NewError("mTableChange_Pos neither kAdd nor kCut");
}
void morkTableChange::NegativeMovePosError(morkEnv* ev) const
// move must be non-neg position
{
ev->NewError("negative mTableChange_Pos for row move");
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
morkTableMap::~morkTableMap()
{
}
morkTableMap::morkTableMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
: morkNodeMap(ev, inUsage, ioHeap, ioSlotHeap)
{
if ( ev->Good() )
mNode_Derived = morkDerived_kTableMap;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,376 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKTABLE_
#define _MORKTABLE_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKDEQUE_
#include "morkDeque.h"
#endif
#ifndef _MORKOBJECT_
#include "morkObject.h"
#endif
#ifndef _MORKARRAY_
#include "morkArray.h"
#endif
#ifndef _MORKROWMAP_
#include "morkRowMap.h"
#endif
#ifndef _MORKNODEMAP_
#include "morkNodeMap.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
class nsIMdbTable;
#define morkDerived_kTable /*i*/ 0x5462 /* ascii 'Tb' */
/*| kStartRowArraySize: starting physical size of array for mTable_RowArray.
**| We want this number very small, so that a table containing exactly one
**| row member will not pay too significantly in space overhead. But we want
**| a number bigger than one, so there is some space for growth.
|*/
#define morkTable_kStartRowArraySize 3 /* modest starting size for array */
/*| kMakeRowMapThreshold: this is the number of rows in a table which causes
**| a hash table (mTable_RowMap) to be lazily created for faster member row
**| identification, during such operations as cuts and adds. This number must
**| be small enough that linear searches are not bad for member counts less
**| than this; but this number must also be large enough that creating a hash
**| table does not increase the per-row space overhead by a big percentage.
**| For speed, numbers on the order of ten to twenty are all fine; for space,
**| I believe a number as small as ten will have too much space overhead.
|*/
#define morkTable_kMakeRowMapThreshold 17 /* when to build mTable_RowMap */
#define morkTable_kStartRowMapSlotCount 13
#define morkTable_kMaxTableGcUses 0x0FF /* max for 8-bit unsigned int */
#define morkTable_kUniqueBit ((mork_u1) (1 << 0))
#define morkTable_kVerboseBit ((mork_u1) (1 << 1))
#define morkTable_kNotedBit ((mork_u1) (1 << 2)) /* space has change notes */
#define morkTable_kRewriteBit ((mork_u1) (1 << 3)) /* must rewrite all rows */
#define morkTable_kNewMetaBit ((mork_u1) (1 << 4)) /* new table meta row */
class morkTable : public morkObject, public morkLink {
// NOTE the morkLink base is for morkRowSpace::mRowSpace_TablesByPriority
// 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
// morkHandle* mObject_Handle; // weak ref to handle for this object
public: // state is public because the entire Mork system is private
morkStore* mTable_Store; // weak ref to port
// mTable_RowSpace->mSpace_Scope is row scope
morkRowSpace* mTable_RowSpace; // weak ref to containing space
morkRow* mTable_MetaRow; // table's actual meta row
mdbOid mTable_MetaRowOid; // oid for meta row
morkRowMap* mTable_RowMap; // (strong ref) hash table of all members
morkArray mTable_RowArray; // array of morkRow pointers
morkList mTable_ChangeList; // list of table changes
mork_u2 mTable_ChangesCount; // length of changes list
mork_u2 mTable_ChangesMax; // max list length before rewrite
mork_tid mTable_Id;
mork_kind mTable_Kind;
mork_u1 mTable_Flags; // bit flags
mork_priority mTable_Priority; // 0..9, any other value equals 9
mork_u1 mTable_GcUses; // persistent references from cells
mork_u1 mTable_Pad; // for u4 alignment
public: // flags bit twiddling
void SetTableUnique() { mTable_Flags |= morkTable_kUniqueBit; }
void SetTableVerbose() { mTable_Flags |= morkTable_kVerboseBit; }
void SetTableNoted() { mTable_Flags |= morkTable_kNotedBit; }
void SetTableRewrite() { mTable_Flags |= morkTable_kRewriteBit; }
void SetTableNewMeta() { mTable_Flags |= morkTable_kNewMetaBit; }
void ClearTableUnique() { mTable_Flags &= (mork_u1) ~morkTable_kUniqueBit; }
void ClearTableVerbose() { mTable_Flags &= (mork_u1) ~morkTable_kVerboseBit; }
void ClearTableNoted() { mTable_Flags &= (mork_u1) ~morkTable_kNotedBit; }
void ClearTableRewrite() { mTable_Flags &= (mork_u1) ~morkTable_kRewriteBit; }
void ClearTableNewMeta() { mTable_Flags &= (mork_u1) ~morkTable_kNewMetaBit; }
mork_bool IsTableUnique() const
{ return ( mTable_Flags & morkTable_kUniqueBit ) != 0; }
mork_bool IsTableVerbose() const
{ return ( mTable_Flags & morkTable_kVerboseBit ) != 0; }
mork_bool IsTableNoted() const
{ return ( mTable_Flags & morkTable_kNotedBit ) != 0; }
mork_bool IsTableRewrite() const
{ return ( mTable_Flags & morkTable_kRewriteBit ) != 0; }
mork_bool IsTableNewMeta() const
{ return ( mTable_Flags & morkTable_kNewMetaBit ) != 0; }
public: // table dirty handling more complex than morkNode::SetNodeDirty() etc.
void SetTableDirty() { this->SetNodeDirty(); }
void SetTableClean(morkEnv* ev);
mork_bool IsTableClean() const { return this->IsNodeClean(); }
mork_bool IsTableDirty() const { return this->IsNodeDirty(); }
public: // morkNode memory management operators
void* operator new(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev)
{ return morkNode::MakeNew(inSize, ioHeap, ev); }
void operator delete(void* ioAddress)
{ morkNode::OnDeleteAssert(ioAddress); }
// do NOT call delete on morkNode instances. Call ZapOld() instead.
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseTable() if open
virtual ~morkTable(); // assert that close executed earlier
public: // morkTable construction & destruction
morkTable(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioNodeHeap, morkStore* ioStore,
nsIMdbHeap* ioSlotHeap, morkRowSpace* ioRowSpace,
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
mork_tid inTableId,
mork_kind inKind, mork_bool inMustBeUnique);
void CloseTable(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkTable(const morkTable& other);
morkTable& operator=(const morkTable& other);
public: // dynamic type identification
mork_bool IsTable() const
{ return IsNode() && mNode_Derived == morkDerived_kTable; }
// } ===== end morkNode methods =====
public: // errors
static void NonTableTypeError(morkEnv* ev);
static void NonTableTypeWarning(morkEnv* ev);
static void NilRowSpaceError(morkEnv* ev);
public: // warnings
static void TableGcUsesUnderflowWarning(morkEnv* ev);
public: // noting table changes
mork_bool HasChangeOverflow() const
{ return mTable_ChangesCount >= mTable_ChangesMax; }
void NoteTableSetAll(morkEnv* ev);
void NoteTableMoveRow(morkEnv* ev, morkRow* ioRow, mork_pos inPos);
void note_row_change(morkEnv* ev, mork_change inChange, morkRow* ioRow);
void note_row_move(morkEnv* ev, morkRow* ioRow, mork_pos inNewPos);
void NoteTableAddRow(morkEnv* ev, morkRow* ioRow)
{ this->note_row_change(ev, morkChange_kAdd, ioRow); }
void NoteTableCutRow(morkEnv* ev, morkRow* ioRow)
{ this->note_row_change(ev, morkChange_kCut, ioRow); }
protected: // internal row map methods
morkRow* find_member_row(morkEnv* ev, morkRow* ioRow);
void build_row_map(morkEnv* ev);
public: // other table methods
mork_bool MaybeDirtySpaceStoreAndTable();
morkRow* GetMetaRow(morkEnv* ev, const mdbOid* inOptionalMetaRowOid);
mork_u2 AddTableGcUse(morkEnv* ev);
mork_u2 CutTableGcUse(morkEnv* ev);
// void DirtyAllTableContent(morkEnv* ev);
mork_seed TableSeed() const { return mTable_RowArray.mArray_Seed; }
morkRow* SafeRowAt(morkEnv* ev, mork_pos inPos)
{ return (morkRow*) mTable_RowArray.SafeAt(ev, inPos); }
nsIMdbTable* AcquireTableHandle(morkEnv* ev); // mObject_Handle
mork_count GetRowCount() const { return mTable_RowArray.mArray_Fill; }
void GetTableOid(morkEnv* ev, mdbOid* outOid);
mork_pos ArrayHasOid(morkEnv* ev, const mdbOid* inOid);
mork_bool MapHasOid(morkEnv* ev, const mdbOid* inOid);
mork_bool AddRow(morkEnv* ev, morkRow* ioRow); // returns ev->Good()
mork_bool CutRow(morkEnv* ev, morkRow* ioRow); // returns ev->Good()
mork_bool CutAllRows(morkEnv* ev); // returns ev->Good()
mork_pos MoveRow(morkEnv* ev, morkRow* ioRow, // change row position
mork_pos inHintFromPos, // suggested hint regarding start position
mork_pos inToPos); // desired new position for row ioRow
// MoveRow() returns the actual position of ioRow afterwards; this
// position is -1 if and only if ioRow was not found as a member.
morkTableRowCursor* NewTableRowCursor(morkEnv* ev, mork_pos inRowPos);
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakTable(morkTable* me,
morkEnv* ev, morkTable** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongTable(morkTable* me,
morkEnv* ev, morkTable** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// use negative values for kCut and kAdd, to keep non-neg move pos distinct:
#define morkTableChange_kCut ((mork_pos) -1) /* shows row was cut */
#define morkTableChange_kAdd ((mork_pos) -2) /* shows row was added */
#define morkTableChange_kNone ((mork_pos) -3) /* unknown change */
class morkTableChange : public morkNext {
public: // state is public because the entire Mork system is private
morkRow* mTableChange_Row; // the row in the change
mork_pos mTableChange_Pos; // kAdd, kCut, or non-neg for row move
public:
morkTableChange(morkEnv* ev, mork_change inChange, morkRow* ioRow);
// use this constructor for inChange == morkChange_kAdd or morkChange_kCut
morkTableChange(morkEnv* ev, morkRow* ioRow, mork_pos inPos);
// use this constructor when the row is moved
public:
void UnknownChangeError(morkEnv* ev) const; // morkChange_kAdd or morkChange_kCut
void NegativeMovePosError(morkEnv* ev) const; // move must be non-neg position
public:
mork_bool IsAddRowTableChange() const
{ return ( mTableChange_Pos == morkTableChange_kAdd ); }
mork_bool IsCutRowTableChange() const
{ return ( mTableChange_Pos == morkTableChange_kCut ); }
mork_bool IsMoveRowTableChange() const
{ return ( mTableChange_Pos >= 0 ); }
public:
mork_pos GetMovePos() const { return mTableChange_Pos; }
// GetMovePos() assumes that IsMoveRowTableChange() is true.
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kTableMap /*i*/ 0x744D /* ascii 'tM' */
/*| morkTableMap: maps mork_token -> morkTable
|*/
class morkTableMap : public morkNodeMap { // for mapping tokens to tables
public:
virtual ~morkTableMap();
morkTableMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap);
public: // other map methods
mork_bool AddTable(morkEnv* ev, morkTable* ioTable)
{ return this->AddNode(ev, ioTable->mTable_Id, ioTable); }
// the AddTable() boolean return equals ev->Good().
mork_bool CutTable(morkEnv* ev, mork_tid inTid)
{ return this->CutNode(ev, inTid); }
// The CutTable() boolean return indicates whether removal happened.
morkTable* GetTable(morkEnv* ev, mork_tid inTid)
{ return (morkTable*) this->GetNode(ev, inTid); }
// Note the returned table does NOT have an increase in refcount for this.
mork_num CutAllTables(morkEnv* ev)
{ return this->CutAllNodes(ev); }
// CutAllTables() releases all the referenced table values.
};
class morkTableMapIter: public morkMapIter{ // typesafe wrapper class
public:
morkTableMapIter(morkEnv* ev, morkTableMap* ioMap)
: morkMapIter(ev, ioMap) { }
morkTableMapIter( ) : morkMapIter() { }
void InitTableMapIter(morkEnv* ev, morkTableMap* ioMap)
{ this->InitMapIter(ev, ioMap); }
mork_change*
FirstTable(morkEnv* ev, mork_tid* outTid, morkTable** outTable)
{ return this->First(ev, outTid, outTable); }
mork_change*
NextTable(morkEnv* ev, mork_tid* outTid, morkTable** outTable)
{ return this->Next(ev, outTid, outTable); }
mork_change*
HereTable(morkEnv* ev, mork_tid* outTid, morkTable** outTable)
{ return this->Here(ev, outTid, outTable); }
// cutting while iterating hash map might dirty the parent table:
mork_change*
CutHereTable(morkEnv* ev, mork_tid* outTid, morkTable** outTable)
{ return this->CutHere(ev, outTid, outTable); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKTABLE_ */

View File

@@ -1,208 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKCURSOR_
#include "morkCursor.h"
#endif
#ifndef _MORKTABLEROWCURSOR_
#include "morkTableRowCursor.h"
#endif
#ifndef _ORKINTABLEROWCURSOR_
#include "orkinTableRowCursor.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
#ifndef _MORKTABLE_
#include "morkTable.h"
#endif
#ifndef _MORKROW_
#include "morkRow.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkTableRowCursor::CloseMorkNode(morkEnv* ev) // CloseTableRowCursor() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseTableRowCursor(ev);
this->MarkShut();
}
}
/*public virtual*/
morkTableRowCursor::~morkTableRowCursor() // CloseTableRowCursor() executed earlier
{
MORK_ASSERT(this->IsShutNode());
}
/*public non-poly*/
morkTableRowCursor::morkTableRowCursor(morkEnv* ev,
const morkUsage& inUsage,
nsIMdbHeap* ioHeap, morkTable* ioTable, mork_pos inRowPos)
: morkCursor(ev, inUsage, ioHeap)
, mTableRowCursor_Table( 0 )
{
if ( ev->Good() )
{
if ( ioTable )
{
mCursor_Pos = inRowPos;
mCursor_Seed = ioTable->TableSeed();
morkTable::SlotWeakTable(ioTable, ev, &mTableRowCursor_Table);
if ( ev->Good() )
mNode_Derived = morkDerived_kTableRowCursor;
}
else
ev->NilPointerError();
}
}
/*public non-poly*/ void
morkTableRowCursor::CloseTableRowCursor(morkEnv* ev)
{
if ( this )
{
if ( this->IsNode() )
{
mCursor_Pos = -1;
mCursor_Seed = 0;
morkTable::SlotWeakTable((morkTable*) 0, ev, &mTableRowCursor_Table);
this->CloseCursor(ev);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
/*static*/ void
morkTableRowCursor::NonTableRowCursorTypeError(morkEnv* ev)
{
ev->NewError("non morkTableRowCursor");
}
orkinTableRowCursor*
morkTableRowCursor::AcquireTableRowCursorHandle(morkEnv* ev)
{
orkinTableRowCursor* outCursor = 0;
orkinTableRowCursor* c = (orkinTableRowCursor*) mObject_Handle;
if ( c ) // have an old handle?
c->AddStrongRef(ev->AsMdbEnv());
else // need new handle?
{
c = orkinTableRowCursor::MakeTableRowCursor(ev, this);
mObject_Handle = c;
}
if ( c )
outCursor = c;
return outCursor;
}
mdb_pos
morkTableRowCursor::NextRowOid(morkEnv* ev, mdbOid* outOid)
{
mdb_pos outPos = -1;
(void) this->NextRow(ev, outOid, &outPos);
return outPos;
}
morkRow*
morkTableRowCursor::NextRow(morkEnv* ev, mdbOid* outOid, mdb_pos* outPos)
{
morkRow* outRow = 0;
mork_pos pos = -1;
morkTable* table = mTableRowCursor_Table;
if ( table )
{
if ( table->IsOpenNode() )
{
morkArray* array = &table->mTable_RowArray;
pos = mCursor_Pos;
if ( pos < 0 )
pos = 0;
else
++pos;
if ( pos < array->mArray_Fill )
{
mCursor_Pos = pos; // update for next time
morkRow* row = (morkRow*) array->At(pos);
if ( row )
{
if ( row->IsRow() )
{
outRow = row;
*outOid = row->mRow_Oid;
}
else
row->NonRowTypeError(ev);
}
else
ev->NilPointerError();
}
else
{
outOid->mOid_Scope = 0;
outOid->mOid_Id = morkId_kMinusOne;
}
}
else
table->NonOpenNodeError(ev);
}
else
ev->NilPointerError();
*outPos = pos;
return outRow;
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,103 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKTABLEROWCURSOR_
#define _MORKTABLEROWCURSOR_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKCURSOR_
#include "morkCursor.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
class orkinTableRowCursor;
#define morkDerived_kTableRowCursor /*i*/ 0x7243 /* ascii 'rC' */
class morkTableRowCursor : public morkCursor { // row iterator
// public: // slots inherited from morkObject (meant to inform only)
// nsIMdbHeap* mNode_Heap;
// mork_able mNode_Mutable; // can this node be modified?
// mork_load mNode_Load; // is this node clean or dirty?
// 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_uses mNode_Uses; // refcount for strong refs
// mork_refs mNode_Refs; // refcount for strong refs + weak refs
// morkFactory* mObject_Factory; // weak ref to suite factory
// mork_seed mCursor_Seed;
// mork_pos mCursor_Pos;
// mork_bool mCursor_DoFailOnSeedOutOfSync;
// mork_u1 mCursor_Pad[ 3 ]; // explicitly pad to u4 alignment
public: // state is public because the entire Mork system is private
morkTable* mTableRowCursor_Table; // weak ref to table
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseTableRowCursor()
virtual ~morkTableRowCursor(); // assert that close executed earlier
public: // morkTableRowCursor construction & destruction
morkTableRowCursor(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, morkTable* ioTable, mork_pos inRowPos);
void CloseTableRowCursor(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkTableRowCursor(const morkTableRowCursor& other);
morkTableRowCursor& operator=(const morkTableRowCursor& other);
public: // dynamic type identification
mork_bool IsTableRowCursor() const
{ return IsNode() && mNode_Derived == morkDerived_kTableRowCursor; }
// } ===== end morkNode methods =====
public: // typing
static void NonTableRowCursorTypeError(morkEnv* ev);
public: // other table row cursor methods
orkinTableRowCursor* AcquireTableRowCursorHandle(morkEnv* ev);
mdb_pos NextRowOid(morkEnv* ev, mdbOid* outOid);
morkRow* NextRow(morkEnv* ev, mdbOid* outOid, mdb_pos* outPos);
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakTableRowCursor(morkTableRowCursor* me,
morkEnv* ev, morkTableRowCursor** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongTableRowCursor(morkTableRowCursor* me,
morkEnv* ev, morkTableRowCursor** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKTABLEROWCURSOR_ */

View File

@@ -1,515 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKTHUMB_
#include "morkThumb.h"
#endif
#ifndef _ORKINTHUMB_
#include "orkinThumb.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
#ifndef _MORKFILE_
#include "morkFile.h"
#endif
#ifndef _MORKWRITER_
#include "morkWriter.h"
#endif
#ifndef _MORKPARSER_
#include "morkParser.h"
#endif
#ifndef _MORKBUILDER_
#include "morkBuilder.h"
#endif
#ifndef _MORKFILE_
#include "morkFile.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkThumb::CloseMorkNode(morkEnv* ev) // CloseThumb() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseThumb(ev);
this->MarkShut();
}
}
/*public virtual*/
morkThumb::~morkThumb() // assert CloseThumb() executed earlier
{
MORK_ASSERT(mThumb_Magic==0);
MORK_ASSERT(mThumb_Store==0);
MORK_ASSERT(mThumb_File==0);
}
/*public non-poly*/
morkThumb::morkThumb(morkEnv* ev,
const morkUsage& inUsage, nsIMdbHeap* ioHeap,
nsIMdbHeap* ioSlotHeap, mork_magic inMagic)
: morkObject(ev, inUsage, ioHeap, (morkHandle*) 0)
, mThumb_Magic( 0 )
, mThumb_Total( 0 )
, mThumb_Current( 0 )
, mThumb_Done( morkBool_kFalse )
, mThumb_Broken( morkBool_kFalse )
, mThumb_Seed( 0 )
, mThumb_Store( 0 )
, mThumb_File( 0 )
, mThumb_Writer( 0 )
, mThumb_Builder( 0 )
, mThumb_SourcePort( 0 )
, mThumb_DoCollect( morkBool_kFalse )
{
if ( ev->Good() )
{
if ( ioSlotHeap )
{
mThumb_Magic = inMagic;
mNode_Derived = morkDerived_kThumb;
}
else
ev->NilPointerError();
}
}
/*public non-poly*/ void
morkThumb::CloseThumb(morkEnv* ev) // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
{
mThumb_Magic = 0;
if ( mThumb_Builder && mThumb_Store )
mThumb_Store->ForgetBuilder(ev);
morkBuilder::SlotStrongBuilder((morkBuilder*) 0, ev, &mThumb_Builder);
morkWriter::SlotStrongWriter((morkWriter*) 0, ev, &mThumb_Writer);
morkFile::SlotStrongFile((morkFile*) 0, ev, &mThumb_File);
morkStore::SlotStrongStore((morkStore*) 0, ev, &mThumb_Store);
morkPort::SlotStrongPort((morkPort*) 0, ev, &mThumb_SourcePort);
this->MarkShut();
}
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
/*static*/ void morkThumb::NonThumbTypeError(morkEnv* ev)
{
ev->NewError("non morkThumb");
}
/*static*/ void morkThumb::UnsupportedThumbMagicError(morkEnv* ev)
{
ev->NewError("unsupported mThumb_Magic");
}
/*static*/ void morkThumb::NilThumbStoreError(morkEnv* ev)
{
ev->NewError("nil mThumb_Store");
}
/*static*/ void morkThumb::NilThumbFileError(morkEnv* ev)
{
ev->NewError("nil mThumb_File");
}
/*static*/ void morkThumb::NilThumbWriterError(morkEnv* ev)
{
ev->NewError("nil mThumb_Writer");
}
/*static*/ void morkThumb::NilThumbBuilderError(morkEnv* ev)
{
ev->NewError("nil mThumb_Builder");
}
/*static*/ void morkThumb::NilThumbSourcePortError(morkEnv* ev)
{
ev->NewError("nil mThumb_SourcePort");
}
nsIMdbThumb*
morkThumb::AcquireThumbHandle(morkEnv* ev)
{
nsIMdbThumb* outThumb = 0;
orkinThumb* t = (orkinThumb*) mObject_Handle;
if ( t ) // have an old handle?
t->AddStrongRef(ev->AsMdbEnv());
else // need new handle?
{
t = orkinThumb::MakeThumb(ev, this);
mObject_Handle = t;
}
if ( t )
outThumb = t;
return outThumb;
}
/*static*/ morkThumb*
morkThumb::Make_OpenFileStore(morkEnv* ev, nsIMdbHeap* ioHeap,
morkStore* ioStore)
{
morkThumb* outThumb = 0;
if ( ioHeap && ioStore )
{
morkFile* file = ioStore->mStore_File;
if ( file )
{
mork_pos fileEof = file->Length(ev);
if ( ev->Good() )
{
outThumb = new(*ioHeap, ev)
morkThumb(ev, morkUsage::kHeap, ioHeap, ioHeap,
morkThumb_kMagic_OpenFileStore);
if ( outThumb )
{
morkBuilder* builder = ioStore->LazyGetBuilder(ev);
if ( builder )
{
outThumb->mThumb_Total = (mork_count) fileEof;
morkStore::SlotStrongStore(ioStore, ev, &outThumb->mThumb_Store);
morkBuilder::SlotStrongBuilder(builder, ev,
&outThumb->mThumb_Builder);
}
}
}
}
else
ioStore->NilStoreFileError(ev);
}
else
ev->NilPointerError();
return outThumb;
}
/*static*/ morkThumb*
morkThumb::Make_LargeCommit(morkEnv* ev,
nsIMdbHeap* ioHeap, morkStore* ioStore)
{
morkThumb* outThumb = 0;
if ( ioHeap && ioStore )
{
morkFile* file = ioStore->mStore_File;
if ( file )
{
outThumb = new(*ioHeap, ev)
morkThumb(ev, morkUsage::kHeap, ioHeap, ioHeap,
morkThumb_kMagic_LargeCommit);
if ( outThumb )
{
morkWriter* writer = new(*ioHeap, ev)
morkWriter(ev, morkUsage::kHeap, ioHeap, ioStore, file, ioHeap);
if ( writer )
{
writer->mWriter_CommitGroupIdentity =
++ioStore->mStore_CommitGroupIdentity;
writer->mWriter_NeedDirtyAll = morkBool_kFalse;
outThumb->mThumb_DoCollect = morkBool_kFalse;
morkStore::SlotStrongStore(ioStore, ev, &outThumb->mThumb_Store);
morkFile::SlotStrongFile(file, ev, &outThumb->mThumb_File);
morkWriter::SlotStrongWriter(writer, ev, &outThumb->mThumb_Writer);
}
}
}
else
ioStore->NilStoreFileError(ev);
}
else
ev->NilPointerError();
return outThumb;
}
/*static*/ morkThumb*
morkThumb::Make_CompressCommit(morkEnv* ev,
nsIMdbHeap* ioHeap, morkStore* ioStore, mork_bool inDoCollect)
{
morkThumb* outThumb = 0;
if ( ioHeap && ioStore )
{
morkFile* file = ioStore->mStore_File;
if ( file )
{
outThumb = new(*ioHeap, ev)
morkThumb(ev, morkUsage::kHeap, ioHeap, ioHeap,
morkThumb_kMagic_CompressCommit);
if ( outThumb )
{
morkWriter* writer = new(*ioHeap, ev)
morkWriter(ev, morkUsage::kHeap, ioHeap, ioStore, file, ioHeap);
if ( writer )
{
writer->mWriter_NeedDirtyAll = morkBool_kTrue;
outThumb->mThumb_DoCollect = inDoCollect;
morkStore::SlotStrongStore(ioStore, ev, &outThumb->mThumb_Store);
morkFile::SlotStrongFile(file, ev, &outThumb->mThumb_File);
morkWriter::SlotStrongWriter(writer, ev, &outThumb->mThumb_Writer);
// cope with fact that parsed transaction groups are going away:
ioStore->mStore_FirstCommitGroupPos = 0;
ioStore->mStore_SecondCommitGroupPos = 0;
}
}
}
else
ioStore->NilStoreFileError(ev);
}
else
ev->NilPointerError();
return outThumb;
}
// { ===== begin non-poly methods imitating nsIMdbThumb =====
void morkThumb::GetProgress(morkEnv* ev, mdb_count* outTotal,
mdb_count* outCurrent, mdb_bool* outDone, mdb_bool* outBroken)
{
MORK_USED_1(ev);
if ( outTotal )
*outTotal = mThumb_Total;
if ( outCurrent )
*outCurrent = mThumb_Current;
if ( outDone )
*outDone = mThumb_Done;
if ( outBroken )
*outBroken = mThumb_Broken;
}
void morkThumb::DoMore(morkEnv* ev, mdb_count* outTotal,
mdb_count* outCurrent, mdb_bool* outDone, mdb_bool* outBroken)
{
if ( !mThumb_Done && !mThumb_Broken )
{
switch ( mThumb_Magic )
{
case morkThumb_kMagic_OpenFilePort: // 1 /* factory method */
this->DoMore_OpenFilePort(ev); break;
case morkThumb_kMagic_OpenFileStore: // 2 /* factory method */
this->DoMore_OpenFileStore(ev); break;
case morkThumb_kMagic_ExportToFormat: // 3 /* port method */
this->DoMore_ExportToFormat(ev); break;
case morkThumb_kMagic_ImportContent: // 4 /* store method */
this->DoMore_ImportContent(ev); break;
case morkThumb_kMagic_LargeCommit: // 5 /* store method */
this->DoMore_LargeCommit(ev); break;
case morkThumb_kMagic_SessionCommit: // 6 /* store method */
this->DoMore_SessionCommit(ev); break;
case morkThumb_kMagic_CompressCommit: // 7 /* store method */
this->DoMore_CompressCommit(ev); break;
case morkThumb_kMagic_SearchManyColumns: // 8 /* table method */
this->DoMore_SearchManyColumns(ev); break;
case morkThumb_kMagic_NewSortColumn: // 9 /* table metho) */
this->DoMore_NewSortColumn(ev); break;
case morkThumb_kMagic_NewSortColumnWithCompare: // 10 /* table method */
this->DoMore_NewSortColumnWithCompare(ev); break;
case morkThumb_kMagic_CloneSortColumn: // 11 /* table method */
this->DoMore_CloneSortColumn(ev); break;
case morkThumb_kMagic_AddIndex: // 12 /* table method */
this->DoMore_AddIndex(ev); break;
case morkThumb_kMagic_CutIndex: // 13 /* table method */
this->DoMore_CutIndex(ev); break;
default:
this->UnsupportedThumbMagicError(ev);
break;
}
}
if ( outTotal )
*outTotal = mThumb_Total;
if ( outCurrent )
*outCurrent = mThumb_Current;
if ( outDone )
*outDone = mThumb_Done;
if ( outBroken )
*outBroken = mThumb_Broken;
}
void morkThumb::CancelAndBreakThumb(morkEnv* ev)
{
MORK_USED_1(ev);
mThumb_Broken = morkBool_kTrue;
}
// } ===== end non-poly methods imitating nsIMdbThumb =====
morkStore*
morkThumb::ThumbToOpenStore(morkEnv* ev)
// for orkinFactory::ThumbToOpenStore() after OpenFileStore()
{
MORK_USED_1(ev);
return mThumb_Store;
}
void morkThumb::DoMore_OpenFilePort(morkEnv* ev)
{
this->UnsupportedThumbMagicError(ev);
}
void morkThumb::DoMore_OpenFileStore(morkEnv* ev)
{
morkBuilder* builder = mThumb_Builder;
if ( builder )
{
mork_pos pos = 0;
builder->ParseMore(ev, &pos, &mThumb_Done, &mThumb_Broken);
// mThumb_Total = builder->mBuilder_TotalCount;
// mThumb_Current = builder->mBuilder_DoneCount;
mThumb_Current = (mork_count) pos;
}
else
{
this->NilThumbBuilderError(ev);
mThumb_Broken = morkBool_kTrue;
mThumb_Done = morkBool_kTrue;
}
}
void morkThumb::DoMore_ExportToFormat(morkEnv* ev)
{
this->UnsupportedThumbMagicError(ev);
}
void morkThumb::DoMore_ImportContent(morkEnv* ev)
{
this->UnsupportedThumbMagicError(ev);
}
void morkThumb::DoMore_LargeCommit(morkEnv* ev)
{
this->DoMore_Commit(ev);
}
void morkThumb::DoMore_SessionCommit(morkEnv* ev)
{
this->DoMore_Commit(ev);
}
void morkThumb::DoMore_Commit(morkEnv* ev)
{
morkWriter* writer = mThumb_Writer;
if ( writer )
{
writer->WriteMore(ev);
mThumb_Total = writer->mWriter_TotalCount;
mThumb_Current = writer->mWriter_DoneCount;
mThumb_Done = ( ev->Bad() || writer->IsWritingDone() );
mThumb_Broken = ev->Bad();
}
else
{
this->NilThumbWriterError(ev);
mThumb_Broken = morkBool_kTrue;
mThumb_Done = morkBool_kTrue;
}
}
void morkThumb::DoMore_CompressCommit(morkEnv* ev)
{
this->DoMore_Commit(ev);
}
void morkThumb::DoMore_SearchManyColumns(morkEnv* ev)
{
this->UnsupportedThumbMagicError(ev);
}
void morkThumb::DoMore_NewSortColumn(morkEnv* ev)
{
this->UnsupportedThumbMagicError(ev);
}
void morkThumb::DoMore_NewSortColumnWithCompare(morkEnv* ev)
{
this->UnsupportedThumbMagicError(ev);
}
void morkThumb::DoMore_CloneSortColumn(morkEnv* ev)
{
this->UnsupportedThumbMagicError(ev);
}
void morkThumb::DoMore_AddIndex(morkEnv* ev)
{
this->UnsupportedThumbMagicError(ev);
}
void morkThumb::DoMore_CutIndex(morkEnv* ev)
{
this->UnsupportedThumbMagicError(ev);
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,182 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKTHUMB_
#define _MORKTHUMB_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKOBJECT_
#include "morkObject.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkThumb_kMagic_OpenFilePort 1 /* factory method */
#define morkThumb_kMagic_OpenFileStore 2 /* factory method */
#define morkThumb_kMagic_ExportToFormat 3 /* port method */
#define morkThumb_kMagic_ImportContent 4 /* store method */
#define morkThumb_kMagic_LargeCommit 5 /* store method */
#define morkThumb_kMagic_SessionCommit 6 /* store method */
#define morkThumb_kMagic_CompressCommit 7 /* store method */
#define morkThumb_kMagic_SearchManyColumns 8 /* table method */
#define morkThumb_kMagic_NewSortColumn 9 /* table metho) */
#define morkThumb_kMagic_NewSortColumnWithCompare 10 /* table method */
#define morkThumb_kMagic_CloneSortColumn 11 /* table method */
#define morkThumb_kMagic_AddIndex 12 /* table method */
#define morkThumb_kMagic_CutIndex 13 /* table method */
#define morkDerived_kThumb /*i*/ 0x5468 /* ascii 'Th' */
/*| morkThumb:
|*/
class morkThumb : public morkObject {
// public: // slots inherited from morkNode (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
// morkHandle* mObject_Handle; // weak ref to handle for this object
public: // state is public because the entire Mork system is private
// might as well include all the return values here:
mork_magic mThumb_Magic; // magic sig different in each thumb type
mork_count mThumb_Total;
mork_count mThumb_Current;
mork_bool mThumb_Done;
mork_bool mThumb_Broken;
mork_u2 mThumb_Seed; // optional seed for u4 alignment padding
morkStore* mThumb_Store; // weak ref to created store
morkFile* mThumb_File; // strong ref to file (store, import, export)
morkWriter* mThumb_Writer; // strong ref to writer (for commit)
morkBuilder* mThumb_Builder; // strong ref to builder (for store open)
morkPort* mThumb_SourcePort; // strong ref to port for import
mork_bool mThumb_DoCollect; // influence whether a collect happens
mork_bool mThumb_Pad[ 3 ]; // padding for u4 alignment
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseThumb() only if open
virtual ~morkThumb(); // assert that CloseThumb() executed earlier
public: // morkThumb construction & destruction
morkThumb(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap, mork_magic inMagic);
void CloseThumb(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkThumb(const morkThumb& other);
morkThumb& operator=(const morkThumb& other);
public: // dynamic type identification
mork_bool IsThumb() const
{ return IsNode() && mNode_Derived == morkDerived_kThumb; }
// } ===== end morkNode methods =====
public: // typing
static void NonThumbTypeError(morkEnv* ev);
static void UnsupportedThumbMagicError(morkEnv* ev);
static void NilThumbStoreError(morkEnv* ev);
static void NilThumbFileError(morkEnv* ev);
static void NilThumbWriterError(morkEnv* ev);
static void NilThumbBuilderError(morkEnv* ev);
static void NilThumbSourcePortError(morkEnv* ev);
public: // 'do more' methods
void DoMore_OpenFilePort(morkEnv* ev);
void DoMore_OpenFileStore(morkEnv* ev);
void DoMore_ExportToFormat(morkEnv* ev);
void DoMore_ImportContent(morkEnv* ev);
void DoMore_LargeCommit(morkEnv* ev);
void DoMore_SessionCommit(morkEnv* ev);
void DoMore_CompressCommit(morkEnv* ev);
void DoMore_Commit(morkEnv* ev);
void DoMore_SearchManyColumns(morkEnv* ev);
void DoMore_NewSortColumn(morkEnv* ev);
void DoMore_NewSortColumnWithCompare(morkEnv* ev);
void DoMore_CloneSortColumn(morkEnv* ev);
void DoMore_AddIndex(morkEnv* ev);
void DoMore_CutIndex(morkEnv* ev);
public: // other thumb methods
nsIMdbThumb* AcquireThumbHandle(morkEnv* ev); // mObject_Handle
morkStore* ThumbToOpenStore(morkEnv* ev);
// for orkinFactory::ThumbToOpenStore() after OpenFileStore()
public: // assorted thumb constructors
static morkThumb* Make_OpenFileStore(morkEnv* ev,
nsIMdbHeap* ioHeap, morkStore* ioStore);
static morkThumb* Make_CompressCommit(morkEnv* ev,
nsIMdbHeap* ioHeap, morkStore* ioStore, mork_bool inDoCollect);
static morkThumb* Make_LargeCommit(morkEnv* ev,
nsIMdbHeap* ioHeap, morkStore* ioStore);
// { ===== begin non-poly methods imitating nsIMdbThumb =====
void GetProgress(morkEnv* ev, mdb_count* outTotal,
mdb_count* outCurrent, mdb_bool* outDone, mdb_bool* outBroken);
void DoMore(morkEnv* ev, mdb_count* outTotal,
mdb_count* outCurrent, mdb_bool* outDone, mdb_bool* outBroken);
void CancelAndBreakThumb(morkEnv* ev);
// } ===== end non-poly methods imitating nsIMdbThumb =====
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakThumb(morkThumb* me,
morkEnv* ev, morkThumb** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongThumb(morkThumb* me,
morkEnv* ev, morkThumb** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKTHUMB_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,354 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKWRITER_
#define _MORKWRITER_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKMAP_
#include "morkMap.h"
#endif
#ifndef _MORKROWMAP_
#include "morkRowMap.h"
#endif
#ifndef _MORKTABLE_
#include "morkTable.h"
#endif
#ifndef _MORKATOMMAP_
#include "morkAtomMap.h"
#endif
#ifndef _MORKATOMSPACE_
#include "morkAtomSpace.h"
#endif
#ifndef _MORKROWSPACE_
#include "morkRowSpace.h"
#endif
#ifndef _MORKSTREAM_
#include "morkStream.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkWriter_kStreamBufSize /*i*/ (16 * 1024) /* buffer size for stream */
#define morkDerived_kWriter /*i*/ 0x5772 /* ascii 'Wr' */
#define morkWriter_kPhaseNothingDone 0 /* nothing has yet been done */
#define morkWriter_kPhaseDirtyAllDone 1 /* DirtyAll() is done */
#define morkWriter_kPhasePutHeaderDone 2 /* PutHeader() is done */
#define morkWriter_kPhaseRenumberAllDone 3 /* RenumberAll() is done */
#define morkWriter_kPhaseStoreAtomSpaces 4 /*mWriter_StoreAtomSpacesIter*/
#define morkWriter_kPhaseAtomSpaceAtomAids 5 /*mWriter_AtomSpaceAtomAidsIter*/
#define morkWriter_kPhaseStoreRowSpacesTables 6 /*mWriter_StoreRowSpacesIter*/
#define morkWriter_kPhaseRowSpaceTables 7 /*mWriter_RowSpaceTablesIter*/
#define morkWriter_kPhaseTableRowArray 8 /*mWriter_TableRowArrayPos */
#define morkWriter_kPhaseStoreRowSpacesRows 9 /*mWriter_StoreRowSpacesIter*/
#define morkWriter_kPhaseRowSpaceRows 10 /*mWriter_RowSpaceRowsIter*/
#define morkWriter_kPhaseContentDone 11 /* all content written */
#define morkWriter_kPhaseWritingDone 12 /* everthing has been done */
#define morkWriter_kCountNumberOfPhases 13 /* part of mWrite_TotalCount */
#define morkWriter_kMaxColumnNameSize 128 /* longest writable col name */
#define morkWriter_kMaxIndent 66 /* default value for mWriter_MaxIndent */
#define morkWriter_kMaxLine 78 /* default value for mWriter_MaxLine */
#define morkWriter_kYarnEscapeSlop 4 /* guess average yarn escape overhead */
#define morkWriter_kTableMetaCellDepth 4 /* */
#define morkWriter_kTableMetaCellValueDepth 6 /* */
#define morkWriter_kDictMetaCellDepth 4 /* */
#define morkWriter_kDictMetaCellValueDepth 6 /* */
#define morkWriter_kDictAliasDepth 2 /* */
#define morkWriter_kDictAliasValueDepth 4 /* */
#define morkWriter_kRowDepth 2 /* */
#define morkWriter_kRowCellDepth 4 /* */
#define morkWriter_kRowCellValueDepth 6 /* */
#define morkWriter_kGroupBufSize 64 /* */
// v=1.1 retired on 23-Mar-99 (for metainfo one char column names)
// v=1.2 retired on 20-Apr-99 (for ":c" suffix on table kind hex refs)
// v=1.3 retired on 20-Apr-99 (for 1CE:m instead of ill-formed 1CE:^6D)
#define morkWriter_kFileHeader "// <!-- <mdb:mork:z v=\"1.4\"/> -->"
class morkWriter : public morkNode { // row iterator
// public: // slots inherited from morkObject (meant to inform only)
// nsIMdbHeap* mNode_Heap;
// mork_able mNode_Mutable; // can this node be modified?
// mork_load mNode_Load; // is this node clean or dirty?
// 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_uses mNode_Uses; // refcount for strong refs
// mork_refs mNode_Refs; // refcount for strong refs + weak refs
public: // state is public because the entire Mork system is private
morkStore* mWriter_Store; // weak ref to committing store
morkFile* mWriter_File; // strong ref to store's file
morkFile* mWriter_Bud; // strong ref to bud of mWriter_File
morkStream* mWriter_Stream; // strong ref to stream on bud file
nsIMdbHeap* mWriter_SlotHeap; // strong ref to slot heap
// GroupIdentity should be based on mStore_CommitGroupIdentity:
mork_gid mWriter_CommitGroupIdentity; // transaction ID number
// GroupBuf holds a hex version of mWriter_CommitGroupIdentity:
char mWriter_GroupBuf[ morkWriter_kGroupBufSize ];
mork_fill mWriter_GroupBufFill; // actual bytes in GroupBuf
mork_count mWriter_TotalCount; // count of all things to be written
mork_count mWriter_DoneCount; // count of things already written
mork_size mWriter_LineSize; // length of current line being written
mork_size mWriter_MaxIndent; // line size forcing a line break
mork_size mWriter_MaxLine; // line size forcing a value continuation
mork_cscode mWriter_TableForm; // current charset metainfo
mork_scope mWriter_TableAtomScope; // current atom scope
mork_scope mWriter_TableRowScope; // current row scope
mork_kind mWriter_TableKind; // current table kind
mork_cscode mWriter_RowForm; // current charset metainfo
mork_scope mWriter_RowAtomScope; // current atom scope
mork_scope mWriter_RowScope; // current row scope
mork_cscode mWriter_DictForm; // current charset metainfo
mork_scope mWriter_DictAtomScope; // current atom scope
mork_bool mWriter_NeedDirtyAll; // need to call DirtyAll()
mork_bool mWriter_Incremental; // opposite of mWriter_NeedDirtyAll
mork_bool mWriter_DidStartDict; // true when a dict has been started
mork_bool mWriter_DidEndDict; // true when a dict has been ended
mork_bool mWriter_SuppressDirtyRowNewline; // for table meta rows
mork_bool mWriter_DidStartGroup; // true when a group has been started
mork_bool mWriter_DidEndGroup; // true when a group has been ended
mork_u1 mWriter_Phase; // status of writing process
mork_bool mWriter_BeVerbose; // driven by env and table verbose settings:
// mWriter_BeVerbose equals ( ev->mEnv_BeVerbose || table->IsTableVerbose() )
mork_u1 mWriter_Pad[ 3 ]; // for u4 alignment
mork_pos mWriter_TableRowArrayPos; // index into mTable_RowArray
char mWriter_SafeNameBuf[ (morkWriter_kMaxColumnNameSize * 2) + 4 ];
// Note: extra four bytes in ColNameBuf means we can always append to yarn
char mWriter_ColNameBuf[ morkWriter_kMaxColumnNameSize + 4 ];
// Note: extra four bytes in ColNameBuf means we can always append to yarn
mdbYarn mWriter_ColYarn; // a yarn to describe space in ColNameBuf:
// mYarn_Buf == mWriter_ColNameBuf, mYarn_Size == morkWriter_kMaxColumnNameSize
mdbYarn mWriter_SafeYarn; // a yarn to describe space in ColNameBuf:
// mYarn_Buf == mWriter_SafeNameBuf, mYarn_Size == (kMaxColumnNameSize * 2)
morkAtomSpaceMapIter mWriter_StoreAtomSpacesIter; // for mStore_AtomSpaces
morkAtomAidMapIter mWriter_AtomSpaceAtomAidsIter; // for AtomSpace_AtomAids
morkRowSpaceMapIter mWriter_StoreRowSpacesIter; // for mStore_RowSpaces
morkTableMapIter mWriter_RowSpaceTablesIter; // for mRowSpace_Tables
morkRowMapIter mWriter_RowSpaceRowsIter; // for mRowSpace_Rows
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseWriter()
virtual ~morkWriter(); // assert that close executed earlier
public: // morkWriter construction & destruction
morkWriter(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, morkStore* ioStore, morkFile* ioFile,
nsIMdbHeap* ioSlotHeap);
void CloseWriter(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkWriter(const morkWriter& other);
morkWriter& operator=(const morkWriter& other);
public: // dynamic type identification
mork_bool IsWriter() const
{ return IsNode() && mNode_Derived == morkDerived_kWriter; }
// } ===== end morkNode methods =====
public: // typing & errors
static void NonWriterTypeError(morkEnv* ev);
static void NilWriterStoreError(morkEnv* ev);
static void NilWriterBudError(morkEnv* ev);
static void NilWriterStreamError(morkEnv* ev);
static void NilWriterFileError(morkEnv* ev);
static void UnsupportedPhaseError(morkEnv* ev);
public: // utitlities
void ChangeRowForm(morkEnv* ev, mork_cscode inNewForm);
void ChangeDictForm(morkEnv* ev, mork_cscode inNewForm);
void ChangeDictAtomScope(morkEnv* ev, mork_scope inScope);
public: // inlines
mork_bool DidStartDict() const { return mWriter_DidStartDict; }
mork_bool DidEndDict() const { return mWriter_DidEndDict; }
mork_bool NeedLineBreak() const
{ return ( mWriter_LineSize > mWriter_MaxIndent ); }
void IndentAsNeeded(morkEnv* ev, mork_size inDepth)
{
if ( mWriter_LineSize > mWriter_MaxIndent )
mWriter_LineSize = mWriter_Stream->PutIndent(ev, inDepth);
}
void IndentOverMaxLine(morkEnv* ev,
mork_size inPendingSize, mork_size inDepth)
{
if ( mWriter_LineSize + inPendingSize > mWriter_MaxLine )
mWriter_LineSize = mWriter_Stream->PutIndent(ev, inDepth);
}
public: // delayed construction
void MakeWriterStream(morkEnv* ev); // give writer a suitable stream
public: // iterative/asynchronous writing
mork_bool WriteMore(morkEnv* ev); // call until IsWritingDone() is true
mork_bool IsWritingDone() const // don't call WriteMore() any longer?
{ return mWriter_Phase == morkWriter_kPhaseWritingDone; }
public: // marking all content dirty
mork_bool DirtyAll(morkEnv* ev);
// DirtyAll() visits every store sub-object and marks
// them dirty, including every table, row, cell, and atom. The return
// equals ev->Good(), to show whether any error happened. This method is
// intended for use in the beginning of a "compress commit" which writes
// all store content, whether dirty or not. We dirty everything first so
// that later iterations over content can mark things clean as they are
// written, and organize the process of serialization so that objects are
// written only at need (because of being dirty). Note the method can
// stop early when any error happens, since this will abort any commit.
public: // group commit transactions
mork_bool StartGroup(morkEnv* ev);
mork_bool CommitGroup(morkEnv* ev);
mork_bool AbortGroup(morkEnv* ev);
public: // phase methods
mork_bool OnNothingDone(morkEnv* ev);
mork_bool OnDirtyAllDone(morkEnv* ev);
mork_bool OnPutHeaderDone(morkEnv* ev);
mork_bool OnRenumberAllDone(morkEnv* ev);
mork_bool OnStoreAtomSpaces(morkEnv* ev);
mork_bool OnAtomSpaceAtomAids(morkEnv* ev);
mork_bool OnStoreRowSpacesTables(morkEnv* ev);
mork_bool OnRowSpaceTables(morkEnv* ev);
mork_bool OnTableRowArray(morkEnv* ev);
mork_bool OnStoreRowSpacesRows(morkEnv* ev);
mork_bool OnRowSpaceRows(morkEnv* ev);
mork_bool OnContentDone(morkEnv* ev);
mork_bool OnWritingDone(morkEnv* ev);
public: // writing dict items first pass
mork_bool PutTableDict(morkEnv* ev, morkTable* ioTable);
mork_bool PutRowDict(morkEnv* ev, morkRow* ioRow);
public: // writing node content second pass
mork_bool PutTable(morkEnv* ev, morkTable* ioTable);
mork_bool PutRow(morkEnv* ev, morkRow* ioRow);
mork_bool PutRowCells(morkEnv* ev, morkRow* ioRow);
mork_bool PutVerboseRowCells(morkEnv* ev, morkRow* ioRow);
mork_bool PutCell(morkEnv* ev, morkCell* ioCell, mork_bool inWithVal);
mork_bool PutVerboseCell(morkEnv* ev, morkCell* ioCell, mork_bool inWithVal);
mork_bool PutTableChange(morkEnv* ev, const morkTableChange* inChange);
public: // other writer methods
mork_bool IsYarnAllValue(const mdbYarn* inYarn);
mork_size WriteYarn(morkEnv* ev, const mdbYarn* inYarn);
// return number of atom bytes written on the current line (which
// implies that escaped line breaks will make the size value smaller
// than the entire yarn's size, since only part goes on a last line).
mork_size WriteAtom(morkEnv* ev, const morkAtom* inAtom);
// return number of atom bytes written on the current line (which
// implies that escaped line breaks will make the size value smaller
// than the entire atom's size, since only part goes on a last line).
void WriteAllStoreTables(morkEnv* ev);
void WriteAtomSpaceAsDict(morkEnv* ev, morkAtomSpace* ioSpace);
void WriteTokenToTokenMetaCell(morkEnv* ev, mork_token inCol,
mork_token inValue);
void WriteStringToTokenDictCell(morkEnv* ev, const char* inCol,
mork_token inValue);
// Note inCol should begin with '(' and end with '=', with col in between.
void StartDict(morkEnv* ev);
void EndDict(morkEnv* ev);
void StartTable(morkEnv* ev, morkTable* ioTable);
void EndTable(morkEnv* ev);
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakWriter(morkWriter* me,
morkEnv* ev, morkWriter** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongWriter(morkWriter* me,
morkEnv* ev, morkWriter** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKTABLEROWCURSOR_ */

View File

@@ -1,93 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKYARN_
#include "morkYarn.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void
morkYarn::CloseMorkNode(morkEnv* ev) /*i*/ // CloseYarn() only if open
{
if ( this->IsOpenNode() )
{
this->MarkClosing();
this->CloseYarn(ev);
this->MarkShut();
}
}
/*public virtual*/
morkYarn::~morkYarn() /*i*/ // assert CloseYarn() executed earlier
{
MORK_ASSERT(mYarn_Body.mYarn_Buf==0);
}
/*public non-poly*/
morkYarn::morkYarn(morkEnv* ev, /*i*/
const morkUsage& inUsage, nsIMdbHeap* ioHeap)
: morkNode(ev, inUsage, ioHeap)
{
if ( ev->Good() )
mNode_Derived = morkDerived_kYarn;
}
/*public non-poly*/ void
morkYarn::CloseYarn(morkEnv* ev) /*i*/ // called by CloseMorkNode();
{
if ( this )
{
if ( this->IsNode() )
this->MarkShut();
else
this->NonNodeError(ev);
}
else
ev->NilPointerError();
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
/*static*/ void
morkYarn::NonYarnTypeError(morkEnv* ev)
{
ev->NewError("non morkYarn");
}
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,88 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKYARN_
#define _MORKYARN_ 1
#ifndef _MORK_
#include "mork.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kYarn /*i*/ 0x7952 /* ascii 'yR' */
/*| morkYarn: a reference counted nsIMdbYarn C struct. This is for use in those
**| few cases where single instances of reference counted buffers are needed
**| in Mork, and we expect few enough instances that overhead is not a factor
**| in decided whether to use such a thing.
|*/
class morkYarn : public morkNode { // refcounted yarn
// public: // slots inherited from morkNode (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
public: // state is public because the entire Mork system is private
mdbYarn mYarn_Body;
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseYarn() only if open
virtual ~morkYarn(); // assert that CloseYarn() executed earlier
public: // morkYarn construction & destruction
morkYarn(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap);
void CloseYarn(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkYarn(const morkYarn& other);
morkYarn& operator=(const morkYarn& other);
public: // dynamic type identification
mork_bool IsYarn() const
{ return IsNode() && mNode_Derived == morkDerived_kYarn; }
// } ===== end morkNode methods =====
public: // typing
static void NonYarnTypeError(morkEnv* ev);
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakYarn(morkYarn* me,
morkEnv* ev, morkYarn** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongYarn(morkYarn* me,
morkEnv* ev, morkYarn** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKYARN_ */

View File

@@ -1,725 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKHANDLE_
#include "morkHandle.h"
#endif
#ifndef _MORKCELL_
#include "morkCell.h"
#endif
#ifndef _MORKCELLOBJECT_
#include "morkCellObject.h"
#endif
#ifndef _MORKROWOBJECT_
#include "morkRowObject.h"
#endif
#ifndef _ORKINCELL_
#include "orkinCell.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _MORKPOOL_
#include "morkPool.h"
#endif
#ifndef _MORKROW_
#include "morkRow.h"
#endif
#ifndef _MORKATOM_
#include "morkAtom.h"
#endif
#ifndef _MORKSPACE_
#include "morkSpace.h"
#endif
#ifndef _MORKROWSPACE_
#include "morkRowSpace.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/* public virtual*/
orkinCell:: ~orkinCell() // morkHandle destructor does everything
{
}
/*protected non-poly construction*/
orkinCell::orkinCell(morkEnv* ev, // morkUsage is morkUsage_kPool
morkHandleFace* ioFace, // must not be nil, cookie for this handle
morkCellObject* ioObject) // must not be nil, the object for this handle
: morkHandle(ev, ioFace, ioObject, morkMagic_kCell)
{
// do not modify mNode_Derived; leave it equal to morkDerived_kHandle
}
/*static */ orkinCell*
orkinCell::MakeCell(morkEnv* ev, morkCellObject* ioObject)
{
mork_bool isEnv = ev->IsEnv();
MORK_ASSERT(isEnv);
if ( isEnv )
{
morkHandleFace* face = ev->NewHandle(sizeof(orkinCell));
if ( face )
return new(face) orkinCell(ev, face, ioObject);
else
ev->OutOfMemoryError();
}
return (orkinCell*) 0;
}
// ResyncWithRow() moved to the morkCellObject class:
// mork_bool
// orkinCell::ResyncWithRow(morkEnv* ev)
// {
// morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
// morkRow* row = cellObj->mCellObject_Row;
// mork_pos pos = 0;
// morkCell* cell = row->GetCell(ev, cellObj->mCellObject_Col, &pos);
// if ( cell )
// {
// cellObj->mCellObject_Pos = pos;
// cellObj->mCellObject_Cell = cell;
// cellObj->mCellObject_RowSeed = row->mRow_Seed;
// }
// else
// {
// cellObj->mCellObject_Cell = 0;
// cellObj->MissingRowColumnError(ev);
// }
// return ev->Good();
// }
morkEnv*
orkinCell::CanUseCell(nsIMdbEnv* mev, mork_bool inMutable,
mdb_err* outErr, morkCell** outCell) const
{
morkEnv* outEnv = 0;
morkCell* cell = 0;
morkEnv* ev = morkEnv::FromMdbEnv(mev);
if ( ev )
{
morkCellObject* cellObj = (morkCellObject*)
this->GetGoodHandleObject(ev, inMutable, morkMagic_kCell);
if ( cellObj )
{
if ( cellObj->IsCellObject() )
{
if ( cellObj->IsMutable() || !inMutable )
{
morkRowObject* rowObj = cellObj->mCellObject_RowObject;
if ( rowObj )
{
morkRow* row = cellObj->mCellObject_Row;
if ( row )
{
if ( rowObj->mRowObject_Row == row )
{
mork_u2 oldSeed = cellObj->mCellObject_RowSeed;
if ( row->mRow_Seed == oldSeed || cellObj->ResyncWithRow(ev) )
{
cell = cellObj->mCellObject_Cell;
if ( cell )
{
outEnv = ev;
}
else
cellObj->NilCellError(ev);
}
}
else
cellObj->WrongRowObjectRowError(ev);
}
else
cellObj->NilRowError(ev);
}
else
cellObj->NilRowObjectError(ev);
}
else
cellObj->NonMutableNodeError(ev);
}
else
cellObj->NonCellObjectTypeError(ev);
}
*outErr = ev->AsErr();
}
MORK_ASSERT(outEnv);
*outCell = cell;
return outEnv;
}
// { ===== begin nsIMdbISupports methods =====
/*virtual*/ mdb_err
orkinCell::AddRef() // add strong ref with no
{
morkEnv* ev = mHandle_Env;
if ( ev && ev->IsEnv() )
return this->Handle_AddStrongRef(ev->AsMdbEnv());
else
return morkEnv_kNonEnvTypeError;
}
/*virtual*/ mdb_err
orkinCell::Release() // cut strong ref
{
morkEnv* ev = mHandle_Env;
if ( ev && ev->IsEnv() )
return this->Handle_CutStrongRef(ev->AsMdbEnv());
else
return morkEnv_kNonEnvTypeError;
}
// } ===== end nsIMdbISupports methods =====
// { ===== begin nsIMdbObject methods =====
// { ----- begin attribute methods -----
/*virtual*/ mdb_err
orkinCell::IsFrozenMdbObject(nsIMdbEnv* mev, mdb_bool* outIsReadonly)
{
return this->Handle_IsFrozenMdbObject(mev, outIsReadonly);
}
// same as nsIMdbPort::GetIsPortReadonly() when this object is inside a port.
// } ----- end attribute methods -----
// { ----- begin factory methods -----
/*virtual*/ mdb_err
orkinCell::GetMdbFactory(nsIMdbEnv* mev, nsIMdbFactory** acqFactory)
{
return this->Handle_GetMdbFactory(mev, acqFactory);
}
// } ----- end factory methods -----
// { ----- begin ref counting for well-behaved cyclic graphs -----
/*virtual*/ mdb_err
orkinCell::GetWeakRefCount(nsIMdbEnv* mev, // weak refs
mdb_count* outCount)
{
return this->Handle_GetWeakRefCount(mev, outCount);
}
/*virtual*/ mdb_err
orkinCell::GetStrongRefCount(nsIMdbEnv* mev, // strong refs
mdb_count* outCount)
{
return this->Handle_GetStrongRefCount(mev, outCount);
}
/*virtual*/ mdb_err
orkinCell::AddWeakRef(nsIMdbEnv* mev)
{
return this->Handle_AddWeakRef(mev);
}
/*virtual*/ mdb_err
orkinCell::AddStrongRef(nsIMdbEnv* mev)
{
return this->Handle_AddStrongRef(mev);
}
/*virtual*/ mdb_err
orkinCell::CutWeakRef(nsIMdbEnv* mev)
{
return this->Handle_CutWeakRef(mev);
}
/*virtual*/ mdb_err
orkinCell::CutStrongRef(nsIMdbEnv* mev)
{
return this->Handle_CutStrongRef(mev);
}
/*virtual*/ mdb_err
orkinCell::CloseMdbObject(nsIMdbEnv* mev)
{
return this->Handle_CloseMdbObject(mev);
}
/*virtual*/ mdb_err
orkinCell::IsOpenMdbObject(nsIMdbEnv* mev, mdb_bool* outOpen)
{
return this->Handle_IsOpenMdbObject(mev, outOpen);
}
// } ----- end ref counting -----
// } ===== end nsIMdbObject methods =====
// { ===== begin nsIMdbBlob methods =====
// { ----- begin attribute methods -----
/*virtual*/ mdb_err
orkinCell::SetBlob(nsIMdbEnv* mev,
nsIMdbBlob* ioBlob)
{
MORK_USED_1(ioBlob);
mdb_err outErr = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
// remember row->MaybeDirtySpaceStoreAndRow();
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
return outErr;
} // reads inBlob slots
// when inBlob is in the same suite, this might be fastest cell-to-cell
/*virtual*/ mdb_err
orkinCell::ClearBlob( // make empty (so content has zero length)
nsIMdbEnv* mev)
{
mdb_err outErr = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
// remember row->MaybeDirtySpaceStoreAndRow();
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
return outErr;
}
// clearing a yarn is like SetYarn() with empty yarn instance content
/*virtual*/ mdb_err
orkinCell::GetBlobFill(nsIMdbEnv* mev,
mdb_fill* outFill)
// Same value that would be put into mYarn_Fill, if one called GetYarn()
// with a yarn instance that had mYarn_Buf==nil and mYarn_Size==0.
{
mdb_err outErr = 0;
mdb_fill fill = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
if ( outFill )
*outFill = fill;
return outErr;
} // size of blob
/*virtual*/ mdb_err
orkinCell::SetYarn(nsIMdbEnv* mev,
const mdbYarn* inYarn)
{
mdb_err outErr = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
morkRow* row = cellObj->mCellObject_Row;
if ( row )
{
morkStore* store = row->GetRowSpaceStore(ev);
if ( store )
{
cell->SetYarn(ev, inYarn, store);
if ( row->IsRowClean() && store->mStore_CanDirty )
row->MaybeDirtySpaceStoreAndRow();
}
}
else
ev->NilPointerError();
outErr = ev->AsErr();
}
return outErr;
} // reads from yarn slots
// make this text object contain content from the yarn's buffer
/*virtual*/ mdb_err
orkinCell::GetYarn(nsIMdbEnv* mev,
mdbYarn* outYarn)
{
mdb_err outErr = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
morkAtom* atom = cell->GetAtom();
atom->GetYarn(outYarn);
outErr = ev->AsErr();
}
return outErr;
} // writes some yarn slots
// copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form
/*virtual*/ mdb_err
orkinCell::AliasYarn(nsIMdbEnv* mev,
mdbYarn* outYarn)
{
mdb_err outErr = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
morkAtom* atom = cell->GetAtom();
atom->AliasYarn(outYarn);
outErr = ev->AsErr();
}
return outErr;
} // writes ALL yarn slots
// } ----- end attribute methods -----
// } ===== end nsIMdbBlob methods =====
// { ===== begin nsIMdbCell methods =====
// { ----- begin attribute methods -----
/*virtual*/ mdb_err
orkinCell::SetColumn(nsIMdbEnv* mev, mdb_column inColumn)
{
MORK_USED_1(inColumn);
mdb_err outErr = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
// remember row->MaybeDirtySpaceStoreAndRow();
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
MORK_USED_1(cellObj);
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
return outErr;
}
/*virtual*/ mdb_err
orkinCell::GetColumn(nsIMdbEnv* mev, mdb_column* outColumn)
{
mdb_err outErr = 0;
mdb_column col = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
col = cellObj->mCellObject_Col;
outErr = ev->AsErr();
}
if ( outColumn )
*outColumn = col;
return outErr;
}
/*virtual*/ mdb_err
orkinCell::GetCellInfo( // all cell metainfo except actual content
nsIMdbEnv* mev,
mdb_column* outColumn, // the column in the containing row
mdb_fill* outBlobFill, // the size of text content in bytes
mdbOid* outChildOid, // oid of possible row or table child
mdb_bool* outIsRowChild) // nonzero if child, and a row child
// Checking all cell metainfo is a good way to avoid forcing a large cell
// in to memory when you don't actually want to use the content.
{
mdb_err outErr = 0;
mdb_bool isRowChild = morkBool_kFalse;
mdbOid childOid;
childOid.mOid_Scope = 0;
childOid.mOid_Id = 0;
mork_fill blobFill = 0;
mdb_column column = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
morkCellObject* cellObj;
cellObj = (morkCellObject*) mHandle_Object;
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
if ( outIsRowChild )
*outIsRowChild = isRowChild;
if ( outChildOid )
*outChildOid = childOid;
if ( outBlobFill )
*outBlobFill = blobFill;
if ( outColumn )
*outColumn = column;
return outErr;
}
/*virtual*/ mdb_err
orkinCell::GetRow(nsIMdbEnv* mev, // parent row for this cell
nsIMdbRow** acqRow)
{
mdb_err outErr = 0;
nsIMdbRow* outRow = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
morkRowObject* rowObj = cellObj->mCellObject_RowObject;
outRow = rowObj->AcquireRowHandle(ev);
outErr = ev->AsErr();
}
if ( acqRow )
*acqRow = outRow;
return outErr;
}
/*virtual*/ mdb_err
orkinCell::GetPort(nsIMdbEnv* mev, // port containing cell
nsIMdbPort** acqPort)
{
mdb_err outErr = 0;
nsIMdbPort* outPort = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
morkRow* row = cellObj->mCellObject_Row;
if ( row )
{
morkStore* store = row->GetRowSpaceStore(ev);
if ( store )
outPort = store->AcquireStoreHandle(ev);
}
else
ev->NilPointerError();
outErr = ev->AsErr();
}
if ( acqPort )
*acqPort = outPort;
return outErr;
}
// } ----- end attribute methods -----
// { ----- begin children methods -----
/*virtual*/ mdb_err
orkinCell::HasAnyChild( // does cell have a child instead of text?
nsIMdbEnv* mev,
mdbOid* outOid, // out id of row or table (or unbound if no child)
mdb_bool* outIsRow) // nonzero if child is a row (rather than a table)
{
mdb_err outErr = 0;
mdb_bool isRow = morkBool_kFalse;
outOid->mOid_Scope = 0;
outOid->mOid_Id = morkId_kMinusOne;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
morkAtom* atom = cellObj->GetCellAtom(ev);
if ( atom )
{
isRow = atom->IsRowOid();
if ( isRow || atom->IsTableOid() )
*outOid = ((morkOidAtom*) atom)->mOidAtom_Oid;
}
outErr = ev->AsErr();
}
if ( outIsRow )
*outIsRow = isRow;
return outErr;
}
/*virtual*/ mdb_err
orkinCell::GetAnyChild( // access table of specific attribute
nsIMdbEnv* mev, // context
nsIMdbRow** acqRow, // child row (or null)
nsIMdbTable** acqTable) // child table (or null)
{
mdb_err outErr = 0;
nsIMdbRow* outRow = 0;
nsIMdbTable* outTable = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
morkCellObject* cellObj;
cellObj = (morkCellObject*) mHandle_Object;
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
MORK_ASSERT(acqTable);
if ( acqTable )
*acqTable = outTable;
MORK_ASSERT(acqRow);
if ( acqRow )
*acqRow = outRow;
return outErr;
}
/*virtual*/ mdb_err
orkinCell::SetChildRow( // access table of specific attribute
nsIMdbEnv* mev, // context
nsIMdbRow* ioRow)
{
MORK_USED_1(ioRow);
mdb_err outErr = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
// remember row->MaybeDirtySpaceStoreAndRow();
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
MORK_USED_1(cellObj);
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
return outErr;
} // inRow must be bound inside this same db port
/*virtual*/ mdb_err
orkinCell::GetChildRow( // access row of specific attribute
nsIMdbEnv* mev, // context
nsIMdbRow** acqRow) // acquire child row (or nil if no child)
{
mdb_err outErr = 0;
nsIMdbRow* outRow = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
morkCellObject* cellObj;
cellObj = (morkCellObject*) mHandle_Object;
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
if ( acqRow )
*acqRow = outRow;
return outErr;
}
/*virtual*/ mdb_err
orkinCell::SetChildTable( // access table of specific attribute
nsIMdbEnv* mev, // context
nsIMdbTable* inTable) // table must be bound inside this same db port
{
MORK_USED_1(inTable);
mdb_err outErr = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
// remember row->MaybeDirtySpaceStoreAndRow();
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
MORK_USED_1(cellObj);
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
return outErr;
}
/*virtual*/ mdb_err
orkinCell::GetChildTable( // access table of specific attribute
nsIMdbEnv* mev, // context
nsIMdbTable** acqTable) // acquire child tabdle (or nil if no chil)
{
mdb_err outErr = 0;
nsIMdbTable* outTable = 0;
morkCell* cell = 0;
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
&outErr, &cell);
if ( ev )
{
morkCellObject* cellObj;
cellObj = (morkCellObject*) mHandle_Object;
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
if ( acqTable )
*acqTable = outTable;
return outErr;
}
// } ----- end children methods -----
// } ===== end nsIMdbCell methods =====
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,253 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _ORKINCELL_
#define _ORKINCELL_ 1
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKHANDLE_
#include "morkHandle.h"
#endif
#ifndef _MORKCELL_
#include "morkCell.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkMagic_kCell 0x43656C6C /* ascii 'Cell' */
class orkinCell : public morkHandle, public nsIMdbCell { // nsIMdbBlob
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
// virtual void CloseMorkNode(morkEnv* ev); // morkHandle is fine
virtual ~orkinCell(); // morkHandle destructor does everything
protected: // construction is protected (use the static Make() method)
orkinCell(morkEnv* ev, // note morkUsage is always morkUsage_kPool
morkHandleFace* ioFace, // must not be nil, cookie for this handle
morkCellObject* ioObject); // must not be nil, the object for this handle
// void CloseHandle(morkEnv* ev); // don't need to specialize closing
private: // copying is not allowed
orkinCell(const morkHandle& other);
orkinCell& operator=(const morkHandle& other);
// public: // dynamic type identification
// mork_bool IsHandle() const //
// { return IsNode() && mNode_Derived == morkDerived_kHandle; }
// } ===== end morkNode methods =====
protected: // morkHandle memory management operators
void* operator new(size_t inSize, morkPool& ioPool, morkEnv* ev)
{ return ioPool.NewHandle(ev, inSize); }
void* operator new(size_t inSize, morkHandleFace* ioFace)
{ MORK_USED_1(inSize); return ioFace; }
void operator delete(void* ioAddress)
{ morkNode::OnDeleteAssert(ioAddress); }
// do NOT call delete on morkHandle instances. They are collected.
public: // construction:
static orkinCell* MakeCell(morkEnv* ev, morkCellObject* ioObject);
public: // utilities:
// ResyncWithRow() moved to the morkCellObject class:
// mork_bool ResyncWithRow(morkEnv* ev); // return ev->Good()
morkEnv* CanUseCell(nsIMdbEnv* ev, mork_bool inMutable,
mdb_err* outErr, morkCell** outCell) const;
public: // type identification
mork_bool IsOrkinCell() const
{ return mHandle_Magic == morkMagic_kCell; }
mork_bool IsOrkinCellHandle() const
{ return this->IsHandle() && this->IsOrkinCell(); }
// { ===== begin nsIMdbISupports methods =====
virtual mdb_err AddRef(); // add strong ref with no
virtual mdb_err Release(); // cut strong ref
// } ===== end nsIMdbObject methods =====
// { ===== begin nsIMdbObject methods =====
// { ----- begin attribute methods -----
virtual mdb_err IsFrozenMdbObject(nsIMdbEnv* ev, mdb_bool* outIsReadonly);
// same as nsIMdbPort::GetIsPortReadonly() when this object is inside a port.
// } ----- end attribute methods -----
// { ----- begin factory methods -----
virtual mdb_err GetMdbFactory(nsIMdbEnv* ev, nsIMdbFactory** acqFactory);
// } ----- end factory methods -----
// { ----- begin ref counting for well-behaved cyclic graphs -----
virtual mdb_err GetWeakRefCount(nsIMdbEnv* ev, // weak refs
mdb_count* outCount);
virtual mdb_err GetStrongRefCount(nsIMdbEnv* ev, // strong refs
mdb_count* outCount);
virtual mdb_err AddWeakRef(nsIMdbEnv* ev);
virtual mdb_err AddStrongRef(nsIMdbEnv* ev);
virtual mdb_err CutWeakRef(nsIMdbEnv* ev);
virtual mdb_err CutStrongRef(nsIMdbEnv* ev);
virtual mdb_err CloseMdbObject(nsIMdbEnv* ev); // called at strong refs zero
virtual mdb_err IsOpenMdbObject(nsIMdbEnv* ev, mdb_bool* outOpen);
// } ----- end ref counting -----
// } ===== end nsIMdbObject methods =====
// { ===== begin nsIMdbBlob methods =====
// { ----- begin attribute methods -----
virtual mdb_err SetBlob(nsIMdbEnv* ev,
nsIMdbBlob* ioBlob); // reads inBlob slots
// when inBlob is in the same suite, this might be fastest cell-to-cell
virtual mdb_err ClearBlob( // make empty (so content has zero length)
nsIMdbEnv* ev);
// clearing a yarn is like SetYarn() with empty yarn instance content
virtual mdb_err GetBlobFill(nsIMdbEnv* ev,
mdb_fill* outFill); // size of blob
// Same value that would be put into mYarn_Fill, if one called GetYarn()
// with a yarn instance that had mYarn_Buf==nil and mYarn_Size==0.
virtual mdb_err SetYarn(nsIMdbEnv* ev,
const mdbYarn* inYarn); // reads from yarn slots
// make this text object contain content from the yarn's buffer
virtual mdb_err GetYarn(nsIMdbEnv* ev,
mdbYarn* outYarn); // writes some yarn slots
// copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form
virtual mdb_err AliasYarn(nsIMdbEnv* ev,
mdbYarn* outYarn); // writes ALL yarn slots
// AliasYarn() reveals sensitive internal text buffer state to the caller
// by setting mYarn_Buf to point into the guts of this text implementation.
//
// The caller must take great care to avoid writing on this space, and to
// avoid calling any method that would cause the state of this text object
// to change (say by directly or indirectly setting the text to hold more
// content that might grow the size of the buffer and free the old buffer).
// In particular, callers should scrupulously avoid making calls into the
// mdb interface to write any content while using the buffer pointer found
// in the returned yarn instance. Best safe usage involves copying content
// into some other kind of external content representation beyond mdb.
//
// (The original design of this method a week earlier included the concept
// of very fast and efficient cooperative locking via a pointer to some lock
// member slot. But let's ignore that complexity in the current design.)
//
// AliasYarn() is specifically intended as the first step in transferring
// content from nsIMdbBlob to a nsString representation, without forcing extra
// allocations and/or memory copies. (A standard nsIMdbBlob_AsString() utility
// will use AliasYarn() as the first step in setting a nsString instance.)
//
// This is an alternative to the GetYarn() method, which has copy semantics
// only; AliasYarn() relaxes a robust safety principle only for performance
// reasons, to accomodate the need for callers to transform text content to
// some other canonical representation that would necessitate an additional
// copy and transformation when such is incompatible with the mdbYarn format.
//
// The implementation of AliasYarn() should have extremely little overhead
// besides the virtual dispatch to the method implementation, and the code
// necessary to populate all the mdbYarn member slots with internal buffer
// address and metainformation that describes the buffer content. Note that
// mYarn_Grow must always be set to nil to indicate no resizing is allowed.
// } ----- end attribute methods -----
// } ===== end nsIMdbBlob methods =====
// { ===== begin nsIMdbCell methods =====
// { ----- begin attribute methods -----
virtual mdb_err SetColumn(nsIMdbEnv* ev, mdb_column inColumn);
virtual mdb_err GetColumn(nsIMdbEnv* ev, mdb_column* outColumn);
virtual mdb_err GetCellInfo( // all cell metainfo except actual content
nsIMdbEnv* ev,
mdb_column* outColumn, // the column in the containing row
mdb_fill* outBlobFill, // the size of text content in bytes
mdbOid* outChildOid, // oid of possible row or table child
mdb_bool* outIsRowChild); // nonzero if child, and a row child
// Checking all cell metainfo is a good way to avoid forcing a large cell
// in to memory when you don't actually want to use the content.
virtual mdb_err GetRow(nsIMdbEnv* ev, // parent row for this cell
nsIMdbRow** acqRow);
virtual mdb_err GetPort(nsIMdbEnv* ev, // port containing cell
nsIMdbPort** acqPort);
// } ----- end attribute methods -----
// { ----- begin children methods -----
virtual mdb_err HasAnyChild( // does cell have a child instead of text?
nsIMdbEnv* ev,
mdbOid* outOid, // out id of row or table (or unbound if no child)
mdb_bool* outIsRow); // nonzero if child is a row (rather than a table)
virtual mdb_err GetAnyChild( // access table of specific attribute
nsIMdbEnv* ev, // context
nsIMdbRow** acqRow, // child row (or null)
nsIMdbTable** acqTable); // child table (or null)
virtual mdb_err SetChildRow( // access table of specific attribute
nsIMdbEnv* ev, // context
nsIMdbRow* ioRow); // inRow must be bound inside this same db port
virtual mdb_err GetChildRow( // access row of specific attribute
nsIMdbEnv* ev, // context
nsIMdbRow** acqRow); // acquire child row (or nil if no child)
virtual mdb_err SetChildTable( // access table of specific attribute
nsIMdbEnv* ev, // context
nsIMdbTable* inTable); // table must be bound inside this same db port
virtual mdb_err GetChildTable( // access table of specific attribute
nsIMdbEnv* ev, // context
nsIMdbTable** acqTable); // acquire child table (or nil if no child)
// } ----- end children methods -----
// } ===== end nsIMdbCell methods =====
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _ORKINCELL_ */

View File

@@ -1,433 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKHANDLE_
#include "morkHandle.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
#ifndef _ORKINENV_
#include "orkinEnv.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/* public virtual*/
orkinEnv:: ~orkinEnv() // morkHandle destructor does everything
{
}
/*protected non-poly construction*/
orkinEnv::orkinEnv(morkEnv* ev, // morkUsage is morkUsage_kPool
morkHandleFace* ioFace, // must not be nil, cookie for this handle
morkEnv* ioObject) // must not be nil, the object for this handle
: morkHandle(ev, ioFace, ioObject, morkMagic_kEnv)
{
// do not modify mNode_Derived; leave it equal to morkDerived_kHandle
}
/*static */ orkinEnv*
orkinEnv::MakeEnv(morkEnv* ev, morkEnv* ioObject)
{
mork_bool isEnv = ev->IsEnv();
MORK_ASSERT(isEnv);
if ( isEnv )
{
morkHandleFace* face = ev->NewHandle(sizeof(orkinEnv));
if ( face )
return new(face) orkinEnv(ev, face, ioObject);
else
ev->OutOfMemoryError();
}
return (orkinEnv*) 0;
}
morkEnv*
orkinEnv::CanUseEnv(mork_bool inMutable, mdb_err* outErr) const
{
MORK_USED_1(inMutable);
morkEnv* outEnv = 0;
mdb_err err = morkEnv_kBadEnvError;
if ( this->IsHandle() )
{
if ( this->IsOpenNode() )
{
morkEnv* ev = (morkEnv*) this->mHandle_Object;
if ( ev && ev->IsEnv() )
{
outEnv = ev;
err = 0;
}
else
{
err = morkEnv_kNonEnvTypeError;
MORK_ASSERT(outEnv);
}
}
else
{
err = morkEnv_kNonOpenNodeError;
MORK_ASSERT(outEnv);
}
}
else
{
err = morkEnv_kNonHandleTypeError;
MORK_ASSERT(outEnv);
}
*outErr = err;
return outEnv;
}
// { ===== begin nsIMdbISupports methods =====
/*virtual*/ mdb_err
orkinEnv::AddRef() // add strong ref with no
{
morkEnv* ev = mHandle_Env;
if ( ev && ev->IsEnv() )
return this->Handle_AddStrongRef(ev->AsMdbEnv());
else
return morkEnv_kNonEnvTypeError;
}
/*virtual*/ mdb_err
orkinEnv::Release() // cut strong ref
{
morkEnv* ev = mHandle_Env;
if ( ev && ev->IsEnv() )
return this->Handle_CutStrongRef(ev->AsMdbEnv());
else
return morkEnv_kNonEnvTypeError;
}
// } ===== end nsIMdbObject methods =====
// { ===== begin nsIMdbObject methods =====
// { ----- begin attribute methods -----
/*virtual*/ mdb_err
orkinEnv::IsFrozenMdbObject(nsIMdbEnv* mev, mdb_bool* outIsReadonly)
{
return this->Handle_IsFrozenMdbObject(mev, outIsReadonly);
}
// same as nsIMdbPort::GetIsPortReadonly() when this object is inside a port.
// } ----- end attribute methods -----
// { ----- begin factory methods -----
/*virtual*/ mdb_err
orkinEnv::GetMdbFactory(nsIMdbEnv* mev, nsIMdbFactory** acqFactory)
{
return this->Handle_GetMdbFactory(mev, acqFactory);
}
// } ----- end factory methods -----
// { ----- begin ref counting for well-behaved cyclic graphs -----
/*virtual*/ mdb_err
orkinEnv::GetWeakRefCount(nsIMdbEnv* mev, // weak refs
mdb_count* outCount)
{
return this->Handle_GetWeakRefCount(mev, outCount);
}
/*virtual*/ mdb_err
orkinEnv::GetStrongRefCount(nsIMdbEnv* mev, // strong refs
mdb_count* outCount)
{
return this->Handle_GetStrongRefCount(mev, outCount);
}
/*virtual*/ mdb_err
orkinEnv::AddWeakRef(nsIMdbEnv* mev)
{
return this->Handle_AddWeakRef(mev);
}
/*virtual*/ mdb_err
orkinEnv::AddStrongRef(nsIMdbEnv* mev)
{
return this->Handle_AddStrongRef(mev);
}
/*virtual*/ mdb_err
orkinEnv::CutWeakRef(nsIMdbEnv* mev)
{
return this->Handle_CutWeakRef(mev);
}
/*virtual*/ mdb_err
orkinEnv::CutStrongRef(nsIMdbEnv* mev)
{
return this->Handle_CutStrongRef(mev);
}
/*virtual*/ mdb_err
orkinEnv::CloseMdbObject(nsIMdbEnv* mev)
{
return this->Handle_CloseMdbObject(mev);
}
/*virtual*/ mdb_err
orkinEnv::IsOpenMdbObject(nsIMdbEnv* mev, mdb_bool* outOpen)
{
return this->Handle_IsOpenMdbObject(mev, outOpen);
}
// } ----- end ref counting -----
// } ===== end nsIMdbObject methods =====
// { ===== begin nsIMdbEnv methods =====
// { ----- begin attribute methods -----
/*virtual*/ mdb_err
orkinEnv::GetErrorCount(mdb_count* outCount,
mdb_bool* outShouldAbort)
{
mdb_err outErr = 0;
mdb_count count = 1;
mork_bool shouldAbort = morkBool_kFalse;
morkEnv* ev = this->CanUseEnv(/*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
count = (mdb_count) ev->mEnv_ErrorCount;
shouldAbort = ev->mEnv_ShouldAbort;
}
if ( outCount )
*outCount = count;
if ( outShouldAbort )
*outShouldAbort = shouldAbort;
return outErr;
}
/*virtual*/ mdb_err
orkinEnv::GetWarningCount(mdb_count* outCount,
mdb_bool* outShouldAbort)
{
mdb_err outErr = 0;
mdb_count count = 1;
mork_bool shouldAbort = morkBool_kFalse;
morkEnv* ev = this->CanUseEnv(/*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
count = (mdb_count) ev->mEnv_WarningCount;
shouldAbort = ev->mEnv_ShouldAbort;
}
if ( outCount )
*outCount = count;
if ( outShouldAbort )
*outShouldAbort = shouldAbort;
return outErr;
}
/*virtual*/ mdb_err
orkinEnv::GetEnvBeVerbose(mdb_bool* outBeVerbose)
{
mdb_err outErr = 0;
mork_bool beVerbose = morkBool_kFalse;
morkEnv* ev = this->CanUseEnv(/*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
beVerbose = ev->mEnv_BeVerbose;
}
if ( outBeVerbose )
*outBeVerbose = beVerbose;
return outErr;
}
/*virtual*/ mdb_err
orkinEnv::SetEnvBeVerbose(mdb_bool inBeVerbose)
{
mdb_err outErr = 0;
morkEnv* ev = this->CanUseEnv(/*inMutable*/ morkBool_kTrue, &outErr);
if ( ev )
{
ev->mEnv_BeVerbose = inBeVerbose;
}
return outErr;
}
/*virtual*/ mdb_err
orkinEnv::GetDoTrace(mdb_bool* outDoTrace)
{
mdb_err outErr = 0;
mork_bool doTrace = morkBool_kFalse;
morkEnv* ev = this->CanUseEnv(/*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
doTrace = ev->mEnv_DoTrace;
}
if ( outDoTrace )
*outDoTrace = doTrace;
return outErr;
}
/*virtual*/ mdb_err
orkinEnv::SetDoTrace(mdb_bool inDoTrace)
{
mdb_err outErr = 0;
morkEnv* ev = this->CanUseEnv(/*inMutable*/ morkBool_kTrue, &outErr);
if ( ev )
{
ev->mEnv_DoTrace = inDoTrace;
}
return outErr;
}
/*virtual*/ mdb_err
orkinEnv::GetAutoClear(mdb_bool* outAutoClear)
{
mdb_err outErr = 0;
mork_bool autoClear = morkBool_kFalse;
morkEnv* ev = this->CanUseEnv(/*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
autoClear = ev->DoAutoClear();
}
if ( outAutoClear )
*outAutoClear = autoClear;
return outErr;
}
/*virtual*/ mdb_err
orkinEnv::SetAutoClear(mdb_bool inAutoClear)
{
mdb_err outErr = 0;
morkEnv* ev = this->CanUseEnv(/*inMutable*/ morkBool_kTrue, &outErr);
if ( ev )
{
if ( inAutoClear )
ev->EnableAutoClear();
else
ev->DisableAutoClear();
}
return outErr;
}
/*virtual*/ mdb_err
orkinEnv::GetErrorHook(nsIMdbErrorHook** acqErrorHook)
{
mdb_err outErr = 0;
nsIMdbErrorHook* outErrorHook = 0;
morkEnv* ev = this->CanUseEnv(/*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
outErrorHook = ev->mEnv_ErrorHook;
}
if ( acqErrorHook )
*acqErrorHook = outErrorHook;
return outErr;
}
/*virtual*/ mdb_err
orkinEnv::SetErrorHook(
nsIMdbErrorHook* ioErrorHook) // becomes referenced
{
mdb_err outErr = 0;
morkEnv* ev = this->CanUseEnv(/*inMutable*/ morkBool_kTrue, &outErr);
if ( ev )
{
ev->mEnv_ErrorHook = ioErrorHook;
}
return outErr;
}
/*virtual*/ mdb_err
orkinEnv::GetHeap(nsIMdbHeap** acqHeap)
{
mdb_err outErr = 0;
nsIMdbHeap* outHeap = 0;
morkEnv* ev = this->CanUseEnv(/*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
nsIMdbHeap* heap = ev->mEnv_Heap;
if ( heap && heap->AddStrongRef(this) == 0 )
outHeap = heap;
}
if ( acqHeap )
*acqHeap = outHeap;
return outErr;
}
/*virtual*/ mdb_err
orkinEnv::SetHeap(
nsIMdbHeap* ioHeap) // becomes referenced
{
mdb_err outErr = 0;
morkEnv* ev = this->CanUseEnv(/*inMutable*/ morkBool_kTrue, &outErr);
if ( ev )
{
nsIMdbHeap_SlotStrongHeap(ioHeap, ev, &ev->mEnv_Heap);
}
return outErr;
}
// } ----- end attribute methods -----
/*virtual*/ mdb_err
orkinEnv::ClearErrors() // clear errors beore re-entering db API
{
mdb_err outErr = 0;
morkEnv* ev = this->CanUseEnv(/*inMutable*/ morkBool_kTrue, &outErr);
if ( ev )
{
ev->mEnv_ErrorCount = 0;
ev->mEnv_ErrorCode = 0;
ev->mEnv_ShouldAbort = morkBool_kFalse;
}
return outErr;
}
/*virtual*/ mdb_err
orkinEnv::ClearWarnings() // clear warning
{
mdb_err outErr = 0;
morkEnv* ev = this->CanUseEnv(/*inMutable*/ morkBool_kTrue, &outErr);
if ( ev )
{
ev->mEnv_WarningCount = 0;
}
return outErr;
}
/*virtual*/ mdb_err
orkinEnv::ClearErrorsAndWarnings() // clear both errors & warnings
{
mdb_err outErr = 0;
morkEnv* ev = this->CanUseEnv(/*inMutable*/ morkBool_kTrue, &outErr);
if ( ev )
{
ev->ClearMorkErrorsAndWarnings();
}
return outErr;
}
// } ===== end nsIMdbEnv methods =====
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

View File

@@ -1,167 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _ORKINENV_
#define _ORKINENV_ 1
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKHANDLE_
#include "morkHandle.h"
#endif
#ifndef _MORKEnv_
#include "morkEnv.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkMagic_kEnv 0x456E7669 /* ascii 'Envi' */
/*| orkinEnv:
|*/
class orkinEnv : public morkHandle, public nsIMdbEnv { // nsIMdbObject
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
// virtual void CloseMorkNode(morkEnv* ev); // morkHandle is fine
virtual ~orkinEnv(); // morkHandle destructor does everything
protected: // construction is protected (use the static Make() method)
orkinEnv(morkEnv* ev, // note morkUsage is always morkUsage_kPool
morkHandleFace* ioFace, // must not be nil, cookie for this handle
morkEnv* ioObject); // must not be nil, the object for this handle
// void CloseHandle(morkEnv* ev); // don't need to specialize closing
private: // copying is not allowed
orkinEnv(const morkHandle& other);
orkinEnv& operator=(const morkHandle& other);
// public: // dynamic type identification
// mork_bool IsHandle() const //
// { return IsNode() && mNode_Derived == morkDerived_kHandle; }
// } ===== end morkNode methods =====
protected: // morkHandle memory management operators
void* operator new(size_t inSize, morkPool& ioPool, morkEnv* ev)
{ return ioPool.NewHandle(ev, inSize); }
void* operator new(size_t inSize, morkHandleFace* ioFace)
{ MORK_USED_1(inSize); return ioFace; }
void operator delete(void* ioAddress)
{ morkNode::OnDeleteAssert(ioAddress); }
// do NOT call delete on morkHandle instances. They are collected.
public: // construction:
static orkinEnv* MakeEnv(morkEnv* ev, morkEnv* ioObject);
public: // utilities:
morkEnv* CanUseEnv(mork_bool inMutable, mdb_err* outErr) const;
public: // type identification
mork_bool IsOrkinEnv() const
{ return mHandle_Magic == morkMagic_kEnv; }
mork_bool IsOrkinEnvHandle() const
{ return this->IsHandle() && this->IsOrkinEnv(); }
public:
// { ===== begin nsIMdbISupports methods =====
virtual mdb_err AddRef(); // add strong ref with no
virtual mdb_err Release(); // cut strong ref
// } ===== end nsIMdbObject methods =====
// { ===== begin nsIMdbObject methods =====
// { ----- begin attribute methods -----
virtual mdb_err IsFrozenMdbObject(nsIMdbEnv* ev, mdb_bool* outIsReadonly);
// same as nsIMdbPort::GetIsPortReadonly() when this object is inside a port.
// } ----- end attribute methods -----
// { ----- begin factory methods -----
virtual mdb_err GetMdbFactory(nsIMdbEnv* ev, nsIMdbFactory** acqFactory);
// } ----- end factory methods -----
// { ----- begin ref counting for well-behaved cyclic graphs -----
virtual mdb_err GetWeakRefCount(nsIMdbEnv* ev, // weak refs
mdb_count* outCount);
virtual mdb_err GetStrongRefCount(nsIMdbEnv* ev, // strong refs
mdb_count* outCount);
virtual mdb_err AddWeakRef(nsIMdbEnv* ev);
virtual mdb_err AddStrongRef(nsIMdbEnv* ev);
virtual mdb_err CutWeakRef(nsIMdbEnv* ev);
virtual mdb_err CutStrongRef(nsIMdbEnv* ev);
virtual mdb_err CloseMdbObject(nsIMdbEnv* ev); // called at strong refs zero
virtual mdb_err IsOpenMdbObject(nsIMdbEnv* ev, mdb_bool* outOpen);
// } ----- end ref counting -----
// } ===== end nsIMdbObject methods =====
// { ===== begin nsIMdbEnv methods =====
// { ----- begin attribute methods -----
virtual mdb_err GetErrorCount(mdb_count* outCount,
mdb_bool* outShouldAbort);
virtual mdb_err GetWarningCount(mdb_count* outCount,
mdb_bool* outShouldAbort);
virtual mdb_err GetEnvBeVerbose(mdb_bool* outBeVerbose);
virtual mdb_err SetEnvBeVerbose(mdb_bool inBeVerbose);
virtual mdb_err GetDoTrace(mdb_bool* outDoTrace);
virtual mdb_err SetDoTrace(mdb_bool inDoTrace);
virtual mdb_err GetAutoClear(mdb_bool* outAutoClear);
virtual mdb_err SetAutoClear(mdb_bool inAutoClear);
virtual mdb_err GetErrorHook(nsIMdbErrorHook** acqErrorHook);
virtual mdb_err SetErrorHook(
nsIMdbErrorHook* ioErrorHook); // becomes referenced
virtual mdb_err GetHeap(nsIMdbHeap** acqHeap);
virtual mdb_err SetHeap(
nsIMdbHeap* ioHeap); // becomes referenced
// } ----- end attribute methods -----
virtual mdb_err ClearErrors(); // clear errors beore re-entering db API
virtual mdb_err ClearWarnings(); // clear warnings
virtual mdb_err ClearErrorsAndWarnings(); // clear both errors & warnings
// } ===== end nsIMdbEnv methods =====
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _ORKINENV_ */

View File

@@ -1,91 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MDB_
#include "mdb.h"
#endif
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _ORKINERRORHOOK_
#include "orkinErrorHook.h"
#endif
#ifndef _MORKENV_
#include "morkEnv.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
orkinHeap::orkinHeap() // does nothing
{
}
/*virtual*/
orkinHeap::~orkinHeap() // does nothing
{
}
// { ===== begin nsIMdbHeap methods =====
/*virtual*/ mdb_err
orkinHeap::Alloc(nsIMdbEnv* ev, // allocate a piece of memory
mdb_size inSize, // requested size of new memory block
void** outBlock) // memory block of inSize bytes, or nil
{
mdb_err outErr = 0;
void* block = new char[ inSize ];
if ( !block )
outErr = morkEnv_kOutOfMemoryError;
MORK_ASSERT(outBlock);
if ( outBlock )
*outBlock = block;
return outErr;
}
/*virtual*/ mdb_err
orkinHeap::Free(nsIMdbEnv* ev, // free block allocated earlier by Alloc()
void* inBlock)
{
MORK_ASSERT(inBlock);
if ( inBlock )
delete [] inBlock;
return 0;
}
/*virtual*/ mdb_err
orkinHeap::AddStrongRef(nsIMdbEnv* ev) // does nothing
{
MORK_USED_1(ev);
return 0;
}
/*virtual*/ mdb_err
orkinHeap::CutStrongRef(nsIMdbEnv* ev) // does nothing
{
MORK_USED_1(ev);
return 0;
}
// } ===== end nsIMdbHeap methods =====
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

Some files were not shown because too many files have changed in this diff Show More