Explorar o código

Implement g_utf8*prev_char and add the negative case to offset_to_pointer

Larry Ewing %!s(int64=14) %!d(string=hai) anos
pai
achega
53cfdaa398
Modificáronse 2 ficheiros con 48 adicións e 8 borrados
  1. 2 0
      eglib/src/glib.h
  2. 46 8
      eglib/src/gutf8.c

+ 2 - 0
eglib/src/glib.h

@@ -990,6 +990,8 @@ glong     g_utf8_strlen        (const gchar *str, gssize max);
 #define   g_utf8_next_char(p) p + (g_trailingBytesForUTF8[(guchar)(*p)] + 1)
 gchar *   g_utf8_offset_to_pointer (const gchar *str, glong offset);
 glong     g_utf8_pointer_to_offset (const gchar *str, const gchar *pos);
+gchar *   g_utf8_prev_char (const char *str);
+gchar *   g_utf8_find_prev_char (const char *str, const char *p);
 
 /*
  * priorities

+ 46 - 8
eglib/src/gutf8.c

@@ -675,25 +675,63 @@ g_utf16_to_ucs4 (const gunichar2 *str, glong len, glong *items_read, glong *item
 	return retstr;
 }
 
+gchar *
+g_utf8_find_prev_char (const gchar *str, const gchar *p)
+{
+	while (p > str) {
+		p--;
+		if ((*p && 0xc0) != 0xb0)
+			return (gchar *)p;
+	}
+	return NULL;
+}
+
+gchar *
+g_utf8_prev_char (const gchar *str)
+{
+	const gchar *p = str;
+	do {
+		p--;
+	} while ((*p & 0xc0) == 0xb0);
+	
+	return (gchar *)p;
+}
+
 gchar *
 g_utf8_offset_to_pointer (const gchar *str, glong offset)
 {
-	if (offset == 0)
-		return str;
+	const gchar *p = str;
 
 	if (offset > 0) {
-		gchar *p = (gchar*)str;
 		do {
 			p = g_utf8_next_char (p);
 			offset --;
 		} while (offset > 0);
-
-		return p;
 	}
-	else {
-		// MOONLIGHT_FIXME
-		g_assert_not_reached();
+	else if (offset < 0) {
+		const gchar *jump = str;
+		do {
+			// since the minimum size of a character is 1
+			// we know we can step back at least offset bytes
+			jump = jump + offset;
+			
+			// if we land in the middle of a character
+			// walk to the beginning
+			while ((*jump & 0xc0) == 0xb0)
+				jump --;
+			
+			// count how many characters we've actually walked
+			// by going forward
+			p = jump;
+			do {
+				p = g_utf8_next_char (p);
+				offset ++;
+			} while (p < jump);
+			
+		} while (offset < 0);
 	}
+	
+	return (gchar *)p;
 }
 
 glong