aboutsummaryrefslogtreecommitdiff
path: root/SrcShared/EcmIf.h
diff options
context:
space:
mode:
Diffstat (limited to 'SrcShared/EcmIf.h')
-rw-r--r--SrcShared/EcmIf.h388
1 files changed, 388 insertions, 0 deletions
diff --git a/SrcShared/EcmIf.h b/SrcShared/EcmIf.h
new file mode 100644
index 0000000..fc96525
--- /dev/null
+++ b/SrcShared/EcmIf.h
@@ -0,0 +1,388 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 PocketPyro, Inc.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+
+#ifndef EcmIf_h
+#define EcmIf_h
+
+#include <string>
+
+/*
+ This file is the root file for ECM, the Extended Component Model
+ system used within the Palm OS Emulator.
+
+ ECM is a COM-like component system. "Packages" (that is, plug-ins
+ in the form of DLLs and the like) publicize their functionality in
+ the form of "interfaces". Packages can be queried (that is, the
+ module can be asked for a particular interface by name, and the
+ module can either return the interface, or fail, indicating that the
+ requested facility is not supported).
+
+ Interfaces are expressed as a table of function pointers. As such,
+ they are very similar to C++ vtables, are are often created using
+ C++ class definitions.
+
+ Every interface has base functionality. That is, every interface
+ starts off its function table with three standard functions:
+ RequestInterface, Refer, and Release. These three functions are
+ defined as member functions of the pure virtual class IEcmComponent.
+ Therefore, for consistancy, all C++ classes defining interfaces
+ should ultimately descend from IEcmComponent.
+
+ The three methods in IEcmComponent are pure virtual, and so need to
+ be implemented in the class descending from it. The implementation
+ of these functions will likely be the same for all interfaces, and
+ so there is a concrete subclass of IEcmComponent that provides a
+ standard implementation. This subclass is EcmObject. Therefore,
+ most interface implementation classes will probably descend from
+ EcmObject and not directly from IEcmComponent.
+
+ When an interface is defined (that is, the set of functions in the
+ function table is established), it is introduced with the macro
+ "ecm_interface". This tells the reader that the following C++
+ struct/class merely defines a set of functions for a client to use.
+ Thus a new interface would look as follows:
+
+ ecm_interface MyBaseInterface
+ {
+ virtual EcmErr MyFunction1() = 0;
+ virtual EcmErr MyFunction2() = 0;
+ virtual EcmErr MyFunction3() = 0;
+ };
+
+ When an interface needs to be extended (that is, a base interface
+ needs to have some more functions added to it), the interface
+ is again introduced with "ecm_interface", but is followed by the
+ macro "ecm_extends" in the place where a C++ class indicates the
+ base class it descends from. Thus, an interface that inherited
+ from a base interface would look as follows:
+
+ ecm_interface MyDerivedInterface : ecm_extends MyBaseInterface
+ {
+ virtual EcmErr MyFunction4() = 0;
+ virtual EcmErr MyFunction5() = 0;
+ virtual EcmErr MyFunction6() = 0;
+ };
+
+ So far, we've just defined interfaces: the layout of the function
+ pointer table. We also need to implement the functions. To do
+ that, we create a class that descends from the interface we want
+ to implement, using the macro "ecm_implements". Thus, to implement
+ the functions described by MyDerivedInterface, we use the following:
+
+ class MyDerivedImplementation : ecm_implements MyDerivedInterface
+ {
+ virtual EcmErr MyFunction1();
+ virtual EcmErr MyFunction2();
+ virtual EcmErr MyFunction3();
+ virtual EcmErr MyFunction4();
+ virtual EcmErr MyFunction5();
+ virtual EcmErr MyFunction6();
+ };
+
+ Once all of these interface and implementation classes are defined,
+ they need to be used somehow. The plug-in needs to be given a way
+ to get to the interfaces it needs, and the container for the plug-in
+ needs to know what interfaces the plug-in supports.
+
+ This exchange of interface information takes place when the plug-in
+ is loaded. The plug-in needs to support an entry point that will
+ (a) accept a container object and (b) return a package object. The
+ as with all interfaces, these objects contain RequestInterface methods
+ from with all other interfaces can be obtained.
+
+ Obtaining an interface using RequestInterface is simple: you pass a
+ "name" of an interface to some ECM object, and that object will
+ say that it supports or doesn't support that interface. If it does
+ support that interface, it returns a pointer to the interface.
+*/
+
+
+#define ecm_interface struct
+#define ecm_implements virtual public
+#define ecm_extends virtual public
+
+
+#define ECM_CLASS_IF_LIST_BEGIN(classname, basename) \
+ virtual EcmErr FindInterface(const EcmIfName &name, void **iPP) \
+ { \
+ if (iPP == NULL) \
+ return kEcmErrInvalidParameter;
+
+
+#define ECM_CLASS_IF(ifid, iftype) \
+ if (name == (ifid)) \
+ { \
+ *iPP = (void *) static_cast<iftype *>(this); \
+ return kEcmErrNone; \
+ }
+
+
+#define ECM_CLASS_IF_LIST_END(classname, basename) \
+ return(basename::FindInterface(name, iPP)); \
+ }
+
+
+
+// ===========================================================================
+//
+// Extended Component Model (ECM) -- Interfaces
+//
+// We're adding support for component interfaces because
+// exporting c++ classes is a real pain from loadable libraries
+// (at least Windows DLLs), Anyway, component design using interfaces
+// works really well for "plugin" type designs.
+//
+// In our implementation, an interface is a c++ abstract base class.
+// ===========================================================================
+
+
+enum EcmErr
+{
+ kEcmErrNone,
+ kEcmErrYikes, // if this shows up, something really unexpected happened!
+ // flag any appearance of this return code as a defect.
+
+ kEcmErrInvalidParameter, // a parameter was not set up correctly
+ kEcmErrInvalidHandle, // handle doesn't refer to anything appropriate
+ kEcmErrInvalidIfName, // invalid name of interface or event interface
+ kEcmErrInvalidPubName, // invalid name of publisher
+ kEcmErrInvalidSrvName, // invalid name of service
+ kEcmErrInvalidCompName, // invalid name of component
+ kEcmErrBadEventType, // inapropriate event type
+ kEcmErrInvalidConnection, //
+ kEcmErrAlreadyConnected, //
+ kEcmErrNotInitialized //
+};
+
+
+
+
+// ===========================================================================
+// EcmIfName -- type to define name used to reference an interface.
+// NOTE: If ECM becomes more widely used, this can be optimized to use an
+// atom table of strings. An actual string comparison would then only need
+// to be done once.
+// ===========================================================================
+
+typedef string EcmIfName;
+typedef string EcmCompName;
+
+
+// ===========================================================================
+// EcmHandle -- Handle used for opaque references
+// ===========================================================================
+
+typedef void* EcmHandle;
+
+
+
+// ===========================================================================
+// IEcmComponent all interfaces must extend IEcmComponent..
+// this is how all patch modules appear to the patching sub-system
+// ===========================================================================
+
+const EcmIfName kEcmComponentIfn = "component.i.ecm";
+
+ecm_interface IEcmComponent
+{
+ /***********************************************************************
+ *
+ * FUNCTION: RequestInterface
+ *
+ * DESCRIPTION: Requests an interface of type EcmIfName from the component
+ *
+ * PARAMETERS: name [IN ] Name of the interface being requested.
+ * iPP [OUT ] Interface to the event being sent.
+ *
+ * RETURNED: ECMErrNone
+ * ECMErrInvalidName
+ *
+ *
+ ***********************************************************************/
+
+ virtual EcmErr RequestInterface(const EcmIfName &name, void **iPP) = 0;
+
+
+ /***********************************************************************
+ *
+ * FUNCTION: Refer
+ *
+ * DESCRIPTION: Called before handing an interface pointer off to another
+ * "piece of code", adding an addition owner. This is used to
+ * maintain the reference count so the component can be destroyed
+ * at the appropriate time.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: ECMErrNone
+ *
+ *
+ ***********************************************************************/
+
+ virtual EcmErr Refer() = 0;
+
+
+ /***********************************************************************
+ *
+ * FUNCTION: Release
+ *
+ * DESCRIPTION: Releases the interface from a reference, when the reference count is 0,
+ * the component can be destroyed.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: ECMErrNone
+ *
+ *
+ ***********************************************************************/
+
+ virtual EcmErr Release() = 0;
+};
+
+
+
+// ===========================================================================
+// IEcmContainer
+// ===========================================================================
+
+const EcmIfName kEcmContainerIfn = "container.i.ecm";
+
+ecm_interface IEcmContainer : ecm_extends IEcmComponent
+{
+};
+
+
+
+// ===========================================================================
+// IEcmPackage
+// ===========================================================================
+
+const EcmIfName kEcmPackageIfn = "package.i.ecm";
+
+ecm_interface IEcmPackage : ecm_extends IEcmComponent
+{
+};
+
+
+
+// ===========================================================================
+// IEcmEventBase
+// ===========================================================================
+
+const EcmIfName kEcmEventBaseIfn = "eventbase.events.i.ecm";
+
+ecm_interface IEcmEventBase : ecm_extends IEcmComponent
+{
+
+
+};
+
+
+
+// ===========================================================================
+// IEcmEventListener
+// ===========================================================================
+
+const EcmIfName kEcmEventListenerIfn = "listener.events.i.ecm";
+
+/**
+ ** Base interface for all event sinks.
+ **/
+ecm_interface IEcmEventListener
+{
+ /***********************************************************************
+ *
+ * FUNCTION: OnEvent
+ *
+ * DESCRIPTION: Delivers an event to the event listener
+ *
+ * PARAMETERS: evtIP [IN ] Interface to the event being sent.
+ *
+ * RETURNED: ECMErrNone
+ * ECMErrBadEventType
+ *
+ *
+ ***********************************************************************/
+
+ EcmErr OnEvent(const IEcmEventBase *evtIP);
+};
+
+
+// ===========================================================================
+// IEcmEvents
+// ===========================================================================
+
+const EcmIfName kEcmEventsIfn = "events.i.ecm";
+
+ecm_interface IEcmEvents
+{
+ /***********************************************************************
+ *
+ * FUNCTION: RequestListener
+ *
+ * DESCRIPTION: Obtains an event listener interface (for a "category of events")
+ *
+ * PARAMETERS: name [IN ] Name of the event interface being requested.
+ * listenerIPP [OUT ] Interface to the given event listener.
+ *
+ * RETURNED: ECMErrNone
+ * ECMErrInvalidParameter
+ * ECMErrInvalidName
+ *
+ *
+ ***********************************************************************/
+
+ virtual EcmErr RequestListener(const EcmIfName &name, void **listenerIPP) = 0;
+
+
+ /***********************************************************************
+ *
+ * FUNCTION: Subscribe
+ *
+ * DESCRIPTION: Allows an event "consumer" to subscribe to the named "category of events"
+ *
+ * PARAMETERS: publisher [IN ] Name of the event publisher being requested.
+ * subscriberIP [IN ] Interface to the subscribers event listener interface
+ * handle [OUT ] Unique identifier handle associated with the subscription.
+ *
+ * RETURNED: ECMErrNone
+ * ECMErrInvalidParameter
+ * ECMErrInvalidName
+ *
+ *
+ ***********************************************************************/
+
+ virtual EcmErr Subscribe(const EcmIfName &publisher, const IEcmEventListener *subscriberIP, EcmHandle &handle) = 0;
+
+
+ /***********************************************************************
+ *
+ * FUNCTION: Unsubscribe
+ *
+ * DESCRIPTION: Unsubscribes from an event publisher.
+ *
+ * PARAMETERS: handle [IN ] Unique identifier created by "IEcmComponent::Subscribe".
+ *
+ * RETURNED: ECMErrNone
+ * ECMErrInvalidHandle
+ *
+ *
+ ***********************************************************************/
+
+ virtual EcmErr Unsubscribe(const EcmHandle handle) = 0;
+
+};
+
+
+#endif // EcmIf_h