This is MLParameters.m in view mode; [Download] [Up]
// Copyright (94) by melonSoft Ralf Suckow Berlin, All Rights Reserved #import "MLParameters.h" typedef struct { NXAtom name; const char * value; BOOL literal; } param_struct; static id template; @implementation MLParameters + initialize { if (self == [MLParameters class]) template = [[self alloc] init]; return self; } + template { return template; } + newFromStream:(NXStream *)stream syntaxOK:(BOOL *)flag { return [[self alloc] initFromStream:stream syntaxOK:flag]; } - init { return [super initCount:0 elementSize:sizeof (param_struct) description: // @encode (param_struct) gives the wrong result {?=**c}, better is: "{%*c}"]; } - initFromStream:(NXStream *)stream syntaxOK:(BOOL *)flag { [super init]; if ([self readFromStream:stream syntaxOK:flag]) return self; else return [self free]; } - copy { id newParameters; int i; param_struct * oldElement; param_struct newElement; newParameters = [[[self class] alloc] init]; for (i = 0; oldElement = [self elementAt:i]; i++) { newElement.name = oldElement->name; newElement.value = oldElement->value ? NXCopyStringBuffer (oldElement->value) : NULL; newElement.literal = oldElement->literal; [newParameters addElement:&newElement]; } return newParameters; } - initCount:(unsigned int)count elementSize:(unsigned int)sizeInBytes description:(const char *)string { // there is no choice of contents return [self init]; } - free { [self empty]; return [super free]; } - empty { char * value; int iterator = [self startParameterIteration]; while ([self next:&iterator parName:NULL value:(const char **)&value literal:NULL]) if (value) free (value); return [super empty]; } - (int)startParameterIteration { return 0; // using the index as iterator } - (BOOL)next:(int *)state parName:(NXAtom *)name value:(const char **)value literal:(BOOL *)flag { NXAtom dummyName; const char * dummyValue; BOOL dummyFlag; if (!name) name = &dummyName; if (!value) value = &dummyValue; if (!flag) flag = &dummyFlag; return [self getParName:name value:value literal:flag at:(*state)++]; } - (BOOL)getParName:(NXAtom *)name value:(const char **)value literal:(BOOL *)flag at:(int)index { param_struct * parp; parp = (param_struct *) [self elementAt:index]; if (parp == NULL) return NO; else { if (name) *name = parp->name; if (value) *value = parp->value; if (flag) *flag = parp->literal; return YES; } } - (param_struct *)_getElementFor:(NXAtom)name { int i; param_struct * parp; for (i = 0; parp = (param_struct *) [self elementAt:i]; i++) if (parp->name == name) return parp; return NULL; } - _setValue:(const char *)value forElement:(param_struct *)parp { if (parp->value) free ((char *)parp->value); if (value) value = NXCopyStringBuffer (value); parp->value = value; return self; } - (const char *)_stringFromDouble:(double)value; { // valid only until the next call static char stringValue[80]; sprintf (stringValue, "%.14g", value); return stringValue; } - (const char *)_stringFromInt:(int)value; { // valid only until the next call static char stringValue[80]; sprintf (stringValue, "%d", value); return stringValue; } - getValue:(const char **)value literal:(BOOL *)flag forParName:(NXAtom)name { param_struct * parp; if ((parp = [self _getElementFor:name]) == NULL) return nil; if (value) *value = parp->value; if (flag) *flag = parp->literal; return self; } - setPar:(NXAtom)name to:(const char *)val { param_struct * parp; if ((parp = [self _getElementFor:name]) == NULL) return nil; return [self _setValue:val forElement:parp]; } - setPar:(NXAtom)name toDouble:(double)val { return [self setPar:name to:[self _stringFromDouble:val]]; } - setPar:(NXAtom)name toInt:(int)val { return [self setPar:name to:[self _stringFromInt:val]]; } - (const char *)valueFor:(NXAtom)name { param_struct * parp; if ((parp = [self _getElementFor:name]) != NULL) return parp->value; else return NULL; } - (double)doubleValueFor:(NXAtom)name { const char * val; if (val = [self valueFor:name]) return atof (val); else return 0.0; } - (int)intValueFor:(NXAtom)name { const char * val; if (val = [self valueFor:name]) return atoi (val); else return 0; } - (BOOL)isLiteral:(NXAtom)name { param_struct * parp; if ((parp = [self _getElementFor:name]) != NULL) return parp->literal; else return NO; } - (BOOL)contains:(NXAtom)name { return ([self _getElementFor:name] != NULL); } - addPar:(NXAtom)name value:(const char *)value literal:(BOOL)flag { param_struct newp, * parp; if ((parp = [self _getElementFor:name]) != NULL) { [self _setValue:value forElement:parp]; parp->literal = flag; } else { newp.name = name; newp.value = NULL; [self _setValue:value forElement:&newp]; newp.literal = flag; [self addElement:&newp]; } return self; } - addPar:(NXAtom)name doubleValue:(double)value literal:(BOOL)flag { return [self addPar:name value:[self _stringFromDouble:value] literal:flag]; } - addPar:(NXAtom)name intValue:(int)value literal:(BOOL)flag { return [self addPar:name value:[self _stringFromInt:value] literal:flag]; } - addPar:(NXAtom)name literal:(const char *)val { return [self addPar:name value:val literal:YES]; } - addPar:(NXAtom)name mathValue:(const char *)val { return [self addPar:name value:val literal:NO]; } - addPar:(NXAtom)name mathDoubleValue:(double)val { return [self addPar:name doubleValue:val literal:NO]; } - addParametersFrom:otherParameters { int state; NXAtom name; const char * val; BOOL flag; state = [otherParameters startParameterIteration]; while ([otherParameters next:&state parName:&name value:&val literal:&flag]) [self addPar:name value:val literal:flag]; return self; } - (NXAtom)atomForPar:(const char *)name value:(const char *)value literal:(BOOL)flag { NXAtom atom; if (name && *name) { atom = NXUniqueString (name); [self addPar:atom value:value literal:flag]; return atom; } else return NULL; } - takePar:(NXAtom)name from:parameters { const char * value; BOOL flag; if (![parameters getValue:&value literal:&flag forParName:name]) return nil; return [self addPar:name value:value literal:flag]; } - removeElementAt:(int)index { param_struct * parp; if (parp = (param_struct *) [self elementAt:index]) { if (parp->value) free ((char *)parp->value); [super removeElementAt:index]; } return self; } - removePar:(NXAtom)name { int i; param_struct * parp; for (i = 0; parp = (param_struct *) [self elementAt:i]; i++) if (parp->name == name) { [self removeElementAt:i]; break; } return self; } - (BOOL)isEqual:otherList { int i; param_struct * parp; const char * value; BOOL flag; if (!otherList || ![otherList isKindOf:[MLParameters class]]) return NO; if ([self count] != [otherList count]) return NO; for (i = 0; parp = [self elementAt:i]; i++) { if (![otherList getValue:&value literal:&flag forParName:parp->name]) return NO; if ((value == NULL) != (parp->value == NULL)) return NO; if (value && strcmp (value, parp->value) != 0) return NO; if (flag != parp->literal) return NO; } return YES; } // PARSING a note from a stream: { pname = ["]<expression>["] ; ... ; } // end of file not expected #define MAXIDENT 1000 #define GETC(c, x) if ((c = NXGetc (x)) == EOF) goto end_of_file #define SKIP_SPACES(c, x) while (NXIsSpace (c)) GETC (c, x) #define GET_NONSPACE_C(c, x) GETC(c, x); while (NXIsSpace (c)) GETC (c, x) - readFromStream:(NXStream *)stream syntaxOK:(BOOL *)flag { unsigned int c; char token[MAXIDENT + 1]; int index; NXAtom name; BOOL literal; BOOL inside; inside = NO; GET_NONSPACE_C (c, stream); if (c != '{') goto syntax_error; // { inside = YES; again: GET_NONSPACE_C (c, stream); if (c == '}') goto success; // } index = 0; while (NXIsAlNum (c) && index < MAXIDENT) { // pname token[index++] = c; GETC (c, stream); } if (index == MAXIDENT) goto syntax_error; token [index] = '\0'; name = NXUniqueString (token); SKIP_SPACES (c, stream); if (c != '=') goto syntax_error; // = GET_NONSPACE_C (c, stream); if (c == '"') { // "... literal = YES; index = 0; GETC (c, stream); while (index < MAXIDENT && c != '"') { // ..." token[index++] = c; // expression GETC (c, stream); } if (index == MAXIDENT) goto syntax_error; token [index] = '\0'; GET_NONSPACE_C (c, stream); if (c != ';') goto syntax_error; // ; } else { // expression; literal = NO; index = 0; while (index < MAXIDENT && c != ';') { token[index++] = c; GETC (c, stream); } if (index == MAXIDENT) goto syntax_error; token [index] = '\0'; } [self addPar:name value:token literal:literal]; goto again; success: *flag = YES; return self; end_of_file: if (inside) *flag = NO; else *flag = YES; return nil; syntax_error: *flag = NO; return nil; } - readFromMathString:(const char *)string syntaxOK:(BOOL *)flag { NXStream * stream; id result; // we are doing it a bit tricky if (!string || !*string) { // it's empty but OK *flag = YES; return self; } if ((stream = NXOpenMemory (NULL, 0, NX_READWRITE)) == NULL) { *flag = YES; return nil; } NXPrintf (stream, "{\n"); NXWrite (stream, string, strlen (string)); NXPrintf (stream, "}\n"); NXSeek (stream, 0, NX_FROMSTART); result = [self readFromStream:stream syntaxOK:flag]; NXCloseMemory (stream, NX_FREEBUFFER); return result; } - writeToStream:(NXStream *)stream { NXPrintf (stream, "{\n"); [self writeMathToStream:stream]; NXPrintf (stream, "}\n"); return self; } - writeMathToStream:(NXStream *)stream { int i; param_struct * parp; for (i = 0; i < [self count]; i++) if (parp = (param_struct *) [self elementAt:i]) if (parp->literal) NXPrintf (stream, " %s = \"%s\";\n", parp->name, (parp->value ? parp->value : "")); else NXPrintf (stream, " %s = %s;\n", parp->name, (parp->value ? parp->value : "0")); return self; } - (char *)getMathString { NXStream * inputParameters; const char * buf; int len, maxlen; char * string; inputParameters = NXOpenMemory (NULL, 0, NX_READWRITE); [self writeMathToStream:inputParameters]; NXPutc (inputParameters, '\0'); NXSeek (inputParameters, 0, NX_FROMSTART); NXGetMemoryBuffer (inputParameters, &buf, &len, &maxlen); string = malloc (len); strcpy (string, buf); NXCloseMemory (inputParameters, NX_FREEBUFFER); return string; } // methods of the NXTransport protocol - encodeUsing:(id <NXEncoding>)portal { int i; param_struct * element; i = [self count]; [portal encodeData:&i ofType:"i"]; for (i = 0; element = [self elementAt:i]; i++) [portal encodeData:element ofType:"{?=%*c}"]; // @encode (param_struct)]; return self; } - decodeUsing:(id <NXDecoding>)portal { int i, n; param_struct element; [portal decodeData:&n ofType:"i"]; [super initCount:n elementSize:sizeof (param_struct) description:"{%*c}"]; // @encode(param_struct)]; for (i = 0; i < n; i++) { [portal decodeData:&element ofType:"{?=%*c}"]; // @encode (param_struct)]; [self addElement:&element]; } return self; } - encodeRemotelyFor:(NXConnection *)connection freeAfterEncoding:(BOOL *)flagp isBycopy:(BOOL)isBycopy { if (isBycopy) return self; return [super encodeRemotelyFor:connection freeAfterEncoding:flagp isBycopy:isBycopy]; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.