+++ /dev/null
-#ifndef __TRANSFORM__
-#define __TRANSFORM__
-
-#include <CoreFoundation/CFError.h>
-#include "CoreFoundationBasics.h"
-#include "SecTransform.h"
-#include "SecCustomTransform.h"
-#include <dispatch/dispatch.h>
-#include "misc.h"
-
-// Since we are doing everything in CF, we just define an
-// attribute as a CFDictionary containing a value and
-// a CFArray of objects which need notification when that
-// value changes
-
-// defines for transform externalization
-#define EXTERN_TRANSFORM_TRANSFORM_ARRAY CFSTR("TRANSFORMS")
-#define EXTERN_TRANSFORM_CONNECTION_ARRAY CFSTR("ARRAY")
-#define EXTERN_TRANSFORM_CUSTOM_EXPORTS_DICTIONARY CFSTR("CUSTOM_EXPORTS")
-
-#define EXTERN_TRANSFORM_NAME CFSTR("NAME")
-#define EXTERN_TRANSFORM_TYPE CFSTR("TYPE")
-#define EXTERN_TRANSFORM_STATE CFSTR("STATE")
-#define EXTERN_TRANSFORM_FROM_NAME CFSTR("FROM_NAME")
-#define EXTERN_TRANSFORM_FROM_ATTRIBUTE CFSTR("FROM_ATTRIBUTE")
-#define EXTERN_TRANSFORM_TO_NAME CFSTR("TO_NAME")
-#define EXTERN_TRANSFORM_TO_ATTRIBUTE CFSTR("TO_ATTRIBUTE")
-
-#ifndef __clang__
-#define GCC_BUG_WORKAROUND ::
-#else
-#define GCC_BUG_WORKAROUND
-#endif
-
-
-class Monitor;
-typedef CFTypeRef SecMonitorRef;
-
-struct transform_attribute {
- CFStringRef name;
- CFTypeRef value;
- CFMutableArrayRef connections;
- // NOTE: this does NOT have a reference.
- class Transform *transform;
- static CFTypeID cftype;
-
- // NOTE: NULL is a valid value to pushback, so we can't just use pushback_value==NULL for "nothing pushed back"
- // pb_empty => no value currently pushed back
- // pb_value => we have a value, we havn't presented it yet (if pushback_value==NULL we won't present again until another attribute changes)
- // pb_repush => pushed back value currently being re-processed
- // pb_presented_once => we have a value, and tried to process it and got it back again (don't present until another attribute changes)
- //
- enum pushback_states { pb_empty, pb_value, pb_repush, pb_presented_once, pb_discard } pushback_state;
- CFTypeRef pushback_value;
-
- // (for pushback support; also need pushback state & value)
- dispatch_queue_t q;
- dispatch_semaphore_t semaphore;
-
- // This attribute needs a value set, or to have something connected to it before running the transform
- unsigned int required:1;
- // This attribute needs to have an outgoing connection before running the transform
- unsigned int requires_outbound_connection:1;
- // This attribute should not be presented to the transform until after execution starts
- unsigned int deferred:1;
- // This attribute comes in N chunks followed by a NULL
- unsigned int stream:1;
- // This attribute should be saved when externalizing
- unsigned int ignore_while_externalizing:1;
- // Set by Transform::Connect
- unsigned int has_incoming_connection:1;
- // CustomTransform should't special case CFErrors for this attribute
- unsigned int direct_error_handling:1;
- // External sets are problematic, I think they should be disallowed full stop, but 7947393 says we need them sometimes
- unsigned int allow_external_sets:1;
- // Value has been created as a source (therefore deferred), give it special treatment
- unsigned int has_been_deferred:1;
-
- void *attribute_changed_block;
- void *attribute_validate_block;
-};
-
-typedef void (^ActivityMonitor)(CFStringRef name, CFTypeRef value);
-
-class GroupTransform; // Forward reference so we do not have to include
- // the header and break a circular dependency
-class BlockMonitor;
-
-class Transform : public CoreFoundationObject
-{
- friend CFTypeRef SecTransformExecute(SecTransformRef tranformRef, CFErrorRef* errorRef);
- friend CFTypeRef SecTransformGetAttribute(SecTransformRef transformRef, CFStringRef key);
- friend class BlockMonitor;
-protected:
- dispatch_queue_t mDispatchQueue, mActivationQueue;
- dispatch_group_t mActivationPending;
- CFMutableSetRef mAttributes;
- CFMutableArrayRef mPushedback;
- Boolean mIsActive;
- Boolean mIsFinalizing;
- Boolean mAlwaysSelfNotify, mProcessingPushbacks;
- GroupTransform *mGroup;
- CFErrorRef mAbortError;
- CFStringRef mTypeName;
-
- SecTransformAttributeRef AbortAH, DebugAH;
-
- Transform(CFStringRef transformType, CFStringRef CFobjectType = CFSTR("SecTransform"));
-
- transform_attribute *getTA(SecTransformStringOrAttributeRef attr, bool create_ok);
- void TAGetAll(transform_attribute **attributes);
- CFIndex GetAttributeCount();
-
- CFDictionaryRef GetAHDictForSaveState(SecTransformStringOrAttributeRef key);
-
- CFTypeRef ValueForNewAttribute(CFStringRef key, CFTypeRef value);
- CFMutableDictionaryRef AddNewAttribute(CFStringRef key, CFTypeRef value);
- CFErrorRef SetAttributeNoCallback(SecTransformStringOrAttributeRef key, CFTypeRef value);
-
- CFErrorRef ProcessExecute(CFStringRef &outputAttached, SecMonitorRef monitor);
- typedef void (^AccumulateDictonary)(CFDictionaryRef d);
- CFErrorRef ProcessExternalize(CFMutableArrayRef transforms, CFMutableArrayRef connections);
-
- void FinalizeForClang();
-
- virtual void Finalize();
- // subclasses with non-trivial finalization can implement this (default: delete this)
- virtual void FinalizePhase2();
- // subclasses that want to reject some connections can use this
- virtual bool validConnectionPoint(CFStringRef attributeName);
-
- void try_pushbacks();
-
- void Initialize();
-
- void ActivateInputs();
-
- virtual std::string DebugDescription();
-
- typedef CFErrorRef (^TransformOperation)(Transform*);
- typedef void (^TransformAsyncOperation)(Transform*);
- CFErrorRef ForAllNodes(bool parallel, bool includeOwningGroup, TransformOperation op);
-
- CFErrorRef TraverseTransform(CFMutableSetRef visited, TransformOperation t);
-
-
- CFErrorRef SendAttribute(SecTransformStringOrAttributeRef key, CFTypeRef value);
- CFErrorRef SendMetaAttribute(SecTransformStringOrAttributeRef key, SecTransformMetaAttributeType type, CFTypeRef value);
-
- // Abort all transforms in this transform's RootGroup, including this transform
- virtual void AbortAllTransforms(CFTypeRef error);
- // Abort just this transform (and maybe schedule a later call to AbortAllTransforms), should only be
- // called via AbortAllTransforms
- virtual void AbortJustThisTransform(CFErrorRef abortMsg);
-
- void phase3Activation();
- void DoPhase3Activation();
-
- bool HasNoInboundConnections();
- bool HasNoOutboundConnections();
-
-private:
- CFErrorRef ExecuteOperation(CFStringRef &outputAttached, SecMonitorRef output, dispatch_queue_t phase2, dispatch_queue_t phase3);
- SecTransformAttributeRef makeAH(transform_attribute *ta);
-
-public:
-
- static CFTypeID GetCFTypeID();
-
- // these functions are overloaded to implement the functionality of your transform
- virtual ~Transform();
-
- // this is called when one of your attributes (e.g. input) changes
- virtual void AttributeChanged(SecTransformAttributeRef ah, CFTypeRef value);
- // this is for backwards compatibility only (XXX: convert all existing Transform subclasses to not use it then remove)
- virtual void AttributeChanged(CFStringRef name, CFTypeRef value);
-
- // overload to return true if your transform can be externalized (generally true unless you are a monitor)
- virtual bool IsExternalizable();
-
- // Base implementation saves all attributes that have kSecTransformMetaAttributeExternalize TRUE (which is the default).
- // If that isn't useful for your transform overload to return a CFDictionary that contains the state of
- // your transform. Values returned should be serializable. Remember that this state will be restored
- // before SecTransformExecute is called. Do not include the transform name in your state (this will be
- // done for you by SecTransformCopyExternalRep).
- virtual CFDictionaryRef CopyState();
-
- // overload to restore the state of your transform
- virtual void RestoreState(CFDictionaryRef state);
- virtual void SetCustomExternalData(CFDictionaryRef customData);
-
- virtual Boolean TransformCanExecute();
- virtual CFErrorRef TransformStartingExecution();
-
- SecTransformAttributeRef getAH(SecTransformStringOrAttributeRef attr, bool create_ok =true, bool create_undesrscore_ok =false);
- CFArrayRef GetAllAH();
-
- CFStringRef GetName();
-
- // Output debugging information if the DEBUG attribute is set for this transform
- void Debug(const char *fmt, ...);
-
- CFErrorRef RefactorErrorToIncludeAbortingTransform(CFErrorRef sourceError);
-
-public:
- CFErrorRef Connect(GroupTransform *group, Transform* destinationTransform, CFStringRef myKey, CFStringRef hisKey);
- CFErrorRef Disconnect(Transform* destinationTransform, CFStringRef myKey, CFStringRef hisKey);
-
- CFErrorRef ExternalSetAttribute(SecTransformStringOrAttributeRef key, CFTypeRef value);
- CFErrorRef SetAttribute(SecTransformStringOrAttributeRef key, CFTypeRef value);
- CFTypeRef GetAttribute(SecTransformStringOrAttributeRef key);
- CFTypeRef GetMetaAttribute(SecTransformStringOrAttributeRef key, SecTransformMetaAttributeType type);
-
- CFErrorRef Pushback(SecTransformAttributeRef ah, CFTypeRef value);
-
- void Do(SecTransformAttributeRef name, CFTypeRef value);
-
- CFTypeRef Execute(dispatch_queue_t deliveryQueue, SecMessageBlock deliveryBlock, CFErrorRef* errorRef);
-
- // set to get notified every time this transform does something -- used for debugging
- void SetActivityMonitor(ActivityMonitor am);
-
- virtual CFDictionaryRef Externalize(CFErrorRef *error);
-
- // Returns NULL if not in a group; can return this
- GroupTransform* GetRootGroup();
-
- friend class GroupTransform;
- friend Transform::TransformOperation makeIdleOp(dispatch_group_t idle_group);
-
- void SetGroup(GroupTransform* group) {mGroup = group;}
- CFDictionaryRef GetCustomExternalData();
-};
-
-
-inline struct transform_attribute *ah2ta(SecTransformAttributeRef ah) {
- // CF stores our data just after the CFRuntimeBase, we just have a single pointer there.
- return *(struct transform_attribute **)(1 + (CFRuntimeBase*)ah);
-}
-
-#endif