aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Hoa V. Dinh <dinh.viet.hoa@gmail.com>2014-10-24 17:09:53 -0700
committerGravatar Hoa V. Dinh <dinh.viet.hoa@gmail.com>2014-10-24 17:09:53 -0700
commit128a11a36103c3a57372cf72a51e52744524d827 (patch)
tree92c59ef7861668bc3a0f3944cd64793615457781
parentaa94649aabb8bf5f83155dd09d2f3db367c6225f (diff)
Implemented String primitive using CoreFoundation instead of ICU
-rwxr-xr-xbuild-mac/mailcore2.xcodeproj/project.pbxproj26
-rw-r--r--src/core/basetypes/MCString.cc152
-rw-r--r--unittest/unittest.mm9
3 files changed, 156 insertions, 31 deletions
diff --git a/build-mac/mailcore2.xcodeproj/project.pbxproj b/build-mac/mailcore2.xcodeproj/project.pbxproj
index 8154243b..5f6b6aca 100755
--- a/build-mac/mailcore2.xcodeproj/project.pbxproj
+++ b/build-mac/mailcore2.xcodeproj/project.pbxproj
@@ -4454,15 +4454,11 @@
OTHER_LDFLAGS = (
"-lctemplate-ios",
"-letpan-ios",
- "-licudata",
- "-licui18n",
- "-licuuc",
"-lxml2",
"-lsasl2",
"-liconv",
"-ltidy",
"-lz",
- "-licucore",
"-ObjC",
);
PRODUCT_NAME = "MailCore-ios";
@@ -4484,15 +4480,11 @@
OTHER_LDFLAGS = (
"-lctemplate-ios",
"-letpan-ios",
- "-licudata",
- "-licui18n",
- "-licuuc",
"-lxml2",
"-lsasl2",
"-liconv",
"-ltidy",
"-lz",
- "-licucore",
"-ObjC",
);
PRODUCT_NAME = "MailCore-ios";
@@ -4652,16 +4644,12 @@
OTHER_LDFLAGS = (
"-lctemplate-ios",
"-letpan-ios",
- "-licudata",
- "-licui18n",
- "-licuuc",
"-lxml2",
"-lsasl2",
"-liconv",
"-all_load",
"-ltidy",
"-lz",
- "-licucore",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -4687,16 +4675,12 @@
OTHER_LDFLAGS = (
"-lctemplate-ios",
"-letpan-ios",
- "-licudata",
- "-licui18n",
- "-licuuc",
"-lxml2",
"-lsasl2",
"-liconv",
"-all_load",
"-ltidy",
"-lz",
- "-licucore",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -4807,9 +4791,6 @@
OTHER_LDFLAGS = (
"-lctemplate",
"-letpan",
- "-licudata",
- "-licui18n",
- "-licuuc",
"-lxml2",
"-lssl",
"-lcrypto",
@@ -4818,7 +4799,7 @@
"-all_load",
"-ltidy",
"-lz",
- "-licucore",
+ "-luchardet",
);
PRODUCT_NAME = MailCore;
SDKROOT = macosx;
@@ -4838,9 +4819,6 @@
OTHER_LDFLAGS = (
"-lctemplate",
"-letpan",
- "-licudata",
- "-licui18n",
- "-licuuc",
"-lxml2",
"-lssl",
"-lcrypto",
@@ -4849,7 +4827,7 @@
"-all_load",
"-ltidy",
"-lz",
- "-licucore",
+ "-luchardet",
);
PRODUCT_NAME = MailCore;
SDKROOT = macosx;
diff --git a/src/core/basetypes/MCString.cc b/src/core/basetypes/MCString.cc
index bcc1ec9d..de975d44 100644
--- a/src/core/basetypes/MCString.cc
+++ b/src/core/basetypes/MCString.cc
@@ -1,10 +1,14 @@
#include "MCString.h"
+#define DISABLE_ICU 1
+
#include <string.h>
#include <stdlib.h>
+#if !DISABLE_ICU
#include <unicode/ustring.h>
#include <unicode/ucnv.h>
#include <unicode/utypes.h>
+#endif
#include <uuid/uuid.h>
#include <pthread.h>
#include <libetpan/libetpan.h>
@@ -30,9 +34,68 @@
using namespace mailcore;
+#if DISABLE_ICU
+static int32_t u_strlen(const UChar *s) {
+ if (s == NULL) {
+ return 0;
+ }
+ const UChar * p = s;
+ while (* p != 0) {
+ p ++;
+ }
+ return (int32_t) (p - s);
+}
+
+static UChar * u_memcpy(UChar * dest, const UChar * src, int32_t count) {
+ memcpy(dest, src, count * sizeof(* src));
+ return dest;
+}
+
+static UChar * u_strstr(const UChar * s, const UChar * substring)
+{
+ if (s == NULL) {
+ return NULL;
+ }
+ CFStringRef cfS = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) s, u_strlen(s), kCFAllocatorNull);
+ CFStringRef cfSubstring = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) substring, u_strlen(substring), kCFAllocatorNull);
+
+ CFRange range = CFStringFind(cfS, cfSubstring, 0);
+ CFRelease(cfSubstring);
+ CFRelease(cfS);
+ if (range.length == 0) {
+ return NULL;
+ }
+ return (UChar *) (s + range.location);
+}
+
+static UChar * u_strrstr(const UChar * s, const UChar * substring)
+{
+ if (s == NULL) {
+ return NULL;
+ }
+ CFStringRef cfS = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) s, u_strlen(s), kCFAllocatorNull);
+ CFStringRef cfSubstring = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) substring, u_strlen(substring), kCFAllocatorNull);
+
+ CFRange range = CFStringFind(cfS, cfSubstring, kCFCompareBackwards);
+ CFRelease(cfSubstring);
+ CFRelease(cfS);
+ if (range.length == 0) {
+ return NULL;
+ }
+ return (UChar *) (s + range.location);
+}
+
+static int32_t u_memcmp(const UChar * buf1, const UChar * buf2, int32_t count)
+{
+ return memcmp(buf1, buf2, count * sizeof(* buf1));
+}
+#endif
+
void mailcore::setICUDataDirectory(String * directory)
{
+#if !DISABLE_ICU
u_setDataDirectory(directory->fileSystemRepresentation());
+#endif
}
#pragma mark quote headers string
@@ -814,7 +877,11 @@ void String::appendCharactersLength(const UChar * unicodeCharacters, unsigned in
return;
}
allocate(mLength + length);
+#if DISABLE_ICU
+ memcpy(&mUnicodeChars[mLength], unicodeCharacters, length * sizeof(* mUnicodeChars));
+#else
u_strncpy(&mUnicodeChars[mLength], unicodeCharacters, length);
+#endif
mLength += length;
mUnicodeChars[mLength] = 0;
}
@@ -843,7 +910,16 @@ void String::appendUTF8CharactersLength(const char * UTF8Characters, unsigned in
if (UTF8Characters == NULL) {
return;
}
-
+
+#if DISABLE_ICU
+ CFStringRef cfStr = CFStringCreateWithBytes(NULL, (const UInt8 *) UTF8Characters, length,
+ kCFStringEncodingUTF8, false);
+ UniChar * characters = (UniChar *) malloc(sizeof(* characters) * CFStringGetLength(cfStr));
+ CFStringGetCharacters(cfStr, CFRangeMake(0, CFStringGetLength(cfStr)), characters);
+ appendCharactersLength(characters, (unsigned int) CFStringGetLength(cfStr));
+ free(characters);
+ CFRelease(cfStr);
+#else
UChar * dest;
int32_t destLength;
int32_t destCapacity;
@@ -866,6 +942,7 @@ void String::appendUTF8CharactersLength(const char * UTF8Characters, unsigned in
appendCharactersLength(dest, destLength);
free(dest);
+#endif
}
void String::appendUTF8Characters(const char * UTF8Characters)
@@ -888,6 +965,17 @@ const UChar * String::unicodeCharacters()
const char * String::UTF8Characters()
{
+#if DISABLE_ICU
+ CFStringRef cfStr = CFStringCreateWithCharactersNoCopy(NULL, mUnicodeChars, mLength, kCFAllocatorNull);
+ char * buffer = (char *) malloc(mLength * 6 + 1);
+ CFIndex usedBufLen;
+ CFStringGetBytes(cfStr, CFRangeMake(0, mLength), kCFStringEncodingUTF8, '?', false, (UInt8 *) buffer, mLength * 6, &usedBufLen);
+ buffer[usedBufLen] = 0;
+ Data * data = Data::dataWithBytes(buffer, (unsigned int) usedBufLen + 1);
+ free(buffer);
+
+ return data->bytes();
+#else
char * dest;
int32_t destLength;
int32_t destCapacity;
@@ -905,6 +993,7 @@ const char * String::UTF8Characters()
free(dest);
return data->bytes();
+#endif
}
unsigned int String::length()
@@ -1092,12 +1181,21 @@ int String::compareWithCaseSensitive(String * otherString, bool caseSensitive)
return -1;
}
+#if DISABLE_ICU
+ CFStringRef cfThis = CFStringCreateWithCharactersNoCopy(NULL, mUnicodeChars, mLength, kCFAllocatorNull);
+ CFStringRef cfOther = CFStringCreateWithCharactersNoCopy(NULL, otherString->mUnicodeChars, otherString->mLength, kCFAllocatorNull);
+ CFComparisonResult result = CFStringCompare(cfThis, cfOther, caseSensitive ? 0 : kCFCompareCaseInsensitive);
+ CFRelease(cfThis);
+ CFRelease(cfOther);
+ return result;
+#else
if (caseSensitive) {
return u_strcmp(unicodeCharacters(), otherString->unicodeCharacters());
}
else {
return u_strcasecmp(unicodeCharacters(), otherString->unicodeCharacters(), 0);
}
+#endif
}
int String::compare(String * otherString)
@@ -1110,8 +1208,20 @@ int String::caseInsensitiveCompare(String * otherString)
return compareWithCaseSensitive(otherString, false);
}
+//Any-Lower, Any-Upper
String * String::lowercaseString()
{
+#if DISABLE_ICU
+ CFMutableStringRef cfStr = CFStringCreateMutable(NULL, 0);
+ CFStringAppendCharacters(cfStr, (const UniChar *) mUnicodeChars, mLength);
+ CFStringLowercase(cfStr, NULL);
+ UniChar * characters = (UniChar *) malloc(sizeof(* characters) * mLength);
+ CFStringGetCharacters(cfStr, CFRangeMake(0, mLength), characters);
+ String * result = String::stringWithCharacters(characters, mLength);
+ free(characters);
+ CFRelease(cfStr);
+ return result;
+#else
UErrorCode err;
String * result = (String *) copy()->autorelease();
err = U_ZERO_ERROR;
@@ -1119,10 +1229,22 @@ String * String::lowercaseString()
result->mUnicodeChars, result->mLength,
NULL, &err);
return result;
+#endif
}
String * String::uppercaseString()
{
+#if DISABLE_ICU
+ CFMutableStringRef cfStr = CFStringCreateMutable(NULL, 0);
+ CFStringAppendCharacters(cfStr, (const UniChar *) mUnicodeChars, mLength);
+ CFStringUppercase(cfStr, NULL);
+ UniChar * characters = (UniChar *) malloc(sizeof(* characters) * mLength);
+ CFStringGetCharacters(cfStr, CFRangeMake(0, mLength), characters);
+ String * result = String::stringWithCharacters(characters, mLength);
+ free(characters);
+ CFRelease(cfStr);
+ return result;
+#else
UErrorCode err;
String * result = (String *) copy()->autorelease();
err = U_ZERO_ERROR;
@@ -1130,6 +1252,7 @@ String * String::uppercaseString()
result->mUnicodeChars, result->mLength,
NULL, &err);
return result;
+#endif
}
void String::appendBytes(const char * bytes, unsigned int length, const char * charset)
@@ -1272,7 +1395,14 @@ unsigned int String::replaceOccurrencesOfString(String * occurrence, String * re
}
// copy remaining
if(p) {
- u_strcpy(dest_p, p);
+#if DISABLE_ICU
+ unsigned int remainingLength = mLength - (unsigned int) (p - mUnicodeChars);
+ memcpy(dest_p, p, remainingLength * sizeof(* p));
+ dest_p += remainingLength;
+ * dest_p = 0;
+#else
+ u_strcpy(dest_p, p);
+#endif
}
free(mUnicodeChars);
@@ -1300,7 +1430,11 @@ void String::deleteCharactersInRange(Range range)
}
int32_t count = mLength - (int32_t) (range.location + range.length);
+#if DISABLE_ICU
+ memmove(&mUnicodeChars[range.location], &mUnicodeChars[range.location + range.length], count * sizeof(* mUnicodeChars));
+#else
u_memmove(&mUnicodeChars[range.location], &mUnicodeChars[range.location + range.length], count);
+#endif
mLength -= range.length;
mUnicodeChars[mLength] = 0;
}
@@ -1862,7 +1996,14 @@ String * String::lastPathComponent()
// TODO: Improve Windows compatibility.
if (mUnicodeChars == NULL)
return MCSTR("");
+#if DISABLE_ICU
+ UChar slash[2];
+ slash[0] = '/';
+ slash[1] = 0;
+ UChar * component = u_strrstr(mUnicodeChars, slash);
+#else
UChar * component = u_strrchr(mUnicodeChars, '/');
+#endif
if (component == NULL)
return (String *) this->copy()->autorelease();
return String::stringWithCharacters(component + 1);
@@ -1870,7 +2011,14 @@ String * String::lastPathComponent()
String * String::pathExtension()
{
+#if DISABLE_ICU
+ UChar point[2];
+ point[0] = '.';
+ point[1] = 0;
+ UChar * component = u_strrstr(mUnicodeChars, point);
+#else
UChar * component = u_strrchr(mUnicodeChars, '.');
+#endif
if (component == NULL)
return MCSTR("");
return String::stringWithCharacters(component + 1);
diff --git a/unittest/unittest.mm b/unittest/unittest.mm
index 44e367d1..ee543766 100644
--- a/unittest/unittest.mm
+++ b/unittest/unittest.mm
@@ -104,8 +104,6 @@
}
- (void)testMessageBuilder1 {
- // This is an example of a functional test case.
- //XCTAssert(YES, @"Pass");
MCOMessageBuilder * builder = [[MCOMessageBuilder alloc] init];
[[builder header] setFrom:[MCOAddress addressWithRFC822String:@"HoĆ  <dinh.viet.hoa@gmail.com>"]];
[[builder header] setTo:@[[MCOAddress addressWithRFC822String:@"Foo Bar <dinh.viet.hoa@gmail.com>"]]];
@@ -117,7 +115,8 @@
NSData * expectedData = [NSData dataWithContentsOfFile:path];
[builder _setBoundaries:@[@"1", @"2", @"3", @"4", @"5"]];
//[[builder data] writeToFile:@"/Users/hoa/builder1-now.eml" atomically:YES];
- XCTAssertEqualObjects([builder data], expectedData, @"Pass");
+ XCTAssertEqualObjects([[NSString alloc] initWithData:[builder data] encoding:NSUTF8StringEncoding], [[NSString alloc] initWithData:expectedData encoding:NSUTF8StringEncoding], @"Pass");
+ //XCTAssertEqualObjects([builder data], expectedData, @"Pass");
}
- (void)testMessageBuilder2 {
@@ -137,7 +136,7 @@
path = [_builderOutputPath stringByAppendingPathComponent:@"builder2.eml"];
NSData * expectedData = [NSData dataWithContentsOfFile:path];
//[[builder data] writeToFile:@"/Users/hoa/builder2-now.eml" atomically:YES];
- XCTAssertEqualObjects([builder data], expectedData, @"Pass");
+ XCTAssertEqualObjects([[NSString alloc] initWithData:[builder data] encoding:NSUTF8StringEncoding], [[NSString alloc] initWithData:expectedData encoding:NSUTF8StringEncoding], @"Pass");
}
- (void)testMessageBuilder3 {
@@ -159,7 +158,7 @@
path = [_builderOutputPath stringByAppendingPathComponent:@"builder3.eml"];
NSData * expectedData = [NSData dataWithContentsOfFile:path];
//[[builder data] writeToFile:@"/Users/hoa/builder3-now.eml" atomically:YES];
- XCTAssertEqualObjects([builder data], expectedData, @"Pass");
+ XCTAssertEqualObjects([[NSString alloc] initWithData:[builder data] encoding:NSUTF8StringEncoding], [[NSString alloc] initWithData:expectedData encoding:NSUTF8StringEncoding], @"Pass");
}
- (void)testMessageParser {