~martanne/ciopfs

d4f674930e0a479d4e021c781ac6e3fd7e0df0bd — Marc Andre Tanner 13 years ago 73dc23b
Split case folding and uppercase detection into separate files

Add 3 new files which each implements the following two functions:

 static inline bool str_contains_upper(const char *s);
 static inline char *str_fold(const char *s);

By default a glib based implementation is used, the other options
are still available via Makefile targets ascii and unicode-icu.
6 files changed, 147 insertions(+), 118 deletions(-)

M Makefile
A ascii.c
M ciopfs.c
M config.mk
A unicode-glib.c
A unicode-icu.c
M Makefile => Makefile +10 -1
@@ 24,6 24,15 @@ ciopfs: ${OBJ}
debug: clean
	@make CFLAGS='${DEBUG_CFLAGS}'

ascii: clean
	@make CFLAGS_UNICODE='' LDFLAGS_UNICODE=''

unicode-glib: clean
	@make CFLAGS_UNICODE='${CFLAGS_GLIB}' LDFLAGS_UNICODE='${LDFLAGS_GLIB}'

unicode-icu: clean
	@make CFLAGS_UNICODE='${CFLAGS_ICU}' LDFLAGS_UNICODE='${LDFLAGS_ICU}'

clean:
	@echo cleaning
	@rm -f ciopfs ${OBJ} ciopfs-${VERSION}.tar.gz


@@ 58,4 67,4 @@ uninstall:
#	@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
#	@rm -f ${DESTDIR}${MANPREFIX}/man1/ciopfs.1

.PHONY: all options clean dist install uninstall debug
.PHONY: all options clean dist install uninstall debug ascii unicode-glib unicode-icu

A ascii.c => ascii.c +21 -0
@@ 0,0 1,21 @@
#include <ctype.h>

static inline bool str_contains_upper(const char *s)
{
	while (*s) {
		if (isupper(*s++))
			return true;
	}
	return false;
}

static inline char *str_fold(const char *src)
{
	char *t, *dest = malloc(strlen(src));
	if (!dest)
		return NULL;
	for (t = dest; *src; src++, t++)
		*t = tolower(*src);
	*t = '\0';
	return dest;
}

M ciopfs.c => ciopfs.c +11 -114
@@ 55,7 55,6 @@
#include <sys/time.h>
#include <assert.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdarg.h>


@@ 67,9 66,17 @@
#include <syslog.h>
#include <grp.h>

#ifdef HAVE_LIBICUUC
#include <unicode/ustring.h>
#include <unicode/uchar.h>
/* each *.c file implements the following two functions:
 *
 * static inline bool str_contains_upper(const char *s);
 * static inline char *str_fold(const char *s);
 */
#ifdef HAVE_GLIB
# include "unicode-glib.c"
#elif defined HAVE_LIBICUUC
# include "unicode-icu.c"
#else
# include "ascii.c"
#endif

#define log_print(format, args...) (*dolog)(format, ## args)


@@ 90,7 97,6 @@
#define FILENAME_MAX 4096
#endif


static const char *dirname;

void stderr_print(const char *fmt, ...)


@@ 112,115 118,6 @@ void syslog_print(const char *fmt, ...)

static void (*dolog)(const char *fmt, ...) = syslog_print;

#ifdef HAVE_LIBICUUC

static inline UChar *utf8_to_utf16(const char *str, int32_t *length)
{
	UChar *ustr;
	UErrorCode status = U_ZERO_ERROR;

	u_strFromUTF8(NULL, 0, length, str, -1, &status);
	status = U_ZERO_ERROR;
	(*length)++; /* for the NUL char */
	ustr = malloc(sizeof(UChar) * (*length));
	if (!ustr)
		return NULL;
	u_strFromUTF8(ustr, *length, NULL, str, -1, &status);
	if (U_FAILURE(status)) {
		free(ustr);
		return NULL;
	}
	return ustr;
}

static inline char *utf16_to_utf8(UChar *ustr, int32_t *length)
{
	char *str;
	UErrorCode status = U_ZERO_ERROR;

	u_strToUTF8(NULL, 0, length, ustr, -1, &status);
	status = U_ZERO_ERROR;
	(*length)++; /* for the NUL char */
	str = malloc(*length);
	if (!str)
		return NULL;
	u_strToUTF8(str, *length, NULL, ustr, -1, &status);
	if (U_FAILURE(status)) {
		free(str);
		return NULL;
	}
	return str;
}

static inline char *utf_fold(const char *s)
{
	int32_t length;
	char *str;
	UChar *ustr;
	UErrorCode status = U_ZERO_ERROR;

	ustr = utf8_to_utf16(s, &length);
	if (!ustr)
		return NULL;
	u_strFoldCase(ustr, length, ustr, length, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &status);
	if (U_FAILURE(status))
		return NULL;
	str = utf16_to_utf8(ustr, &length);
	free(ustr);
	return str;
}

static inline bool utf_contains_upper(const char *s)
{
	bool ret = false;
	int32_t length, i;
	UChar32 c;
	UChar *ustr = utf8_to_utf16(s, &length);
	if (!ustr)
		return true;
	for (i = 0; i < length; /* U16_NEXT post-increments */) {
		U16_NEXT(ustr, i, length, c);
		if (u_isupper(c)) {
			ret = true;
			goto out;
		}
	}
out:
	free(ustr);
	return ret;
}

#endif /* HAVE_LIBICUUC */

static inline bool str_contains_upper(const char *s)
{
#ifdef HAVE_LIBICUUC
	return utf_contains_upper(s);
#else
	while (*s) {
		if (isupper(*s++))
			return true;
	}
	return false;
#endif
}

static inline char *str_fold(const char *src)
{
#ifdef HAVE_LIBICUUC
	return utf_fold(src);
#else
	char *t;
	char *dest = malloc(strlen(src));
	if (!dest)
		return NULL;
	for (t = dest; *src; src++, t++)
		*t = tolower(*src);
	*t = '\0';
	return dest;
#endif
}

static char *map_path(const char *path)
{
	char *p;

M config.mk => config.mk +11 -3
@@ 12,11 12,19 @@ LDFLAGS_FUSE = $(shell pkg-config --libs fuse) -lulockmgr

LDFLAGS_XATTR = -lattr

# optional for unicode supprt
# unicode support form glib
CFLAGS_GLIB  = $(shell pkg-config --cflags glib-2.0) -DHAVE_GLIB
LDFLAGS_GLIB = $(shell pkg-config --libs glib-2.0)

# unicode support from libicu from icu-project.org
CFLAGS_ICU  = -DHAVE_LIBICUUC
LDFLAGS_ICU = -licuuc

CFLAGS  += ${CFLAGS_FUSE}  ${CFLAGS_ICU} -DVERSION=\"${VERSION}\" -DNDEBUG -Os
LDFLAGS += ${LDFLAGS_FUSE} ${LDFLAGS_ICU} ${LDFLAGS_XATTR}
# unicode flags set this to either {C,LD}FLAGS_GLIB or {C,LD}FLAGS_ICU
CFLAGS_UNICODE  = ${CFLAGS_GLIB}
LDFLAGS_UNICODE = ${LDFLAGS_GLIB}

CFLAGS  += ${CFLAGS_FUSE}  ${CFLAGS_UNICODE} -DVERSION=\"${VERSION}\" -DNDEBUG -Os
LDFLAGS += ${LDFLAGS_FUSE} ${LDFLAGS_UNICODE} ${LDFLAGS_XATTR}

DEBUG_CFLAGS = ${CFLAGS} -UNDEBUG -O0 -g -ggdb -Wall

A unicode-glib.c => unicode-glib.c +16 -0
@@ 0,0 1,16 @@
#include <glib.h>

static inline bool str_contains_upper(const char *s)
{
	while (*s) {
		if(g_unichar_isupper(g_utf8_get_char(s)))
			return true;
		s = g_utf8_next_char(s);
	}
	return false;
}

static inline char *str_fold(const char *s)
{
	return g_utf8_casefold(s, -1);
}

A unicode-icu.c => unicode-icu.c +78 -0
@@ 0,0 1,78 @@
#include <unicode/ustring.h>
#include <unicode/uchar.h>

static inline UChar *utf8_to_utf16(const char *str, int32_t *length)
{
	UChar *ustr;
	UErrorCode status = U_ZERO_ERROR;

	u_strFromUTF8(NULL, 0, length, str, -1, &status);
	status = U_ZERO_ERROR;
	(*length)++; /* for the NUL char */
	ustr = malloc(sizeof(UChar) * (*length));
	if (!ustr)
		return NULL;
	u_strFromUTF8(ustr, *length, NULL, str, -1, &status);
	if (U_FAILURE(status)) {
		free(ustr);
		return NULL;
	}
	return ustr;
}

static inline char *utf16_to_utf8(UChar *ustr, int32_t *length)
{
	char *str;
	UErrorCode status = U_ZERO_ERROR;

	u_strToUTF8(NULL, 0, length, ustr, -1, &status);
	status = U_ZERO_ERROR;
	(*length)++; /* for the NUL char */
	str = malloc(*length);
	if (!str)
		return NULL;
	u_strToUTF8(str, *length, NULL, ustr, -1, &status);
	if (U_FAILURE(status)) {
		free(str);
		return NULL;
	}
	return str;
}

static inline bool str_contains_upper(const char *s)
{
	bool ret = false;
	int32_t length, i;
	UChar32 c;
	UChar *ustr = utf8_to_utf16(s, &length);
	if (!ustr)
		return true;
	for (i = 0; i < length; /* U16_NEXT post-increments */) {
		U16_NEXT(ustr, i, length, c);
		if (u_isupper(c)) {
			ret = true;
			goto out;
		}
	}
out:
	free(ustr);
	return ret;
}

static inline char *str_fold(const char *s)
{
	int32_t length;
	char *str;
	UChar *ustr;
	UErrorCode status = U_ZERO_ERROR;

	ustr = utf8_to_utf16(s, &length);
	if (!ustr)
		return NULL;
	u_strFoldCase(ustr, length, ustr, length, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &status);
	if (U_FAILURE(status))
		return NULL;
	str = utf16_to_utf8(ustr, &length);
	free(ustr);
	return str;
}