master xplshn/aruu / shared / libutf / utf.c
  1/* MIT/X Consortium Copyright (c) 2012 Connor Lane Smith <cls@lubutu.com>
  2 *
  3 * Permission is hereby granted, free of charge, to any person obtaining a
  4 * copy of this software and associated documentation files (the "Software"),
  5 * to deal in the Software without restriction, including without limitation
  6 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  7 * and/or sell copies of the Software, and to permit persons to whom the
  8 * Software is furnished to do so, subject to the following conditions:
  9 *
 10 * The above copyright notice and this permission notice shall be included in
 11 * all copies or substantial portions of the Software.
 12 *
 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 16 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 19 * DEALINGS IN THE SOFTWARE.
 20 */
 21#include <string.h>
 22#include "../utf.h"
 23
 24char *
 25utfecpy(char *to, char *end, const char *from)
 26{
 27	Rune r = Runeerror;
 28	size_t i, n;
 29
 30	/* seek through to find final full rune */
 31	for(i = 0; r != '\0' && (n = charntorune(&r, &from[i], end - &to[i])); i += n)
 32		;
 33	memcpy(to, from, i); /* copy over bytes up to this rune */
 34
 35	if(i > 0 && r != '\0')
 36		to[i] = '\0'; /* terminate if unterminated */
 37	return &to[i];
 38}
 39
 40size_t
 41utflen(const char *s)
 42{
 43	const char *p = s;
 44	size_t i;
 45	Rune r;
 46
 47	for(i = 0; *p != '\0'; i++)
 48		p += chartorune(&r, p);
 49	return i;
 50}
 51
 52size_t
 53utfnlen(const char *s, size_t len)
 54{
 55	const char *p = s;
 56	size_t i;
 57	Rune r;
 58	int n;
 59
 60	for(i = 0; (n = charntorune(&r, p, len-(p-s))) && r != '\0'; i++)
 61		p += n;
 62	return i;
 63}
 64
 65size_t
 66utfmemlen(const char *s, size_t len)
 67{
 68	const char *p = s;
 69	size_t i;
 70	Rune r;
 71	int n;
 72
 73	for(i = 0; (n = charntorune(&r, p, len-(p-s))); i++)
 74		p += n;
 75	return i;
 76}
 77
 78char *
 79utfrune(const char *s, Rune r)
 80{
 81	if(r < Runeself) {
 82		return strchr(s, r);
 83	}
 84	else if(r == Runeerror) {
 85		Rune r0;
 86		int n;
 87
 88		for(; *s != '\0'; s += n) {
 89			n = chartorune(&r0, s);
 90			if(r == r0)
 91				return (char *)s;
 92		}
 93	}
 94	else {
 95		char buf[UTFmax+1];
 96		int n;
 97
 98		if(!(n = runetochar(buf, &r)))
 99			return NULL;
100		buf[n] = '\0';
101		return strstr(s, buf);
102	}
103	return NULL;
104}
105
106char *
107utfrrune(const char *s, Rune r)
108{
109	const char *p = NULL;
110	Rune r0;
111	int n;
112
113	if(r < Runeself)
114		return strrchr(s, r);
115
116	for(; *s != '\0'; s += n) {
117		n = chartorune(&r0, s);
118		if(r == r0)
119			p = s;
120	}
121	return (char *)p;
122}
123
124char *
125utfutf(const char *s, const char *t)
126{
127	const char *p, *q;
128	Rune r0, r1, r2;
129	int n, m;
130
131	for(chartorune(&r0, t); (s = utfrune(s, r0)); s++) {
132		for(p = s, q = t; *q && *p; p += n, q += m) {
133			n = chartorune(&r1, p);
134			m = chartorune(&r2, q);
135			if(r1 != r2)
136				break;
137		}
138		if(!*q)
139			return (char *)s;
140	}
141	return NULL;
142}