534 строки
14 KiB
C
534 строки
14 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <xpwn/plist.h>
|
|
#include "common.h"
|
|
|
|
Tag* getNextTag(char** xmlPtr) {
|
|
char* xml;
|
|
char* tagEnd;
|
|
char* curChar;
|
|
Tag* tag;
|
|
int tagDepth;
|
|
|
|
xml = *xmlPtr;
|
|
xml = strchr(xml, '<');
|
|
|
|
if(xml == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
tag = (Tag*) malloc(sizeof(Tag));
|
|
|
|
tagEnd = strchr(xml, '>');
|
|
tag->name = (char*) malloc(sizeof(char) * (tagEnd - xml));
|
|
memcpy(tag->name, xml + 1, tagEnd - xml - 1);
|
|
tag->name[tagEnd - xml - 1] = '\0';
|
|
if((tagEnd - xml - 1) > 0) {
|
|
if(tag->name[tagEnd - xml - 2] == '/') {
|
|
tag->xml = malloc(sizeof(char) * 1);
|
|
tag->xml[0] = '\0';
|
|
*xmlPtr = tagEnd + 1;
|
|
return tag;
|
|
}
|
|
}
|
|
|
|
xml = tagEnd;
|
|
curChar = xml;
|
|
tagDepth = 1;
|
|
while(*curChar != '\0') {
|
|
if(*curChar == '<') {
|
|
if(*(curChar + 1) == '/') {
|
|
tagDepth--;
|
|
if(tagDepth == 0) {
|
|
break;
|
|
}
|
|
} else {
|
|
tagDepth++;
|
|
}
|
|
} else if(*curChar == '>') {
|
|
if(*(curChar - 1) == '/') {
|
|
tagDepth--;
|
|
}
|
|
}
|
|
curChar++;
|
|
}
|
|
|
|
tag->xml = (char*) malloc(sizeof(char) * (curChar - xml));
|
|
memcpy(tag->xml, xml + 1, curChar - xml - 1);
|
|
tag->xml[curChar - xml - 1] = '\0';
|
|
|
|
*xmlPtr = strchr(curChar, '>') + 1;
|
|
|
|
return tag;
|
|
}
|
|
|
|
void releaseTag(Tag* tag) {
|
|
free(tag->name);
|
|
free(tag->xml);
|
|
free(tag);
|
|
}
|
|
|
|
void releaseArray(ArrayValue* myself) {
|
|
int i;
|
|
|
|
free(myself->dValue.key);
|
|
for(i = 0; i < myself->size; i++) {
|
|
switch(myself->values[i]->type) {
|
|
case DictionaryType:
|
|
releaseDictionary((Dictionary*) myself->values[i]);
|
|
break;
|
|
case ArrayType:
|
|
releaseArray((ArrayValue*) myself->values[i]);
|
|
break;
|
|
case StringType:
|
|
free(((StringValue*)(myself->values[i]))->value);
|
|
case BoolType:
|
|
case IntegerType:
|
|
free(myself->values[i]->key);
|
|
free(myself->values[i]);
|
|
break;
|
|
}
|
|
}
|
|
free(myself->values);
|
|
free(myself);
|
|
}
|
|
|
|
void releaseDictionary(Dictionary* myself) {
|
|
DictValue* next;
|
|
DictValue* toRelease;
|
|
|
|
free(myself->dValue.key);
|
|
next = myself->values;
|
|
while(next != NULL) {
|
|
toRelease = next;
|
|
next = next->next;
|
|
|
|
switch(toRelease->type) {
|
|
case DictionaryType:
|
|
releaseDictionary((Dictionary*) toRelease);
|
|
break;
|
|
case ArrayType:
|
|
releaseArray((ArrayValue*) toRelease);
|
|
break;
|
|
case StringType:
|
|
free(((StringValue*)(toRelease))->value);
|
|
case IntegerType:
|
|
case BoolType:
|
|
free(toRelease->key);
|
|
free(toRelease);
|
|
break;
|
|
}
|
|
}
|
|
free(myself);
|
|
}
|
|
void createArray(ArrayValue* myself, char* xml) {
|
|
Tag* valueTag;
|
|
DictValue* curValue;
|
|
|
|
myself->values = NULL;
|
|
myself->size = 0;
|
|
while(*xml != '\0') {
|
|
valueTag = getNextTag(&xml);
|
|
if(valueTag == NULL) {
|
|
break;
|
|
}
|
|
|
|
myself->size++;
|
|
myself->values = realloc(myself->values, sizeof(DictValue*) * myself->size);
|
|
curValue = (DictValue*) malloc(sizeof(DictValue));
|
|
|
|
curValue->key = (char*) malloc(sizeof("arraykey"));
|
|
strcpy(curValue->key, "arraykey");
|
|
curValue->next = NULL;
|
|
|
|
if(strcmp(valueTag->name, "dict") == 0) {
|
|
curValue->type = DictionaryType;
|
|
curValue = (DictValue*) realloc(curValue, sizeof(Dictionary));
|
|
createDictionary((Dictionary*) curValue, valueTag->xml);
|
|
} else if(strcmp(valueTag->name, "string") == 0) {
|
|
curValue->type = StringType;
|
|
curValue = (DictValue*) realloc(curValue, sizeof(StringValue));
|
|
((StringValue*)curValue)->value = (char*) malloc(sizeof(char) * (strlen(valueTag->xml) + 1));
|
|
strcpy(((StringValue*)curValue)->value, valueTag->xml);
|
|
} else if(strcmp(valueTag->name, "integer") == 0) {
|
|
curValue->type = IntegerType;
|
|
curValue = (DictValue*) realloc(curValue, sizeof(IntegerValue));
|
|
sscanf(valueTag->xml, "%d", &(((IntegerValue*)curValue)->value));
|
|
} else if(strcmp(valueTag->name, "array") == 0) {
|
|
curValue->type = ArrayType;
|
|
curValue = (DictValue*) realloc(curValue, sizeof(ArrayValue));
|
|
createArray((ArrayValue*) curValue, valueTag->xml);
|
|
} else if(strcmp(valueTag->name, "true/") == 0) {
|
|
curValue->type = BoolType;
|
|
curValue = (DictValue*) realloc(curValue, sizeof(BoolValue));
|
|
((BoolValue*)curValue)->value = TRUE;
|
|
} else if(strcmp(valueTag->name, "false/") == 0) {
|
|
curValue->type = BoolType;
|
|
curValue = (DictValue*) realloc(curValue, sizeof(BoolValue));
|
|
((BoolValue*)curValue)->value = FALSE;
|
|
}
|
|
|
|
myself->values[myself->size - 1] = curValue;
|
|
|
|
releaseTag(valueTag);
|
|
}
|
|
}
|
|
|
|
void removeKey(Dictionary* dict, char* key) {
|
|
DictValue* next;
|
|
DictValue* toRelease;
|
|
next = dict->values;
|
|
while(next != NULL) {
|
|
if(strcmp(next->key, key) == 0) {
|
|
toRelease = next;
|
|
if(toRelease->prev) {
|
|
toRelease->prev->next = toRelease->next;
|
|
} else {
|
|
dict->values = toRelease->next;
|
|
}
|
|
if(toRelease->next) {
|
|
toRelease->next->prev = toRelease->prev;
|
|
}
|
|
switch(toRelease->type) {
|
|
case DictionaryType:
|
|
releaseDictionary((Dictionary*) toRelease);
|
|
break;
|
|
case ArrayType:
|
|
releaseArray((ArrayValue*) toRelease);
|
|
break;
|
|
case StringType:
|
|
free(((StringValue*)(toRelease))->value);
|
|
case IntegerType:
|
|
case BoolType:
|
|
free(toRelease->key);
|
|
free(toRelease);
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
next = next->next;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void createDictionary(Dictionary* myself, char* xml) {
|
|
Tag* keyTag;
|
|
Tag* valueTag;
|
|
DictValue* curValue;
|
|
DictValue* lastValue;
|
|
|
|
curValue = NULL;
|
|
lastValue = NULL;
|
|
|
|
while(*xml != '\0') {
|
|
keyTag = getNextTag(&xml);
|
|
if(keyTag == NULL) {
|
|
break;
|
|
}
|
|
|
|
if(strcmp(keyTag->name, "key") != 0) {
|
|
releaseTag(keyTag);
|
|
continue;
|
|
}
|
|
|
|
curValue = (DictValue*) malloc(sizeof(DictValue));
|
|
curValue->key = (char*) malloc(sizeof(char) * (strlen(keyTag->xml) + 1));
|
|
strcpy(curValue->key, keyTag->xml);
|
|
curValue->next = NULL;
|
|
releaseTag(keyTag);
|
|
|
|
|
|
valueTag = getNextTag(&xml);
|
|
if(valueTag == NULL) {
|
|
break;
|
|
}
|
|
|
|
if(strcmp(valueTag->name, "dict") == 0) {
|
|
curValue->type = DictionaryType;
|
|
curValue = (DictValue*) realloc(curValue, sizeof(Dictionary));
|
|
createDictionary((Dictionary*) curValue, valueTag->xml);
|
|
} else if(strcmp(valueTag->name, "string") == 0) {
|
|
curValue->type = StringType;
|
|
curValue = (DictValue*) realloc(curValue, sizeof(StringValue));
|
|
((StringValue*)curValue)->value = (char*) malloc(sizeof(char) * (strlen(valueTag->xml) + 1));
|
|
strcpy(((StringValue*)curValue)->value, valueTag->xml);
|
|
} else if(strcmp(valueTag->name, "integer") == 0) {
|
|
curValue->type = IntegerType;
|
|
curValue = (DictValue*) realloc(curValue, sizeof(IntegerValue));
|
|
sscanf(valueTag->xml, "%d", &(((IntegerValue*)curValue)->value));
|
|
} else if(strcmp(valueTag->name, "array") == 0) {
|
|
curValue->type = ArrayType;
|
|
curValue = (DictValue*) realloc(curValue, sizeof(ArrayValue));
|
|
createArray((ArrayValue*) curValue, valueTag->xml);
|
|
} else if(strcmp(valueTag->name, "true/") == 0) {
|
|
curValue->type = BoolType;
|
|
curValue = (DictValue*) realloc(curValue, sizeof(BoolValue));
|
|
((BoolValue*)curValue)->value = TRUE;
|
|
} else if(strcmp(valueTag->name, "false/") == 0) {
|
|
curValue->type = BoolType;
|
|
curValue = (DictValue*) realloc(curValue, sizeof(BoolValue));
|
|
((BoolValue*)curValue)->value = FALSE;
|
|
}
|
|
|
|
curValue->prev = lastValue;
|
|
if(lastValue == NULL) {
|
|
myself->values = curValue;
|
|
} else {
|
|
lastValue->next = curValue;
|
|
}
|
|
|
|
lastValue = curValue;
|
|
|
|
releaseTag(valueTag);
|
|
}
|
|
}
|
|
|
|
char* getXmlFromArrayValue(ArrayValue* myself, int tabsCount) {
|
|
char tabs[100];
|
|
char buffer[4096];
|
|
char* toReturn;
|
|
char* ret;
|
|
size_t toReturnSize;
|
|
int i;
|
|
DictValue* curValue;
|
|
|
|
tabs[0] = '\0';
|
|
for(i = 0; i < tabsCount; i++) {
|
|
strcat(tabs, "\t");
|
|
}
|
|
|
|
|
|
sprintf(buffer, "%s<array>\n", tabs);
|
|
toReturnSize = sizeof(char) * (strlen(buffer) + 1);
|
|
toReturn = malloc(toReturnSize);
|
|
toReturn = strcpy(toReturn, buffer);
|
|
|
|
for(i = 0; i < myself->size; i++) {
|
|
curValue = myself->values[i];
|
|
|
|
if(curValue->type == DictionaryType) {
|
|
ret = getXmlFromDictionary((Dictionary*)curValue, tabsCount + 1);
|
|
toReturnSize += sizeof(char) * (strlen(ret) + 1);
|
|
toReturn = realloc(toReturn, toReturnSize);
|
|
toReturn = strcat(toReturn, ret);
|
|
free(ret);
|
|
} else if(curValue->type == StringType) {
|
|
sprintf(buffer, "%s\t<string>%s</string>\n", tabs, ((StringValue*)curValue)->value);
|
|
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
|
|
toReturn = realloc(toReturn, toReturnSize);
|
|
toReturn = strcat(toReturn, buffer);
|
|
} else if(curValue->type == IntegerType) {
|
|
sprintf(buffer, "%s\t<integer>%d</integer>\n", tabs, ((IntegerValue*)curValue)->value);
|
|
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
|
|
toReturn = realloc(toReturn, toReturnSize);
|
|
toReturn = strcat(toReturn, buffer);
|
|
} else if(curValue->type == ArrayType) {
|
|
ret = getXmlFromArrayValue((ArrayValue*)curValue, tabsCount + 1);
|
|
toReturnSize += sizeof(char) * (strlen(ret) + 1);
|
|
toReturn = realloc(toReturn, toReturnSize);
|
|
toReturn = strcat(toReturn, ret);
|
|
free(ret);
|
|
} else if(curValue->type == BoolType) {
|
|
if(((BoolValue*)curValue)->value) {
|
|
sprintf(buffer, "%s\t<true/>\n", tabs);
|
|
} else {
|
|
sprintf(buffer, "%s\t<false/>\n", tabs);
|
|
}
|
|
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
|
|
toReturn = realloc(toReturn, toReturnSize);
|
|
toReturn = strcat(toReturn, buffer);
|
|
}
|
|
}
|
|
|
|
sprintf(buffer, "%s</array>\n", tabs);
|
|
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
|
|
toReturn = realloc(toReturn, toReturnSize);
|
|
toReturn = strcat(toReturn, buffer);
|
|
|
|
return toReturn;
|
|
}
|
|
|
|
char* getXmlFromDictionary(Dictionary* myself, int tabsCount) {
|
|
char tabs[100];
|
|
char buffer[4096];
|
|
char* toReturn;
|
|
char* ret;
|
|
size_t toReturnSize;
|
|
int i;
|
|
DictValue* curValue;
|
|
|
|
tabs[0] = '\0';
|
|
for(i = 0; i < tabsCount; i++) {
|
|
strcat(tabs, "\t");
|
|
}
|
|
|
|
|
|
sprintf(buffer, "%s<dict>\n", tabs);
|
|
toReturnSize = sizeof(char) * (strlen(buffer) + 1);
|
|
toReturn = malloc(toReturnSize);
|
|
toReturn = strcpy(toReturn, buffer);
|
|
|
|
curValue = myself->values;
|
|
while(curValue != NULL) {
|
|
sprintf(buffer, "%s\t<key>%s</key>\n", tabs, curValue->key);
|
|
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
|
|
toReturn = realloc(toReturn, toReturnSize);
|
|
toReturn = strcat(toReturn, buffer);
|
|
|
|
if(curValue->type == DictionaryType) {
|
|
ret = getXmlFromDictionary((Dictionary*)curValue, tabsCount + 1);
|
|
toReturnSize += sizeof(char) * (strlen(ret) + 1);
|
|
toReturn = realloc(toReturn, toReturnSize);
|
|
toReturn = strcat(toReturn, ret);
|
|
free(ret);
|
|
} else if(curValue->type == StringType) {
|
|
sprintf(buffer, "%s\t<string>%s</string>\n", tabs, ((StringValue*)curValue)->value);
|
|
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
|
|
toReturn = realloc(toReturn, toReturnSize);
|
|
toReturn = strcat(toReturn, buffer);
|
|
} else if(curValue->type == IntegerType) {
|
|
sprintf(buffer, "%s\t<integer>%d</integer>\n", tabs, ((IntegerValue*)curValue)->value);
|
|
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
|
|
toReturn = realloc(toReturn, toReturnSize);
|
|
toReturn = strcat(toReturn, buffer);
|
|
} else if(curValue->type == ArrayType) {
|
|
ret = getXmlFromArrayValue((ArrayValue*)curValue, tabsCount + 1);
|
|
toReturnSize += sizeof(char) * (strlen(ret) + 1);
|
|
toReturn = realloc(toReturn, toReturnSize);
|
|
toReturn = strcat(toReturn, ret);
|
|
free(ret);
|
|
} else if(curValue->type == BoolType) {
|
|
if(((BoolValue*)curValue)->value) {
|
|
sprintf(buffer, "%s\t<true/>\n", tabs);
|
|
} else {
|
|
sprintf(buffer, "%s\t<false/>\n", tabs);
|
|
}
|
|
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
|
|
toReturn = realloc(toReturn, toReturnSize);
|
|
toReturn = strcat(toReturn, buffer);
|
|
}
|
|
|
|
curValue = curValue->next;
|
|
}
|
|
|
|
sprintf(buffer, "%s</dict>\n", tabs);
|
|
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
|
|
toReturn = realloc(toReturn, toReturnSize);
|
|
toReturn = strcat(toReturn, buffer);
|
|
|
|
return toReturn;
|
|
}
|
|
|
|
Dictionary* createRoot(char* xml) {
|
|
Tag* tag;
|
|
Dictionary* dict;
|
|
|
|
xml = strstr(xml, "<dict>");
|
|
tag = getNextTag(&xml);
|
|
dict = malloc(sizeof(Dictionary));
|
|
dict->dValue.next = NULL;
|
|
dict->dValue.key = malloc(sizeof("root"));
|
|
strcpy(dict->dValue.key, "root");
|
|
dict->values = NULL;
|
|
createDictionary(dict, tag->xml);
|
|
releaseTag(tag);
|
|
return dict;
|
|
}
|
|
|
|
char* getXmlFromRoot(Dictionary* root) {
|
|
char buffer[4096];
|
|
char* toReturn;
|
|
char* ret;
|
|
size_t toReturnSize;
|
|
|
|
sprintf(buffer, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n");
|
|
toReturnSize = sizeof(char) * (strlen(buffer) + 1);
|
|
toReturn = malloc(toReturnSize);
|
|
toReturn = strcpy(toReturn, buffer);
|
|
|
|
ret = getXmlFromDictionary(root, 0);
|
|
toReturnSize += sizeof(char) * (strlen(ret) + 1);
|
|
toReturn = realloc(toReturn, toReturnSize);
|
|
toReturn = strcat(toReturn, ret);
|
|
free(ret);
|
|
|
|
sprintf(buffer, "</plist>\n");
|
|
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
|
|
toReturn = realloc(toReturn, toReturnSize);
|
|
toReturn = strcat(toReturn, buffer);
|
|
|
|
return toReturn;
|
|
|
|
}
|
|
|
|
DictValue* getValueByKey(Dictionary* myself, const char* key) {
|
|
DictValue* next;
|
|
|
|
if(myself == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
next = myself->values;
|
|
while(next != NULL) {
|
|
if(strcmp(next->key, key) == 0)
|
|
return next;
|
|
next = next->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void addStringToArray(ArrayValue* array, char* str) {
|
|
DictValue* curValue;
|
|
|
|
array->size++;
|
|
array->values = realloc(array->values, sizeof(DictValue*) * array->size);
|
|
curValue = (DictValue*) malloc(sizeof(StringValue));
|
|
|
|
curValue->key = (char*) malloc(sizeof("arraykey"));
|
|
strcpy(curValue->key, "arraykey");
|
|
curValue->next = NULL;
|
|
curValue->prev = NULL;
|
|
curValue->type = StringType;
|
|
curValue = (DictValue*) realloc(curValue, sizeof(StringValue));
|
|
((StringValue*)curValue)->value = (char*) malloc(sizeof(char) * (strlen(str) + 1));
|
|
strcpy(((StringValue*)curValue)->value, str);
|
|
|
|
array->values[array->size - 1] = curValue;
|
|
}
|
|
|
|
void addBoolToDictionary(Dictionary* dict, const char* key, int value) {
|
|
BoolValue* dValue = malloc(sizeof(BoolValue));
|
|
dValue->dValue.type = BoolType;
|
|
dValue->value = value;
|
|
addValueToDictionary(dict, key, (DictValue*) dValue);
|
|
}
|
|
|
|
void addIntegerToDictionary(Dictionary* dict, const char* key, int value) {
|
|
IntegerValue* dValue = malloc(sizeof(IntegerValue));
|
|
dValue->dValue.type = IntegerType;
|
|
dValue->value = value;
|
|
addValueToDictionary(dict, key, (DictValue*) dValue);
|
|
}
|
|
|
|
void addValueToDictionary(Dictionary* dict, const char* key, DictValue* value) {
|
|
value->key = (char*) malloc(sizeof(char) * (strlen(key) + 1));
|
|
strcpy(value->key, key);
|
|
DictValue* curValue = dict->values;
|
|
DictValue* prevValue = NULL;
|
|
|
|
while(curValue != NULL) {
|
|
prevValue = curValue;
|
|
curValue = curValue->next;
|
|
}
|
|
|
|
value->next = NULL;
|
|
value->prev = prevValue;
|
|
|
|
if(prevValue == NULL)
|
|
dict->values = value;
|
|
else
|
|
prevValue->next = value;
|
|
}
|
|
|