I know I believe in nothing but it is my sweet nothing.:2004年02月06日分

2004/02/06(Fri)

(tbs

@widec.h

に定義されてる関数のうち、ws*系は殆どがwcs*と同じなんだけど、
ws(n)casecmpとかwsdupはwchar.hにはない機能なので実装するのもいいかもね。
glibcだとwcs(n)casecmpやwcsdupという拡張があるようですが。

でっちあげるとこんな感じか。
str(n)casecmpとstrdupのコードが元なので、それぞれのライセンスに準じまつ。

#include "namespace.h"
#include <assert.h>
#include <wctype.h>
#include <widec.h>

#include "runetype.h"

int
wscasecmp(s1, s2)
	const wchar_t *s1, *s2;
{
	_DIAGASSERT(s1 != NULL);
	_DIAGASSERT(s2 != NULL);

	while (towlower(*s1) == towlower(*s2++))
		if (*s1++ == L'\0')
			return (0);
	return ((int)((__nbrune_t)towlower(*s1) - (__nbrune_t)towlower(*--s2)));
}

int
wsncasecmp(s1, s2, n)
	const wchar_t *s1, *s2;
	size_t n;
{

	_DIAGASSERT(s1 != NULL);
	_DIAGASSERT(s2 != NULL);
	if (s1 == NULL || s2 == NULL)
		return (0);

	if (n != 0) {
		do {
			if (towlower(*s1) != towlower(*s2++))
				return ((int)((__nbrune_t)towlower(*s1) -
					      (__nbrune_t)towlower(*--s2)));
			if (*s1++ == L'\0')
				break;
		} while (--n != 0);
	}
	return (0);
}
#include "namespace.h"

#include <assert.h>
#include <wchar.h>
#include <widec.h>

wchar_t *
wsdup(str)
	const wchar_t *str;
{
	size_t len;
	wchar_t *copy;

	_DIAGASSERT(str != NULL);

	len = (wcslen(str) + 1) * sizeof(wchar_t);
	if (!(copy = malloc(len)))
		return (NULL);
	memcpy(copy, str, len);

	return (copy);
}

strtows/wstostrとかも実装するならこんな感じ↓にして
citrus_ctype_templete.h行きかね。

static int
_FUNCNAME(ctype_strtows)(_citrus_ctype_rec_t * __restrict cc,
			 wchar_t * __restrict ws,
			 char * __restrict s,
			 wchar_t ** __restrict ret)
{
	_ENCODING_INFO *ei;
	_ENCODING_STATE state;
	wchar_t *ws0;
	size_t mbcurmax, siz;
	int err;

	_DIAGASSERT(cc != NULL && cc->cc_closure != NULL);
	_DIAGASSERT(ws != NULL);
	_DIAGASSERT(s != NULL);
	_DIAGASSERT(ret != NULL);

	ws0 = ws;
	ei = _CEI_TO_EI(_TO_CEI(cc->cc_closure));
	_FUNCNAME(init_state)(ei, &state);
	mbcurmax = _ENCODING_MB_CUR_MAX(ei);

	for (;;) {
		err = _FUNCNAME(mbrtowc_priv)(ei,
			ws0, &s, mbcurmax, &state, &siz);
		_DIAGASSERT(siz != (size_t)-2)
		if (err) {
			err = EILSEQ;
			*ret = (wchar_t *)NULL;
			break;
		}
		if (siz == 0) {
			*ret = ws;
			break;
		}
		ws0++;
		s += siz;
	}

	return (err);
}

static int
_FUNCNAME(ctype_wstostr)(_citrus_ctype_rec_t * __restrict cc,
			 char * __restrict s,
			 wchar_t * __restrict ws,
			 char ** __restrict s)
{
	_ENCODING_INFO *ei;
	_ENCODING_STATE state;
	char *s0;
	size_t mbcurmax, siz;
	int err;

	_DIAGASSERT(cc != NULL & cc->cc_closure != NULL);
	_DIAGASSERT(s != NULL);
	_DIAGASSERT(ws != NULL);
	_DIAGASSERT(ret != NULL);

	s0 = s;
	ei = _CEI_TO_EI(_TO_CEI(cc->cc_closure));
	_FUNCNAME(init_state)(ei, &state);
	mbcurmax = _ENCODING_MB_CUR_MAX(ei);

	for (;;) {
		err = _FUNCNAME(wcrtomb_priv)(ei,
			s0, mbcurmax, *ws, &state, &siz);
		if (err) {
			err = EILSEQ;
			*ret = NULL;
			break;
		}
		if (*ws == L'\0') {
			*ret = s;
			break;
		}
		s0 += siz;
		ws++;
	}

	return (err);
}

ただしこいつはlength checkのないヤバい関数だから__warn_reference要かも。