#ifndef __TRANSFORM__
#define __TRANSFORM__
#include <CoreFoundation/CFError.h>
#include "CoreFoundationBasics.h"
#include "SecTransform.h"
#include "SecCustomTransform.h"
#include <dispatch/dispatch.h>
#include "misc.h"
#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;
class Transform *transform;
static CFTypeID cftype;
enum pushback_states { pb_empty, pb_value, pb_repush, pb_presented_once, pb_discard } pushback_state;
CFTypeRef pushback_value;
dispatch_queue_t q;
dispatch_semaphore_t semaphore;
unsigned int required:1;
unsigned int requires_outbound_connection:1;
unsigned int deferred:1;
unsigned int stream:1;
unsigned int ignore_while_externalizing:1;
unsigned int has_incoming_connection:1;
unsigned int direct_error_handling:1;
unsigned int allow_external_sets:1;
unsigned int has_been_deferred:1;
void *attribute_changed_block;
void *attribute_validate_block;
};
typedef void (^ActivityMonitor)(CFStringRef name, CFTypeRef value);
class GroupTransform; 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();
virtual void FinalizePhase2();
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);
virtual void AbortAllTransforms(CFTypeRef error);
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();
virtual ~Transform();
virtual void AttributeChanged(SecTransformAttributeRef ah, CFTypeRef value);
virtual void AttributeChanged(CFStringRef name, CFTypeRef value);
virtual bool IsExternalizable();
virtual CFDictionaryRef CopyState();
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();
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);
void SetActivityMonitor(ActivityMonitor am);
virtual CFDictionaryRef Externalize(CFErrorRef *error);
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) {
return *(struct transform_attribute **)(1 + (CFRuntimeBase*)ah);
}
#endif