summaryrefslogtreecommitdiffstats
path: root/libraries/librewrite/var.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/librewrite/var.c')
-rw-r--r--libraries/librewrite/var.c273
1 files changed, 273 insertions, 0 deletions
diff --git a/libraries/librewrite/var.c b/libraries/librewrite/var.c
new file mode 100644
index 0000000..61adc57
--- /dev/null
+++ b/libraries/librewrite/var.c
@@ -0,0 +1,273 @@
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2000-2021 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENT:
+ * This work was initially developed by Pierangelo Masarati for
+ * inclusion in OpenLDAP Software.
+ */
+
+#include <portable.h>
+
+#include "rewrite-int.h"
+
+/*
+ * Compares two vars
+ */
+static int
+rewrite_var_cmp(
+ const void *c1,
+ const void *c2
+)
+{
+ const struct rewrite_var *v1, *v2;
+
+ v1 = ( const struct rewrite_var * )c1;
+ v2 = ( const struct rewrite_var * )c2;
+
+ assert( v1 != NULL );
+ assert( v2 != NULL );
+ assert( v1->lv_name != NULL );
+ assert( v2->lv_name != NULL );
+
+ return strcasecmp( v1->lv_name, v2->lv_name );
+}
+
+/*
+ * Duplicate var ?
+ */
+static int
+rewrite_var_dup(
+ void *c1,
+ void *c2
+)
+{
+ struct rewrite_var *v1, *v2;
+
+ v1 = ( struct rewrite_var * )c1;
+ v2 = ( struct rewrite_var * )c2;
+
+ assert( v1 != NULL );
+ assert( v2 != NULL );
+ assert( v1->lv_name != NULL );
+ assert( v2->lv_name != NULL );
+
+ return ( strcasecmp( v1->lv_name, v2->lv_name ) == 0 ? -1 : 0 );
+}
+
+/*
+ * Frees a var
+ */
+static void
+rewrite_var_free(
+ void *v_var
+)
+{
+ struct rewrite_var *var = v_var;
+ assert( var != NULL );
+
+ assert( var->lv_name != NULL );
+ assert( var->lv_value.bv_val != NULL );
+
+ if ( var->lv_flags & REWRITE_VAR_COPY_NAME )
+ free( var->lv_name );
+ if ( var->lv_flags & REWRITE_VAR_COPY_VALUE )
+ free( var->lv_value.bv_val );
+ free( var );
+}
+
+/*
+ * Deletes a var tree
+ */
+int
+rewrite_var_delete(
+ Avlnode *tree
+)
+{
+ avl_free( tree, rewrite_var_free );
+ return REWRITE_SUCCESS;
+}
+
+/*
+ * Finds a var
+ */
+struct rewrite_var *
+rewrite_var_find(
+ Avlnode *tree,
+ const char *name
+)
+{
+ struct rewrite_var var;
+
+ assert( name != NULL );
+
+ var.lv_name = ( char * )name;
+ return ( struct rewrite_var * )avl_find( tree,
+ ( caddr_t )&var, rewrite_var_cmp );
+}
+
+int
+rewrite_var_replace(
+ struct rewrite_var *var,
+ const char *value,
+ int flags
+)
+{
+ ber_len_t len;
+
+ assert( value != NULL );
+
+ len = strlen( value );
+
+ if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) {
+ if ( flags & REWRITE_VAR_COPY_VALUE ) {
+ if ( len <= var->lv_value.bv_len ) {
+ AC_MEMCPY(var->lv_value.bv_val, value, len + 1);
+
+ } else {
+ free( var->lv_value.bv_val );
+ var->lv_value.bv_val = strdup( value );
+ }
+
+ } else {
+ free( var->lv_value.bv_val );
+ var->lv_value.bv_val = (char *)value;
+ var->lv_flags &= ~REWRITE_VAR_COPY_VALUE;
+ }
+
+ } else {
+ if ( flags & REWRITE_VAR_COPY_VALUE ) {
+ var->lv_value.bv_val = strdup( value );
+ var->lv_flags |= REWRITE_VAR_COPY_VALUE;
+
+ } else {
+ var->lv_value.bv_val = (char *)value;
+ }
+ }
+
+ if ( var->lv_value.bv_val == NULL ) {
+ return -1;
+ }
+
+ var->lv_value.bv_len = len;
+
+ return 0;
+}
+
+/*
+ * Inserts a newly created var
+ */
+struct rewrite_var *
+rewrite_var_insert_f(
+ Avlnode **tree,
+ const char *name,
+ const char *value,
+ int flags
+)
+{
+ struct rewrite_var *var;
+ int rc = 0;
+
+ assert( tree != NULL );
+ assert( name != NULL );
+ assert( value != NULL );
+
+ var = rewrite_var_find( *tree, name );
+ if ( var != NULL ) {
+ if ( flags & REWRITE_VAR_UPDATE ) {
+ (void)rewrite_var_replace( var, value, flags );
+ goto cleanup;
+ }
+ rc = -1;
+ goto cleanup;
+ }
+
+ var = calloc( sizeof( struct rewrite_var ), 1 );
+ if ( var == NULL ) {
+ return NULL;
+ }
+
+ memset( var, 0, sizeof( struct rewrite_var ) );
+
+ if ( flags & REWRITE_VAR_COPY_NAME ) {
+ var->lv_name = strdup( name );
+ if ( var->lv_name == NULL ) {
+ rc = -1;
+ goto cleanup;
+ }
+ var->lv_flags |= REWRITE_VAR_COPY_NAME;
+
+ } else {
+ var->lv_name = (char *)name;
+ }
+
+ if ( flags & REWRITE_VAR_COPY_VALUE ) {
+ var->lv_value.bv_val = strdup( value );
+ if ( var->lv_value.bv_val == NULL ) {
+ rc = -1;
+ goto cleanup;
+ }
+ var->lv_flags |= REWRITE_VAR_COPY_VALUE;
+
+ } else {
+ var->lv_value.bv_val = (char *)value;
+ }
+ var->lv_value.bv_len = strlen( value );
+ rc = avl_insert( tree, ( caddr_t )var,
+ rewrite_var_cmp, rewrite_var_dup );
+
+cleanup:;
+ if ( rc != 0 && var ) {
+ avl_delete( tree, ( caddr_t )var, rewrite_var_cmp );
+ rewrite_var_free( var );
+ var = NULL;
+ }
+
+ return var;
+}
+
+/*
+ * Sets/inserts a var
+ */
+struct rewrite_var *
+rewrite_var_set_f(
+ Avlnode **tree,
+ const char *name,
+ const char *value,
+ int flags
+)
+{
+ struct rewrite_var *var;
+
+ assert( tree != NULL );
+ assert( name != NULL );
+ assert( value != NULL );
+
+ var = rewrite_var_find( *tree, name );
+ if ( var == NULL ) {
+ if ( flags & REWRITE_VAR_INSERT ) {
+ return rewrite_var_insert_f( tree, name, value, flags );
+
+ } else {
+ return NULL;
+ }
+
+ } else {
+ assert( var->lv_value.bv_val != NULL );
+
+ (void)rewrite_var_replace( var, value, flags );
+ }
+
+ return var;
+}
+