// Copyright 1997-1999 Omni Development, Inc.  All rights reserved.
//
// This software may only be used and reproduced according to the
// terms in the file OmniSourceLicense.html, which should be
// distributed with this project and can also be found at
// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.

#import "NSString-OWSGMLString.h"

#import <Foundation/Foundation.h>
#import <OmniBase/OmniBase.h>
#import <OmniFoundation/OmniFoundation.h>

RCS_ID("$Header: /Network/Source/CVS/OmniGroup/Frameworks/OWF/Processors.subproj/SGML.subproj/NSString-OWSGMLString.m,v 1.8 1999/03/30 21:26:43 kc Exp $")

@interface NSString (OWSGMLStringPrivate)
+ (NSCharacterSet *)needsEscapeCharacterSet;
@end

@implementation NSString (OWSGMLString)

- (NSString *)stringWithEntitiesQuoted;
{
    OFDataBuffer dataBuffer;
    NSString *escapedString;

    if (![self rangeOfCharacterFromSet:[NSString needsEscapeCharacterSet]].length)
        return self;

    // Set up output buffer
    OFDataBufferInit(&dataBuffer);
    dataBuffer.byteOrder = NS_BigEndian;

    OFStringStartLoopThroughCharacters(self, ch) {
        switch (ch) {
            case '&':
                OFDataBufferAppendUnicodeString(&dataBuffer, @"&amp;");
                break;
            case '<':
                OFDataBufferAppendUnicodeString(&dataBuffer, @"&lt;");
                break;
            case '>':
                OFDataBufferAppendUnicodeString(&dataBuffer, @"&gt;");
                break;
            case '"': // a quote mark
                OFDataBufferAppendUnicodeString(&dataBuffer, @"&quot;");
                break;
            default:
                if (ch > 0x007f) {
                    // &#dddd;
                    OFDataBufferAppendUnicodeString(&dataBuffer, [NSString stringWithFormat:@"&#%d;", ch]);
                } else {
                    OFDataBufferAppendUnichar(&dataBuffer, ch);
                }
                break;
        }
    } OFStringEndLoopThroughCharacters;

    // Slurp data into string
    escapedString = [[NSString alloc] initWithData:OFDataBufferData(&dataBuffer) encoding:NSUnicodeStringEncoding];

    OFDataBufferRelease(&dataBuffer);

    return [escapedString autorelease];
}

// OWSGMLToken protocol

- (NSString *)htmlString;
{
    return [self stringWithEntitiesQuoted];
}

- (NSString *)string;
{
    return self;
}

- (OWSGMLTokenType)tokenType;
{
    return OWSGMLTokenTypeCData;
}

@end

@implementation NSString (OWSGMLStringPrivate)

+ (void)didLoad;
{
    // Ensure +needsEscapeCharacterSet gets set up before we go multithreaded, since then we'd have to deal with leaks or locks.
    [self needsEscapeCharacterSet];
}

+ (NSCharacterSet *)needsEscapeCharacterSet;
{
    static NSMutableCharacterSet *needsEscapeCharacterSet = nil;

    if (needsEscapeCharacterSet)
        return needsEscapeCharacterSet;

    needsEscapeCharacterSet = [[NSMutableCharacterSet alloc] init];
    [needsEscapeCharacterSet addCharactersInRange:NSMakeRange(0, 128)];
    [needsEscapeCharacterSet invert];
    [needsEscapeCharacterSet addCharactersInString:@"&<>\""];

    return needsEscapeCharacterSet;
}

@end
