aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/basetypes/MCBaseTypes.h2
-rw-r--r--src/core/basetypes/MCICUTypes.h18
-rw-r--r--src/core/basetypes/MCIterator.h124
-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
8 files changed, 1054 insertions, 248 deletions
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..e9be60e0
--- /dev/null
+++ b/src/core/basetypes/MCIterator.h
@@ -0,0 +1,124 @@
+//
+// 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>
+
+#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
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);