aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar CodaFi <devteam.codafi@gmail.com>2013-04-28 13:13:25 -0600
committerGravatar CodaFi <devteam.codafi@gmail.com>2013-04-28 13:13:25 -0600
commit10c9d0abf0e8009277fb2006cffb76b8a26865c7 (patch)
tree73dd16206a521984a5a26b479038a4d7300070c9 /src
parent6216eee4d6c6514c2b1e324d1a999b0d7018ab7a (diff)
parent9a5c778214090b9c0fa58d65521c35b01cbcd663 (diff)
Merge remote-tracking branch 'upstream/master' into Providers-API
Merge upstream/master
Diffstat (limited to 'src')
-rw-r--r--src/core/abstract/MCAbstractPart.cc13
-rw-r--r--src/core/abstract/MCAbstractPart.h2
-rw-r--r--src/core/abstract/MCAddress.cc26
-rw-r--r--src/core/abstract/MCAddress.h3
-rw-r--r--src/core/abstract/MCMessageHeader.cc49
-rw-r--r--src/core/basetypes/MCArray.cc6
-rw-r--r--src/core/basetypes/MCArray.h2
-rw-r--r--src/core/basetypes/MCBaseTypes.h2
-rw-r--r--src/core/basetypes/MCICUTypes.h18
-rw-r--r--src/core/basetypes/MCIterator.h128
-rw-r--r--src/core/basetypes/MCJSON.cpp235
-rw-r--r--src/core/basetypes/MCJSON.h21
-rw-r--r--src/core/basetypes/MCJSONParser.cpp827
-rw-r--r--src/core/basetypes/MCJSONParser.h66
-rw-r--r--src/core/basetypes/MCString.h9
-rw-r--r--src/core/renderer/MCAddressDisplay.cpp10
-rw-r--r--src/core/renderer/MCHTMLRenderer.cpp12
-rw-r--r--src/core/rfc822/MCAttachment.cc11
-rw-r--r--src/core/rfc822/MCAttachment.h1
-rw-r--r--src/objc/abstract/MCOAbstractMessageRendererCallback.mm4
-rw-r--r--src/objc/abstract/MCOAbstractPart.h3
-rw-r--r--src/objc/abstract/MCOAbstractPart.mm5
-rw-r--r--src/objc/abstract/MCOAddress.h25
-rw-r--r--src/objc/abstract/MCOAddress.mm23
-rw-r--r--src/objc/rfc822/MCOAttachment.h3
-rw-r--r--src/objc/rfc822/MCOAttachment.mm6
-rw-r--r--src/objc/rfc822/MCOMessageBuilder.mm8
-rw-r--r--src/objc/utils/NSArray+MCO.mm2
-rw-r--r--src/objc/utils/NSString+MCO.h7
-rw-r--r--src/objc/utils/NSString+MCO.mm27
30 files changed, 1256 insertions, 298 deletions
diff --git a/src/core/abstract/MCAbstractPart.cc b/src/core/abstract/MCAbstractPart.cc
index b07063ad..f0446167 100644
--- a/src/core/abstract/MCAbstractPart.cc
+++ b/src/core/abstract/MCAbstractPart.cc
@@ -3,6 +3,7 @@
#include <string.h>
#include <stdlib.h>
#include <libetpan/libetpan.h>
+#include "MCData.h"
using namespace mailcore;
@@ -249,3 +250,15 @@ AbstractPart * AbstractPart::partForUniqueID(String * uniqueID)
}
}
+String * AbstractPart::decodedStringForData(Data * data)
+{
+ String *lowerMimeType = mMimeType ? mMimeType->lowercaseString() : NULL;
+
+ if (lowerMimeType && lowerMimeType->hasPrefix(MCSTR("text/"))) {
+ bool isHTML = lowerMimeType->isEqual(MCSTR("text/html"));
+ return data->stringWithDetectedCharset(mCharset, isHTML);
+ }
+ else {
+ return NULL;
+ }
+}
diff --git a/src/core/abstract/MCAbstractPart.h b/src/core/abstract/MCAbstractPart.h
index 970b5e04..b01ba4f4 100644
--- a/src/core/abstract/MCAbstractPart.h
+++ b/src/core/abstract/MCAbstractPart.h
@@ -46,6 +46,8 @@ namespace mailcore {
virtual AbstractPart * partForContentID(String * contentID);
virtual AbstractPart * partForUniqueID(String * uniqueID);
+ virtual String * decodedStringForData(Data * data);
+
public: // subclass behavior
AbstractPart(AbstractPart * other);
virtual String * description();
diff --git a/src/core/abstract/MCAddress.cc b/src/core/abstract/MCAddress.cc
index 4f6fc303..dce52cff 100644
--- a/src/core/abstract/MCAddress.cc
+++ b/src/core/abstract/MCAddress.cc
@@ -206,6 +206,32 @@ Array * Address::addressesWithNonEncodedRFC822String(String * string)
return result;
}
+String * Address::RFC822StringForAddresses(Array * addresses)
+{
+ String * result = String::string();
+ for(unsigned int i = 0 ; i < addresses->count() ; i ++) {
+ Address * address = (Address *) addresses->objectAtIndex(i);
+ if (i != 0) {
+ result->appendString(MCSTR(", "));
+ }
+ result->appendString(address->RFC822String());
+ }
+ return result;
+}
+
+String * Address::nonEncodedRFC822StringForAddresses(Array * addresses)
+{
+ String * result = String::string();
+ for(unsigned int i = 0 ; i < addresses->count() ; i ++) {
+ Address * address = (Address *) addresses->objectAtIndex(i);
+ if (i != 0) {
+ result->appendString(MCSTR(", "));
+ }
+ result->appendString(address->nonEncodedRFC822String());
+ }
+ return result;
+}
+
String * Address::description()
{
String * result = String::string();
diff --git a/src/core/abstract/MCAddress.h b/src/core/abstract/MCAddress.h
index 4c132ed3..ad8a36f6 100644
--- a/src/core/abstract/MCAddress.h
+++ b/src/core/abstract/MCAddress.h
@@ -21,6 +21,9 @@ namespace mailcore {
static Array * addressesWithRFC822String(String * string);
static Array * addressesWithNonEncodedRFC822String(String * string);
+ static String * RFC822StringForAddresses(Array * addresses);
+ static String * nonEncodedRFC822StringForAddresses(Array * addresses);
+
virtual void setDisplayName(String * displayName);
virtual String * displayName();
diff --git a/src/core/abstract/MCMessageHeader.cc b/src/core/abstract/MCMessageHeader.cc
index 61c126ff..e0476743 100644
--- a/src/core/abstract/MCMessageHeader.cc
+++ b/src/core/abstract/MCMessageHeader.cc
@@ -1070,8 +1070,9 @@ Array * MessageHeader::recipientWithReplyAll(bool replyAll, bool includeTo, bool
hasCc = false;
addedAddresses = new Set();
- if (senderEmails->containsObject(from()->mailbox()->lowercaseString()) ||
- senderEmails->containsObject(sender()->mailbox()->lowercaseString())) {
+ if (senderEmails != NULL &&
+ (senderEmails->containsObject(from()->mailbox()->lowercaseString()) ||
+ senderEmails->containsObject(sender()->mailbox()->lowercaseString()))) {
Array * recipient;
recipient = new Array();
@@ -1130,7 +1131,7 @@ Array * MessageHeader::recipientWithReplyAll(bool replyAll, bool includeTo, bool
else {
addedAddresses->addObjectsFromArray(senderEmails);
- if (replyTo()->count() > 0) {
+ if (replyTo() != NULL && replyTo()->count() > 0) {
hasTo = true;
toField = replyTo();
for(unsigned int i = 0 ; i < replyTo()->count() ; i ++) {
@@ -1141,7 +1142,7 @@ Array * MessageHeader::recipientWithReplyAll(bool replyAll, bool includeTo, bool
}
}
else {
- if (from()->mailbox() != NULL) {
+ if (from() != NULL && from()->mailbox() != NULL) {
hasTo = true;
toField = Array::arrayWithObject(from());
addedAddresses->addObject(from()->mailbox()->lowercaseString());
@@ -1201,14 +1202,23 @@ MessageHeader * MessageHeader::replyHeader(bool replyAll, Array * addressesExclu
Array * inReplyTo;
Array * toValue;
Array * ccValue;
-
+
+ referencesValue = NULL;
+ inReplyTo = NULL;
+
result = new MessageHeader();
subjectValue = MCSTR("Re: ")->stringByAppendingString(subject());
- referencesValue = (Array *) (references()->copy());
- referencesValue->autorelease();
- referencesValue->addObject(messageID());
- inReplyTo = Array::array();
- inReplyTo->addObject(messageID());
+ if (references() != NULL) {
+ referencesValue = (Array *) (references()->copy());
+ referencesValue->autorelease();
+ if (messageID() != NULL ) {
+ referencesValue->addObject(messageID());
+ }
+ }
+ if (messageID()) {
+ inReplyTo = Array::array();
+ inReplyTo->addObject(messageID());
+ }
toValue = recipientWithReplyAll(replyAll, true, false, addressesExcludedFromRecipient);
ccValue = recipientWithReplyAll(replyAll, false, true, addressesExcludedFromRecipient);;
@@ -1229,13 +1239,22 @@ MessageHeader * MessageHeader::forwardHeader()
Array * referencesValue;
Array * inReplyTo;
+ referencesValue = NULL;
+ inReplyTo = NULL;
+
result = new MessageHeader();
subjectValue = MCSTR("Fw: ")->stringByAppendingString(subject());
- referencesValue = (Array *) (references()->copy());
- referencesValue->autorelease();
- referencesValue->addObject(messageID());
- inReplyTo = Array::array();
- inReplyTo->addObject(messageID());
+ if (references() != NULL) {
+ referencesValue = (Array *) (references()->copy());
+ referencesValue->autorelease();
+ if (messageID() != NULL ) {
+ referencesValue->addObject(messageID());
+ }
+ }
+ if (messageID()) {
+ inReplyTo = Array::array();
+ inReplyTo->addObject(messageID());
+ }
result->setSubject(subjectValue);
result->setReferences(referencesValue);
result->setInReplyTo(inReplyTo);
diff --git a/src/core/basetypes/MCArray.cc b/src/core/basetypes/MCArray.cc
index 73921085..c77d29ad 100644
--- a/src/core/basetypes/MCArray.cc
+++ b/src/core/basetypes/MCArray.cc
@@ -204,7 +204,7 @@ static int sortCompare(Object ** pa, Object ** pb, struct sortData * data)
return data->compare(a, b, data->context);
}
-Array * Array::sortedArray(int (* compare)(void *, void *, void *), void * context)
+Array * Array::sortedArray(int (* compare)(void * a, void * b, void * context), void * context)
{
struct sortData data;
Array * result = (Array *) this->copy()->autorelease();
@@ -212,13 +212,13 @@ Array * Array::sortedArray(int (* compare)(void *, void *, void *), void * conte
data.context = context;
#ifdef __MACH__
qsort_r(carray_data(result->mArray), carray_count(result->mArray),
- sizeof(* carray_data(result->mArray)), this,
+ sizeof(* carray_data(result->mArray)), &data,
(int (*)(void *, const void *, const void *)) sortCompare);
#else
qsort_r(carray_data(result->mArray), carray_count(result->mArray),
sizeof(* carray_data(result->mArray)),
(int (*)(const void *, const void *, void *)) sortCompare,
- this);
+ &data);
#endif
return result;
}
diff --git a/src/core/basetypes/MCArray.h b/src/core/basetypes/MCArray.h
index ebbf1e5f..564924f8 100644
--- a/src/core/basetypes/MCArray.h
+++ b/src/core/basetypes/MCArray.h
@@ -34,7 +34,7 @@ namespace mailcore {
virtual Object * lastObject();
virtual bool containsObject(Object * obj);
- virtual Array * sortedArray(int (* compare)(void *, void *, void *), void * context);
+ virtual Array * sortedArray(int (* compare)(void * a, void * b, void * context), void * context);
virtual String * componentsJoinedByString(String * delimiter);
public: // subclass behavior
diff --git a/src/core/basetypes/MCBaseTypes.h b/src/core/basetypes/MCBaseTypes.h
index 6d08cdaa..4919e1f5 100644
--- a/src/core/basetypes/MCBaseTypes.h
+++ b/src/core/basetypes/MCBaseTypes.h
@@ -23,5 +23,7 @@
#include <MailCore/MCOperationQueue.h>
#include <MailCore/MCOperationCallback.h>
#include <MailCore/MCLibetpanTypes.h>
+#include <MailCore/MCICUTypes.h>
+#include <MailCore/MCIterator.h>
#endif
diff --git a/src/core/basetypes/MCICUTypes.h b/src/core/basetypes/MCICUTypes.h
new file mode 100644
index 00000000..e1cff6d6
--- /dev/null
+++ b/src/core/basetypes/MCICUTypes.h
@@ -0,0 +1,18 @@
+//
+// MCICUTypes.h
+// mailcore2
+//
+// Created by DINH Viêt Hoà on 4/18/13.
+// Copyright (c) 2013 MailCore. All rights reserved.
+//
+
+#ifndef __MAILCORE_MCICUTYPES_H_
+#define __MAILCORE_MCICUTYPES_H_
+
+#if defined(__CHAR16_TYPE__)
+typedef __CHAR16_TYPE__ UChar;
+#else
+typedef uint16_t UChar;
+#endif
+
+#endif
diff --git a/src/core/basetypes/MCIterator.h b/src/core/basetypes/MCIterator.h
new file mode 100644
index 00000000..00ff38db
--- /dev/null
+++ b/src/core/basetypes/MCIterator.h
@@ -0,0 +1,128 @@
+//
+// MCIterator.h
+// mailcore2
+//
+// Created by DINH Viêt Hoà on 4/18/13.
+// Copyright (c) 2013 MailCore. All rights reserved.
+//
+
+#ifndef __MAILCORE_ITERATOR_H_
+#define __MAILCORE_ITERATOR_H_
+
+#include <MailCore/MCArray.h>
+#include <MailCore/MCHashMap.h>
+#include <MailCore/MCAutoreleasePool.h>
+#include <string.h>
+
+#ifdef __cplusplus
+
+#define mc_foreacharray(type, __variable, __array) \
+type * __variable; \
+mailcore::ArrayIterator __variable##__iterator = mailcore::ArrayIteratorInit(__array); \
+for (; NULL != (__variable = (type *) mailcore::ArrayIteratorNext(&__variable##__iterator)); )
+
+#define mc_foreacharrayIndex(__index, type, __variable, __array) \
+type * __variable; \
+mailcore::ArrayIterator __variable##__iterator = mailcore::ArrayIteratorInit(__array); \
+for (unsigned int __index = 0; NULL != (__variable = mailcore::ArrayIteratorNext(&__variable##__iterator)); __index++)
+
+#define mc_foreachdictionaryKey(keyType, __key, __dictionary) \
+keyType * __key; \
+DictionaryIterator __key##__iterator = DictionaryIteratorInit(__dictionary, true, false); \
+while (DictionaryIteratorRun(&__key##__iterator)) \
+while (DictionaryIteratorNext(&__key##__iterator, &__key, NULL))
+
+#define mc_foreachdictionaryValue(valueType, __value, __dictionary) \
+valueType * __value; \
+DictionaryIterator __value##__iterator = DictionaryIteratorInit(__dictionary, false, true); \
+while (DictionaryIteratorRun(&__value##__iterator)) \
+while (DictionaryIteratorNext(&__value##__iterator, NULL, &__value))
+
+#define mc_foreachdictionaryKeyAndValue(__key, __value, __dictionary) \
+keyType * __key; \
+valueType * __value; \
+DictionaryIterator __key##__value##__iterator = DictionaryIteratorInit(__dictionary, true, true); \
+while (DictionaryIteratorRun(&__key##__value##__iterator)) \
+while (DictionaryIteratorNext(&__key##__value##__iterator, &__key, &__value))
+
+namespace mailcore {
+
+ struct ArrayIterator {
+ unsigned index;
+ unsigned count;
+ Array * array;
+ };
+
+ static inline ArrayIterator ArrayIteratorInit(Array * array)
+ {
+ ArrayIterator iterator = { 0, array->count(), array };
+ return iterator;
+ }
+
+ static inline Object * ArrayIteratorNext(ArrayIterator * iterator)
+ {
+ if (iterator->index >= iterator->count) {
+ return NULL;
+ }
+
+ Object * result = iterator->array->objectAtIndex(iterator->index);
+ ++ iterator->index;
+ return result;
+ }
+
+
+ struct HashMapIterator {
+ bool cleanup;
+ unsigned index;
+ unsigned count;
+ Array * keys;
+ Array * values;
+ };
+
+ static inline HashMapIterator FastDictionaryIteratorInit(HashMap * hashmap, bool useKeys, bool useValues)
+ {
+ AutoreleasePool * pool = new AutoreleasePool();
+ Array * keys = useKeys ? hashmap->allKeys() : NULL;
+ Array * values = useValues ? hashmap->allValues() : NULL;
+ keys->retain();
+ values->retain();
+ HashMapIterator iterator = { false, 0, hashmap->count(), keys, values };
+ pool->release();
+
+ return iterator;
+ }
+
+ static inline bool HashMapIteratorNext(HashMapIterator * iterator, Object ** keyp, Object ** valuep)
+ {
+ if (iterator->index >= iterator->count) {
+ return false;
+ }
+
+ if (keyp != NULL) {
+ * keyp = iterator->keys->objectAtIndex(iterator->index);
+ }
+ if (valuep != NULL) {
+ * valuep = iterator->values->objectAtIndex(iterator->index);
+ }
+ iterator->index ++;
+ return true;
+ }
+
+
+ static inline bool DictionaryIteratorRun(HashMapIterator * iterator)
+ {
+ if (iterator->cleanup) {
+ iterator->cleanup = true;
+ return true;
+ } else {
+ iterator->keys->release();
+ iterator->values->release();
+ return false;
+ }
+ }
+
+};
+
+#endif
+
+#endif
diff --git a/src/core/basetypes/MCJSON.cpp b/src/core/basetypes/MCJSON.cpp
index f6bc5956..20b4876f 100644
--- a/src/core/basetypes/MCJSON.cpp
+++ b/src/core/basetypes/MCJSON.cpp
@@ -10,241 +10,32 @@
#include <string.h>
-#include "libjson.h"
-#include "MCNull.h"
-#include <MailCore/MCUtils.h>
-#include <MailCore/MCAssert.h>
+#include "MCJSONParser.h"
using namespace mailcore;
-String * JSON::objectToJSONString(Object * object, bool pretty)
-{
- void * node = objectToJSON(object);
- char * cstr;
- if (pretty) {
- cstr = json_write_formatted(node);
- }
- else {
- cstr = json_write(node);
- }
-
- String * result = String::stringWithUTF8Characters(cstr);
-
- json_free(cstr);
- json_delete(node);
-
- return result;
-}
-
-Data * JSON::objectToJSONData(Object * object, bool pretty)
-{
- void * node = objectToJSON(object);
- char * cstr;
- if (pretty) {
- cstr = json_write_formatted(node);
- }
- else {
- cstr = json_write(node);
- }
-
- Data * result = Data::dataWithBytes(cstr, (unsigned int) strlen(cstr));
-
- json_free(cstr);
- json_delete(node);
-
- return result;
-}
-
-Object * JSON::objectFromJSONString(String * json)
-{
- void * node = json_parse(json->UTF8Characters());
- Object * object = objectFromJSON(node);
- json_delete(node);
- return object;
-}
-
-Object * JSON::objectFromJSONData(Data * json)
-{
- //printf("rcv: [%.*s]\n", (int) json->length(), json->bytes());
-
- void * node = json_parse(json->bytes());
- Object * object = objectFromJSON(node);
- json_delete(node);
- return object;
-}
-
-void * JSON::hashMapToJSON(HashMap * hashmap)
-{
- JSONNODE * result = json_new(JSON_NODE);
- Array * keys = hashmap->allKeys();
- for(unsigned int i = 0 ; i < keys->count() ; i ++) {
- String * key = (String *) keys->objectAtIndex(i);
- JSONNODE * item = objectToJSON(hashmap->objectForKey(key));
- json_set_name(item, key->UTF8Characters());
- json_push_back(result, item);
- }
- return result;
-}
-
-void * JSON::arrayToJSON(Array * array)
-{
- JSONNODE * result = json_new(JSON_ARRAY);
- for(unsigned int i = 0 ; i < array->count() ; i ++) {
- Object * value = array->objectAtIndex(i);
- JSONNODE * item = objectToJSON(value);
- json_push_back(result, item);
- }
- return result;
-}
-
-void * JSON::stringToJSON(String * string)
-{
- return json_new_a("", string->UTF8Characters());
-}
+static Object * objectFromData(Data * data);
+static Object * objectFromString(String * str);
-void * JSON::doubleToJSON(Value * value)
-{
- switch (value->type()) {
- case ValueTypeChar:
- return json_new_f("", value->charValue());
- case ValueTypeUnsignedChar:
- return json_new_f("", value->unsignedCharValue());
- case ValueTypeShort:
- return json_new_f("", value->shortValue());
- case ValueTypeUnsignedShort:
- return json_new_f("", value->unsignedShortValue());
- case ValueTypeInt:
- return json_new_f("", value->intValue());
- case ValueTypeUnsignedInt:
- return json_new_f("", value->unsignedIntValue());
- case ValueTypeLong:
- return json_new_f("", value->longValue());
- case ValueTypeUnsignedLong:
- return json_new_f("", value->unsignedLongValue());
- case ValueTypeLongLong:
- return json_new_f("", value->longLongValue());
- case ValueTypeUnsignedLongLong:
- return json_new_f("", value->unsignedLongLongValue());
- case ValueTypeFloat:
- return json_new_f("", value->floatValue());
- case ValueTypeDouble:
- return json_new_f("", value->doubleValue());
- default:
- return json_new_f("", 0.);
- }
-}
-
-void * JSON::boolToJSON(Value * value)
-{
- return json_new_b("", value->boolValue());
-}
-
-void * JSON::nullToJSON(Null * value)
-{
- return json_new(JSON_NULL);
-}
-
-void * JSON::objectToJSON(Object * object)
-{
- String * name = object->className();
- if (name->isEqual(MCSTR("mailcore::Null"))) {
- return nullToJSON((Null *) object);
- }
- else if (name->isEqual(MCSTR("mailcore::Value"))) {
- Value * value = (Value *) object;
- if (value->type() == ValueTypeBool) {
- return boolToJSON(value);
- }
- else {
- return doubleToJSON(value);
- }
- }
- else if (name->isEqual(MCSTR("mailcore::String"))) {
- return stringToJSON((String *) object);
- }
- else if (name->isEqual(MCSTR("mailcore::Array"))) {
- return arrayToJSON((Array *) object);
- }
- else if (name->isEqual(MCSTR("mailcore::HashMap"))) {
- return hashMapToJSON((HashMap *) object);
- }
- else {
- MCAssert(0);
- return NULL;
- }
-}
+static Data * dataFromObject(Object * object);
+static String * stringFromObject(Object * object);
-HashMap * JSON::hashMapFromJSON(void * json)
+String * JSON::objectToJSONString(Object * object)
{
- HashMap * result = HashMap::hashMap();
- JSONNODE_ITERATOR i = json_begin(json);
- while (i != json_end(json)){
- json_char * ckey = json_name(*i);
- String * key = String::stringWithUTF8Characters(ckey);
- Object * value = objectFromJSON(* i);
-
- result->setObjectForKey(key, value);
-
- json_free(ckey);
- ++i;
- }
- return result;
+ return JSONParser::stringFromObject(object);
}
-Array * JSON::arrayFromJSON(void * json)
+Data * JSON::objectToJSONData(Object * object)
{
- Array * result = Array::array();
- JSONNODE_ITERATOR i = json_begin(json);
- while (i != json_end(json)){
- Object * obj = objectFromJSON(* i);
- result->addObject(obj);
- ++i;
- }
- return result;
+ return JSONParser::dataFromObject(object);
}
-String * JSON::stringFromJSON(void * json)
-{
- json_char * cstr = json_as_string(json);
- String * result = String::stringWithUTF8Characters(cstr);
- json_free(cstr);
- return result;
-}
-
-Value * JSON::doubleFromJSON(void * json)
-{
- json_number value = json_as_float(json);
- return Value::valueWithDoubleValue(value);
-}
-
-Value * JSON::boolFromJSON(void * json)
-{
- json_bool_t value = json_as_bool(json);
- return Value::valueWithBoolValue(value);
-}
-
-Null * JSON::nullFromJSON(void * json)
+Object * JSON::objectFromJSONString(String * json)
{
- return Null::null();
+ return JSONParser::objectFromString(json);
}
-Object * JSON::objectFromJSON(void * json)
+Object * JSON::objectFromJSONData(Data * json)
{
- switch (json_type(json)) {
- case JSON_NULL:
- return nullFromJSON(json);
- case JSON_STRING:
- return stringFromJSON(json);
- case JSON_NUMBER:
- return doubleFromJSON(json);
- case JSON_BOOL:
- return boolFromJSON(json);
- case JSON_ARRAY:
- return arrayFromJSON(json);
- case JSON_NODE:
- return hashMapFromJSON(json);
- default:
- MCAssert(0);
- return NULL;
- }
+ return JSONParser::objectFromData(json);
}
diff --git a/src/core/basetypes/MCJSON.h b/src/core/basetypes/MCJSON.h
index 77100991..c49fd813 100644
--- a/src/core/basetypes/MCJSON.h
+++ b/src/core/basetypes/MCJSON.h
@@ -24,27 +24,10 @@ namespace mailcore {
class JSON {
public:
- static String * objectToJSONString(Object * object, bool pretty = false);
- static Data * objectToJSONData(Object * object, bool pretty = false);
+ static String * objectToJSONString(Object * object);
+ static Data * objectToJSONData(Object * object);
static Object * objectFromJSONString(String * json);
static Object * objectFromJSONData(Data * json);
-
- private:
- static void * hashMapToJSON(HashMap * hashmap);
- static void * arrayToJSON(Array * array);
- static void * stringToJSON(String * string);
- static void * doubleToJSON(Value * value);
- static void * boolToJSON(Value * value);
- static void * nullToJSON(Null * value);
- static void * objectToJSON(Object * object);
-
- static HashMap * hashMapFromJSON(void * json);
- static Array * arrayFromJSON(void * json);
- static String * stringFromJSON(void * json);
- static Value * doubleFromJSON(void * json);
- static Value * boolFromJSON(void * json);
- static Null * nullFromJSON(void * json);
- static Object * objectFromJSON(void * json);
};
}
diff --git a/src/core/basetypes/MCJSONParser.cpp b/src/core/basetypes/MCJSONParser.cpp
new file mode 100644
index 00000000..c72f0c8b
--- /dev/null
+++ b/src/core/basetypes/MCJSONParser.cpp
@@ -0,0 +1,827 @@
+//
+// JSONParser.cpp
+// mailcore2
+//
+// Created by DINH Viêt Hoà on 4/17/13.
+// Copyright (c) 2013 MailCore. All rights reserved.
+//
+
+#include "MCJSONParser.h"
+
+#include <stdlib.h>
+
+#include "MCUtils.h"
+#include "MCString.h"
+#include "MCData.h"
+#include "MCHashMap.h"
+#include "MCArray.h"
+#include "MCValue.h"
+#include "MCNull.h"
+#include "MCAutoreleasePool.h"
+#include "MCAssert.h"
+
+using namespace mailcore;
+
+void JSONParser::init()
+{
+ mContent = NULL;
+ mResult = NULL;
+ mPosition = 0;
+}
+
+JSONParser::JSONParser()
+{
+ init();
+}
+
+JSONParser::~JSONParser()
+{
+ MC_SAFE_RELEASE(mResult);
+ MC_SAFE_RELEASE(mContent);
+}
+
+String * JSONParser::content()
+{
+ return mContent;
+}
+
+void JSONParser::setContent(String * content)
+{
+ MC_SAFE_REPLACE_COPY(String, mContent, content);
+}
+
+unsigned int JSONParser::position()
+{
+ return mPosition;
+}
+
+void JSONParser::setPosition(unsigned int position)
+{
+ mPosition = position;
+}
+
+Object * JSONParser::result()
+{
+ return mResult;
+}
+
+bool JSONParser::parse()
+{
+ skipBlank();
+ if (parseDictionary())
+ return true;
+ if (parseArray())
+ return true;
+ if (parseBoolean())
+ return true;
+ if (parseNull())
+ return true;
+ if (parseFloat())
+ return true;
+ if (parseString())
+ return true;
+
+ return false;
+}
+
+bool JSONParser::isEndOfExpression()
+{
+ if (mPosition == mContent->length())
+ return true;
+
+ if (mContent->characterAtIndex(mPosition) == ';')
+ return true;
+
+ return false;
+}
+
+void JSONParser::skipBlank()
+{
+ mPosition = skipBlank(mPosition);
+}
+
+unsigned int JSONParser::skipBlank(unsigned int position)
+{
+ while (1) {
+ UChar ch;
+
+ if (position >= mContent->length())
+ break;
+
+ ch = mContent->characterAtIndex(position);
+ if ((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n'))
+ position ++;
+ else
+ break;
+ }
+
+ return position;
+}
+
+bool JSONParser::parseDictionary()
+{
+ int position;
+ HashMap * dict;
+
+ position = mPosition;
+
+ if (!scanCharacter('{', position)) {
+ return false;
+ }
+ position ++;
+ position = skipBlank(position);
+
+ dict = HashMap::hashMap();
+
+ if (scanCharacter('}', position)) {
+ position ++;
+ }
+ else {
+ while (1) {
+ JSONParser * keyParser;
+ JSONParser * valueParser;
+ String * key;
+ Object * value;
+
+ if (position >= mContent->length())
+ return false;
+
+ key = NULL;
+ keyParser = new JSONParser();
+ keyParser->autorelease();
+ keyParser->setContent(mContent);
+ keyParser->setPosition(position);
+ if (!keyParser->parse())
+ return false;
+
+ if (!keyParser->result()->className()->isEqual(MCSTR("mailcore::String")))
+ return false;
+
+ key = (String *) keyParser->result();
+ position = keyParser->position();
+
+ position = skipBlank(position);
+
+ if (!scanCharacter(':', position))
+ return false;
+ position ++;
+
+ position = skipBlank(position);
+
+ value = NULL;
+ valueParser = new JSONParser();
+ valueParser->autorelease();
+ valueParser->setContent(mContent);
+ valueParser->setPosition(position);
+ if (!valueParser->parse())
+ return false;
+
+ value = valueParser->result();
+ position = valueParser->position();
+
+ dict->setObjectForKey(key, value);
+
+ position = skipBlank(position);
+
+ if (scanCharacter(',', position)) {
+ position ++;
+ position = skipBlank(position);
+ }
+ else if (scanCharacter('}', position)) {
+ position ++;
+ break;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+
+ mResult = dict->retain();
+ mPosition = position;
+
+ return true;
+}
+
+bool JSONParser::scanCharacter(UChar ch, unsigned int position)
+{
+ if (position >= mContent->length())
+ return false;
+
+ if (mContent->characterAtIndex(position) != ch)
+ return false;
+
+ return true;
+}
+
+bool JSONParser::scanKeyword(String * str, unsigned int position)
+{
+ bool result;
+ AutoreleasePool * pool;
+
+ if (position + str->length() >= mContent->length())
+ return false;
+
+ pool = new AutoreleasePool();
+
+ result = false;
+ if (mContent->substringWithRange(RangeMake(position, str->length()))->isEqual(str))
+ result = true;
+ pool->release();
+
+ return result;
+}
+
+bool JSONParser::parseArray()
+{
+ int position;
+ Array * array;
+
+ position = mPosition;
+
+ if (!scanCharacter('[', position)) {
+ return false;
+ }
+ position ++;
+ position = skipBlank(position);
+
+ array = Array::array();
+
+ if (scanCharacter(']', position)) {
+ position ++;
+ }
+ else {
+ while (1) {
+ JSONParser * valueParser;
+ Object * value;
+
+ if (position >= mContent->length())
+ return false;
+
+ value = NULL;
+ valueParser = new JSONParser();
+ valueParser->setContent(mContent);
+ valueParser->setPosition(position);
+ valueParser->autorelease();
+ if (!valueParser->parse())
+ return false;
+
+ value = valueParser->result();
+
+ position = valueParser->position();
+ array->addObject(value);
+
+ position = skipBlank(position);
+
+ if (scanCharacter(',', position)) {
+ position ++;
+ position = skipBlank(position);
+ }
+ else if (scanCharacter(']', position)) {
+ position ++;
+ break;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+
+ mResult = array->retain();
+ mPosition = position;
+
+ return true;
+}
+
+static inline int hexToInt(UChar inCharacter)
+{
+ if (inCharacter >= '0' && inCharacter <= '9') {
+ return inCharacter - '0';
+ }
+ else if (inCharacter >= 'a' && inCharacter <= 'f') {
+ return inCharacter - 'a' + 10;
+ }
+ else if (inCharacter >= 'A' && inCharacter <= 'F') {
+ return inCharacter - 'A' + 10;
+ }
+ else {
+ return -1;
+ }
+}
+
+bool JSONParser::parseString()
+{
+ unsigned int position;
+ String * str;
+ bool doubleQuote = false;
+ bool startString;
+ bool endOfString;
+
+ position = mPosition;
+
+ startString = false;
+ if (scanCharacter('\"', position)) {
+ doubleQuote = true;
+ startString = true;
+ }
+ else if (scanCharacter('\'', position)) {
+ startString = true;
+ }
+
+ if (!startString)
+ return false;
+
+ position ++;
+
+ str = String::string();
+
+ endOfString = false;
+ while (1) {
+ UChar ch;
+
+ if (position >= mContent->length())
+ return false;
+
+ ch = mContent->characterAtIndex(position);
+ switch (ch) {
+ case '\\':
+ {
+ position ++;
+
+ if (position >= mContent->length())
+ return false;
+
+ ch = mContent->characterAtIndex(position);
+ switch (ch) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7': {
+ UChar char_value;
+ unsigned int count;
+
+ count = 0;
+ char_value = 0;
+ while ((ch >= '0') && (ch <= '7')) {
+ int value;
+
+ value = hexToInt(ch);
+ if (value == -1)
+ break;
+
+ char_value = char_value * 8 + value;
+ count ++;
+ position ++;
+ if (count >= 3)
+ break;
+ if (position >= mContent->length())
+ break;
+ ch = mContent->characterAtIndex(position);
+ }
+ UChar characters[2];
+ characters[0] = char_value;
+ characters[1] = 0;
+ str->appendCharactersLength(characters, 1);
+ break;
+ }
+ case 'b':
+ str->appendString(MCSTR("\b"));
+ position ++;
+ break;
+ case 't':
+ str->appendString(MCSTR("\t"));
+ position ++;
+ break;
+ case 'n':
+ str->appendString(MCSTR("\n"));
+ position ++;
+ break;
+ case 'r':
+ str->appendString(MCSTR("\r"));
+ position ++;
+ break;
+ case 'f':
+ str->appendString(MCSTR("\f"));
+ position ++;
+ break;
+ case 'v':
+ str->appendString(MCSTR("\v"));
+ position ++;
+ break;
+ case '\"':
+ str->appendString(MCSTR("\""));
+ position ++;
+ break;
+ case '\'':
+ str->appendString(MCSTR("\'"));
+ position ++;
+ break;
+ case '\\':
+ str->appendString(MCSTR("\\"));
+ position ++;
+ break;
+ case '/':
+ str->appendString(MCSTR("/"));
+ position ++;
+ break;
+ case 'u': {
+ unsigned int i;
+ UChar char_value;
+
+ position ++;
+ char_value = 0;
+ for(i = 0 ; i < 4 ; i ++) {
+ int value;
+
+ if (position >= mContent->length())
+ return false;
+ ch = mContent->characterAtIndex(position);
+ value = hexToInt(ch);
+ if (value == -1)
+ break;
+
+ char_value = char_value * 16 + value;
+ position ++;
+ }
+
+ UChar characters[2];
+ characters[0] = char_value;
+ characters[1] = 0;
+ str->appendCharactersLength(characters, 1);
+
+ break;
+ }
+ case 'x': {
+ unsigned int i;
+ UChar char_value;
+
+ position ++;
+ char_value = 0;
+ for(i = 0 ; i < 2 ; i ++) {
+ int value;
+
+ if (position >= mContent->length())
+ return false;
+ ch = mContent->characterAtIndex(position);
+ value = hexToInt(ch);
+ if (value == -1)
+ break;
+
+ char_value = char_value * 16 + value;
+ position ++;
+ }
+
+ UChar characters[2];
+ characters[0] = char_value;
+ characters[1] = 0;
+ str->appendCharactersLength(characters, 1);
+
+ break;
+ }
+ default: {
+ UChar characters[3];
+ characters[0] = '\\';
+ characters[1] = ch;
+ characters[2] = 0;
+ str->appendCharactersLength(characters, 2);
+
+ position ++;
+ break;
+ }
+ }
+ break;
+ }
+
+ case '\'':
+ position ++;
+ if (!doubleQuote)
+ endOfString = true;
+ else
+ str->appendString(MCSTR("\'"));
+ break;
+ case '\"':
+ position ++;
+ if (doubleQuote)
+ endOfString = true;
+ else
+ str->appendString(MCSTR("\""));
+ break;
+ default: {
+ position ++;
+ UChar characters[2];
+ characters[0] = ch;
+ characters[1] = 0;
+ str->appendCharactersLength(characters, 1);
+ break;
+ }
+ }
+
+ if (endOfString)
+ break;
+ }
+
+ mResult = str->retain();
+ mPosition = position;
+
+ return true;
+}
+
+bool JSONParser::parseBoolean()
+{
+ if (scanKeyword(MCSTR("true"), mPosition)) {
+ mPosition += MCSTR("true")->length();
+ mResult = Value::valueWithBoolValue(true)->retain();;
+ return true;
+ }
+
+ if (scanKeyword(MCSTR("false"), mPosition)) {
+ mPosition += MCSTR("false")->length();
+ mResult = Value::valueWithBoolValue(false)->retain();;
+ return true;
+ }
+
+ return false;
+}
+
+bool JSONParser::parseNull()
+{
+ if (scanKeyword(MCSTR("null"), mPosition)) {
+ mPosition += MCSTR("null")->length();
+ mResult = Null::null()->retain();
+ return true;
+ }
+
+ return false;
+}
+
+bool JSONParser::parseFloat()
+{
+ const char * str;
+ char * endptr;
+ double value;
+ char * endptrInt;
+ long long valueInt;
+
+ AutoreleasePool * pool;
+
+ pool = new AutoreleasePool();
+ if (mContent->length() > mPosition + 50) {
+ str = mContent->substringWithRange(RangeMake(mPosition, 50))->UTF8Characters();
+ }
+ else {
+ str = mContent->substringFromIndex(mPosition)->UTF8Characters();
+ }
+ value = strtod(str, &endptr);
+ if (endptr == str) {
+ pool->release();
+ return false;
+ }
+ valueInt = strtoll(str, &endptrInt, 0);
+ if (endptr == endptrInt) {
+ mPosition += endptrInt - str;
+ mResult = Value::valueWithLongLongValue(valueInt)->retain();
+ }
+ else {
+ mPosition += endptr - str;
+ mResult = Value::valueWithDoubleValue(value);
+ }
+ pool->release();
+
+ return true;
+}
+
+Object * JSONParser::objectFromData(Data * data)
+{
+ String * str = NULL;
+ Object * result;
+
+ str = String::stringWithData(data, "utf-8");
+ if (str == NULL)
+ return NULL;
+
+ result = objectFromString(str);
+
+ return result;
+}
+
+Object * JSONParser::objectFromString(String * str)
+{
+ Object * result;
+ JSONParser * parser;
+
+ parser = new JSONParser();
+ parser->setContent(str);
+ parser->parse();
+ result = parser->result();
+ result->retain()->autorelease();
+ parser->release();
+
+ return result;
+}
+
+Data * JSONParser::dataFromObject(Object * object)
+{
+ return stringFromObject(object)->dataUsingEncoding("utf-8");
+}
+
+String * JSONParser::stringFromObject(Object * object)
+{
+ String * result;
+
+ result = String::string();
+ appendStringFromObject(object, result);
+
+ return result;
+}
+
+
+String * JSONParser::JSStringFromString(String * str)
+{
+ unsigned int i;
+ String * result;
+
+ result = String::string();
+ for(i = 0 ; i < str->length() ; i ++) {
+ UChar ch;
+
+ ch = str->characterAtIndex(i);
+ if ((ch >= '0') && (ch <= '9')) {
+ UChar characters[2];
+ characters[0] = ch;
+ characters[1] = 0;
+ result->appendCharactersLength(characters, 1);
+ }
+ else if ((ch >= 'a') && (ch <= 'z')) {
+ UChar characters[2];
+ characters[0] = ch;
+ characters[1] = 0;
+ result->appendCharactersLength(characters, 1);
+ }
+ else if ((ch >= 'A') && (ch <= 'Z')) {
+ UChar characters[2];
+ characters[0] = ch;
+ characters[1] = 0;
+ result->appendCharactersLength(characters, 1);
+ }
+ else {
+ switch (ch) {
+ case ' ':
+ case '.':
+ case ',':
+ case '<':
+ case '>':
+ case '(':
+ case ')':
+ case '!':
+ case '@':
+ case '#':
+ case '$':
+ case '%':
+ case '^':
+ case '&':
+ case '*':
+ case '-':
+ case '_':
+ case '+':
+ case '=':
+ case '?':
+ case '{':
+ case '}':
+ case '[':
+ case ']':
+ case ':':
+ case ';':
+ case '|':
+ case '~':
+ case '\'': {
+ UChar characters[2];
+ characters[0] = ch;
+ characters[1] = 0;
+ result->appendCharactersLength(characters, 1);
+ break;
+ }
+ case '"':
+ case '/':
+ case '\\': {
+ UChar characters[3];
+ characters[0] = '\\';
+ characters[1] = ch;
+ characters[2] = 0;
+ result->appendCharactersLength(characters, 2);
+ break;
+ }
+ default: {
+ result->appendUTF8Format("\\u%04x", (unsigned int) ch);
+ break;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+void JSONParser::appendStringFromObject(Object * object, String * string)
+{
+ if (object->className()->isEqual(MCSTR("mailcore::String"))) {
+ string->appendString(MCSTR("\""));
+ string->appendString(JSStringFromString((String *) object));
+ string->appendString(MCSTR("\""));
+ }
+ else if (object->className()->isEqual(MCSTR("mailcore::Value"))) {
+ Value * value = (Value *) object;
+ switch (value->type()) {
+ case ValueTypeBool:
+ string->appendString(value->boolValue() ? MCSTR("true") : MCSTR("false"));
+ break;
+ case ValueTypeChar:
+ string->appendUTF8Format("%i", (int) value->charValue());
+ break;
+ case ValueTypeUnsignedChar:
+ string->appendUTF8Format("%i", (int) value->unsignedCharValue());
+ break;
+ case ValueTypeShort:
+ string->appendUTF8Format("%i", (int) value->shortValue());
+ break;
+ case ValueTypeUnsignedShort:
+ string->appendUTF8Format("%i", (int) value->unsignedShortValue());
+ break;
+ case ValueTypeInt:
+ string->appendUTF8Format("%i", (int) value->intValue());
+ break;
+ case ValueTypeUnsignedInt:
+ string->appendUTF8Format("%u", (int) value->unsignedIntValue());
+ break;
+ case ValueTypeLong:
+ string->appendUTF8Format("%ld", value->longValue());
+ break;
+ case ValueTypeUnsignedLong:
+ string->appendUTF8Format("%lu", value->unsignedLongValue());
+ break;
+ case ValueTypeLongLong:
+ string->appendUTF8Format("%lld", value->longLongValue());
+ break;
+ case ValueTypeUnsignedLongLong:
+ string->appendUTF8Format("%llu", value->unsignedLongLongValue());
+ break;
+ case ValueTypeFloat:
+ string->appendUTF8Format("%g", value->floatValue());
+ break;
+ case ValueTypeDouble:
+ string->appendUTF8Format("%lg", value->doubleValue());
+ break;
+ default:
+ MCAssert(0);
+ break;
+ }
+ }
+ else if (object->className()->isEqual(MCSTR("mailcore::Null"))) {
+ string->appendString(MCSTR("null"));
+ }
+ else if (object->className()->isEqual(MCSTR("mailcore::Array"))) {
+ Array * array;
+ bool first;
+
+ first = true;
+ array = (Array *) object;
+ string->appendString(MCSTR("["));
+ for(unsigned int i = 0 ; i < array->count() ; i ++) {
+ Object * arrayElement = array->objectAtIndex(i);
+ if (first) {
+ first = false;
+ }
+ else {
+ string->appendString(MCSTR(","));
+ }
+ appendStringFromObject(arrayElement, string);
+ }
+ string->appendString(MCSTR("]"));
+ }
+ else if (object->className()->isEqual(MCSTR("mailcore::HashMap"))) {
+ HashMap * dict;
+ bool first;
+
+ first = true;
+ dict = (HashMap *) object;
+ string->appendString(MCSTR("{"));
+ Array * keys = dict->allKeys();
+ for(unsigned int i = 0 ; i < keys->count() ; i ++) {
+ String * key = (String *) keys->objectAtIndex(i);
+
+ if (first) {
+ first = false;
+ }
+ else {
+ string->appendString(MCSTR(","));
+ }
+ appendStringFromObject(key, string);
+ string->appendString(MCSTR(":"));
+ appendStringFromObject(dict->objectForKey(key), string);
+ }
+ string->appendString(MCSTR("}"));
+ }
+}
diff --git a/src/core/basetypes/MCJSONParser.h b/src/core/basetypes/MCJSONParser.h
new file mode 100644
index 00000000..f27e924e
--- /dev/null
+++ b/src/core/basetypes/MCJSONParser.h
@@ -0,0 +1,66 @@
+//
+// JSONParser.h
+// mailcore2
+//
+// Created by DINH Viêt Hoà on 4/17/13.
+// Copyright (c) 2013 MailCore. All rights reserved.
+//
+
+#ifndef __MAILCORE_MCJSONPARSER_H_
+#define __MAILCORE_MCJSONPARSER_H_
+
+#include <MailCore/MCObject.h>
+#include <MailCore/MCICUTypes.h>
+
+namespace mailcore {
+
+ class Data;
+ class String;
+
+ class JSONParser : public Object {
+
+ public:
+ JSONParser();
+ virtual ~JSONParser();
+
+ virtual String * content();
+ virtual void setContent(String * content);
+
+ virtual unsigned int position();
+ virtual void setPosition(unsigned int position);
+
+ virtual Object * result();
+
+ virtual bool parse();
+
+ virtual bool isEndOfExpression();
+
+ static Object * objectFromData(Data * data);
+ static Object * objectFromString(String * str);
+
+ static Data * dataFromObject(Object * object);
+ static String * stringFromObject(Object * object);
+
+ private:
+ Object * mResult;
+ unsigned int mPosition;
+ String * mContent;
+ void init();
+
+ void skipBlank();
+ unsigned int skipBlank(unsigned int position);
+ bool parseDictionary();
+ bool scanCharacter(UChar ch, unsigned int position);
+ bool scanKeyword(String * str, unsigned int position);
+ bool parseArray();
+ bool parseString();
+ bool parseBoolean();
+ bool parseNull();
+ bool parseFloat();
+ static String * JSStringFromString(String * str);
+ static void appendStringFromObject(Object * object, String * string);
+ };
+
+}
+
+#endif \ No newline at end of file
diff --git a/src/core/basetypes/MCString.h b/src/core/basetypes/MCString.h
index c7da4788..fdbf174a 100644
--- a/src/core/basetypes/MCString.h
+++ b/src/core/basetypes/MCString.h
@@ -4,17 +4,12 @@
#include <MailCore/MCObject.h>
#include <MailCore/MCRange.h>
+#include <MailCore/MCICUTypes.h>
#include <stdarg.h>
#ifdef __cplusplus
-#if defined(__CHAR16_TYPE__)
-typedef __CHAR16_TYPE__ UChar;
-#else
-typedef uint16_t UChar;
-#endif
-
namespace mailcore {
class Data;
@@ -44,6 +39,7 @@ namespace mailcore {
virtual void appendString(String * otherString);
virtual void appendUTF8Format(const char * format, ...);
virtual void appendCharacters(const UChar * unicodeCharacters);
+ virtual void appendCharactersLength(const UChar * unicodeCharacters, unsigned int length);
virtual void appendUTF8Characters(const char * UTF8Characters);
virtual void setString(String * otherString);
virtual void setUTF8Characters(const char * UTF8Characters);
@@ -126,7 +122,6 @@ namespace mailcore {
unsigned int mLength;
unsigned int mAllocated;
void allocate(unsigned int length);
- void appendCharactersLength(const UChar * unicodeCharacters, unsigned int length);
void reset();
int compareWithCaseSensitive(String * otherString, bool caseSensitive);
void appendBytes(const char * bytes, unsigned int length, const char * charset);
diff --git a/src/core/renderer/MCAddressDisplay.cpp b/src/core/renderer/MCAddressDisplay.cpp
index 842dd0df..4a0fe44b 100644
--- a/src/core/renderer/MCAddressDisplay.cpp
+++ b/src/core/renderer/MCAddressDisplay.cpp
@@ -56,15 +56,7 @@ String * AddressDisplay::veryShortDisplayStringForAddress(Address * address)
String * AddressDisplay::displayStringForAddresses(Array * addresses)
{
- String * result = String::string();
- for(unsigned int i = 0 ; i < addresses->count() ; i ++) {
- Address * address = (Address *) addresses->objectAtIndex(i);
- if (i != 0) {
- result->appendString(MCSTR(", "));
- }
- result->appendString(displayStringForAddress(address));
- }
- return result;
+ return Address::nonEncodedRFC822StringForAddresses(addresses);
}
String * AddressDisplay::shortDisplayStringForAddresses(Array * addresses)
diff --git a/src/core/renderer/MCHTMLRenderer.cpp b/src/core/renderer/MCHTMLRenderer.cpp
index 71454a0e..7d03f650 100644
--- a/src/core/renderer/MCHTMLRenderer.cpp
+++ b/src/core/renderer/MCHTMLRenderer.cpp
@@ -328,17 +328,21 @@ String * htmlForAbstractSinglePart(AbstractPart * part, htmlRendererContext * co
String * htmlForAbstractMessagePart(AbstractMessagePart * part, htmlRendererContext * context)
{
- String * substring = htmlForAbstractPart(part->mainPart(), context);
if (context->pass == 0) {
return NULL;
}
+ String * substring = htmlForAbstractPart(part->mainPart(), context);
MCAssert(substring != NULL);
- String * result = String::string();
HashMap * values = context->htmlCallback->templateValuesForHeader(part->header());
String * headerString = renderTemplate(context->htmlCallback->templateForEmbeddedMessageHeader(), values);
- result->appendString(headerString);
- result->appendString(substring);
+
+ HashMap * msgValues = new HashMap();
+ msgValues->setObjectForKey(MCSTR("HEADER"), headerString);
+ msgValues->setObjectForKey(MCSTR("BODY"), substring);
+ String * result = renderTemplate(context->htmlCallback->templateForEmbeddedMessage(), msgValues);
+ msgValues->release();
+
return result;
}
diff --git a/src/core/rfc822/MCAttachment.cc b/src/core/rfc822/MCAttachment.cc
index c75e689a..b6167941 100644
--- a/src/core/rfc822/MCAttachment.cc
+++ b/src/core/rfc822/MCAttachment.cc
@@ -247,6 +247,17 @@ Data * Attachment::data()
return mData;
}
+String * Attachment::decodedString()
+{
+ if (mData) {
+ return decodedStringForData(mData);
+ }
+ else {
+ return NULL;
+ }
+}
+
+
AbstractPart * Attachment::attachmentsWithMIME(struct mailmime * mime)
{
return attachmentsWithMIMEWithMain(mime, true);
diff --git a/src/core/rfc822/MCAttachment.h b/src/core/rfc822/MCAttachment.h
index c1fc232e..272e589d 100644
--- a/src/core/rfc822/MCAttachment.h
+++ b/src/core/rfc822/MCAttachment.h
@@ -26,6 +26,7 @@ namespace mailcore {
virtual void setData(Data * data);
virtual Data * data();
+ virtual String * decodedString();
public: // subclass behavior
Attachment(Attachment * other);
diff --git a/src/objc/abstract/MCOAbstractMessageRendererCallback.mm b/src/objc/abstract/MCOAbstractMessageRendererCallback.mm
index 8905acf5..883cb25f 100644
--- a/src/objc/abstract/MCOAbstractMessageRendererCallback.mm
+++ b/src/objc/abstract/MCOAbstractMessageRendererCallback.mm
@@ -104,7 +104,7 @@ mailcore::String * MCOAbstractMessageRendererCallback::templateForEmbeddedMessag
{
mailcore::String * result = NULL;
if ([mRendererDelegate respondsToSelector:@selector(MCOAbstractMessage_templateForEmbeddedMessage:)]) {
- return MCO_FROM_OBJC(mailcore::String, [mRendererDelegate MCOAbstractMessage_templateForEmbeddedMessage:mMessage]);
+ result = MCO_FROM_OBJC(mailcore::String, [mRendererDelegate MCOAbstractMessage_templateForEmbeddedMessage:mMessage]);
}
if (result == NULL) {
result = mailcore::HTMLRendererTemplateCallback::templateForEmbeddedMessage();
@@ -116,7 +116,7 @@ mailcore::String * MCOAbstractMessageRendererCallback::templateForEmbeddedMessag
{
mailcore::String * result = NULL;
if ([mRendererDelegate respondsToSelector:@selector(MCOAbstractMessage_templateForEmbeddedMessageHeader:)]) {
- return MCO_FROM_OBJC(mailcore::String, [mRendererDelegate MCOAbstractMessage_templateForEmbeddedMessageHeader:mMessage]);
+ result = MCO_FROM_OBJC(mailcore::String, [mRendererDelegate MCOAbstractMessage_templateForEmbeddedMessageHeader:mMessage]);
}
if (result == NULL) {
result = mailcore::HTMLRendererTemplateCallback::templateForEmbeddedMessageHeader();
diff --git a/src/objc/abstract/MCOAbstractPart.h b/src/objc/abstract/MCOAbstractPart.h
index 6fb14fcd..5c636a19 100644
--- a/src/objc/abstract/MCOAbstractPart.h
+++ b/src/objc/abstract/MCOAbstractPart.h
@@ -74,6 +74,9 @@ typedef enum {
// Returns the part with the given unique identifier among this part and its subparts.
- (MCOAbstractPart *) partForUniqueID:(NSString *)uniqueID;
+// Returns a string representation of the data according to charset.
+- (NSString *) decodedStringForData:(NSData *)data;
+
@end
#endif
diff --git a/src/objc/abstract/MCOAbstractPart.mm b/src/objc/abstract/MCOAbstractPart.mm
index 1d17ca20..47191ce9 100644
--- a/src/objc/abstract/MCOAbstractPart.mm
+++ b/src/objc/abstract/MCOAbstractPart.mm
@@ -14,6 +14,7 @@
#import "NSString+MCO.h"
#import "NSObject+MCO.h"
+#import "NSData+MCO.h"
@implementation MCOAbstractPart {
mailcore::AbstractPart * _part;
@@ -68,4 +69,8 @@ MCO_OBJC_SYNTHESIZE(AbstractMessage, setMessage, message)
return MCO_TO_OBJC(MCO_NATIVE_INSTANCE->partForUniqueID([uniqueID mco_mcString]));
}
+- (NSString *) decodedStringForData:(NSData *)data
+{
+ return [NSString mco_stringWithMCString:MCO_NATIVE_INSTANCE->decodedStringForData([data mco_mcData])];
+}
@end
diff --git a/src/objc/abstract/MCOAddress.h b/src/objc/abstract/MCOAddress.h
index 33f2c545..c7552676 100644
--- a/src/objc/abstract/MCOAddress.h
+++ b/src/objc/abstract/MCOAddress.h
@@ -31,6 +31,17 @@
// Example: [MCOAddress addressWithRFC822String:@"DINH Viêt Hoà <hoa@etpan.org>"]
+ (MCOAddress *) addressWithNonEncodedRFC822String:(NSString *)nonEncodedRFC822String;
+// Returns an NSArray of MCOAddress objects that contain the parsed
+// forms of the RFC822 encoded addresses.
+// For example: @[ @"DINH Vi=C3=AAt Ho=C3=A0 <hoa@etpan.org>" ]
++ (NSArray *) addressesWithRFC822String:(NSString *)string;
+
+// Returns an NSArray of MCOAddress objects that contain the parsed
+// forms of non-encoded RFC822 addresses.
+// For example: @[ "DINH Viêt Hoà <hoa@etpan.org>" ]
++ (NSArray *) addressesWithNonEncodedRFC822String:(NSString *)string;
+
+
// Returns the display name of the address.
@property (nonatomic, copy) NSString * displayName;
@@ -47,17 +58,13 @@
@end
-@interface MCOAddress (MCONSArray)
+@interface NSArray (MCONSArray)
-// Returns an NSArray of MCOAddress objects that contain the parsed
-// forms of the RFC822 encoded addresses.
-// For example: @[ @"DINH Vi=C3=AAt Ho=C3=A0 <hoa@etpan.org>" ]
-+ (NSArray *) addressesWithRFC822String:(NSString *)string;
+// Returns the RFC822 encoding of the addresses.
+- (NSString *) mco_RFC822StringForAddresses;
-// Returns an NSArray of MCOAddress objects that contain the parsed
-// forms of non-encoded RFC822 addresses.
-// For example: @[ "DINH Viêt Hoà <hoa@etpan.org>" ]
-+ (NSArray *) addressesWithNonEncodedRFC822String:(NSString *)string;
+// Returns the non-MIME-encoded RFC822 of the addresses.
+- (NSString *) mco_nonEncodedRFC822StringForAddresses;
@end
diff --git a/src/objc/abstract/MCOAddress.mm b/src/objc/abstract/MCOAddress.mm
index 6676e1a2..7a398421 100644
--- a/src/objc/abstract/MCOAddress.mm
+++ b/src/objc/abstract/MCOAddress.mm
@@ -83,6 +83,17 @@
return result;
}
++ (NSArray *) addressesWithRFC822String:(NSString *)string
+{
+ return [NSArray mco_arrayWithMCArray:mailcore::Address::addressesWithRFC822String(string.mco_mcString)];
+}
+
++ (NSArray *) addressesWithNonEncodedRFC822String:(NSString *)string
+{
+ return [NSArray mco_arrayWithMCArray:mailcore::Address::addressesWithNonEncodedRFC822String(string.mco_mcString)];
+}
+
+
- (id) init
{
self = [super init];
@@ -136,16 +147,16 @@ MCO_OBJC_SYNTHESIZE_STRING(setMailbox, mailbox)
@end
-@implementation MCOAddress (MCONSArray)
+@implementation NSArray (MCONSArray)
-+ (NSArray *) addressesWithRFC822String:(NSString *)string
+- (NSString *) mco_RFC822StringForAddresses
{
- return [NSArray mco_arrayWithMCArray:mailcore::Address::addressesWithRFC822String(string.mco_mcString)];
+ return [NSString mco_stringWithMCString:mailcore::Address::RFC822StringForAddresses([self mco_mcArray])];
}
-+ (NSArray *) addressesWithNonEncodedRFC822String:(NSString *)string
-{
- return [NSArray mco_arrayWithMCArray:mailcore::Address::addressesWithNonEncodedRFC822String(string.mco_mcString)];
+- (NSString *) mco_nonEncodedRFC822StringForAddresses
+{
+ return [NSString mco_stringWithMCString:mailcore::Address::nonEncodedRFC822StringForAddresses([self mco_mcArray ])];
}
@end
diff --git a/src/objc/rfc822/MCOAttachment.h b/src/objc/rfc822/MCOAttachment.h
index 7c6a0d7b..584bdece 100644
--- a/src/objc/rfc822/MCOAttachment.h
+++ b/src/objc/rfc822/MCOAttachment.h
@@ -34,6 +34,9 @@
// Decoded data of the part.
@property (nonatomic, strong) NSData * data;
+
+// Returns string representation according to charset
+- (NSString *) decodedString;
@end
diff --git a/src/objc/rfc822/MCOAttachment.mm b/src/objc/rfc822/MCOAttachment.mm
index 55430f78..423ac0df 100644
--- a/src/objc/rfc822/MCOAttachment.mm
+++ b/src/objc/rfc822/MCOAttachment.mm
@@ -86,4 +86,10 @@
MCO_OBJC_SYNTHESIZE_DATA(setData, data)
+- (NSString *) decodedString
+{
+ mailcore::String *result = MCO_NATIVE_INSTANCE->decodedString();
+ return [NSString mco_stringWithMCString:result];
+}
+
@end
diff --git a/src/objc/rfc822/MCOMessageBuilder.mm b/src/objc/rfc822/MCOMessageBuilder.mm
index 5537b895..2cb26448 100644
--- a/src/objc/rfc822/MCOMessageBuilder.mm
+++ b/src/objc/rfc822/MCOMessageBuilder.mm
@@ -23,6 +23,14 @@
MCORegisterClass(self, &typeid(nativeType));
}
+- (id)init
+{
+ mailcore::MessageBuilder * message = new mailcore::MessageBuilder();
+ self = [super initWithMCMessage:message];
+ MC_SAFE_RELEASE(message);
+ return self;
+}
+
- (id) copyWithZone:(NSZone *)zone
{
nativeType * nativeObject = (nativeType *) [self mco_mcObject]->copy();
diff --git a/src/objc/utils/NSArray+MCO.mm b/src/objc/utils/NSArray+MCO.mm
index 0b8b21bf..022960f0 100644
--- a/src/objc/utils/NSArray+MCO.mm
+++ b/src/objc/utils/NSArray+MCO.mm
@@ -32,7 +32,7 @@
{
mailcore::Array * result = mailcore::Array::array();
for(NSObject * value in self) {
- [value mco_mcObject];
+ result->addObject([value mco_mcObject]);
}
return result;
}
diff --git a/src/objc/utils/NSString+MCO.h b/src/objc/utils/NSString+MCO.h
index b459a846..8e6bbf6b 100644
--- a/src/objc/utils/NSString+MCO.h
+++ b/src/objc/utils/NSString+MCO.h
@@ -28,6 +28,13 @@ namespace mailcore {
- (mailcore::String *) mco_mcString;
#endif
+- (NSString *) mco_flattenHTML;
+- (NSString *) mco_flattenHTMLAndShowBlockquote:(BOOL)showBlockquote;
+- (NSString *) mco_flattenHTMLAndShowBlockquote:(BOOL)showBlockquote showLink:(BOOL)showLink;
+
+- (NSString *) mco_htmlEncodedString;
+- (NSString *) mco_cleanedHTMLString;
+
@end
#endif
diff --git a/src/objc/utils/NSString+MCO.mm b/src/objc/utils/NSString+MCO.mm
index 3b8253ce..e9933fab 100644
--- a/src/objc/utils/NSString+MCO.mm
+++ b/src/objc/utils/NSString+MCO.mm
@@ -39,4 +39,31 @@
return mailcore::String::stringWithCharacters(characters, (unsigned int) [self length]);
}
+- (NSString *) mco_flattenHTML
+{
+ return [NSString mco_stringWithMCString:[self mco_mcString]->flattenHTML()];
+}
+
+- (NSString *) mco_flattenHTMLAndShowBlockquote:(BOOL)showBlockquote
+{
+ return [NSString mco_stringWithMCString:[self mco_mcString]->flattenHTMLAndShowBlockquote(showBlockquote)];
+}
+
+- (NSString *) mco_flattenHTMLAndShowBlockquote:(BOOL)showBlockquote showLink:(BOOL)showLink
+{
+ return [NSString mco_stringWithMCString:[self mco_mcString]->flattenHTMLAndShowBlockquoteAndLink(showBlockquote, showLink)];
+}
+
+
+- (NSString *) mco_htmlEncodedString
+{
+ return [NSString mco_stringWithMCString:[self mco_mcString]->htmlEncodedString()];
+}
+
+- (NSString *) mco_cleanedHTMLString
+{
+ return [NSString mco_stringWithMCString:[self mco_mcString]->cleanedHTMLString()];
+}
+
+
@end