From a2562989af4b1c489336128686961fc0ea38b444 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Sun, 20 Jul 2008 18:32:25 +0200
Subject: [PATCH] Removed remaining code duplication among comparators, match
 types and address parts.

---
 TODO                                    |  1 -
 src/lib-sieve/plugins/regex/ext-regex.c |  2 +-
 src/lib-sieve/sieve-actions.c           |  1 -
 src/lib-sieve/sieve-address-parts.c     | 72 ++++------------------
 src/lib-sieve/sieve-comparators.c       | 81 ++++++-------------------
 src/lib-sieve/sieve-match-types.c       | 79 +++++-------------------
 src/lib-sieve/sieve-validator.c         | 73 ++++++++++++++++++++++
 src/lib-sieve/sieve-validator.h         | 19 ++++++
 8 files changed, 139 insertions(+), 189 deletions(-)

diff --git a/TODO b/TODO
index 6fd73a01b..3a59fe0c3 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,4 @@
 Next (in order of descending priority/precedence):
-* Remove remaining code duplication among the different sieveobjects.
 * Improve handling of old/corrupt binaries.
 
 * Full standards compliance review for the engine and all fully implemented 
diff --git a/src/lib-sieve/plugins/regex/ext-regex.c b/src/lib-sieve/plugins/regex/ext-regex.c
index b5d28acb0..0eac65508 100644
--- a/src/lib-sieve/plugins/regex/ext-regex.c
+++ b/src/lib-sieve/plugins/regex/ext-regex.c
@@ -52,7 +52,7 @@ const struct sieve_extension regex_extension = {
 	ext_regex_validator_load,
 	NULL, NULL, NULL, NULL, NULL,  
 	SIEVE_EXT_DEFINE_NO_OPERATIONS, 
-	SIEVE_EXT_DEFINE_NO_OPERANDS
+	SIEVE_EXT_DEFINE_OPERAND(regex_match_type_operand)
 };
 
 static bool ext_regex_load(int ext_id)
diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c
index 79b648cb5..8b671957a 100644
--- a/src/lib-sieve/sieve-actions.c
+++ b/src/lib-sieve/sieve-actions.c
@@ -35,7 +35,6 @@ const char *sieve_get_new_message_id
 static int ext_my_id = -1;
 
 static bool seffect_extension_load(int ext_id);
-static bool seffect_binary_load(struct sieve_binary *sbin);
 
 const struct sieve_extension side_effects_extension = {
 	"@side-effects",
diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c
index af3b86937..f13ac3dcd 100644
--- a/src/lib-sieve/sieve-address-parts.c
+++ b/src/lib-sieve/sieve-address-parts.c
@@ -60,88 +60,42 @@ static bool addrp_extension_load(int ext_id)
 /* 
  * Validator context:
  *   name-based address-part registry. 
- *
- * FIXME: This code will be duplicated across all extensions that introduce 
- * a registry of some kind in the validator. 
  */
  
-struct addrp_validator_registration {
-	int ext_id;
-	const struct sieve_address_part *address_part;
-};
- 
-struct addrp_validator_context {
-	struct hash_table *registrations;
-};
-
-static inline struct addrp_validator_context *
-	get_validator_context(struct sieve_validator *validator)
-{
-	return (struct addrp_validator_context *) 
-		sieve_validator_extension_get_context(validator, ext_my_id);
-}
-
-static void _sieve_address_part_register
-	(pool_t pool, struct addrp_validator_context *ctx, 
-	const struct sieve_address_part *addrp, int ext_id) 
-{
-	struct addrp_validator_registration *reg;
-	
-	reg = p_new(pool, struct addrp_validator_registration, 1);
-	reg->address_part = addrp;
-	reg->ext_id = ext_id;
-	
-	hash_insert
-		(ctx->registrations, (void *) addrp->object.identifier, (void *) reg);
-}
- 
 void sieve_address_part_register
 	(struct sieve_validator *validator, 
 	const struct sieve_address_part *addrp, int ext_id) 
 {
-	pool_t pool = sieve_validator_pool(validator);
-	struct addrp_validator_context *ctx = get_validator_context(validator);
-
-	_sieve_address_part_register(pool, ctx, addrp, ext_id);
+	struct sieve_validator_object_registry *regs = 
+		sieve_validator_object_registry_get(validator, ext_my_id);
+	
+	sieve_validator_object_registry_add(regs, &addrp->object, ext_id);
 }
 
 const struct sieve_address_part *sieve_address_part_find
 	(struct sieve_validator *validator, const char *identifier,
 		int *ext_id) 
 {
-	struct addrp_validator_context *ctx = get_validator_context(validator);
-	struct addrp_validator_registration *reg =
-		(struct addrp_validator_registration *) 
-			hash_lookup(ctx->registrations, identifier);
-			
-	if ( reg == NULL ) return NULL;
+	struct sieve_validator_object_registry *regs = 
+		sieve_validator_object_registry_get(validator, ext_my_id);
+	const struct sieve_object *object = 
+		sieve_validator_object_registry_find(regs, identifier, ext_id);
 
-	if ( ext_id != NULL ) *ext_id = reg->ext_id;
-
-  return reg->address_part;
+  return (const struct sieve_address_part *) object;
 }
 
 bool addrp_validator_load(struct sieve_validator *validator)
 {
+	struct sieve_validator_object_registry *regs = 
+		sieve_validator_object_registry_init(validator, ext_my_id);
 	unsigned int i;
-	pool_t pool = sieve_validator_pool(validator);
-	
-	struct addrp_validator_context *ctx = 
-		p_new(pool, struct addrp_validator_context, 1);
-	
-	/* Setup address-part registry */
-	ctx->registrations = hash_create
-		(pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp);
 
 	/* Register core address-parts */
 	for ( i = 0; i < sieve_core_address_parts_count; i++ ) {
-		const struct sieve_address_part *addrp = sieve_core_address_parts[i];
-		
-		_sieve_address_part_register(pool, ctx, addrp, -1);
+		sieve_validator_object_registry_add
+			(regs, &(sieve_core_address_parts[i]->object), -1);
 	}
 
-	sieve_validator_extension_set_context(validator, ext_my_id, ctx);
-
 	return TRUE;
 }
 
diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c
index 48745377e..479d0466b 100644
--- a/src/lib-sieve/sieve-comparators.c
+++ b/src/lib-sieve/sieve-comparators.c
@@ -65,88 +65,41 @@ static bool cmp_extension_load(int ext_id)
 /* 
  * Validator context:
  *   name-based comparator registry. 
- *
- * FIXME: This code will be duplicated across all extensions that introduce 
- * a registry of some kind in the validator. 
  */
  
-struct cmp_validator_registration {
-	int ext_id;
-	const struct sieve_comparator *comparator;
-};
- 
-struct cmp_validator_context {
-	struct hash_table *registrations;
-};
-
-static inline struct cmp_validator_context *
-	get_validator_context(struct sieve_validator *validator)
-{
-	return (struct cmp_validator_context *) 
-		sieve_validator_extension_get_context(validator, ext_my_id);
-}
-
-static void _sieve_comparator_register
-	(pool_t pool, struct cmp_validator_context *ctx, 
-	const struct sieve_comparator *cmp, int ext_id) 
-{
-	struct cmp_validator_registration *reg;
-	
-	reg = p_new(pool, struct cmp_validator_registration, 1);
-	reg->comparator = cmp;
-	reg->ext_id = ext_id;
-	
-	hash_insert
-		(ctx->registrations, (void *) cmp->object.identifier, (void *) reg);
-}
- 
 void sieve_comparator_register
-	(struct sieve_validator *validator, 
-	const struct sieve_comparator *cmp, int ext_id) 
+(struct sieve_validator *validator, const struct sieve_comparator *cmp, 
+	int ext_id) 
 {
-	pool_t pool = sieve_validator_pool(validator);
-	struct cmp_validator_context *ctx = get_validator_context(validator);
-
-	_sieve_comparator_register(pool, ctx, cmp, ext_id);
+	struct sieve_validator_object_registry *regs = 
+		sieve_validator_object_registry_get(validator, ext_my_id);
+	
+	sieve_validator_object_registry_add(regs, &cmp->object, ext_id);
 }
 
 const struct sieve_comparator *sieve_comparator_find
-	(struct sieve_validator *validator, const char *identifier,
-		int *ext_id) 
+(struct sieve_validator *validator, const char *identifier, int *ext_id) 
 {
-	struct cmp_validator_context *ctx = get_validator_context(validator);
-	struct cmp_validator_registration *reg =
-		(struct cmp_validator_registration *) 
-			hash_lookup(ctx->registrations, identifier);
-			
-	if ( reg == NULL ) return NULL;
-
-	if ( ext_id != NULL ) *ext_id = reg->ext_id;
+	struct sieve_validator_object_registry *regs = 
+		sieve_validator_object_registry_get(validator, ext_my_id);
+	const struct sieve_object *object = 
+		sieve_validator_object_registry_find(regs, identifier, ext_id);
 
-  return reg->comparator;
+  return (const struct sieve_comparator *) object;
 }
 
 bool cmp_validator_load(struct sieve_validator *validator)
 {
+	struct sieve_validator_object_registry *regs = 
+		sieve_validator_object_registry_init(validator, ext_my_id);
 	unsigned int i;
-	pool_t pool = sieve_validator_pool(validator);
-	
-	struct cmp_validator_context *ctx = 
-		p_new(pool, struct cmp_validator_context, 1);
-	
-	/* Setup comparator registry */
-	ctx->registrations = hash_create
-		(pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp);
-
+		
 	/* Register core comparators */
 	for ( i = 0; i < sieve_core_comparators_count; i++ ) {
-		const struct sieve_comparator *cmp = sieve_core_comparators[i];
-		
-		_sieve_comparator_register(pool, ctx, cmp, -1);
+		sieve_validator_object_registry_add
+			(regs, &(sieve_core_comparators[i]->object), -1);
 	}
 
-	sieve_validator_extension_set_context(validator, ext_my_id, ctx);
-
 	return TRUE;
 }
 
diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c
index b1e165f59..d860e94a5 100644
--- a/src/lib-sieve/sieve-match-types.c
+++ b/src/lib-sieve/sieve-match-types.c
@@ -65,88 +65,41 @@ static bool mtch_extension_load(int ext_id)
 /* 
  * Validator context:
  *   name-based match-type registry. 
- *
- * FIXME: This code will be duplicated across all extensions that introduce 
- * a registry of some kind in the validator. 
  */
  
-struct mtch_validator_registration {
-	int ext_id;
-	const struct sieve_match_type *match_type;
-};
- 
-struct mtch_validator_context {
-	struct hash_table *registrations;
-};
-
-static inline struct mtch_validator_context *
-	get_validator_context(struct sieve_validator *validator)
-{
-	return (struct mtch_validator_context *) 
-		sieve_validator_extension_get_context(validator, ext_my_id);
-}
-
-static void _sieve_match_type_register
-	(pool_t pool, struct mtch_validator_context *ctx, 
-	const struct sieve_match_type *mtch, int ext_id) 
-{
-	struct mtch_validator_registration *reg;
-	
-	reg = p_new(pool, struct mtch_validator_registration, 1);
-	reg->match_type = mtch;
-	reg->ext_id = ext_id;
-	
-	hash_insert(ctx->registrations, (void *) mtch->object.identifier, 
-		(void *) reg);
-}
- 
 void sieve_match_type_register
-	(struct sieve_validator *validator, 
-	const struct sieve_match_type *mtch, int ext_id) 
+(struct sieve_validator *validator, const struct sieve_match_type *mtch, 
+	int ext_id) 
 {
-	pool_t pool = sieve_validator_pool(validator);
-	struct mtch_validator_context *ctx = get_validator_context(validator);
-
-	_sieve_match_type_register(pool, ctx, mtch, ext_id);
+	struct sieve_validator_object_registry *regs = 
+		sieve_validator_object_registry_get(validator, ext_my_id);
+	
+	sieve_validator_object_registry_add(regs, &mtch->object, ext_id);
 }
 
 const struct sieve_match_type *sieve_match_type_find
-	(struct sieve_validator *validator, const char *identifier,
-		int *ext_id) 
+(struct sieve_validator *validator, const char *identifier, int *ext_id) 
 {
-	struct mtch_validator_context *ctx = get_validator_context(validator);
-	struct mtch_validator_registration *reg =
-		(struct mtch_validator_registration *) 
-			hash_lookup(ctx->registrations, identifier);
-			
-	if ( reg == NULL ) return NULL;
+	struct sieve_validator_object_registry *regs = 
+		sieve_validator_object_registry_get(validator, ext_my_id);
+	const struct sieve_object *object = 
+		sieve_validator_object_registry_find(regs, identifier, ext_id);
 
-	if ( ext_id != NULL ) *ext_id = reg->ext_id;
-
-  return reg->match_type;
+  return (const struct sieve_match_type *) object;
 }
 
 bool mtch_validator_load(struct sieve_validator *validator)
 {
+	struct sieve_validator_object_registry *regs = 
+		sieve_validator_object_registry_init(validator, ext_my_id);
 	unsigned int i;
-	pool_t pool = sieve_validator_pool(validator);
-	
-	struct mtch_validator_context *ctx = 
-		p_new(pool, struct mtch_validator_context, 1);
-	
-	/* Setup match-type registry */
-	ctx->registrations = hash_create
-		(pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp);
 
 	/* Register core match-types */
 	for ( i = 0; i < sieve_core_match_types_count; i++ ) {
-		const struct sieve_match_type *mtch = sieve_core_match_types[i];
-		
-		_sieve_match_type_register(pool, ctx, mtch, -1);
+		sieve_validator_object_registry_add
+			(regs, &(sieve_core_match_types[i]->object), -1);
 	}
 
-	sieve_validator_extension_set_context(validator, ext_my_id, ctx);
-
 	return TRUE;
 }
 
diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c
index aaa3caa7b..b7be9fd2f 100644
--- a/src/lib-sieve/sieve-validator.c
+++ b/src/lib-sieve/sieve-validator.c
@@ -947,5 +947,78 @@ bool sieve_validator_run(struct sieve_validator *validator) {
 	return sieve_validate_block(validator, sieve_ast_root(validator->ast));
 }
 
+/*
+ * Validator object registry
+ */
+
+struct sieve_validator_object_reg {
+	const struct sieve_object *object;
+	int ext_id;
+};
+ 
+struct sieve_validator_object_registry {
+	struct sieve_validator *validator;
+	struct hash_table *registrations;
+};
+
+struct sieve_validator_object_registry *sieve_validator_object_registry_get
+(struct sieve_validator *validator, int ext_id)
+{
+	return (struct sieve_validator_object_registry *) 
+		sieve_validator_extension_get_context(validator, ext_id);
+}
+
+void sieve_validator_object_registry_add
+(struct sieve_validator_object_registry *regs,
+	const struct sieve_object *object, int ext_id) 
+{
+	struct sieve_validator_object_reg *reg;
+	
+	reg = p_new(regs->validator->pool, struct sieve_validator_object_reg, 1);
+	reg->object = object;
+	reg->ext_id = ext_id;
+	
+	hash_insert
+		(regs->registrations, (void *) object->identifier, (void *) reg);
+}
+
+const struct sieve_object *sieve_validator_object_registry_find
+(struct sieve_validator_object_registry *regs, const char *identifier,
+		int *ext_id) 
+{
+	struct sieve_validator_object_reg *reg =(struct sieve_validator_object_reg *) 
+		hash_lookup(regs->registrations, identifier);
+			
+	if ( reg == NULL ) return NULL;
+
+	if ( ext_id != NULL ) *ext_id = reg->ext_id;
+
+  return reg->object;
+}
+
+struct sieve_validator_object_registry *sieve_validator_object_registry_create
+(struct sieve_validator *validator)
+{
+	pool_t pool = validator->pool;
+	struct sieve_validator_object_registry *regs = 
+		p_new(pool, struct sieve_validator_object_registry, 1);
+	
+	/* Setup comparator registry */
+	regs->registrations = hash_create
+		(pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp);
+	regs->validator = validator;
+
+	return regs;
+}
+
+struct sieve_validator_object_registry *sieve_validator_object_registry_init
+(struct sieve_validator *validator, int ext_id)
+{
+	struct sieve_validator_object_registry *regs = 
+		sieve_validator_object_registry_create(validator);
+	
+	sieve_validator_extension_set_context(validator, ext_id, regs);
+	return regs;
+}
 
 
diff --git a/src/lib-sieve/sieve-validator.h b/src/lib-sieve/sieve-validator.h
index 5fdfd552c..ff3595c2a 100644
--- a/src/lib-sieve/sieve-validator.h
+++ b/src/lib-sieve/sieve-validator.h
@@ -94,4 +94,23 @@ void sieve_validator_extension_set_context
 const void *sieve_validator_extension_get_context
 	(struct sieve_validator *validator, int ext_id);
 
+/*
+ * Validator object registry
+ */
+
+struct sieve_validator_object_registry;
+
+struct sieve_validator_object_registry *sieve_validator_object_registry_get
+	(struct sieve_validator *validator, int ext_id);
+void sieve_validator_object_registry_add
+	(struct sieve_validator_object_registry *regs,
+		const struct sieve_object *object, int ext_id);
+const struct sieve_object *sieve_validator_object_registry_find
+	(struct sieve_validator_object_registry *regs, const char *identifier,
+		int *ext_id);
+struct sieve_validator_object_registry *sieve_validator_object_registry_create
+	(struct sieve_validator *validator);
+struct sieve_validator_object_registry *sieve_validator_object_registry_init
+	(struct sieve_validator *validator, int ext_id);
+
 #endif /* __SIEVE_VALIDATOR_H */
-- 
GitLab