changeset 3566:0355b805cd4c HEAD

Added 'H' hash modifier.
author Timo Sirainen <tss@iki.fi>
date Thu, 01 Sep 2005 10:57:35 +0300
parents 2b167cc13887
children 58e3fa234ef4
files src/lib/var-expand.c
diffstat 1 files changed, 69 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/var-expand.c	Mon Aug 29 00:28:59 2005 +0300
+++ b/src/lib/var-expand.c	Thu Sep 01 10:57:35 2005 +0300
@@ -1,18 +1,42 @@
 /* Copyright (C) 2003-2004 Timo Sirainen */
 
 #include "lib.h"
+#include "hash.h"
 #include "str.h"
 #include "strescape.h"
 #include "var-expand.h"
 
 #include <stdlib.h>
 
+struct var_expand_context {
+	unsigned int offset, width;
+};
+
 struct var_expand_modifier {
 	char key;
-	const char *(*func)(const char *);
+	const char *(*func)(const char *, struct var_expand_context *);
 };
 
-static const char *str_hex(const char *str)
+static const char *
+m_str_lcase(const char *str, struct var_expand_context *ctx __attr_unused__)
+{
+	return t_str_lcase(str);
+}
+
+static const char *
+m_str_ucase(const char *str, struct var_expand_context *ctx __attr_unused__)
+{
+	return t_str_lcase(str);
+}
+
+static const char *
+m_str_escape(const char *str, struct var_expand_context *ctx __attr_unused__)
+{
+	return str_escape(str);
+}
+
+static const char *
+m_str_hex(const char *str, struct var_expand_context *ctx __attr_unused__)
 {
 	unsigned long long l;
 
@@ -20,12 +44,32 @@
 	return t_strdup_printf("%llx", l);
 }
 
+static const char *m_str_hash(const char *str, struct var_expand_context *ctx)
+{
+	unsigned int value = str_hash(str);
+	string_t *hash = t_str_new(20);
+
+	if (ctx->width != 0) {
+		value %= ctx->width;
+		ctx->width = 0;
+	}
+	str_printfa(hash, "%x", value);
+	while (str_len(hash) < ctx->offset) {
+		str_insert(hash, 0, "0");
+		ctx->offset--;
+	}
+        ctx->offset = 0;
+
+	return str_c(hash);
+}
+
 #define MAX_MODIFIER_COUNT 10
 static const struct var_expand_modifier modifiers[] = {
-	{ 'L', t_str_lcase },
-	{ 'U', t_str_ucase },
-	{ 'E', str_escape },
-	{ 'X', str_hex },
+	{ 'L', m_str_lcase },
+	{ 'U', m_str_ucase },
+	{ 'E', m_str_escape },
+	{ 'X', m_str_hex },
+	{ 'H', m_str_hash },
 	{ '\0', NULL }
 };
 
@@ -35,11 +79,13 @@
         const struct var_expand_modifier *m;
         const struct var_expand_table *t;
 	const char *var;
-	unsigned int offset, width;
-	const char *(*modifier[MAX_MODIFIER_COUNT])(const char *);
+        struct var_expand_context ctx;
+	const char *(*modifier[MAX_MODIFIER_COUNT])
+		(const char *, struct var_expand_context *);
 	unsigned int i, modifier_count;
 	int zero_padding = FALSE;
 
+	memset(&ctx, 0, sizeof(ctx));
 	for (; *str != '\0'; str++) {
 		if (*str != '%')
 			str_append_c(dest, *str);
@@ -47,24 +93,24 @@
 			str++;
 
 			/* [<offset>.]<width>[<modifiers>]<variable> */
-			width = 0;
+			ctx.width = 0;
 			if (*str == '0') {
 				zero_padding = TRUE;
 				str++;
 			}
 			while (*str >= '0' && *str <= '9') {
-				width = width*10 + (*str - '0');
+				ctx.width = ctx.width*10 + (*str - '0');
 				str++;
 			}
 
 			if (*str != '.')
-				offset = 0;
+				ctx.offset = 0;
 			else {
-				offset = width;
-				width = 0;
+				ctx.offset = ctx.width;
+				ctx.width = 0;
 				str++;
 				while (*str >= '0' && *str <= '9') {
-					width = width*10 + (*str - '0');
+					ctx.width = ctx.width*10 + (*str - '0');
 					str++;
 				}
 			}
@@ -104,20 +150,22 @@
 			}
 
 			if (var != NULL) {
-				for (; *var != '\0' && offset > 0; offset--)
+				for (i = 0; i < modifier_count; i++)
+					var = modifier[i](var, &ctx);
+				while (*var != '\0' && ctx.offset > 0) {
+					ctx.offset--;
 					var++;
-				for (i = 0; i < modifier_count; i++)
-					var = modifier[i](var);
-				if (width == 0)
+				}
+				if (ctx.width == 0)
 					str_append(dest, var);
 				else if (!zero_padding)
-					str_append_n(dest, var, width);
+					str_append_n(dest, var, ctx.width);
 				else {
 					/* %05d -like padding */
 					size_t len = strlen(var);
-					while (len < width) {
+					while (len < ctx.width) {
 						str_append_c(dest, '0');
-						width--;
+						ctx.width--;
 					}
 					str_append(dest, var);
 				}