changeset 11283:1ca1fb00ca36

New module 'memxfrm'.
author Bruno Haible <bruno@clisp.org>
date Sat, 07 Mar 2009 13:38:02 +0100
parents 61dfd8dc1a13
children ee7917a3f050 11b1a7b0a788
files ChangeLog lib/memxfrm.c lib/memxfrm.h modules/memxfrm
diffstat 4 files changed, 197 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2009-03-07  Bruno Haible  <bruno@clisp.org>
+
+	New module 'memxfrm'.
+	* lib/memxfrm.h: New file.
+	* lib/memxfrm.c: New file.
+	* modules/memxfrm: New file.
+
 2009-03-07  Bruno Haible  <bruno@clisp.org>
 
 	New module 'memcmp2'.
new file mode 100644
--- /dev/null
+++ b/lib/memxfrm.c
@@ -0,0 +1,122 @@
+/* Locale dependent memory area transformation for comparison.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2009.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "memxfrm.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *
+memxfrm (char *s, size_t n, size_t *lengthp)
+{
+  /* Result accumulator.  */
+  char *result;
+  size_t length;
+  size_t allocated;
+
+  char orig_sentinel;
+
+  /* Initial memory allocation.  */
+  allocated = (n > 0 ? n : 1);
+  result = (char *) malloc (allocated);
+  if (result == NULL)
+    goto out_of_memory_2;
+  length = 0;
+
+  /* Add sentinel.byte.  */
+  orig_sentinel = s[n];
+  s[n] = '\0';
+
+  /* Iterate through S, transforming each NUL terminated segment.
+     Accumulate the resulting transformed segments in result, separated by
+     NULs.  */
+  {
+    const char *p_end = s + n + 1;
+    const char *p;
+
+    p = s;
+    for (;;)
+      {
+	/* Search next NUL byte.  */
+	const char *q = p + strlen (p);
+
+	for (;;)
+	  {
+	    size_t k;
+
+	    errno = 0;
+	    k = strxfrm (result + length, p, allocated - length);
+	    if (errno != 0)
+	      goto fail;
+	    if (k >= allocated - length)
+	      {
+		/* Grow the result buffer.  */
+		char *new_result;
+
+		allocated = 2 * allocated;
+		new_result = (char *) realloc (result, allocated);
+		if (new_result == NULL)
+		  goto out_of_memory_1;
+		result = new_result;
+	      }
+	    else
+	      {
+		length += k;
+		break;
+	      }
+	  }
+
+	p = q + 1;
+	if (p == p_end)
+	  break;
+	result[length] = '\0';
+        length++;
+      }
+  }
+
+  /* Shrink the allocated memory if possible.  */
+  if ((length > 0 ? length : 1) < allocated)
+    {
+      char *memory = (char *) realloc (result, length > 0 ? length : 1);
+      if (memory != NULL)
+	result = memory;
+    }
+
+  s[n] = orig_sentinel;
+  *lengthp = length;
+  return result;
+
+ fail:
+  {
+    int saved_errno = errno;
+    free (result);
+    s[n] = orig_sentinel;
+    errno = saved_errno;
+    return NULL;
+  }
+
+ out_of_memory_1:
+  free (result);
+  s[n] = orig_sentinel;
+ out_of_memory_2:
+  errno = ENOMEM;
+  return NULL;
+}
new file mode 100644
--- /dev/null
+++ b/lib/memxfrm.h
@@ -0,0 +1,46 @@
+/* Locale dependent memory area transformation for comparison.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef MEMXFRM_H
+#define MEMXFRM_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Generalization of strxfrm() to strings with embedded NUL bytes.  */
+
+/* Transform the memory area [S..S+N-1] to a memory area, in such a way that
+   comparing (S1,N1) and (S2,N2) with memcoll() is equivalent to comparing
+   memxfrm(S1,N1) and memxfrm(S2,N2) with memcmp2().
+   The byte S[N] may be temporarily overwritten by this function, but will be
+   restored before this function returns.
+   The result of this function depends on the LC_COLLATE category of the
+   current locale.
+   If successful, return the freshly allocated transformed string and set
+   *LENGTHP to its length,
+   Upon failure, return NULL, with errno set.  */
+extern char * memxfrm (char *s, size_t n, size_t *lengthp);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MEMXFRM_H */
new file mode 100644
--- /dev/null
+++ b/modules/memxfrm
@@ -0,0 +1,22 @@
+Description:
+Locale dependent memory area transformation for comparison.
+
+Files:
+lib/memxfrm.h
+lib/memxfrm.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += memxfrm.c
+
+Include:
+"memxfrm.h"
+
+License:
+LGPL
+
+Maintainer:
+Bruno Haible