//
// $Id: ContainerCoder.m,v 1.4 2005/05/18 06:46:52 will_mason Exp $
//
// vi: set ft=objc:

/*
 * ObjectiveLib - a library of containers and algorithms for Objective-C
 *
 * Copyright (c) 2004
 * Will Mason
 *
 * Portions:
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Copyright (c) 1996,1997
 * Silicon Graphics Computer Systems, Inc.
 *
 * Copyright (c) 1997
 * Moscow Center for SPARC Technology
 *
 * Copyright (c) 1999 
 * Boris Fomitchev
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * You may contact the author at will_mason@users.sourceforge.net.
 */

#import "ContainerCoder.h"
#import "Constants.h"
#import <Foundation/NSCoder.h>
#import <stddef.h>

@implementation OLContainerCoder

+ (OLAllocator*) decodeAllocatorWithCoder: (NSCoder*)decoder
{
    BOOL isDefaultAllocator;
    OLAllocator* alloc;

    if ([decoder respondsToSelector: @selector(allowsKeyedCoding)] &&
        [decoder allowsKeyedCoding])
    {
        alloc = [decoder decodeBoolForKey: IS_DEFAULT_ALLOCATOR_KEY] ?
            [OLAllocator defaultAllocator] :
            [decoder decodeObjectForKey: ALLOCATOR_KEY];
    }
    else
    {
        [decoder decodeValueOfObjCType: @encode(BOOL) at: &isDefaultAllocator];
        alloc = isDefaultAllocator ? [OLAllocator defaultAllocator] :
            [decoder decodeObject];
    }
    return alloc;
}

+ (id*) decodeWithCoder: (NSCoder*)decoder allocator: (OLAllocator*)alloc returnedCount: (unsigned*)rc
{
    id* array = NULL;
    unsigned i;

    if ([decoder respondsToSelector: @selector(allowsKeyedCoding)] &&
        [decoder allowsKeyedCoding])
    {
        *rc = [decoder decodeIntForKey: LENGTH_KEY];
    }
    else
    {
        [decoder decodeValueOfObjCType: @encode(unsigned) at: rc];
    }
    if (*rc != 0)
    {
        array = [alloc allocateBytes: *rc * sizeof(id)];
        for (i = 0; i < *rc; i++)
            array[i] = [decoder decodeObject];
    }
    return array;
}

+ (void) encodeAllocator: (OLAllocator*)alloc withCoder: (NSCoder*)encoder
{
    BOOL isDefaultAllocator = [alloc isEqual: [OLAllocator defaultAllocator]];

    if ([encoder respondsToSelector: @selector(allowsKeyedCoding)] &&
        [encoder allowsKeyedCoding])
    {
        [encoder encodeBool: isDefaultAllocator forKey: IS_DEFAULT_ALLOCATOR_KEY];
        if (!isDefaultAllocator)
            [encoder encodeObject: alloc forKey: ALLOCATOR_KEY];
    }
    else
    {
        [encoder encodeValueOfObjCType: @encode(BOOL) at: &isDefaultAllocator];
        if (!isDefaultAllocator)
            [encoder encodeObject: alloc];
    }
}

+ (void) encodeFrom: (OLForwardIterator*)first count: (unsigned)count withCoder: (NSCoder*)encoder allocator: (OLAllocator*)alloc
{
    unsigned i;

    if ([encoder respondsToSelector: @selector(allowsKeyedCoding)] &&
        [encoder allowsKeyedCoding])
    {
        [encoder encodeInt: count forKey: LENGTH_KEY];
    }
    else
    {
        [encoder encodeValueOfObjCType: @encode(unsigned) at: &count];
    }
    for (i = 0; i < count; i++, [first advance])
        [encoder encodeObject: [first dereference]];
}

@end
