/*
 **********************************************************************
 *   Copyright (C) 1998-1999, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
*
* File rbdata.cpp
*
* Modification History:
*
*   Date        Name        Description
*   06/11/99    stephen     Creation. (Moved here from resbund.cpp)
*******************************************************************************
*/

#include "rbdata.h"

UClassID StringList::fgClassID = 0; // Value is irrelevant
UClassID String2dList::fgClassID = 0; // Value is irrelevant
UClassID TaggedList::fgClassID = 0; // Value is irrelevant

//-----------------------------------------------------------------------------

StringList::StringList()
  : fCount(0), fStrings(0)
{}

StringList::StringList(UnicodeString *adopted, 
                       int32_t count) 
  : fCount(count), fStrings(adopted)
{}

StringList::~StringList() 
{ delete [] fStrings; }
  
const UnicodeString& 
StringList::operator[](int32_t i) const 
{ return fStrings[i]; }

UClassID 
StringList::getDynamicClassID() const 
{ return getStaticClassID(); }

UClassID 
StringList::getStaticClassID() 
{ return (UClassID)&fgClassID; }

//-----------------------------------------------------------------------------

String2dList::String2dList() 
  : fRowCount(0), fColCount(0), fStrings(0) 
{}
  
String2dList::String2dList(UnicodeString **adopted, 
                           int32_t rowCount, 
                           int32_t colCount) 
  : fRowCount(rowCount), fColCount(colCount), fStrings(adopted) 
{}

String2dList::~String2dList() 
{ 
  for(int32_t i = 0; i < fRowCount; ++i) {
    delete[] fStrings[i]; 
  }
  delete[] fStrings;
}
  
const UnicodeString& 
String2dList::getString(int32_t rowIndex, 
                        int32_t colIndex) 
{ return fStrings[rowIndex][colIndex]; }
  
UClassID 
String2dList::getDynamicClassID() const 
{ return getStaticClassID(); }

UClassID 
String2dList::getStaticClassID() 
{ return (UClassID)&fgClassID; }

//-----------------------------------------------------------------------------

TaggedList::TaggedList() {
    UErrorCode status = U_ZERO_ERROR;
    hash = new Hashtable(status);
    hash->setValueDeleter(uhash_deleteUnicodeString);
}
  
TaggedList::~TaggedList() {
    delete hash;
}

int32_t TaggedList::count() const {
    return hash->count();
}

void 
TaggedList::put(const UnicodeString& tag, 
                const UnicodeString& data) {
    UErrorCode status = U_ZERO_ERROR;
    hash->put(tag, new UnicodeString(data), status);
}

const UnicodeString* 
TaggedList::get(const UnicodeString& tag) const {
    return (const UnicodeString*) hash->get(tag);
}

UBool TaggedList::nextElement(const UnicodeString*& key,
                               const UnicodeString*& value,
                               int32_t& pos) const {
    const UHashElement *e = hash->nextElement(pos);
    if (e != NULL) {
        key   = (const UnicodeString*) e->key;
        value = (const UnicodeString*) e->value;
        return TRUE;
    } else {
        return FALSE;
    }
}

UClassID 
TaggedList::getDynamicClassID() const 
{ return getStaticClassID(); }

UClassID 
TaggedList::getStaticClassID() 
{ return (UClassID)&fgClassID; }
