<commit_before>#ifndef SHOVELER_COMPONENT_H
#define SHOVELER_COMPONENT_H

#include <assert.h> // assert
#include <stdbool.h> // bool

#include <glib.h>

#include <shoveler/types.h>

typedef struct ShovelerComponentStruct ShovelerComponent; // forward declaration: below
typedef struct ShovelerComponentConfigurationValueStruct ShovelerComponentConfigurationValue; // forward declaration: below
typedef struct ShovelerComponentTypeConfigurationOptionStruct ShovelerComponentTypeConfigurationOption; // forward declaration: below
typedef struct ShovelerComponentTypeStruct ShovelerComponentType; // forward declaration: below
typedef struct ShovelerComponentViewAdapterStruct ShovelerComponentViewAdapter; // forward delcaration: below
typedef struct ShovelerViewEntityStruct ShovelerViewEntity; // forward declaration: view.h

typedef enum {
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_ENTITY_ID,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_ENTITY_ID_ARRAY,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_FLOAT,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_BOOL,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_INT,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_STRING,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_VECTOR2,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_VECTOR3,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_VECTOR4,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_BYTES,
} ShovelerComponentConfigurationOptionType;

typedef struct ShovelerComponentConfigurationValueStruct {
	ShovelerComponentConfigurationOptionType type;
	bool isSet;
	union {
		long long int entityIdValue;
		struct {
			long long int *entityIds;
			int size;
		} entityIdArrayValue;
		float floatValue;
		bool boolValue;
		int intValue;
		unsigned int uintValue;
		// string value is owned by the struct itself
		char *stringValue;
		ShovelerVector2 vector2Value;
		ShovelerVector3 vector3Value;
		ShovelerVector4 vector4Value;
		struct {
			unsigned char *data;
			int size;
		} bytesValue;
	};
} ShovelerComponentConfigurationValue;

typedef void (ShovelerComponentTypeConfigurationOptionLiveUpdateFunction)(ShovelerComponent *component, const ShovelerComponentTypeConfigurationOption *configurationOption, const ShovelerComponentConfigurationValue *value);
typedef void (ShovelerComponentTypeConfigurationOptionUpdateDependencyFunction)(ShovelerComponent *component, const ShovelerComponentTypeConfigurationOption *configurationOption, ShovelerComponent *dependencyComponent);

typedef struct ShovelerComponentTypeConfigurationOptionStruct {
	const char *name;
	ShovelerComponentConfigurationOptionType type;
	bool isOptional;
	ShovelerComponentTypeConfigurationOptionLiveUpdateFunction *liveUpdate;
	ShovelerComponentTypeConfigurationOptionUpdateDependencyFunction *updateDependency;
	const char *dependencyComponentTypeId;
} ShovelerComponentTypeConfigurationOption;

typedef void *(ShovelerComponentTypeActivationFunction)(ShovelerComponent *component);
typedef void (ShovelerComponentTypeDeactivationFunction)(ShovelerComponent *component);

typedef struct ShovelerComponentTypeStruct {
	const char *id;
	int numConfigurationOptions;
	ShovelerComponentTypeConfigurationOption *configurationOptions;
	ShovelerComponentTypeActivationFunction *activate;
	ShovelerComponentTypeDeactivationFunction *deactivate;
	bool requiresAuthority;
} ShovelerComponentType;

typedef void (ShovelerComponentAdapterViewForEachReverseDependencyCallbackFunction)(ShovelerComponent *sourceComponent, ShovelerComponent *targetComponent, void *userData);

typedef ShovelerComponent *(ShovelerComponentViewAdapterGetComponentFunction)(ShovelerComponent *component, long long int entityId, const char *componentTypeId, void *userData);
typedef void (ShovelerComponentViewAdapterUpdateAuthoritativeComponentFunction)(ShovelerComponent *component, const ShovelerComponentTypeConfigurationOption *configurationOption, const ShovelerComponentConfigurationValue *value, void *userData);
typedef void *(ShovelerComponentViewAdapterGetTargetFunction)(ShovelerComponent *component, const char *targetName, void *userData);
typedef void (ShovelerComponentViewAdapterAddDependencyFunction)(ShovelerComponent *component, long long int targetEntityId, const char *targetComponentTypeId, void *userData);
typedef bool (ShovelerComponentViewAdapterRemoveDependencyFunction)(ShovelerComponent *component, long long int targetEntityId, const char *targetComponentTypeId, void *userData);
typedef void (ShovelerComponentViewAdapterForEachReverseDependencyFunction)(ShovelerComponent *component, ShovelerComponentAdapterViewForEachReverseDependencyCallbackFunction *callbackFunction, void *callbackUserData, void *adapterUserData);
typedef void (ShovelerComponentViewAdapterReportActivationFunction)(ShovelerComponent *component, int delta, void *userData);

// Adapter struct to make a component integrate with a view.
typedef struct ShovelerComponentViewAdapterStruct {
	ShovelerComponentViewAdapterGetComponentFunction *getComponent;
	ShovelerComponentViewAdapterUpdateAuthoritativeComponentFunction *updateAuthoritativeComponent;
	ShovelerComponentViewAdapterGetTargetFunction *getTarget;
	ShovelerComponentViewAdapterAddDependencyFunction *addDependency;
	ShovelerComponentViewAdapterRemoveDependencyFunction *removeDependency;
	ShovelerComponentViewAdapterForEachReverseDependencyFunction *forEachReverseDependency;
	ShovelerComponentViewAdapterReportActivationFunction *reportActivation;
	void *userData;
} ShovelerComponentViewAdapter;

typedef struct ShovelerComponentStruct {
	ShovelerComponentViewAdapter *viewAdapter;
	long long int entityId;
	ShovelerComponentType *type;
	bool isAuthoritative;
	ShovelerComponentConfigurationValue *configurationValues;
	GQueue *dependencies;
	void *data;
} ShovelerComponent;

/**
 * Constructor for a configuration option.
 *
 * If the passed live update function is not NULL, this indicates that the configuration option can
 * be updated by calling that function instead of deactivating and reactivating the component.
 */
ShovelerComponentTypeConfigurationOption shovelerComponentTypeConfigurationOption(const char *name, ShovelerComponentConfigurationOptionType type, bool isOptional, ShovelerComponentTypeConfigurationOptionLiveUpdateFunction *liveUpdate);
/**
 * Constructor for a dependency configuration option.
 *
 * A dependency configuration option is an option of type entity id that specifies a dependency
 * component type name. Components of this type will only be able to activate if the specified
 * entity ID contains an activated component of the specified type.
 *
 * If the passed live update function is not NULL, this indicates that the configuration option can
 * be updated by calling that function instead of deactivating and reactivating the component.
 *
 * If the component is active and the passed update dependency function is not NULL, it will be
 * called whenever the dependency this component value points to is live updated. This includes
 * updates to the dependency's transitive dependencies.
 */
ShovelerComponentTypeConfigurationOption shovelerComponentTypeConfigurationOptionDependency(const char *name, const char *dependencyComponentTypeId, bool isArray, bool isOptional, ShovelerComponentTypeConfigurationOptionLiveUpdateFunction *liveUpdate, ShovelerComponentTypeConfigurationOptionUpdateDependencyFunction *updateDependency);

ShovelerComponentType *shovelerComponentTypeCreate(const char *id, ShovelerComponentTypeActivationFunction *activate, ShovelerComponentTypeDeactivationFunction *deactivate, bool requiresAuthority, int numConfigurationOptions, const ShovelerComponentTypeConfigurationOption *configurationOptions);
void shovelerComponentTypeFree(ShovelerComponentType *componentType);

ShovelerComponent *shovelerComponentCreate(ShovelerComponentViewAdapter *viewAdapter, long long int entityId, ShovelerComponentType *componentType);
/**
 * Updates a configuration option with the specified id on this component.
 *
 * If isCanonical is true, no authority check is performed and the update is applied without
 * invoking the authoritative update handler.
 */
bool shovelerComponentUpdateConfigurationOption(ShovelerComponent *component, int id, const ShovelerComponentConfigurationValue *value, bool isCanonical);
bool shovelerComponentClearConfigurationOption(ShovelerComponent *component, int id, bool isCanonical);
const ShovelerComponentConfigurationValue *shovelerComponentGetConfigurationValue(ShovelerComponent *component, int id);
/**
 * Activates this component if the activation conditions are satisified.
 *
 * To activate the component, the activation function is called and the returned data is stored
 * within the component's data field.
 *
 * Activation can fail under the following conditions:<commit_msg>added documentation for creating component types<commit_after>#ifndef SHOVELER_COMPONENT_H
#define SHOVELER_COMPONENT_H

#include <assert.h> // assert
#include <stdbool.h> // bool

#include <glib.h>

#include <shoveler/types.h>

typedef struct ShovelerComponentStruct ShovelerComponent; // forward declaration: below
typedef struct ShovelerComponentConfigurationValueStruct ShovelerComponentConfigurationValue; // forward declaration: below
typedef struct ShovelerComponentTypeConfigurationOptionStruct ShovelerComponentTypeConfigurationOption; // forward declaration: below
typedef struct ShovelerComponentTypeStruct ShovelerComponentType; // forward declaration: below
typedef struct ShovelerComponentViewAdapterStruct ShovelerComponentViewAdapter; // forward delcaration: below
typedef struct ShovelerViewEntityStruct ShovelerViewEntity; // forward declaration: view.h

typedef enum {
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_ENTITY_ID,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_ENTITY_ID_ARRAY,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_FLOAT,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_BOOL,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_INT,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_STRING,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_VECTOR2,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_VECTOR3,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_VECTOR4,
	SHOVELER_COMPONENT_CONFIGURATION_OPTION_TYPE_BYTES,
} ShovelerComponentConfigurationOptionType;

typedef struct ShovelerComponentConfigurationValueStruct {
	ShovelerComponentConfigurationOptionType type;
	bool isSet;
	union {
		long long int entityIdValue;
		struct {
			long long int *entityIds;
			int size;
		} entityIdArrayValue;
		float floatValue;
		bool boolValue;
		int intValue;
		unsigned int uintValue;
		// string value is owned by the struct itself
		char *stringValue;
		ShovelerVector2 vector2Value;
		ShovelerVector3 vector3Value;
		ShovelerVector4 vector4Value;
		struct {
			unsigned char *data;
			int size;
		} bytesValue;
	};
} ShovelerComponentConfigurationValue;

typedef void (ShovelerComponentTypeConfigurationOptionLiveUpdateFunction)(ShovelerComponent *component, const ShovelerComponentTypeConfigurationOption *configurationOption, const ShovelerComponentConfigurationValue *value);
typedef void (ShovelerComponentTypeConfigurationOptionUpdateDependencyFunction)(ShovelerComponent *component, const ShovelerComponentTypeConfigurationOption *configurationOption, ShovelerComponent *dependencyComponent);

typedef struct ShovelerComponentTypeConfigurationOptionStruct {
	const char *name;
	ShovelerComponentConfigurationOptionType type;
	bool isOptional;
	ShovelerComponentTypeConfigurationOptionLiveUpdateFunction *liveUpdate;
	ShovelerComponentTypeConfigurationOptionUpdateDependencyFunction *updateDependency;
	const char *dependencyComponentTypeId;
} ShovelerComponentTypeConfigurationOption;

typedef void *(ShovelerComponentTypeActivationFunction)(ShovelerComponent *component);
typedef void (ShovelerComponentTypeDeactivationFunction)(ShovelerComponent *component);

typedef struct ShovelerComponentTypeStruct {
	const char *id;
	int numConfigurationOptions;
	ShovelerComponentTypeConfigurationOption *configurationOptions;
	ShovelerComponentTypeActivationFunction *activate;
	ShovelerComponentTypeDeactivationFunction *deactivate;
	bool requiresAuthority;
} ShovelerComponentType;

typedef void (ShovelerComponentAdapterViewForEachReverseDependencyCallbackFunction)(ShovelerComponent *sourceComponent, ShovelerComponent *targetComponent, void *userData);

typedef ShovelerComponent *(ShovelerComponentViewAdapterGetComponentFunction)(ShovelerComponent *component, long long int entityId, const char *componentTypeId, void *userData);
typedef void (ShovelerComponentViewAdapterUpdateAuthoritativeComponentFunction)(ShovelerComponent *component, const ShovelerComponentTypeConfigurationOption *configurationOption, const ShovelerComponentConfigurationValue *value, void *userData);
typedef void *(ShovelerComponentViewAdapterGetTargetFunction)(ShovelerComponent *component, const char *targetName, void *userData);
typedef void (ShovelerComponentViewAdapterAddDependencyFunction)(ShovelerComponent *component, long long int targetEntityId, const char *targetComponentTypeId, void *userData);
typedef bool (ShovelerComponentViewAdapterRemoveDependencyFunction)(ShovelerComponent *component, long long int targetEntityId, const char *targetComponentTypeId, void *userData);
typedef void (ShovelerComponentViewAdapterForEachReverseDependencyFunction)(ShovelerComponent *component, ShovelerComponentAdapterViewForEachReverseDependencyCallbackFunction *callbackFunction, void *callbackUserData, void *adapterUserData);
typedef void (ShovelerComponentViewAdapterReportActivationFunction)(ShovelerComponent *component, int delta, void *userData);

// Adapter struct to make a component integrate with a view.
typedef struct ShovelerComponentViewAdapterStruct {
	ShovelerComponentViewAdapterGetComponentFunction *getComponent;
	ShovelerComponentViewAdapterUpdateAuthoritativeComponentFunction *updateAuthoritativeComponent;
	ShovelerComponentViewAdapterGetTargetFunction *getTarget;
	ShovelerComponentViewAdapterAddDependencyFunction *addDependency;
	ShovelerComponentViewAdapterRemoveDependencyFunction *removeDependency;
	ShovelerComponentViewAdapterForEachReverseDependencyFunction *forEachReverseDependency;
	ShovelerComponentViewAdapterReportActivationFunction *reportActivation;
	void *userData;
} ShovelerComponentViewAdapter;

typedef struct ShovelerComponentStruct {
	ShovelerComponentViewAdapter *viewAdapter;
	long long int entityId;
	ShovelerComponentType *type;
	bool isAuthoritative;
	ShovelerComponentConfigurationValue *configurationValues;
	GQueue *dependencies;
	void *data;
} ShovelerComponent;

/**
 * Constructor for a configuration option.
 *
 * If the passed live update function is not NULL, this indicates that the configuration option can
 * be updated by calling that function instead of deactivating and reactivating the component.
 */
ShovelerComponentTypeConfigurationOption shovelerComponentTypeConfigurationOption(const char *name, ShovelerComponentConfigurationOptionType type, bool isOptional, ShovelerComponentTypeConfigurationOptionLiveUpdateFunction *liveUpdate);
/**
 * Constructor for a dependency configuration option.
 *
 * A dependency configuration option is an option of type entity id that specifies a dependency
 * component type name. Components of this type will only be able to activate if the specified
 * entity ID contains an activated component of the specified type.
 *
 * If the passed live update function is not NULL, this indicates that the configuration option can
 * be updated by calling that function instead of deactivating and reactivating the component.
 *
 * If the component is active and the passed update dependency function is not NULL, it will be
 * called whenever the dependency this component value points to is live updated. This includes
 * updates to the dependency's transitive dependencies.
 */
ShovelerComponentTypeConfigurationOption shovelerComponentTypeConfigurationOptionDependency(const char *name, const char *dependencyComponentTypeId, bool isArray, bool isOptional, ShovelerComponentTypeConfigurationOptionLiveUpdateFunction *liveUpdate, ShovelerComponentTypeConfigurationOptionUpdateDependencyFunction *updateDependency);

/**
 * Creates a new component type.
 *
 * The specified ID should be a statically defined string with external linkage that will be used
 * as unique identifier for the component type. It is a string so it can be easily printed as part
 * of log messages.
 *
 * If an activation function is specified and not NULL, it will be called whenever a component
 * instance of this type tries to activate. It must return a non-NULL data value if its activation
 * succeeds.
 *
 * If a deactivation function is specified, it will be called when a component instance of this
 * type deactivates. It is intended to free any memory or registrations performed by the activation
 * function and should leave the component instance in a state where it can be reactivated again at
 * any later point in time.
 *
 * If requiresAuthority is true, the component will only attempt to activate if it is currently
 * delegated authority.
 *
 * A component type can be created with any number of configuration options that will be
 * instantiated on each component instance of this type. The caller retains ownership of the passed
 * configuration options.
 */
ShovelerComponentType *shovelerComponentTypeCreate(const char *id, ShovelerComponentTypeActivationFunction *activate, ShovelerComponentTypeDeactivationFunction *deactivate, bool requiresAuthority, int numConfigurationOptions, const ShovelerComponentTypeConfigurationOption *configurationOptions);
void shovelerComponentTypeFree(ShovelerComponentType *componentType);

ShovelerComponent *shovelerComponentCreate(ShovelerComponentViewAdapter *viewAdapter, long long int entityId, ShovelerComponentType *componentType);
/**
 * Updates a configuration option with the specified id on this component.
 *
 * If isCanonical is true, no authority check is performed and the update is applied without
 * invoking the authoritative update handler.
 */
bool shovelerComponentUpdateConfigurationOption(ShovelerComponent *component, int id, const ShovelerComponentConfigurationValue *value, bool isCanonical);
bool shovelerComponentClearConfigurationOption(ShovelerComponent *component, int id, bool isCanonical);
const ShovelerComponentConfigurationValue *shovelerComponentGetConfigurationValue(ShovelerComponent *component, int id);
/**
 * Activates this component if the activation conditions are satisified.
 *
 * To activate the component, the activation function is called and the returned data is stored
 * within the component's data field.
 *
 * Activation can fail under the following conditions:
{'fraction_non_alphanumeric': 0.04580886278697277, 'fraction_numerical': 0.0009610250934329952, 'mean_word_length': 8.72029060716139, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '225724', 'n_tokens_mistral': 4704, 'n_tokens_neox': 4545, 'n_words': 1401}