msvcrt[2/2]: implement _mbsbtype

Mikolaj Zalewski mikolajz at google.com
Thu Aug 16 15:45:03 CDT 2007


Skipped content of type multipart/alternative-------------- next part --------------
From 0596765b14e604221f5cd4efa6ebb68b694a59e1 Mon Sep 17 00:00:00 2001
From: Mikolaj Zalewski <mikolaj at zalewski.pl>
Date: Thu, 16 Aug 2007 12:11:39 -0700
Subject: [PATCH] msvcrt: implement _mbsbtype
---
 dlls/msvcrt/mbcs.c         |   45 ++++++++++++++++++++++++++++++++++++++++++++
 dlls/msvcrt/msvcrt.spec    |    2 +-
 dlls/msvcrt/tests/string.c |   11 ++++++++++-
 3 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/dlls/msvcrt/mbcs.c b/dlls/msvcrt/mbcs.c
index 0dc0120..f5cd1e0 100644
--- a/dlls/msvcrt/mbcs.c
+++ b/dlls/msvcrt/mbcs.c
@@ -921,6 +921,7 @@ int CDECL _ismbblead(unsigned int c)
 int CDECL _ismbbtrail(unsigned int c)
 {
   /* FIXME: should reference MSVCRT_mbctype */
+  /* FIXME: the same code can be a lead byte and a trail byte */
   return !_ismbblead(c);
 }
 
@@ -952,6 +953,50 @@ int CDECL _ismbstrail(const unsigned cha
   return !_ismbslead(start, str) && MSVCRT_isleadbyte(str[-1]);
 }
 
+static int count_leads(const unsigned char *start, const unsigned char *end)
+{
+    int count = 0;
+    while (start <= end)
+    {
+	if (!_ismbblead(*end))
+	    return count;
+	count++;
+    }
+    return count;
+}
+
+/*********************************************************************
+ *              _mbsbtype(MSVCRT.@)
+ */
+int CDECL _mbsbtype(const unsigned char *start, size_t pos)
+{
+    if (start == NULL || start[pos] == 0)
+	return _MBC_ILLEGAL;
+
+    /* Note: the same byte can be a lead and a trail so we must go backward
+     * to check something is really a lead/trail
+     */
+    /* TODO: call _ismbtrail before returning _MBC_TRAIL to check it is correct */
+    if (_ismbblead(start[pos]))
+    {
+	if (count_leads(start, start + pos) % 2)
+	    return _MBC_LEAD;
+	else
+	    return _MBC_TRAIL;
+    }
+    else
+    {
+	int count = count_leads(start, start + pos - 1);
+	if (count == 0)
+	    return _MBC_SINGLE;
+	
+	if (count % 2)
+	    return _MBC_TRAIL;
+	else
+	    return _MBC_LEAD;
+    }
+}
+
 /*********************************************************************
  *		_mbsset(MSVCRT.@)
  */
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index fc81898..1a516f0 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -355,7 +355,7 @@ # extern _mbcasemap
 @ stub _mbctombb #(long)
 @ cdecl _mbctoupper(long)
 @ extern _mbctype MSVCRT_mbctype
-@ stub _mbsbtype #(str long)
+@ cdecl _mbsbtype(str long)
 @ cdecl _mbscat(str str)
 @ cdecl _mbschr(str long)
 @ cdecl _mbscmp(str str)
diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c
index d7148da..ff6266c 100644
--- a/dlls/msvcrt/tests/string.c
+++ b/dlls/msvcrt/tests/string.c
@@ -77,12 +77,21 @@ static void test_swab( void ) {
 
 static void test_ismbblead(void)
 {
+    const unsigned char *str = (const unsigned char *)"\xB0\xB0\xB0\x30\xB0\xB0\x30";
     unsigned int s = '\354';
     int mb_orig_max = __mb_cur_max;
 
-    _setmbcp(936);
+    _setmbcp(936);  /* Codepage 936 - lead bytes 0x81-0xfe, trail bytes: 0x40-0xfe */
     ok(__mb_cur_max == mb_orig_max, "__mb_cur_max shouldn't be updated (is %d != %d)\n", __mb_cur_max, mb_orig_max);
     todo_wine ok(_ismbblead(s), "got result %d\n", _ismbblead(s));
+    todo_wine ok(_mbsbtype(str, 0) == _MBC_LEAD, "char 0 should be LEAD\n");
+    todo_wine ok(_mbsbtype(str, 1) == _MBC_TRAIL, "char 1 should be TRAIL\n");
+    todo_wine ok(_mbsbtype(str, 2) == _MBC_LEAD, "char 2 should be LEAD\n");
+    todo_wine ok(_mbsbtype(str, 3) == _MBC_ILLEGAL, "char 3 should be ILLEGAL\n");
+    todo_wine ok(_mbsbtype(str, 4) == _MBC_LEAD, "char 4 should be LEAD\n");
+    todo_wine ok(_mbsbtype(str, 5) == _MBC_TRAIL, "char 5 should be TRAIL\n");
+    ok(_mbsbtype(str, 6) == _MBC_SINGLE, "char 6 should be SINGLE\n");
+    ok(_mbsbtype(str, 7) == _MBC_ILLEGAL, "char 7 should be ILLEGAL\n");
     _setmbcp(1252);
 }
 
-- 
1.4.1


More information about the wine-patches mailing list