File:  [Apple Darwin 0.x] / objc / NXStringTable.m
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:13:57 2018 UTC (8 years, 2 months ago) by root
Branches: MAIN, Apple
CVS tags: HEAD, Darwin03, Darwin01
Darwin 0.1 In-kernel Objective-C runtime

/*
 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
 * Reserved.  This file contains Original Code and/or Modifications of
 * Original Code as defined in and that are subject to the Apple Public
 * Source License Version 1.0 (the 'License').  You may not use this file
 * except in compliance with the License.  Please obtain a copy of the
 * License at http://www.apple.com/publicsource and read it before using
 * this file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License."
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
/*
	NXStringTable.m
  	Copyright 1990 NeXT, Inc.
	Written by Bertrand Serlet, Jan 89
	Responsibility: Bertrand Serlet
*/

#ifndef KERNEL
#ifdef SHLIB
#import "shlib.h"
#endif SHLIB

#import <stdlib.h>
#import <stdio.h>
#import <string.h>
#import "NXStringTable.h"

@implementation NXStringTable
+ new {
    return [self newKeyDesc:"%" valueDesc:"*"];
}

- init {
    return [self initKeyDesc:"%" valueDesc:"*"];
}

static void noFree (void *item) {}
static void freeString(void *string) { free(string);}
- free {
    [self freeKeys:noFree values:freeString];
    return [super free];
}
    
- (const char *)valueForStringKey:(const char *)aString {
    return (const char *) [super valueForKey:NXUniqueString(aString)];
}

static int skipSpace(NXStream *stream) {
    /* return first significant character */
    int	ch;
    while ((ch = NXGetc(stream)) != EOF) {
	if ((ch != ' ') && (ch != '\n') && (ch != '\t')) return ch;
    }
    return ch;
}

static int parseWord(NXStream *stream, char *word) {
    /* return '"', that is read, or EOF */
    int	length = 0;
    int	ch;
    while (((ch = NXGetc(stream)) != EOF) && (ch != '"') && (length < MAX_NXSTRINGTABLE_LENGTH)) {
	word[length++] = ch;
	if (ch == '\\') {
	    switch (ch = NXGetc(stream)) {
		case 'a':	word[length-1] = '\a'; break;
		case 'b':	word[length-1] = '\b'; break;
		case 'f':	word[length-1] = '\f'; break;
		case 'n':	word[length-1] = '\n'; break;
		case 'r':	word[length-1] = '\r'; break;
		case 't':	word[length-1] = '\t'; break;
		case 'v':	word[length-1] = '\v'; break;
		case '"':	word[length-1] = '\"'; break;
		case EOF:	break;
		case '\'':	word[length-1] = '\''; break;
		case '?':	word[length-1] = '?'; break;
		case '\\':	word[length-1] = '\\'; break;
		case 'x':
		    {
		      unsigned char c2 = 0;
		      
		      while (1)
			{
			  ch = NXGetc (stream);
			  
			  if ('0' <= ch && ch <= '7')
			    c2 = (16 * c2) + (ch - '0');
			  else if ('a' <= ch && ch <= 'f')
			    c2 = (16 * c2) + (ch - 'a' + 0xa);
			  else if ('A' <= ch && ch <= 'F')
			    c2 = (16 * c2) + (ch - 'A' + 0xa);
			  else
			    {
			      NXUngetc (stream);
			      break;
			    }
			}
		      
		      word[length-1] = c2;
		      break;
		    }
		  
		default:
		  if ('0' <= ch && ch <= '7')
		    {
		      unsigned char c2 = ch - '0';
		      unsigned int i;
		      
		      for (i = 0; i < 2; i++)
			{
			  ch = NXGetc (stream);
			  
			  if ('0' <= ch && ch <= '7')
			    c2 = (8 * c2) + (ch - '0');
			  else
			    {
			      NXUngetc (stream);
			      break;
			    }
			}
		      
		      word[length-1] = c2;
		    }
		  else
		    /* unknown escape sequence */
		    word[length-1] = ch;
		  
		  break;
	    }
	}
    }
    word[length] = 0;
    return ch;
}

static void writeWord(NXStream *stream, const char *word) {
    int	ch;
    NXPutc(stream, '"');
    while ((ch = *(word++))) {
	switch (ch) {
	    case '\a':	NXPutc(stream, '\\'); NXPutc(stream, 'a'); break;
	    case '\b':	NXPutc(stream, '\\'); NXPutc(stream, 'b'); break;
	    case '\f':	NXPutc(stream, '\\'); NXPutc(stream, 'f'); break;
	    case '\n':	NXPutc(stream, '\\'); NXPutc(stream, 'n'); break;
	    case '\r':	NXPutc(stream, '\\'); NXPutc(stream, 'r'); break;
	    case '\t':	NXPutc(stream, '\\'); NXPutc(stream, 't'); break;
	    case '\v':	NXPutc(stream, '\\'); NXPutc(stream, 'v'); break;
	    case '\"':	NXPutc(stream, '\\'); NXPutc(stream, '"'); break;
	    case '\\':	NXPutc(stream, '\\'); NXPutc(stream, '\\'); break;
	    default: NXPutc(stream, ch);
	}
    }
    NXPutc(stream, '"');
}

    
- readFromStream:(NXStream *)stream {
    int	ch;
    NXZone *zone = [self zone];
    if (!stream) return nil;
    while ((ch = skipSpace(stream)) != EOF) {
	switch (ch) {
	    case '/':
		ch = NXGetc(stream);
	    	if (ch != '*') goto nope;
		while ((ch = NXGetc(stream)) != EOF) {
		    if (ch == '*') {
			ch = NXGetc(stream);
			if (ch == '/') break;
			NXUngetc(stream);
		    }
		}
		if (ch == EOF) goto nope;
		break;
	    case '"': {
		char	key[MAX_NXSTRINGTABLE_LENGTH+1];
		char	value[MAX_NXSTRINGTABLE_LENGTH+1];
		ch = parseWord(stream, key);
		if (ch != '"') goto nope;
		ch = skipSpace(stream);
		if (ch == '=') {
		    ch = skipSpace(stream);
		    if (ch != '"') goto nope;
		    ch = parseWord(stream, value);
		    if (ch != '"') goto nope;
		    ch = skipSpace(stream);
		} else {
		    strcpy(value, key);
		}
		if (ch != ';') goto nope;
		free([self insertKey:NXUniqueString(key) 
		    value:NXCopyStringBufferFromZone(value, zone)]);
		break;
	    }
	    default:	goto nope;
	}
    }
    return self;
  nope:
    {
        extern void _NXLogError(const char *format, ...);
        if (ch == EOF)
            _NXLogError ("NXStringTable: parse error before end of stream");
        else
            _NXLogError ("NXStringTable: parse error before '%c'", ch);
        return nil;
    }
}

- readFromFile:(const char *)fileName {
    NXStream	*stream = NXMapFile(fileName, NX_READONLY);
    id retval = [self readFromStream:stream];
    if (stream) NXCloseMemory(stream, NX_FREEBUFFER);
    return retval;
}

+ newFromStream:(NXStream *)stream {
    id	table;
    if (! stream) return nil;
    table = [self new];
    if (![table readFromStream:stream])
	table = [table free];
    return table;
}
    
+ newFromFile:(const char *)fileName {
    id	table;
    table = [self new];
    if (![table readFromFile:fileName])
	table = [table free];
    return table;
}

- writeToStream:(NXStream *)stream {
    NXHashState		state = [self initState];
    NXAtom		key;
    const char		*value;
    while ([self nextState:&state key:(const void **)&key value:(void **)&value]) {
	writeWord(stream, key);
	if (strcmp(key, value)) {
	    NXPrintf(stream, "\t= ");
	    writeWord(stream, value);
	}
	NXPrintf(stream, ";\n");
    }
    return self;
}
    
- writeToFile:(const char *)fileName {
    NXStream	*stream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
    int		res;
    [self writeToStream:stream];
    res = NXSaveToFile(stream, fileName);
    NXCloseMemory(stream, NX_FREEBUFFER);
    return (res) ? nil : self;
}

@end
#endif /* KERNEL */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.