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.