quakeforge/tools/Forge/Bundles/MapEdit/Dict.m

565 lines
8.6 KiB
Mathematica
Raw Normal View History

#include "QF/dstring.h"
#include "QF/va.h"
#include "Dict.h"
@implementation Dict
- (id) init
{
[super initCount: 0 elementSize: sizeof (dict_t)
description: NULL];
return self;
}
- (id) print
{
NSUInteger i;
dict_t *d;
for (i = 0; i < numElements; i++) {
d = [self elementAt: i];
printf ("%s : %s\n", d->key, d->value);
}
return self;
}
/*
===========
copyFromZone
JDC
===========
*/
- (id) copy
{
id new;
NSUInteger i;
dict_t *d;
char *old;
new = [super copy];
for (i = 0; i < numElements; i++) {
d = [self elementAt: i];
old = d->key;
d->key = malloc (strlen (old) + 1);
strcpy (d->key, old);
old = d->value;
d->value = malloc (strlen (old) + 1);
strcpy (d->value, old);
}
return new;
}
- (id) initFromFile: (FILE *)fp
{
[self init];
return [self parseBraceBlock: fp];
}
// ===============================================
//
// Dictionary pair functions
//
// ===============================================
//
// Write a { } block out to a FILE*
//
- (id) writeBlockTo: (FILE *)fp
{
int max;
int i;
dict_t *d;
fprintf (fp, "{\n");
max = [super count];
for (i = 0; i < max; i++) {
d = [super elementAt: i];
fprintf (fp, "\t{\"%s\"\t\"%s\"}\n", d->key, d->value);
}
fprintf (fp, "}\n");
return self;
}
//
// Write a single { } block out
//
- (id) writeFile: (const char *)path
{
FILE *fp;
fp = fopen (path, "w+t");
if (fp != NULL) {
printf ("Writing dictionary file %s.\n", path);
fprintf (fp, "// QE_Project file %s\n", path);
[self writeBlockTo: fp];
fclose (fp);
} else {
printf ("Error writing %s!\n", path);
return NULL;
}
return self;
}
// ===============================================
//
// Utility methods
//
// ===============================================
//
// Find a keyword in storage
// Returns * to dict_t, otherwise NULL
//
- (dict_t *) findKeyword: (const char *)key
{
int max;
int i;
dict_t *d;
max = [super count];
for (i = 0; i < max; i++) {
d = [super elementAt: i];
if (!strcmp (d->key, key))
return d;
}
return NULL;
}
//
// Change a keyword's string
//
- (id) changeStringFor: (const char *)key to: (const char *)value
{
dict_t *d;
dict_t newd;
d = [self findKeyword: key];
if (d != NULL) {
free (d->value);
d->value = malloc (strlen (value) + 1);
strcpy (d->value, value);
} else {
newd.key = malloc (strlen (key) + 1);
strcpy (newd.key, key);
newd.value = malloc (strlen (value) + 1);
strcpy (newd.value, value);
[self addElement: &newd];
}
return self;
}
//
// Search for keyword, return the string *
//
- (const char *) getStringFor: (const char *)name
{
dict_t *d;
d = [self findKeyword: name];
if (d != NULL)
return d->value;
return (char *) "";
}
//
// Search for keyword, return the value
//
- (unsigned int) getValueFor: (const char *)name
{
dict_t *d;
d = [self findKeyword: name];
if (d != NULL)
return atol (d->value);
return 0;
}
//
// Return # of units in keyword's value
//
- (int) getValueUnits: (const char *)key
{
id temp;
int count;
temp = [self parseMultipleFrom: key];
count = [temp count];
[temp release];
return count;
}
//
// Convert List to string
//
- (char *) convertListToString: (id)list
{
int i;
int max;
dstring_t *tempstr;
char *s;
max = [list count];
tempstr = dstring_newstr ();
for (i = 0; i < max; i++) {
s = [list elementAt: i];
dstring_appendstr (tempstr, s);
dstring_appendstr (tempstr, " ");
}
return dstring_freeze (tempstr);
}
//
// JDC: I wrote this to simplify removing vectors
//
- (id) removeKeyword: (const char *)key
{
dict_t *d;
d = [self findKeyword: key];
if (d == NULL)
return self;
[self removeElementAt: d - (dict_t *) dataPtr];
return self;
}
//
// Delete string from keyword's value
//
- (id) delString: (const char *)string fromValue: (const char *)key
{
id temp;
int count;
int i;
char *s;
dict_t *d;
d = [self findKeyword: key];
if (d == NULL)
return NULL;
temp = [self parseMultipleFrom: key];
count = [temp count];
for (i = 0; i < count; i++) {
s = [temp elementAt: i];
if (!strcmp (s, string)) {
[temp removeElementAt: i];
free (d->value);
d->value = [self convertListToString: temp];
[temp release];
break;
}
}
return self;
}
//
// Add string to keyword's value
//
- (id) addString: (const char *)string toValue: (const char *)key
{
char *newstr;
dict_t *d;
d = [self findKeyword: key];
if (d == NULL)
return NULL;
newstr = nva ("%s\t%s", d->value, string);
free (d->value);
d->value = newstr;
return self;
}
// ===============================================
//
// Use these for multiple parameters in a keyword value
//
// ===============================================
const char *searchStr;
char item[4096];
- (id) setupMultiple: (const char *)value
{
searchStr = value;
return self;
}
- (char *) getNextParameter
{
char *s;
if (!searchStr)
return NULL;
strcpy (item, searchStr);
s = FindWhitespcInBuffer (item);
if (!*s) {
searchStr = NULL;
} else {
*s = 0;
searchStr = FindNonwhitespcInBuffer (s + 1);
}
return item;
}
//
// Parses a keyvalue string & returns a Storage full of those items
//
- (id) parseMultipleFrom: (const char *)key
{
#define ITEMSIZE 128
id stuff;
char string[ITEMSIZE];
const char *s;
s = [self getStringFor: key];
if (s == NULL)
return NULL;
stuff = [[Storage alloc]
initCount: 0 elementSize: ITEMSIZE description: NULL];
[self setupMultiple: s];
while ((s = [self getNextParameter])) {
bzero (string, ITEMSIZE);
strcpy (string, s);
[stuff addElement: string];
}
return stuff;
}
// ===============================================
//
// Dictionary pair parsing
//
// ===============================================
//
// parse all keyword/value pairs within { } 's
//
- (id) parseBraceBlock: (FILE *)fp
{
int c;
dict_t pair;
char string[1024];
c = FindBrace (fp);
if (c == -1)
return NULL;
while ((c = FindBrace (fp)) != '}') {
if (c == -1)
return NULL;
#if 0
c = FindNonwhitespc (fp);
if (c == -1)
return NULL;
CopyUntilWhitespc (fp, string);
#endif
// JDC: fixed to allow quoted keys
c = FindNonwhitespc (fp);
if (c == -1)
return NULL;
c = fgetc (fp);
if (c == '\"') {
CopyUntilQuote (fp, string);
} else {
ungetc (c, fp);
CopyUntilWhitespc (fp, string);
}
pair.key = malloc (strlen (string) + 1);
strcpy (pair.key, string);
c = FindQuote (fp);
CopyUntilQuote (fp, string);
pair.value = malloc (strlen (string) + 1);
strcpy (pair.value, string);
[super addElement: &pair];
c = FindBrace (fp);
}
return self;
}
@end
// ===============================================
//
// C routines for string parsing
//
// ===============================================
int
GetNextChar (FILE * fp)
{
int c;
int c2;
c = getc (fp);
if (c == EOF)
return -1;
if (c == '/') { // parse comments
c2 = getc (fp);
if (c2 == '/') {
while ((c2 = getc (fp)) != '\n')
;
c = getc (fp);
} else {
ungetc (c2, fp);
}
}
return c;
}
void
CopyUntilWhitespc (FILE * fp, char *buffer)
{
int count = 800;
int c;
while (count--) {
c = GetNextChar (fp);
if (c == EOF)
return;
if (c <= ' ') {
*buffer = 0;
return;
}
*buffer++ = c;
}
}
void
CopyUntilQuote (FILE * fp, char *buffer)
{
int count = 800;
int c;
while (count--) {
c = GetNextChar (fp);
if (c == EOF)
return;
if (c == '\"') {
*buffer = 0;
return;
}
*buffer++ = c;
}
}
int
FindBrace (FILE * fp)
{
int count = 800;
int c;
while (count--) {
c = GetNextChar (fp);
if (c == EOF)
return -1;
if (c == '{' || c == '}')
return c;
}
return -1;
}
int
FindQuote (FILE * fp)
{
int count = 800;
int c;
while (count--) {
c = GetNextChar (fp);
if (c == EOF)
return -1;
if (c == '\"')
return c;
}
return -1;
}
int
FindWhitespc (FILE * fp)
{
int count = 800;
int c;
while (count--) {
c = GetNextChar (fp);
if (c == EOF)
return -1;
if (c <= ' ') {
ungetc (c, fp);
return c;
}
}
return -1;
}
int
FindNonwhitespc (FILE * fp)
{
int count = 800;
int c;
while (count--) {
c = GetNextChar (fp);
if (c == EOF)
return -1;
if (c > ' ') {
ungetc (c, fp);
return c;
}
}
return -1;
}
char *
FindWhitespcInBuffer (char *buffer)
{
int count = 1000;
char *b = buffer;
while (count--) {
if (*b <= ' ')
return b;
else
b++;
}
return NULL;
}
char *
FindNonwhitespcInBuffer (char *buffer)
{
int count = 1000;
char *b = buffer;
while (count--) {
if (*b > ' ')
return b;
else
b++;
}
return NULL;
}