[sword-cvs] icu-sword/source/test/intltest .cvsignore,1.2,1.3 Makefile.in,1.3,1.4 allcoll.cpp,1.2,1.3 allcoll.h,1.2,1.3 apicoll.cpp,1.2,1.3 apicoll.h,1.2,1.3 callimts.cpp,1.2,1.3 callimts.h,1.2,1.3 calregts.cpp,1.2,1.3 calregts.h,1.2,1.3 caltest.cpp,1.2,1.3 caltest.h,1.2,1.3 caltztst.cpp,1.2,1.3 caltztst.h,1.2,1.3 canittst.cpp,NONE,1.1 canittst.h,NONE,1.1 citrtest.cpp,1.3,1.4 citrtest.h,1.2,1.3 cntabcol.cpp,1.2,1.3 cntabcol.h,1.2,1.3 cpdtrtst.cpp,1.3,1.4 cpdtrtst.h,1.2,1.3 cpputils.cpp,1.2,1.3 cpputils.h,1.2,1.3 cputilst.cpp,1.2,1.3 cputilst.h,1.2,1.3 currcoll.cpp,1.2,1.3 currcoll.h,1.2,1.3 dacoll.cpp,1.2,1.3 dacoll.h,1.2,1.3 dadrcoll.cpp,NONE,1.1 dadrcoll.h,NONE,1.1 datamap.cpp,NONE,1.1 datamap.h,NONE,1.1 dcfmapts.cpp,1.2,1.3 dcfmapts.h,1.2,1.3 decoll.cpp,1.2,1.3 decoll.h,1.2,1.3 dtfmapts.cpp,1.2,1.3 dtfmapts.h,1.2,1.3 dtfmrgts.cpp,1.2,1.3 dtfmrgts.h,1.2,1.3 dtfmtrtts.cpp,1.2,1.3 dtfmtrtts.h,1.2,1.3 dtfmttst.cpp,1.2,1.3 dtfmttst.h,1.2,1.3 encoll.cpp,1.2,1.3 encoll.h,1.2,1.3 escoll.cpp,1.2,1.3 escoll.h,1.2,1.3 ficoll.cpp,1.2,1.3 ficoll.h,1.2,1.3 frcoll.cpp,1.2,1.3 frcoll.h,1.2,1.3 g7coll.cpp,1.2,1.3 g7coll.h,1.2,1.3 hxuntrts.cpp,1.2,1.3 hxuntrts.h,1.2,1.3 icusvtst.cpp,NONE,1.1 icusvtst.h,NONE,1.1 idnaref.cpp,NONE,1.1 idnaref.h,NONE,1.1 incaltst.cpp,NONE,1.1 incaltst.h,NONE,1.1 intltest.cpp,1.4,1.5 intltest.dsp,1.3,1.4 intltest.h,1.2,1.3 intltest.vcproj,NONE,1.1 itercoll.cpp,1.3,1.4 itercoll.h,1.2,1.3 itformat.cpp,1.3,1.4 itformat.h,1.2,1.3 itmajor.cpp,1.2,1.3 itmajor.h,1.2,1.3 itrbbi.cpp,1.2,1.3 itrbbi.h,1.2,1.3 itrbnf.cpp,1.4,1.5 itrbnf.h,1.3,1.4 itrbnfrt.cpp,1.2,1.3 itrbnfrt.h,1.2,1.3 ittrans.cpp,1.3,1.4 ittrans.h,1.2,1.3 itutil.cpp,1.2,1.3 itutil.h,1.2,1.3 jacoll.cpp,1.3,1.4 jacoll.h,1.2,1.3 jamotest.cpp,1.3,1.4 jamotest.h,1.2,1.3 lcukocol.cpp,1.2,1.3 lcukocol.h,1.2,1.3 loctest.cpp,1.3,1.4 loctest.h,1.2,1.3 miscdtfm.cpp,1.4,1.5 miscdtfm.h,1.2,1.3 mnkytst.cpp,1.2,1.3 mnkytst.h,1.2,1.3 msfmrgts.cpp,1.2,1.3 msfmrgts.h,1.2,1.3 nmfmapts.cpp,1.2,1.3 nmfmapts.h,1.2,1.3 nmfmtrt.cpp,1.3,1.4 nmfmtrt.h,1.2,1.3 normconf.cpp

sword@www.crosswire.org sword@www.crosswire.org
Tue, 9 Sep 2003 19:43:46 -0700


Update of /usr/local/cvsroot/icu-sword/source/test/intltest
In directory www:/tmp/cvs-serv19862/source/test/intltest

Added Files:
	.cvsignore Makefile.in allcoll.cpp allcoll.h apicoll.cpp 
	apicoll.h callimts.cpp callimts.h calregts.cpp calregts.h 
	caltest.cpp caltest.h caltztst.cpp caltztst.h canittst.cpp 
	canittst.h citrtest.cpp citrtest.h cntabcol.cpp cntabcol.h 
	cpdtrtst.cpp cpdtrtst.h cpputils.cpp cpputils.h cputilst.cpp 
	cputilst.h currcoll.cpp currcoll.h dacoll.cpp dacoll.h 
	dadrcoll.cpp dadrcoll.h datamap.cpp datamap.h dcfmapts.cpp 
	dcfmapts.h decoll.cpp decoll.h dtfmapts.cpp dtfmapts.h 
	dtfmrgts.cpp dtfmrgts.h dtfmtrtts.cpp dtfmtrtts.h dtfmttst.cpp 
	dtfmttst.h encoll.cpp encoll.h escoll.cpp escoll.h ficoll.cpp 
	ficoll.h frcoll.cpp frcoll.h g7coll.cpp g7coll.h hxuntrts.cpp 
	hxuntrts.h icusvtst.cpp icusvtst.h idnaref.cpp idnaref.h 
	incaltst.cpp incaltst.h intltest.cpp intltest.dsp intltest.h 
	intltest.vcproj itercoll.cpp itercoll.h itformat.cpp 
	itformat.h itmajor.cpp itmajor.h itrbbi.cpp itrbbi.h 
	itrbnf.cpp itrbnf.h itrbnfrt.cpp itrbnfrt.h ittrans.cpp 
	ittrans.h itutil.cpp itutil.h jacoll.cpp jacoll.h jamotest.cpp 
	jamotest.h lcukocol.cpp lcukocol.h loctest.cpp loctest.h 
	miscdtfm.cpp miscdtfm.h mnkytst.cpp mnkytst.h msfmrgts.cpp 
	msfmrgts.h nmfmapts.cpp nmfmapts.h nmfmtrt.cpp nmfmtrt.h 
	normconf.cpp normconf.h nptrans.cpp nptrans.h numfmtst.cpp 
	numfmtst.h numrgts.cpp numrgts.h pptest.cpp pptest.h punyref.c 
	punyref.h rbbiapts.cpp rbbiapts.h rbbitst.cpp rbbitst.h 
	regcoll.cpp regcoll.h regextst.cpp regextst.h reptest.cpp 
	reptest.h restest.cpp restest.h restsnew.cpp restsnew.h 
	sdtfmtts.cpp sdtfmtts.h sfwdchit.cpp sfwdchit.h srchtest.cpp 
	srchtest.h strcase.cpp strtest.cpp strtest.h svccoll.cpp 
	svccoll.h tchcfmt.cpp tchcfmt.h testdata.cpp testdata.h 
	testidn.cpp testidna.cpp testidna.h testutil.cpp testutil.h 
	tfsmalls.cpp tfsmalls.h thcoll.cpp thcoll.h tmsgfmt.cpp 
	tmsgfmt.h transapi.cpp transapi.h transrt.cpp transrt.h 
	transtst.cpp transtst.h trcoll.cpp trcoll.h trnserr.cpp 
	trnserr.h tscoll.cpp tscoll.h tsdate.cpp tsdate.h tsdcfmsy.cpp 
	tsdcfmsy.h tsdtfmsy.cpp tsdtfmsy.h tsmthred.cpp tsmthred.h 
	tsmutex.cpp tsmutex.h tsnmfmt.cpp tsnmfmt.h tsputil.cpp 
	tsputil.h tstdtmod.cpp tstdtmod.h tstnorm.cpp tstnorm.h 
	tstnrapi.cpp tzbdtest.cpp tzbdtest.h tzregts.cpp tzregts.h 
	tztest.cpp tztest.h ucaconf.cpp ucaconf.h ucdtest.cpp 
	ucdtest.h ufltlgts.cpp ufltlgts.h unhxtrts.cpp unhxtrts.h 
	uobjtest.cpp uobjtest.h usettest.cpp usettest.h ustrtest.cpp 
	ustrtest.h 
Log Message:
ICU 2.6 commit















--- NEW FILE: canittst.cpp ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 2002-2003, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************
 *
 * @author Mark E. Davis
 * @author Vladimir Weinstein
 */

#include "unicode/utypes.h"

#if !UCONFIG_NO_NORMALIZATION

#include "intltest.h"
#include "cstring.h"
#include "canittst.h"
#include "unicode/caniter.h"
#include "unicode/uchar.h"

#define ARRAY_LENGTH(array) ((int32_t)(sizeof (array) / sizeof (*array)))

#define CASE(id,test) case id:                          \
                          name = #test;                 \
                          if (exec) {                   \
                              logln(#test "---");       \
                              logln((UnicodeString)""); \
                              test();                   \
                          }                             \
                          break

void CanonicalIteratorTest::runIndexedTest(int32_t index, UBool exec,
                                         const char* &name, char* /*par*/) {
    switch (index) {
        CASE(0, TestBasic);
        CASE(1, TestExhaustive);
        CASE(2, TestAPI);
      default: name = ""; break;
    }
}

/**
 * Convert Java-style strings with \u Unicode escapes into UnicodeString objects
static UnicodeString str(const char *input)
{
    UnicodeString str(input, ""); // Invariant conversion
    return str.unescape();
}
 */


CanonicalIteratorTest::CanonicalIteratorTest() :
nameTrans(NULL), hexTrans(NULL)
{
}

CanonicalIteratorTest::~CanonicalIteratorTest()
{
#if !UCONFIG_NO_TRANSLITERATION
  if(nameTrans != NULL) {
    delete(nameTrans);
  }
  if(hexTrans != NULL) {
    delete(hexTrans);
  }
#endif
}

void CanonicalIteratorTest::TestExhaustive() {
    UErrorCode status = U_ZERO_ERROR;
    CanonicalIterator it("", status);
    UChar32 i = 0;
    UnicodeString s, decomp, comp;
	// Test static and dynamic class IDs
    if(it.getDynamicClassID() != CanonicalIterator::getStaticClassID()){
		errln("CanonicalIterator::getStaticClassId ! = CanonicalIterator.getDynamicClassID");
	}
    for (i = 0; i < 0x10FFFF; quick?i+=0x10:++i) {
        //for (i = 0xae00; i < 0xaf00; ++i) {
        
        if ((i % 0x100) == 0) {
            logln("Testing U+%06X", i);
        }
        
        // skip characters we know don't have decomps
        int8_t type = u_charType(i);
        if (type == U_UNASSIGNED || type == U_PRIVATE_USE_CHAR
            || type == U_SURROGATE) continue;
        
        s = i;
        s += (UChar32)0x0345; //"\\u0345";
        
        Normalizer::decompose(s, FALSE, 0, decomp, status);
        Normalizer::compose(s, FALSE, 0, comp, status);
        
        // skip characters that don't have either decomp.
        // need quick test for this!
        if (s == decomp && s == comp) {
            continue;
        }
        
        it.setSource(s, status);
        UBool gotDecomp = FALSE;
        UBool gotComp = FALSE;
        UBool gotSource = FALSE;
        
        while (TRUE) {
            UnicodeString item = it.next();
            if (item.isBogus()) break;
            if (item == s) gotSource = TRUE;
            if (item == decomp) gotDecomp = TRUE;
            if (item == comp) gotComp = TRUE;
        }
        
        if (!gotSource || !gotDecomp || !gotComp) {
            errln("FAIL CanonicalIterator: " + s + (int)i);
        }
    }
}

void CanonicalIteratorTest::TestBasic() {

    UErrorCode status = U_ZERO_ERROR;

    static const char * const testArray[][2] = {
        {"\\u00C5d\\u0307\\u0327", "A\\u030Ad\\u0307\\u0327, A\\u030Ad\\u0327\\u0307, A\\u030A\\u1E0B\\u0327, "
            "A\\u030A\\u1E11\\u0307, \\u00C5d\\u0307\\u0327, \\u00C5d\\u0327\\u0307, "
            "\\u00C5\\u1E0B\\u0327, \\u00C5\\u1E11\\u0307, \\u212Bd\\u0307\\u0327, "
            "\\u212Bd\\u0327\\u0307, \\u212B\\u1E0B\\u0327, \\u212B\\u1E11\\u0307"},
        {"\\u010d\\u017E", "c\\u030Cz\\u030C, c\\u030C\\u017E, \\u010Dz\\u030C, \\u010D\\u017E"},
        {"x\\u0307\\u0327", "x\\u0307\\u0327, x\\u0327\\u0307, \\u1E8B\\u0327"},
    };
    
#if 0
    // This is not interesting for C/C++ as the data is already built beforehand
    // check build
    UnicodeSet ss = CanonicalIterator.getSafeStart();
    logln("Safe Start: " + ss.toPattern(true));
    ss = CanonicalIterator.getStarts('a');
    expectEqual("Characters with 'a' at the start of their decomposition: ", "", CanonicalIterator.getStarts('a'),
        new UnicodeSet("[\u00E0-\u00E5\u0101\u0103\u0105\u01CE\u01DF\u01E1\u01FB"
        + "\u0201\u0203\u0227\u1E01\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7]")
            );
#endif

    // check permute
    // NOTE: we use a TreeSet below to sort the output, which is not guaranteed to be sorted!

    Hashtable *permutations = new Hashtable(FALSE, status);
    permutations->setValueDeleter(uhash_deleteUnicodeString);
    UnicodeString toPermute("ABC");

    CanonicalIterator::permute(toPermute, FALSE, permutations, status);

    logln("testing permutation");
  
    expectEqual("Simple permutation ", "", collectionToString(permutations), "ABC, ACB, BAC, BCA, CAB, CBA");

    delete permutations;
    
    // try samples
    logln("testing samples");
    Hashtable *set = new Hashtable(FALSE, status);
    set->setValueDeleter(uhash_deleteUnicodeString);
    int32_t i = 0;
    CanonicalIterator it("", status);
    if(U_SUCCESS(status)) {
      for (i = 0; i < ARRAY_LENGTH(testArray); ++i) {
          //logln("Results for: " + name.transliterate(testArray[i]));
          UnicodeString testStr = CharsToUnicodeString(testArray[i][0]);
          it.setSource(testStr, status);
          set->removeAll();
          while (TRUE) {
              //UnicodeString *result = new UnicodeString(it.next());
              UnicodeString result(it.next());
              if (result.isBogus()) {
                  break;
              }
              set->put(result, new UnicodeString(result), status); // Add result to the table
              //logln(++counter + ": " + hex.transliterate(result));
              //logln(" = " + name.transliterate(result));
          }
          expectEqual(i + ": ", testStr, collectionToString(set), CharsToUnicodeString(testArray[i][1]));

      }
    } else {
      errln("Couldn't instantiate canonical iterator. Error: %s", u_errorName(status));
    }
    delete set;
}

void CanonicalIteratorTest::expectEqual(const UnicodeString &message, const UnicodeString &item, const UnicodeString &a, const UnicodeString &b) {
    if (!(a==b)) {
        errln("FAIL: " + message + getReadable(item));
        errln("\t" + getReadable(a));
        errln("\t" + getReadable(b));
    } else {
        logln("Checked: " + message + getReadable(item));
        logln("\t" + getReadable(a));
        logln("\t" + getReadable(b));
    }
}

UnicodeString CanonicalIteratorTest::getReadable(const UnicodeString &s) {
  UErrorCode status = U_ZERO_ERROR;
  UnicodeString result = "[";
    if (s.length() == 0) return "";
    // set up for readable display
#if !UCONFIG_NO_TRANSLITERATION
    if(verbose) {
      if (nameTrans == NULL)
          nameTrans = Transliterator::createInstance("[^\\ -\\u007F] name", UTRANS_FORWARD, status);
      UnicodeString sName = s;
      nameTrans->transliterate(sName);
      result += sName;
      result += ";";
    }
    if (hexTrans == NULL)
        hexTrans = Transliterator::createInstance("[^\\ -\\u007F] hex", UTRANS_FORWARD, status);
#endif
    UnicodeString sHex = s;
#if !UCONFIG_NO_TRANSLITERATION
    if(hexTrans) { // maybe there is no data and transliterator cannot be instantiated
      hexTrans->transliterate(sHex);
    }
#endif
    result += sHex;
    result += "]";
    return result;
    //return "[" + (verbose ? name->transliterate(s) + "; " : "") + hex->transliterate(s) + "]";
}

U_CAPI int compareUnicodeStrings(const void *s1, const void *s2) {
  UnicodeString **st1 = (UnicodeString **)s1;
  UnicodeString **st2 = (UnicodeString **)s2;

  return (*st1)->compare(**st2);
}


UnicodeString CanonicalIteratorTest::collectionToString(Hashtable *col) {
    UnicodeString result;

    // Iterate over the Hashtable, then qsort.

    UnicodeString **resArray = new UnicodeString*[col->count()];
    int32_t i = 0;

    const UHashElement *ne = NULL;
    int32_t el = -1;
    //Iterator it = basic.iterator();
    ne = col->nextElement(el);
    //while (it.hasNext()) 
    while (ne != NULL) {
      //String item = (String) it.next();
      UnicodeString *item = (UnicodeString *)(ne->value.pointer);
      resArray[i++] = item;
      ne = col->nextElement(el);
    }

    for(i = 0; i<col->count(); ++i) {
      logln(*resArray[i]);
    }

    qsort(resArray, col->count(), sizeof(UnicodeString *), compareUnicodeStrings);

    result = *resArray[0];

    for(i = 1; i<col->count(); ++i) {
      result += ", ";
      result += *resArray[i];
    }

/*
    Iterator it = col.iterator();
    while (it.hasNext()) {
        if (result.length() != 0) result.append(", ");
        result.append(it.next().toString());
    }
*/

    delete [] resArray;

    return result;
}

void CanonicalIteratorTest::TestAPI() {
  UErrorCode status = U_ZERO_ERROR;
  // Test reset and getSource
  UnicodeString start("ljubav");
  logln("Testing CanonicalIterator::getSource");
  logln("Instantiating canonical iterator with string "+start);
  CanonicalIterator can(start, status);
  UnicodeString source = can.getSource();
  logln("CanonicalIterator::getSource returned "+source);
  if(start != source) {
    errln("CanonicalIterator.getSource() didn't return the starting string. Expected "+start+", got "+source);
  }
  logln("Testing CanonicalIterator::reset");
  UnicodeString next = can.next();
  logln("CanonicalIterator::next returned "+next);

  can.reset();

  UnicodeString afterReset = can.next();
  logln("After reset, CanonicalIterator::next returned "+afterReset);

  if(next != afterReset) {
    errln("Next after instantiation ("+next+") is different from next after reset ("+afterReset+").");
  }
  
  logln("Testing getStaticClassID and getDynamicClassID");
  if(can.getDynamicClassID() != CanonicalIterator::getStaticClassID()){
      errln("RTTI failed for CanonicalIterator getDynamicClassID != getStaticClassID");
  }
}

#endif /* #if !UCONFIG_NO_NORMALIZATION */

--- NEW FILE: canittst.h ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 2002-2003, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************
 *
 * @author Mark E. Davis
 * @author Vladimir Weinstein
 */

/**
 * Test Canonical Iterator
 */

#ifndef _CANITTST
#define _CANITTST

#include "unicode/utypes.h"

#if !UCONFIG_NO_NORMALIZATION


U_NAMESPACE_BEGIN

class Transliterator;

U_NAMESPACE_END

#include "unicode/normlzr.h"
#include "unicode/translit.h"
#include "intltest.h"
#include "hash.h"

class CanonicalIteratorTest : public IntlTest {
public:
    CanonicalIteratorTest();
    virtual ~CanonicalIteratorTest();

    void runIndexedTest( int32_t index, UBool exec, const char* &name, char* par = NULL );

    void TestCanonicalIterator(void);
    void TestExhaustive(void);
    void TestBasic();
    void TestAPI();
    UnicodeString collectionToString(Hashtable *col);
    //static UnicodeString collectionToString(Collection col);
private:
    void expectEqual(const UnicodeString &message, const UnicodeString &item, const UnicodeString &a, const UnicodeString &b);

    Transliterator *nameTrans;
    Transliterator *hexTrans;
        
    UnicodeString getReadable(const UnicodeString &obj);
};

#endif /* #if !UCONFIG_NO_NORMALIZATION */

#endif // _CANITTST















--- NEW FILE: dadrcoll.cpp ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 1997-2003, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

/**
 * IntlTestCollator is the medium level test class for everything in the directory "collate".
 */

/***********************************************************************
* Modification history
* Date        Name        Description
* 02/14/2001  synwee      Compare with cintltst and commented away tests 
*                         that are not run.
***********************************************************************/

#include "unicode/utypes.h"

#if !UCONFIG_NO_COLLATION

#include "unicode/uchar.h"

#include "cstring.h"
#include "ucol_tok.h"

#include "tscoll.h"

#include "dadrcoll.h"

U_CDECL_BEGIN
static void U_CALLCONV deleteSeqElement(void *elem) {
  delete((SeqElement *)elem);
}
U_CDECL_END

DataDrivenCollatorTest::DataDrivenCollatorTest() 
: seq(StringCharacterIterator("")),
status(U_ZERO_ERROR),
sequences(status)
{
  TestLog testLog;

  driver = TestDataModule::getTestDataModule("DataDrivenCollationTest", testLog, status);
  sequences.setDeleter(deleteSeqElement);
}

DataDrivenCollatorTest::~DataDrivenCollatorTest() 
{
  delete driver;
}

void DataDrivenCollatorTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par */)
{
  if(driver != NULL) {
    if (exec)
    {
        logln("TestSuite Collator: ");
    }
    const DataMap *info = NULL;
    TestData *testData = driver->createTestData(index, status);
    if(U_SUCCESS(status)) {
      name = testData->getName();
      if(testData->getInfo(info, status)) {
        log(info->getString("Description", status));
      }
      if(exec) {
        log(name);
          logln("---");
          logln("");
          processTest(testData);
      }
      delete testData;
    } else {
      name = "";
    }
  } else {
    errln("collate/DataDrivenTest data not initialized!");
    name = "";
  }


}

UBool
DataDrivenCollatorTest::setTestSequence(const UnicodeString &setSequence, SeqElement &el) {
  seq.setText(setSequence);
  return getNextInSequence(el);
}

// Parses the sequence to be tested
UBool 
DataDrivenCollatorTest::getNextInSequence(SeqElement &el) {
  el.source.truncate(0);
  UBool quoted = FALSE;
  UBool quotedsingle = FALSE;
  UChar32 currChar = 0;

  while(currChar != CharacterIterator::DONE) {
    currChar= seq.next32PostInc();
    if(!quoted) {
      if(u_isWhitespace(currChar)) {
        continue;
      }
      switch(currChar) {
      case CharacterIterator::DONE:
        break;
      case 0x003C /* < */:
        el.relation = Collator::LESS;
        currChar = CharacterIterator::DONE;
        break;
      case 0x003D /* = */:
        el.relation = Collator::EQUAL;
        currChar = CharacterIterator::DONE;
        break;
      case 0x003E /* > */:
        el.relation = Collator::GREATER;
        currChar = CharacterIterator::DONE;
        break;
      case 0x0027 /* ' */: /* very basic quoting */
        quoted = TRUE;
        quotedsingle = FALSE;
        break;
      case 0x005c /* \ */: /* single quote */
        quoted = TRUE;
        quotedsingle = TRUE;
        break;
      default:
        el.source.append(currChar);
      }
    } else {
      if(currChar == CharacterIterator::DONE) {
        status = U_ILLEGAL_ARGUMENT_ERROR;
        errln("Quote in sequence not closed!");
        return FALSE;
      } else if(currChar == 0x0027) {
        quoted = FALSE;
      } else {
        el.source.append(currChar);
      }
      if(quotedsingle) {
        quoted = FALSE;
      }
    }
  }
  return seq.hasNext();
}

// Reads the options string and sets appropriate attributes in collator
void 
DataDrivenCollatorTest::processArguments(Collator *col, const UChar *start, int32_t optLen) {
  const UChar *end = start+optLen;
  UColAttribute attrib;
  UColAttributeValue value;

  if(optLen == 0) {
    return;
  }

  start = ucol_tok_getNextArgument(start, end, &attrib, &value, &status);
  while(start != NULL) {
    if(U_SUCCESS(status)) {
      col->setAttribute(attrib, value, status);
    }
    start = ucol_tok_getNextArgument(start, end, &attrib, &value, &status);
  }
}

void 
DataDrivenCollatorTest::processTest(TestData *testData) {
  Collator *col = NULL;
  const UChar *arguments = NULL;
  int32_t argLen = 0;
  const DataMap *settings = NULL;
  const DataMap *currentCase = NULL;
  UErrorCode intStatus = U_ZERO_ERROR;
  UnicodeString testSetting;
  while(testData->nextSettings(settings, status)) {
    intStatus = U_ZERO_ERROR;
    // try to get a locale
    testSetting = settings->getString("TestLocale", intStatus);
    if(U_SUCCESS(intStatus)) {
      char localeName[256];
      testSetting.extract(0, testSetting.length(), localeName, "");
      col = Collator::createInstance(localeName, status);
      if(U_SUCCESS(status)) {
        logln("Testing collator for locale "+testSetting);
      } else {
        errln("Unable to instantiate collator for locale "+testSetting);
        return;
      }
    } else {
      // if no locale, try from rules
      intStatus = U_ZERO_ERROR;
      testSetting = settings->getString("Rules", intStatus);
      if(U_SUCCESS(intStatus)) {
        col = new RuleBasedCollator(testSetting, status);
        if(U_SUCCESS(status)) {
          logln("Testing collator for rules "+testSetting);
        } else {
          errln("Unable to instantiate collator for rules "+testSetting);
          return;
        }
      } else {
        errln("No collator definition!");
      }
    }
    if(col != NULL) {
      // get attributes
      testSetting = settings->getString("Arguments", intStatus);
      if(U_SUCCESS(intStatus)) {
        logln("Arguments: "+testSetting);
        argLen = testSetting.length();
        arguments = testSetting.getBuffer();
        processArguments(col, arguments, argLen);
        if(U_FAILURE(status)) {
          errln("Couldn't process arguments");
          break;
        }
      } else {
        intStatus = U_ZERO_ERROR;
      }
      // Start the processing
      while(testData->nextCase(currentCase, status)) {
        UnicodeString sequence = currentCase->getString("sequence", status);
        if(U_SUCCESS(status)) {
            processSequence(col, sequence);
        }
      }
    } else {
      errln("Couldn't instantiate a collator!");
    }
    delete col;
    col = NULL;
  }
}

void 
DataDrivenCollatorTest::processSequence(Collator* col, const UnicodeString &sequence) {
  Collator::EComparisonResult relation = Collator::EQUAL;
  UBool hasNext;
  SeqElement *source = NULL;
  SeqElement *target = NULL;
  int32_t j = 0;

  sequences.removeAllElements();

  target = new SeqElement(); 

  setTestSequence(sequence, *target);
  sequences.addElement(target, status);

  do {
    relation = Collator::EQUAL;
    target = new SeqElement(); 
    hasNext = getNextInSequence(*target);
    for(j = sequences.size(); j > 0; j--) {
      source = (SeqElement *)sequences.elementAt(j-1);
      if(relation == Collator::EQUAL && source->relation != Collator::EQUAL) {
        relation = source->relation;
      }
      doTest(col, source->source, target->source, relation);     
    }
    sequences.addElement(target, status);
    source = target;
  } while(hasNext);
}

#endif /* #if !UCONFIG_NO_COLLATION */

--- NEW FILE: dadrcoll.h ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 2002-2003, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

/**
 * DataDrivenCollatorTest is a test class that uses data stored in resource
 * bundles to perform testing. For more details on data structure, see
 * source/test/testdata/DataDrivenCollationTest.txt
 */

#ifndef _INTLTESTDATADRIVENCOLLATOR
#define _INTLTESTDATADRIVENCOLLATOR

#include "unicode/utypes.h"

#if !UCONFIG_NO_COLLATION

#include "tscoll.h"
#include "uvector.h"
#include "unicode/coll.h"
#include "unicode/tblcoll.h"
#include "unicode/sortkey.h"
#include "unicode/schriter.h"
#include "unicode/ures.h"
#include "tstdtmod.h"

class SeqElement {
public:
  UnicodeString source;
  Collator::EComparisonResult relation;
};

class DataDrivenCollatorTest: public IntlTestCollator {
    void runIndexedTest(int32_t index, UBool exec, const char* &name, char* par = NULL );
public:
    DataDrivenCollatorTest();
    virtual ~DataDrivenCollatorTest();
protected:

    void DataDrivenTest(char *par);
    void processSequence(Collator* col, const UnicodeString &sequence);
    void processTest(TestData *testData);
    void processArguments(Collator *col, const UChar *start, int32_t optLen);
    UBool setTestSequence(const UnicodeString &setSequence, SeqElement &el);
    UBool getNextInSequence(SeqElement &el);
private:
  StringCharacterIterator seq;
  TestDataModule *driver;
  UErrorCode status;
  UVector sequences;
};

#endif /* #if !UCONFIG_NO_COLLATION */

#endif

--- NEW FILE: datamap.cpp ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 2002-2003, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

/* Created by weiv 05/09/2002 */

#include "datamap.h"
#include "unicode/resbund.h"
#include <stdlib.h>

int32_t 
DataMap::utoi(const UnicodeString &s) const
{
  char ch[256];
  const UChar *u = s.getBuffer();
  int32_t len = s.length();
  u_UCharsToChars(u, ch, len);
  ch[len] = 0; /* include terminating \0 */
  return atoi(ch);
}

U_CDECL_BEGIN
void U_CALLCONV
deleteResBund(void *obj) {
  delete (ResourceBundle *)obj;
}
U_CDECL_END


RBDataMap::~RBDataMap()
{
  delete fData;
}

RBDataMap::RBDataMap()
{
  UErrorCode status = U_ZERO_ERROR;
  fData = new Hashtable(TRUE, status);
  fData->setValueDeleter(deleteResBund);
}

// init from table resource
// will put stuff in hashtable according to 
// keys.
RBDataMap::RBDataMap(UResourceBundle *data, UErrorCode &status)
{
  fData = new Hashtable(TRUE, status);
  fData->setValueDeleter(deleteResBund);
  init(data, status);
}

// init from headers and resource
// with checking the whether the size of resource matches 
// header size
RBDataMap::RBDataMap(UResourceBundle *headers, UResourceBundle *data, UErrorCode &status) 
{
  fData = new Hashtable(TRUE, status);
  fData->setValueDeleter(deleteResBund);
  init(headers, data, status);
}


void RBDataMap::init(UResourceBundle *data, UErrorCode &status) {
  int32_t i = 0;
  fData->removeAll();
  UResourceBundle *t = NULL;
  for(i = 0; i < ures_getSize(data); i++) {
    t = ures_getByIndex(data, i, t, &status);
    fData->put(UnicodeString(ures_getKey(t), ""), new ResourceBundle(t, status), status);
  }
  ures_close(t);
}

void RBDataMap::init(UResourceBundle *headers, UResourceBundle *data, UErrorCode &status)
{
  int32_t i = 0;
  fData->removeAll();
  UResourceBundle *t = NULL;
  const UChar *key = NULL;
  int32_t keyLen = 0;
  if(ures_getSize(headers) == ures_getSize(data)) {
    for(i = 0; i < ures_getSize(data); i++) {
      t = ures_getByIndex(data, i, t, &status);
      key = ures_getStringByIndex(headers, i, &keyLen, &status);
      fData->put(UnicodeString(key, keyLen), new ResourceBundle(t, status), status);
    }
  } else {
    // error
    status = U_INVALID_FORMAT_ERROR;
  }
  ures_close(t);
}


const UnicodeString RBDataMap::getString(const char* key, UErrorCode &status) const
{
  UnicodeString hashKey(key, "");
  ResourceBundle *r = (ResourceBundle *)fData->get(hashKey);
  if(r != NULL) {
    return r->getString(status);
  } else {
    status = U_MISSING_RESOURCE_ERROR;
    return UnicodeString("", "");
  }
}


int32_t RBDataMap::getInt(const char* key, UErrorCode &status) const
{
  int32_t result = 0;
  UnicodeString r = this->getString(key, status);
  if(U_SUCCESS(status)) {
    result = utoi(r);
  }
  return result;
}

const UnicodeString* RBDataMap::getStringArray(int32_t& count, const char* key, UErrorCode &status) const 
{
  UnicodeString hashKey(key, "");
  ResourceBundle *r = (ResourceBundle *)fData->get(hashKey);
  if(r != NULL) {
    int32_t i = 0;

    count = r->getSize();
    UnicodeString *result = new UnicodeString[count];
    for(i = 0; i<count; i++) {
      result[i] = r->getStringEx(i, status);
    }
    return result;
  } else {
    status = U_MISSING_RESOURCE_ERROR;
    return NULL;
  }
}

const int32_t* RBDataMap::getIntArray(int32_t& count, const char* key, UErrorCode &status) const
{
  UnicodeString hashKey(key, "");
  ResourceBundle *r = (ResourceBundle *)fData->get(hashKey);
  if(r != NULL) {
    int32_t i = 0;

    count = r->getSize();
    int32_t *result = new int32_t[count];
    UnicodeString stringRes;
    for(i = 0; i<count; i++) {
      stringRes = r->getStringEx(i, status);
      result[i] = utoi(stringRes);
    }
    return result;
  } else {
    status = U_MISSING_RESOURCE_ERROR;
    return NULL;
  }
}



--- NEW FILE: datamap.h ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 2002-2003, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

/* Created by weiv 05/09/2002 */

#ifndef INTLTST_DATAMAP
#define INTLTST_DATAMAP

#include "hash.h"
#include "unicode/ures.h"

/** Holder of test data and settings. Allows addressing of items by name.
 *  For test cases, names are defined in the "Headers" section. For settings
 *  and info data, names are keys in data. Currently, we return scalar strings
 *  and integers and arrays of strings and integers. Arrays should be deposited
 *  of by the user. 
 */
class DataMap {
public:
  virtual ~DataMap() {};

protected:
  DataMap() {};
  int32_t utoi(const UnicodeString &s) const;


public:
  /** get the string from the DataMap. Addressed by name
   *  @param key name of the data field.
   *  @return a string containing the data
   */
  virtual const UnicodeString getString(const char* key, UErrorCode &status) const = 0;

  /** get the string from the DataMap. Addressed by name
   *  @param key name of the data field.
   *  @return an integer containing the data
   */
  virtual int32_t getInt(const char* key, UErrorCode &status) const = 0;
  
  /** get an array of strings from the DataMap. Addressed by name.
   *  The user must dispose of it after usage.
   *  @param key name of the data field.
   *  @return a string array containing the data
   */
  virtual const UnicodeString* getStringArray(int32_t& count, const char* key, UErrorCode &status) const = 0;

  /** get an array of integers from the DataMap. Addressed by name.
   *  The user must dispose of it after usage.
   *  @param key name of the data field.
   *  @return an integer array containing the data
   */
  virtual const int32_t* getIntArray(int32_t& count, const char* key, UErrorCode &status) const = 0;

  // ... etc ...
};

// This one is already concrete - it is going to be instantiated from 
// concrete data by TestData children...
class RBDataMap : public DataMap{
private:
  Hashtable *fData;

public:
  virtual ~RBDataMap();

public:
  RBDataMap();

  RBDataMap(UResourceBundle *data, UErrorCode &status);
  RBDataMap(UResourceBundle *headers, UResourceBundle *data, UErrorCode &status);

public:
  void init(UResourceBundle *data, UErrorCode &status);
  void init(UResourceBundle *headers, UResourceBundle *data, UErrorCode &status);
  
  virtual const UnicodeString getString(const char* key, UErrorCode &status) const;
  virtual int32_t getInt(const char* key, UErrorCode &status) const;
  
  virtual const UnicodeString* getStringArray(int32_t& count, const char* key, UErrorCode &status) const;
  virtual const int32_t* getIntArray(int32_t& count, const char* key, UErrorCode &status) const;

  // ... etc ...
};

#endif


























--- NEW FILE: icusvtst.cpp ---
/**
 *******************************************************************************
 * Copyright (C) 2001-2002, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
 *******************************************************************************
 */

#include "unicode/utypes.h"

#if !UCONFIG_NO_SERVICE

#include "icusvtst.h"

#include "iculserv.h"


class MyListener : public EventListener {
[...1385 lines suppressed...]
  }
  catch (NullPointerException e) {
    logln(e.getMessage());
  }
  catch (Exception e) {
    errln("got wrong exception");
  }

  nf.removeListener(new MyListener());
  nf.notifyChanged();
  nf.addListener(new MyListener());
  nf.removeListener(new MyListener());
#endif
}


/* !UCONFIG_NO_SERVICE */
#endif



--- NEW FILE: icusvtst.h ---
/**
 *******************************************************************************
 * Copyright (C) 2001-2002, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
 *******************************************************************************
 */

#ifndef ICUSVTST_H
#define ICUSVTST_H

#include "unicode/utypes.h"

#if !UCONFIG_NO_SERVICE

#include "intltest.h"

class Integer;

class ICUServiceTest : public IntlTest
{    
 public:
  ICUServiceTest();
  virtual ~ICUServiceTest();

  void runIndexedTest(int32_t index, UBool exec, const char* &name, char* par = NULL);

  void testAPI_One(void);
  void testAPI_Two(void);
  void testRBF(void);
  void testNotification(void);
  void testLocale(void);
  void testWrapFactory(void);
  void testCoverage(void);

 private:
  UnicodeString& lrmsg(UnicodeString& result, const UnicodeString& message, const UObject* lhs, const UObject* rhs) const;
  void confirmBoolean(const UnicodeString& message, UBool val);
#if 0
  void confirmEqual(const UnicodeString& message, const UObject* lhs, const UObject* rhs);
#else
  void confirmEqual(const UnicodeString& message, const Integer* lhs, const Integer* rhs);
  void confirmEqual(const UnicodeString& message, const UnicodeString* lhs, const UnicodeString* rhs);
  void confirmEqual(const UnicodeString& message, const Locale* lhs, const Locale* rhs);
#endif
  void confirmStringsEqual(const UnicodeString& message, const UnicodeString& lhs, const UnicodeString& rhs);
  void confirmIdentical(const UnicodeString& message, const UObject* lhs, const UObject* rhs);
  void confirmIdentical(const UnicodeString& message, int32_t lhs, int32_t rhs);

  void msgstr(const UnicodeString& message, UObject* obj, UBool err = TRUE);
  void logstr(const UnicodeString& message, UObject* obj) {
		msgstr(message, obj, FALSE);
  }
};


/* UCONFIG_NO_SERVICE */
#endif

/* ICUSVTST_H */
#endif

--- NEW FILE: idnaref.cpp ---
/*
 *******************************************************************************
 *
 *   Copyright (C) 2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 *   file name:  idnaref.cpp
 *   encoding:   US-ASCII
 *   tab size:   8 (not used)
 *   indentation:4
 *
 *   created on: 2003feb1
 *   created by: Ram Viswanadha
 */

#include "unicode/utypes.h"

#if !UCONFIG_NO_IDNA && !UCONFIG_NO_TRANSLITERATION
[...982 lines suppressed...]
        *status = U_ZERO_ERROR; // reset error
        
        b2Len = idnaref_IDNToASCII(s2,length2,b2,b2Len,options, &parseError, status);
        
    }
    // when toASCII is applied all label separators are replaced with FULL_STOP
    result = compareCaseInsensitiveASCII(b1,b1Len,b2,b2Len);

CLEANUP:
    if(b1 != b1Stack){
        uprv_free(b1);
    }

    if(b2 != b2Stack){
        uprv_free(b2);
    }

    return result;
}
#endif /* #if !UCONFIG_NO_IDNA */

--- NEW FILE: idnaref.h ---
/*
 *******************************************************************************
 *
 *   Copyright (C) 2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 *   file name:  idnaref.h
 *   encoding:   US-ASCII
 *   tab size:   8 (not used)
 *   indentation:4
 *
 *   created on: 2003feb1
 *   created by: Ram Viswanadha
 */

#ifndef __IDNAREF_H__
#define __IDNAREF_H__

#include "unicode/utypes.h"

#if !UCONFIG_NO_IDNA

#include "unicode/parseerr.h"

#define IDNAREF_DEFAULT          0x0000
#define IDNAREF_ALLOW_UNASSIGNED 0x0001
#define IDNAREF_USE_STD3_RULES   0x0002
    
/**
 * This function implements the ToASCII operation as defined in the IDNA draft.
 * This operation is done on <b>single labels</b> before sending it to something that expects
 * ASCII names. A label is an individual part of a domain name. Labels are usually
 * separated by dots; for e.g." "www.example.com" is composed of 3 labels 
 * "www","example", and "com".
 *
 *
 * @param src               Input Unicode label.
 * @param srcLength         Number of UChars in src, or -1 if NUL-terminated.
 * @param dest              Output Unicode array with ACE encoded ASCII label.
 * @param destCapacity      Size of dest.
 * @param options           A bit set of options:
 *  
 *  - idnaref_UNASSIGNED        Unassigned values can be converted to ASCII for query operations
 *                          If TRUE unassigned values are treated as normal Unicode code points.
 *                          If FALSE the operation fails with U_UNASSIGNED_CODE_POINT_FOUND error code.
 *  - idnaref_USE_STD3_RULES    Use STD3 ASCII rules for host name syntax restrictions
 *                          If TRUE and the input does not statisfy STD3 rules, the operation 
 *                          will fail with U_IDNA_STD3_ASCII_RULES_ERROR
 *
 * @param parseError        Pointer to UParseError struct to recieve information on position 
 *                          of error if an error is encountered. Can be NULL.
 * @param status            ICU in/out error code parameter.
 *                          U_INVALID_CHAR_FOUND if src contains
 *                          unmatched single surrogates.
 *                          U_INDEX_OUTOFBOUNDS_ERROR if src contains
 *                          too many code points.
 *                          U_BUFFER_OVERFLOW_ERROR if destCapacity is not enough
 * @return                  Number of ASCII characters converted.
 * @draft ICU 2.6
 */
U_CFUNC int32_t 
idnaref_toASCII(const UChar* src, int32_t srcLength, 
              UChar* dest, int32_t destCapacity,
              int32_t options,
              UParseError* parseError,
              UErrorCode* status);


/**
 * This function implements the ToUnicode operation as defined in the IDNA draft.
 * This operation is done on <b>single labels</b> before sending it to something that expects
 * ASCII names. A label is an individual part of a domain name. Labels are usually
 * separated by dots; for e.g." "www.example.com" is composed of 3 labels 
 * "www","example", and "com".
 *
 * @param src               Input ASCII (ACE encoded) label.
 * @param srcLength         Number of UChars in src, or -1 if NUL-terminated.
 * @param dest Output       Converted Unicode array.
 * @param destCapacity      Size of dest.
 * @param options           A bit set of options:
 *  
 *  - idnaref_UNASSIGNED        Unassigned values can be converted to ASCII for query operations
 *                          If TRUE unassigned values are treated as normal Unicode code points.
 *                          If FALSE the operation fails with U_UNASSIGNED_CODE_POINT_FOUND error code.
 *  - idnaref_USE_STD3_RULES    Use STD3 ASCII rules for host name syntax restrictions
 *                          If TRUE and the input does not statisfy STD3 rules, the operation 
 *                          will fail with U_IDNA_STD3_ASCII_RULES_ERROR
 *
 * @param parseError        Pointer to UParseError struct to recieve information on position 
 *                          of error if an error is encountered. Can be NULL.
 * @param status            ICU in/out error code parameter.
 *                          U_INVALID_CHAR_FOUND if src contains
 *                          unmatched single surrogates.
 *                          U_INDEX_OUTOFBOUNDS_ERROR if src contains
 *                          too many code points.
 *                          U_BUFFER_OVERFLOW_ERROR if destCapacity is not enough
 * @return                  Number of Unicode characters converted.
 * @draft ICU 2.6
 */
U_CFUNC int32_t 
idnaref_toUnicode(const UChar* src, int32_t srcLength,
                UChar* dest, int32_t destCapacity,
                int32_t options,
                UParseError* parseError,
                UErrorCode* status);


/**
 * Convenience function that implements the IDNToASCII operation as defined in the IDNA draft.
 * This operation is done on complete domain names, e.g: "www.example.com". 
 * It is important to note that this operation can fail. If it fails, then the input 
 * domain name cannot be used as an Internationalized Domain Name and the application
 * should have methods defined to deal with the failure.
 * 
 * <b>Note:</b> IDNA draft specifies that a conformant application should divide a domain name
 * into separate labels, decide whether to apply allowUnassigned and useSTD3ASCIIRules on each, 
 * and then convert. This function does not offer that level of granularity. The options once  
 * set will apply to all labels in the domain name
 *
 * @param src               Input ASCII IDN.
 * @param srcLength         Number of UChars in src, or -1 if NUL-terminated.
 * @param dest Output       Unicode array.
 * @param destCapacity      Size of dest.
 * @param options           A bit set of options:
 *  
 *  - idnaref_UNASSIGNED        Unassigned values can be converted to ASCII for query operations
 *                          If TRUE unassigned values are treated as normal Unicode code points.
 *                          If FALSE the operation fails with U_UNASSIGNED_CODE_POINT_FOUND error code.
 *  - idnaref_USE_STD3_RULES    Use STD3 ASCII rules for host name syntax restrictions
 *                          If TRUE and the input does not statisfy STD3 rules, the operation 
 *                          will fail with U_IDNA_STD3_ASCII_RULES_ERROR
 * 
 * @param parseError        Pointer to UParseError struct to recieve information on position 
 *                          of error if an error is encountered. Can be NULL.
 * @param status            ICU in/out error code parameter.
 *                          U_INVALID_CHAR_FOUND if src contains
 *                          unmatched single surrogates.
 *                          U_INDEX_OUTOFBOUNDS_ERROR if src contains
 *                          too many code points.
 *                          U_BUFFER_OVERFLOW_ERROR if destCapacity is not enough
 * @return                  Number of ASCII characters converted.
 * @draft ICU 2.6
 */
U_CFUNC int32_t  
idnaref_IDNToASCII(  const UChar* src, int32_t srcLength,
                   UChar* dest, int32_t destCapacity,
                   int32_t options,
                   UParseError* parseError,
                   UErrorCode* status);

/**
 * Convenience function that implements the IDNToUnicode operation as defined in the IDNA draft.
 * This operation is done on complete domain names, e.g: "www.example.com". 
 *
 * <b>Note:</b> IDNA draft specifies that a conformant application should divide a domain name
 * into separate labels, decide whether to apply allowUnassigned and useSTD3ASCIIRules on each, 
 * and then convert. This function does not offer that level of granularity. The options once  
 * set will apply to all labels in the domain name
 *
 * @param src               Input Unicode IDN.
 * @param srcLength         Number of UChars in src, or -1 if NUL-terminated.
 * @param dest Output       ASCII array.
 * @param destCapacity      Size of dest.
 * @param options           A bit set of options:
 *  
 *  - idnaref_UNASSIGNED        Unassigned values can be converted to ASCII for query operations
 *                          If TRUE unassigned values are treated as normal Unicode code points.
 *                          If FALSE the operation fails with U_UNASSIGNED_CODE_POINT_FOUND error code.
 *  - idnaref_USE_STD3_RULES    Use STD3 ASCII rules for host name syntax restrictions
 *                          If TRUE and the input does not statisfy STD3 rules, the operation 
 *                          will fail with U_IDNA_STD3_ASCII_RULES_ERROR
 *
 * @param parseError        Pointer to UParseError struct to recieve information on position 
 *                          of error if an error is encountered. Can be NULL.
 * @param status            ICU in/out error code parameter.
 *                          U_INVALID_CHAR_FOUND if src contains
 *                          unmatched single surrogates.
 *                          U_INDEX_OUTOFBOUNDS_ERROR if src contains
 *                          too many code points.
 *                          U_BUFFER_OVERFLOW_ERROR if destCapacity is not enough
 * @return                  Number of ASCII characters converted.
 * @draft ICU 2.6
 */
U_CFUNC int32_t  
idnaref_IDNToUnicode(  const UChar* src, int32_t srcLength,
                     UChar* dest, int32_t destCapacity,
                     int32_t options,
                     UParseError* parseError,
                     UErrorCode* status);

/**
 * Compare two strings for IDNs for equivalence.
 * This function splits the domain names into labels and compares them.
 * According to IDN draft, whenever two labels are compared, they are 
 * considered equal if and only if their ASCII forms (obtained by 
 * applying toASCII) match using an case-insensitive ASCII comparison.
 * Two domain names are considered a match if and only if all labels 
 * match regardless of whether label separators match.
 *
 * @param s1                First source string.
 * @param length1           Length of first source string, or -1 if NUL-terminated.
 *
 * @param s2                Second source string.
 * @param length2           Length of second source string, or -1 if NUL-terminated.
 * @param options           A bit set of options:
 *  
 *  - idnaref_UNASSIGNED        Unassigned values can be converted to ASCII for query operations
 *                          If TRUE unassigned values are treated as normal Unicode code points.
 *                          If FALSE the operation fails with U_UNASSIGNED_CODE_POINT_FOUND error code.
 *  - idnaref_USE_STD3_RULES    Use STD3 ASCII rules for host name syntax restrictions
 *                          If TRUE and the input does not statisfy STD3 rules, the operation 
 *                          will fail with U_IDNA_STD3_ASCII_RULES_ERROR
 *
 * @param status            ICU error code in/out parameter.
 *                          Must fulfill U_SUCCESS before the function call.
 * @return <0 or 0 or >0 as usual for string comparisons
 * @draft ICU 2.6
 */
U_CFUNC int32_t  
idnaref_compare(  const UChar *s1, int32_t length1,
                const UChar *s2, int32_t length2,
                int32_t options,
                UErrorCode* status);

#endif /* #if !UCONFIG_NO_IDNA */

#endif

--- NEW FILE: incaltst.cpp ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 1997-2003, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

/* Test Internationalized Calendars for C++ */

#include "unicode/utypes.h"
#include "string.h"
#include "unicode/locid.h"

#if !UCONFIG_NO_FORMATTING

#include <stdio.h>

#define CHECK(status, msg) \
    if (U_FAILURE(status)) { \
      errln((UnicodeString(u_errorName(status)) + UnicodeString(" : " ) )+ msg); \
        return; \
    }


static UnicodeString escape( const UnicodeString&src)
{
  UnicodeString dst;
    dst.remove();
    for (int32_t i = 0; i < src.length(); ++i) {
        UChar c = src[i];
        if(c < 0x0080) 
            dst += c;
        else {
            dst += UnicodeString("[");
            char buf [8];
            sprintf(buf, "%#x", c);
            dst += UnicodeString(buf);
            dst += UnicodeString("]");
        }
    }

    return dst;
}


#include "incaltst.h"
#include "unicode/gregocal.h"
#include "unicode/smpdtfmt.h"
#include "unicode/simpletz.h"
 
// *****************************************************************************
// class IntlCalendarTest
// *****************************************************************************

static UnicodeString fieldName(UCalendarDateFields f);

// Turn this on to dump the calendar fields 
#define U_DEBUG_DUMPCALS  

static UnicodeString calToStr(const Calendar & cal)
{

  UnicodeString out;
  UErrorCode status = U_ZERO_ERROR;
  int i;
  for(i = 0;i<UCAL_FIELD_COUNT;i++) {
    out += (UnicodeString("+") + fieldName((UCalendarDateFields)i) + "=" +  cal.get((UCalendarDateFields)i, status) + UnicodeString(", "));
  }
  out += UnicodeString(cal.getType());

  out += cal.inDaylightTime(status)?UnicodeString("- DAYLIGHT"):UnicodeString("- NORMAL");

  UnicodeString str2;
  out += cal.getTimeZone().getDisplayName(str2);

  return out;
}

#define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break


void IntlCalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
{
    if (exec) logln("TestSuite IntlCalendarTest");
    switch (index) {
    CASE(0,TestTypes);
    CASE(1,TestGregorian);
    CASE(2,TestBuddhist);
    CASE(3,TestJapanese);
    CASE(4,TestBuddhistFormat);
    CASE(5,TestJapaneseFormat);
    default: name = ""; break;
    }
}

#undef CASE

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

static UnicodeString fieldName(UCalendarDateFields f) {
    switch (f) {
    case UCAL_ERA:           return "ERA";
    case UCAL_YEAR:          return "YEAR";
    case UCAL_MONTH:         return "MONTH";
    case UCAL_WEEK_OF_YEAR:  return "WEEK_OF_YEAR";
    case UCAL_WEEK_OF_MONTH: return "WEEK_OF_MONTH";
    case UCAL_DATE:			 return "DAY_OF_MONTH"; // DATE is synonym for DAY_OF_MONTH
    case UCAL_DAY_OF_YEAR:   return "DAY_OF_YEAR";
    case UCAL_DAY_OF_WEEK:   return "DAY_OF_WEEK";
    case UCAL_DAY_OF_WEEK_IN_MONTH: return "DAY_OF_WEEK_IN_MONTH";
    case UCAL_AM_PM:         return "AM_PM";
    case UCAL_HOUR:          return "HOUR";
    case UCAL_HOUR_OF_DAY:   return "HOUR_OF_DAY";
    case UCAL_MINUTE:        return "MINUTE";
    case UCAL_SECOND:        return "SECOND";
    case UCAL_MILLISECOND:   return "MILLISECOND";
    case UCAL_ZONE_OFFSET:   return "ZONE_OFFSET";
    case UCAL_DST_OFFSET:    return "DST_OFFSET";
    case UCAL_YEAR_WOY:      return "YEAR_WOY";
    case UCAL_DOW_LOCAL:     return "DOW_LOCAL";
    case UCAL_FIELD_COUNT:   return "FIELD_COUNT";
    default:
        return UnicodeString("") + ((int32_t)f);
    }
}

/**
 * Test various API methods for API completeness.
 */
void
IntlCalendarTest::TestTypes()
{
  Calendar *c = NULL;
  UErrorCode status = U_ZERO_ERROR;
  int j;
  const char *locs [40] = { "en_US_VALLEYGIRL",     
                            "ja_JP_TRADITIONAL",   
                            "th_TH_TRADITIONAL", 
                            "en_US", NULL };
  const char *types[40] = { "gregorian", 
                            "japanese",
                            "buddhist",           
                            "gregorian", NULL };

  for(j=0;locs[j];j++) {
    logln(UnicodeString("Creating calendar of locale ")  + locs[j]);
    status = U_ZERO_ERROR;
    c = Calendar::createInstance(locs[j], status);
    CHECK(status, "creating '" + UnicodeString(locs[j]) + "' calendar");
    if(U_SUCCESS(status)) {
      logln(UnicodeString(" type is ") + c->getType());
      if(strcmp(c->getType(), types[j])) {
        errln(UnicodeString(locs[j]) + UnicodeString("Calendar type ") + c->getType() + " instead of " + types[j]);
      }
    }
    delete c;
  }
}



/**
 * Run a test of a quasi-Gregorian calendar.  This is a calendar
 * that behaves like a Gregorian but has different year/era mappings.
 * The int[] data array should have the format:
 * 
 * { era, year, gregorianYear, month, dayOfMonth, ...  ... , -1 }
 */
void IntlCalendarTest::quasiGregorianTest(Calendar& cal, const Locale& gcl, const int32_t *data) {
  UErrorCode status = U_ZERO_ERROR;
  // As of JDK 1.4.1_01, using the Sun JDK GregorianCalendar as
  // a reference throws us off by one hour.  This is most likely
  // due to the JDK 1.4 incorporation of historical time zones.
  //java.util.Calendar grego = java.util.Calendar.getInstance();
  Calendar *grego = Calendar::createInstance(gcl, status);

  int32_t tz1 = cal.get(UCAL_ZONE_OFFSET,status);
  int32_t tz2 = grego -> get (UCAL_ZONE_OFFSET, status);
  if(tz1 != tz2) { 
    errln((UnicodeString)"cal's tz " + tz1 + " != grego's tz " + tz2);
  }

  for (int32_t i=0; data[i]!=-1; ) {
    int32_t era = data[i++];
    int32_t year = data[i++];
    int32_t gregorianYear = data[i++];
    int32_t month = data[i++];
    int32_t dayOfMonth = data[i++];
    
    grego->clear();
    grego->set(gregorianYear, month, dayOfMonth);
    UDate D = grego->getTime(status);
    
    cal.clear();
    cal.set(UCAL_ERA, era);
    cal.set(year, month, dayOfMonth);
    UDate d = cal.getTime(status);
#ifdef U_DEBUG_DUMPCALS
    logln((UnicodeString)"cal  : " + calToStr(cal));
    logln((UnicodeString)"grego: " + calToStr(*grego));
#endif
    if (d == D) {
      logln(UnicodeString("OK: ") + era + ":" + year + "/" + (month+1) + "/" + dayOfMonth +
            " => " + d + " (" + UnicodeString(cal.getType()) + ")");
    } else {
      errln(UnicodeString("Fail: (fields to millis)") + era + ":" + year + "/" + (month+1) + "/" + dayOfMonth +
            " => " + d + ", expected " + D + " (" + UnicodeString(cal.getType()) + "Off by: " + (d-D));
    }
    
    // Now, set the gregorian millis on the other calendar
    cal.clear();
    cal.setTime(D, status);
    int e = cal.get(UCAL_ERA, status);
    int y = cal.get(UCAL_YEAR, status);
#ifdef U_DEBUG_DUMPCALS
    logln((UnicodeString)"cal  : " + calToStr(cal));
    logln((UnicodeString)"grego: " + calToStr(*grego));
#endif
    if (y == year && e == era) {
      logln((UnicodeString)"OK: " + D + " => " + cal.get(UCAL_ERA, status) + ":" +
            cal.get(UCAL_YEAR, status) + "/" +
            (cal.get(UCAL_MONTH, status)+1) + "/" + cal.get(UCAL_DATE, status) +  " (" + UnicodeString(cal.getType()) + ")");
    } else {
      errln((UnicodeString)"Fail: (millis to fields)" + D + " => " + cal.get(UCAL_ERA, status) + ":" +
            cal.get(UCAL_YEAR, status) + "/" +
            (cal.get(UCAL_MONTH, status)+1) + "/" + cal.get(UCAL_DATE, status) +
            ", expected " + era + ":" + year + "/" + (month+1) + "/" +
            dayOfMonth +  " (" + UnicodeString(cal.getType()));
    }
  }
  delete grego;
  CHECK(status, "err during quasiGregorianTest()");
}

// Verify that Gregorian works like Gregorian
void IntlCalendarTest::TestGregorian() { 
    UDate timeA = Calendar::getNow();
    int32_t data[] = { 
        GregorianCalendar::AD, 1868, 1868, UCAL_SEPTEMBER, 8,
        GregorianCalendar::AD, 1868, 1868, UCAL_SEPTEMBER, 9,
        GregorianCalendar::AD, 1869, 1869, UCAL_JUNE, 4,
        GregorianCalendar::AD, 1912, 1912, UCAL_JULY, 29,
        GregorianCalendar::AD, 1912, 1912, UCAL_JULY, 30,
        GregorianCalendar::AD, 1912, 1912, UCAL_AUGUST, 1,
        -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
    };
    
    Calendar *cal;
    UErrorCode status = U_ZERO_ERROR;
    cal = Calendar::createInstance(/*"de_DE", */ status);
    CHECK(status, UnicodeString("Creating de_CH calendar"));
    // Sanity check the calendar 
    UDate timeB = Calendar::getNow();
    UDate timeCal = cal->getTime(status);

    if(!(timeA <= timeCal) || !(timeCal <= timeB)) {
      errln((UnicodeString)"Error: Calendar time " + timeCal +
            " is not within sampled times [" + timeA + " to " + timeB + "]!");
    }
    // end sanity check

    // Note, the following is a good way to test the sanity of the constructed calendars,
    // using Collation as a delay-loop: 
    //
    // $ intltest  format/IntlCalendarTest  collate/G7CollationTest format/IntlCalendarTest

    quasiGregorianTest(*cal,Locale("fr_FR"),data);
    delete cal;
}

/**
 * Verify that BuddhistCalendar shifts years to Buddhist Era but otherwise
 * behaves like GregorianCalendar.
 */
void IntlCalendarTest::TestBuddhist() {
    // BE 2542 == 1999 CE
    UDate timeA = Calendar::getNow();

    int32_t data[] = {
        0,           // B. era
        2542,        // B. year
        1999,        // G. year
        UCAL_JUNE,   // month
        4,           // day

        0,           // B. era
        3,           // B. year
        -540,        // G. year
        UCAL_FEBRUARY, // month
        12,          // day

        0,           // test month calculation:  4795 BE = 4252 AD is a leap year, but 4795 AD is not.
        4795,        // BE
        4252,        // AD
        UCAL_FEBRUARY,
        29,

        -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
    };
    Calendar *cal;
    UErrorCode status = U_ZERO_ERROR;
    cal = Calendar::createInstance("th_TH_TRADITIONAL", status);
    CHECK(status, UnicodeString("Creating th_TH_TRADITIONAL calendar"));

    // Sanity check the calendar 
    UDate timeB = Calendar::getNow();
    UDate timeCal = cal->getTime(status);

    if(!(timeA <= timeCal) || !(timeCal <= timeB)) {
      errln((UnicodeString)"Error: Calendar time " + timeCal +
            " is not within sampled times [" + timeA + " to " + timeB + "]!");
    }
    // end sanity check


    quasiGregorianTest(*cal,Locale("th_TH"),data);
    delete cal;
}

/**
 * Verify that JapaneseCalendar shifts years to Japanese Eras but otherwise
 * behaves like GregorianCalendar.
 */
void IntlCalendarTest::TestJapanese() {
    UDate timeA = Calendar::getNow();
    
    /* Sorry.. japancal.h is private! */
#define JapaneseCalendar_MEIJI  232
#define JapaneseCalendar_TAISHO 233
#define JapaneseCalendar_SHOWA  234
#define JapaneseCalendar_HEISEI 235
    
    // BE 2542 == 1999 CE
    int32_t data[] = { 
        //       Jera         Jyr  Gyear   m             d
        JapaneseCalendar_MEIJI, 1, 1868, UCAL_SEPTEMBER, 8,
        JapaneseCalendar_MEIJI, 1, 1868, UCAL_SEPTEMBER, 9,
        JapaneseCalendar_MEIJI, 2, 1869, UCAL_JUNE, 4,
        JapaneseCalendar_MEIJI, 45, 1912, UCAL_JULY, 29,
        JapaneseCalendar_TAISHO, 1, 1912, UCAL_JULY, 30,
        JapaneseCalendar_TAISHO, 1, 1912, UCAL_AUGUST, 1,
        
        // new tests (not in java)
        JapaneseCalendar_SHOWA,     64,   1989,  UCAL_JANUARY, 7,  // Test current era transition (different code path than others)
        JapaneseCalendar_HEISEI,    1,   1989,  UCAL_JANUARY, 8,   
        JapaneseCalendar_HEISEI,    1,   1989,  UCAL_JANUARY, 9,
        JapaneseCalendar_HEISEI,    1,   1989,  UCAL_DECEMBER, 20,
        JapaneseCalendar_HEISEI,  15,  2003,  UCAL_MAY, 22,
        -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
    };
    
    Calendar *cal;
    UErrorCode status = U_ZERO_ERROR;
    cal = Calendar::createInstance("ja_JP_TRADITIONAL", status);
    CHECK(status, UnicodeString("Creating ja_JP_TRADITIONAL calendar"));
    // Sanity check the calendar 
    UDate timeB = Calendar::getNow();
    UDate timeCal = cal->getTime(status);

    if(!(timeA <= timeCal) || !(timeCal <= timeB)) {
      errln((UnicodeString)"Error: Calendar time " + timeCal +
            " is not within sampled times [" + timeA + " to " + timeB + "]!");
    }
    // end sanity check
    quasiGregorianTest(*cal,Locale("ja_JP"),data);
    delete cal;
}

void IntlCalendarTest::TestBuddhistFormat() {
    Calendar *cal;
    UErrorCode status = U_ZERO_ERROR;
    cal = Calendar::createInstance("th_TH_TRADITIONAL", status);
    CHECK(status, UnicodeString("Creating th_TH_TRADITIONAL calendar"));
    
    // Test simple parse/format with adopt
    
    // First, a contrived english test..
    UDate aDate = 999932400000.0; 
    SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale("en_US"), status);
    CHECK(status, "creating date format instance");
    if(!fmt) { 
        errln("Coudln't create en_US instance");
    } else {
        UnicodeString str;
        fmt->format(aDate, str);
        logln(UnicodeString() + "Test Date: " + str);
        str.remove();
        fmt->adoptCalendar(cal);
        cal = NULL;
        fmt->format(aDate, str);
        logln(UnicodeString() + "as Buddhist Calendar: " + escape(str));
        UnicodeString expected("September 8, 2544 BE");
        if(str != expected) {
            errln("Expected " + escape(expected) + " but got " + escape(str));
        }
        UDate otherDate = fmt->parse(expected, status);
        if(otherDate != aDate) { 
            UnicodeString str3;
            fmt->format(otherDate, str3);
            errln("Parse incorrect of " + escape(expected) + " - wanted " + aDate + " but got " +  otherDate + ", " + escape(str3));
        } else {
            logln("Parsed OK: " + expected);
        }
        delete fmt;
    }
    delete cal;
    
    CHECK(status, "Error occured testing Buddhist Calendar in English ");
    
    status = U_ZERO_ERROR;
    // Now, try in Thai
    {
        UnicodeString expect = CharsToUnicodeString("\\u0E27\\u0E31\\u0E19\\u0E40\\u0E2A\\u0E32\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48"
            " 8 \\u0E01\\u0E31\\u0e19\\u0e22\\u0e32\\u0e22\\u0e19 \\u0e1e.\\u0e28. 2544");
        UDate         expectDate = 999932400000.0;
        Locale        loc("th_TH_TRADITIONAL");
        
        simpleTest(loc, expect, expectDate, status);
    }
}


void IntlCalendarTest::TestJapaneseFormat() {
    Calendar *cal;
    UErrorCode status = U_ZERO_ERROR;
    cal = Calendar::createInstance("ja_JP_TRADITIONAL", status);
    CHECK(status, UnicodeString("Creating ja_JP_TRADITIONAL calendar"));
    
    Calendar *cal2 = cal->clone();
    
    // Test simple parse/format with adopt
    
    UDate aDate = 999932400000.0; 
    SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yy G"), Locale("en_US"), status);
    CHECK(status, "creating date format instance");
    if(!fmt) { 
        errln("Coudln't create en_US instance");
    } else {
        UnicodeString str;
        fmt->format(aDate, str);
        logln(UnicodeString() + "Test Date: " + str);
        str.remove();
        fmt->adoptCalendar(cal);
        cal = NULL;
        fmt->format(aDate, str);
        logln(UnicodeString() + "as Japanese Calendar: " + str);
        UnicodeString expected("September 8, 13 Heisei");
        if(str != expected) {
            errln("Expected " + expected + " but got " + str);
        }
        UDate otherDate = fmt->parse(expected, status);
        if(otherDate != aDate) { 
            UnicodeString str3;
            ParsePosition pp;
            fmt->parse(expected, *cal2, pp);
            fmt->format(otherDate, str3);
            errln("Parse incorrect of " + expected + " - wanted " + aDate + " but got " +  " = " +   otherDate + ", " + str3 + " = " + calToStr(*cal2) );
            
        } else {
            logln("Parsed OK: " + expected);
        }
        delete fmt;
    }

    // Test parse with incomplete information
    fmt = new SimpleDateFormat(UnicodeString("G y"), Locale("en_US"), status);
    aDate = -3197120400000.;
    CHECK(status, "creating date format instance");
    if(!fmt) { 
        errln("Coudln't create en_US instance");
    } else {
        UnicodeString str;
        fmt->format(aDate, str);
        logln(UnicodeString() + "Test Date: " + str);
        str.remove();
        fmt->adoptCalendar(cal2->clone());
        fmt->format(aDate, str);
        logln(UnicodeString() + "as Japanese Calendar: " + str);
        UnicodeString expected("Meiji 1");
        if(str != expected) {
            errln("Expected " + expected + " but got " + str);
        }
        UDate otherDate = fmt->parse(expected, status);
        if(otherDate != aDate) { 
            UnicodeString str3;
            ParsePosition pp;
            fmt->parse(expected, *cal2, pp);
            fmt->format(otherDate, str3);
            errln("Parse incorrect of " + expected + " - wanted " + aDate + " but got " +  " = " +
                otherDate + ", " + str3 + " = " + calToStr(*cal2) );
        } else {
            logln("Parsed OK: " + expected);
        }
        delete fmt;
    }

    delete cal;
    delete cal2;
    CHECK(status, "Error occured");
    
    // Now, try in Japanese
    {
        UnicodeString expect = CharsToUnicodeString("\\u5e73\\u621013\\u5e749\\u67088\\u65e5");
        UDate         expectDate = 999932400000.0; // Testing a recent date
        Locale        loc("ja_JP_TRADITIONAL");
        
        status = U_ZERO_ERROR;
        simpleTest(loc, expect, expectDate, status);
    }
    {
        UnicodeString expect = CharsToUnicodeString("\\u5b89\\u6c385\\u5e747\\u67084\\u65e5");
        UDate         expectDate = -6106035600000.0;
        Locale        loc("ja_JP_TRADITIONAL");
        
        status = U_ZERO_ERROR;
        simpleTest(loc, expect, expectDate, status);    
        
    }
    {   // Jitterbug 1869 - this is an ambiguous era. (Showa 64 = Jan 6 1989, but Showa could be 2 other eras) )
        UnicodeString expect = CharsToUnicodeString("\\u662d\\u548c64\\u5e741\\u67086\\u65e5");
        UDate         expectDate = 600076800000.0;
        Locale        loc("ja_JP_TRADITIONAL");
        
        status = U_ZERO_ERROR;
        simpleTest(loc, expect, expectDate, status);    
        
    }
    {   // This Feb 29th falls on a leap year by gregorian year, but not by Japanese year.
        UnicodeString expect = CharsToUnicodeString("\\u5EB7\\u6B632\\u5e742\\u670829\\u65e5");
        UDate         expectDate =  -16214400000000.0;  // courtesy of date format round trip test
        Locale        loc("ja_JP_TRADITIONAL");
        
        status = U_ZERO_ERROR;
        simpleTest(loc, expect, expectDate, status);    
        
    }
}

void IntlCalendarTest::simpleTest(const Locale& loc, const UnicodeString& expect, UDate expectDate, UErrorCode& status)
{
    UnicodeString tmp;
    UDate         d;
    DateFormat *fmt0 = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull);

    logln("Try format/parse of " + (UnicodeString)loc.getName());
    DateFormat *fmt2 = DateFormat::createDateInstance(DateFormat::kFull, loc);
    if(fmt2) { 
        fmt2->format(expectDate, tmp);
        logln(escape(tmp) + " ( in locale " + loc.getName() + ")");
        if(tmp != expect) {
            errln(UnicodeString("Failed to format " ) + loc.getName() + " expected " + escape(expect) + " got " + escape(tmp) );
        }

        d = fmt2->parse(expect,status);
        CHECK(status, "Error occured parsing " + UnicodeString(loc.getName()));
        if(d != expectDate) {
            fmt2->format(d,tmp);
            errln(UnicodeString("Failed to parse " ) + escape(expect) + ", " + loc.getName() + " expect " + (double)expectDate + " got " + (double)d  + " " + escape(tmp));
            logln( "wanted " + escape(fmt0->format(expectDate,tmp.remove())) + " but got " + escape(fmt0->format(d,tmp.remove())));
        }
        delete fmt2;
    } else {
        errln((UnicodeString)"Can't create " + loc.getName() + " date instance");
    }
    delete fmt0;
}

#undef CHECK

#endif /* #if !UCONFIG_NO_FORMATTING */

//eof

--- NEW FILE: incaltst.h ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 1997-2003, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

#ifndef __IntlCalendarTest__
#define __IntlCalendarTest__
 
#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

#include "unicode/calendar.h"
#include "unicode/smpdtfmt.h"
#include "caltztst.h"

class IntlCalendarTest: public CalendarTimeZoneTest {
public:
    // IntlTest override
    void runIndexedTest( int32_t index, UBool exec, const char* &name, char* par );
public:
    void TestTypes(void);

    void TestGregorian(void);

    void TestBuddhist(void);
    void TestBuddhistFormat(void);

    void TestJapanese(void);
    void TestJapaneseFormat(void);

 protected:
    // Test a Gregorian-Like calendar
    void quasiGregorianTest(Calendar& cal, const Locale& gregoLocale, const int32_t *data);
    void simpleTest(const Locale& loc, const UnicodeString& expect, UDate expectDate, UErrorCode& status);
 
public: // package
    // internal routine for checking date
    static UnicodeString value(Calendar* calendar);
 
};

#endif /* #if !UCONFIG_NO_FORMATTING */
 
#endif // __IntlCalendarTest__




--- NEW FILE: intltest.vcproj ---
<?xml version="1.0" encoding = "Windows-1252"?>
<VisualStudioProject
	ProjectType="Visual C++"
	Version="7.00"
	Name="intltest"
	SccProjectName=""
	SccLocalPath="">
	<Platforms>
		<Platform
			Name="Win32"/>
	</Platforms>
	<Configurations>
		<Configuration
			Name="Debug|Win32"
			OutputDirectory=".\Debug"
			IntermediateDirectory=".\Debug"
			ConfigurationType="1"
			UseOfMFC="0"
			ATLMinimizesCRunTimeLibraryUsage="FALSE"
			CharacterSet="2">
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				ImproveFloatingPointConsistency="TRUE"
				OptimizeForProcessor="2"
				AdditionalIncludeDirectories="..\..\..\include,..\..\..\source\common,..\..\..\source\i18n,..\..\tools\toolutil"
				PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE,UDATA_MAP_DLL"
				BasicRuntimeChecks="3"
				RuntimeLibrary="1"
				DisableLanguageExtensions="TRUE"
				PrecompiledHeaderFile=".\Debug/intltest.pch"
				AssemblerListingLocation=".\Debug/"
				ObjectFile=".\Debug/"
				ProgramDataBaseFileName=".\Debug/"
				BrowseInformation="1"
				WarningLevel="3"
				SuppressStartupBanner="TRUE"
				DebugInformationFormat="4"
				CompileAs="0"/>
			<Tool
				Name="VCCustomBuildTool"/>
			<Tool
				Name="VCLinkerTool"
				AdditionalOptions="/MACHINE:I386"
				AdditionalDependencies="odbc32.lib odbccp32.lib"
				OutputFile=".\Debug/intltest.exe"
				LinkIncremental="2"
				SuppressStartupBanner="TRUE"
				AdditionalLibraryDirectories="..\..\..\lib"
				GenerateDebugInformation="TRUE"
				ProgramDatabaseFile=".\Debug/intltest.pdb"
				SubSystem="1"/>
			<Tool
				Name="VCMIDLTool"
				TypeLibraryName=".\Debug/intltest.tlb"/>
			<Tool
				Name="VCPostBuildEventTool"/>
			<Tool
				Name="VCPreBuildEventTool"/>
			<Tool
				Name="VCPreLinkEventTool"/>
			<Tool
				Name="VCResourceCompilerTool"
				PreprocessorDefinitions="_DEBUG"
				Culture="1033"/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"/>
			<Tool
				Name="VCWebDeploymentTool"/>
		</Configuration>
		<Configuration
			Name="Release|Win32"
			OutputDirectory=".\Release"
			IntermediateDirectory=".\Release"
			ConfigurationType="1"
			UseOfMFC="0"
			ATLMinimizesCRunTimeLibraryUsage="FALSE"
			CharacterSet="2">
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="2"
				ImproveFloatingPointConsistency="TRUE"
				AdditionalIncludeDirectories="..\..\..\include,..\..\..\source\common,..\..\..\source\i18n,..\..\tools\toolutil"
				PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE"
				RuntimeLibrary="0"
				DisableLanguageExtensions="TRUE"
				PrecompiledHeaderFile=".\Release/intltest.pch"
				AssemblerListingLocation=".\Release/"
				ObjectFile=".\Release/"
				ProgramDataBaseFileName=".\Release/"
				WarningLevel="3"
				SuppressStartupBanner="TRUE"
				DebugInformationFormat="3"
				CompileAs="0"/>
			<Tool
				Name="VCCustomBuildTool"/>
			<Tool
				Name="VCLinkerTool"
				AdditionalOptions="/MACHINE:I386"
				AdditionalDependencies="odbc32.lib odbccp32.lib"
				OutputFile=".\Release/intltest.exe"
				LinkIncremental="1"
				SuppressStartupBanner="TRUE"
				AdditionalLibraryDirectories="..\..\..\lib"
				GenerateDebugInformation="TRUE"
				ProgramDatabaseFile=".\Release/intltest.pdb"
				SubSystem="1"/>
			<Tool
				Name="VCMIDLTool"
				TypeLibraryName=".\Release/intltest.tlb"/>
			<Tool
				Name="VCPostBuildEventTool"/>
			<Tool
				Name="VCPreBuildEventTool"/>
			<Tool
				Name="VCPreLinkEventTool"/>
			<Tool
				Name="VCResourceCompilerTool"
				PreprocessorDefinitions="NDEBUG"
				Culture="1033"/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"/>
			<Tool
				Name="VCWebDeploymentTool"/>
		</Configuration>
	</Configurations>
	<Files>
		<Filter
			Name="break iteration"
			Filter="">
			<File
				RelativePath=".\itrbbi.cpp">
			</File>
			<File
				RelativePath=".\itrbbi.h">
			</File>
			<File
				RelativePath=".\rbbiapts.cpp">
			</File>
			<File
				RelativePath=".\rbbiapts.h">
			</File>
			<File
				RelativePath=".\rbbitst.cpp">
			</File>
			<File
				RelativePath=".\rbbitst.h">
			</File>
		</Filter>
		<Filter
			Name="collation"
			Filter="">
			<File
				RelativePath=".\allcoll.cpp">
			</File>
			<File
				RelativePath=".\allcoll.h">
			</File>
			<File
				RelativePath=".\apicoll.cpp">
			</File>
			<File
				RelativePath=".\apicoll.h">
			</File>
			<File
				RelativePath=".\cntabcol.cpp">
			</File>
			<File
				RelativePath=".\cntabcol.h">
			</File>
			<File
				RelativePath=".\currcoll.cpp">
			</File>
			<File
				RelativePath=".\currcoll.h">
			</File>
			<File
				RelativePath=".\dacoll.cpp">
			</File>
			<File
				RelativePath=".\dacoll.h">
			</File>
			<File
				RelativePath=".\dadrcoll.cpp">
			</File>
			<File
				RelativePath=".\dadrcoll.h">
			</File>
			<File
				RelativePath=".\decoll.cpp">
			</File>
			<File
				RelativePath=".\decoll.h">
			</File>
			<File
				RelativePath=".\encoll.cpp">
			</File>
			<File
				RelativePath=".\encoll.h">
			</File>
			<File
				RelativePath=".\escoll.cpp">
			</File>
			<File
				RelativePath=".\escoll.h">
			</File>
			<File
				RelativePath=".\ficoll.cpp">
			</File>
			<File
				RelativePath=".\ficoll.h">
			</File>
			<File
				RelativePath=".\frcoll.cpp">
			</File>
			<File
				RelativePath=".\frcoll.h">
			</File>
			<File
				RelativePath=".\g7coll.cpp">
			</File>
			<File
				RelativePath=".\g7coll.h">
			</File>
			<File
				RelativePath=".\itercoll.cpp">
			</File>
			<File
				RelativePath=".\itercoll.h">
			</File>
			<File
				RelativePath=".\jacoll.cpp">
			</File>
			<File
				RelativePath=".\jacoll.h">
			</File>
			<File
				RelativePath=".\lcukocol.cpp">
			</File>
			<File
				RelativePath=".\lcukocol.h">
			</File>
			<File
				RelativePath=".\mnkytst.cpp">
			</File>
			<File
				RelativePath=".\mnkytst.h">
			</File>
			<File
				RelativePath=".\regcoll.cpp">
			</File>
			<File
				RelativePath=".\regcoll.h">
			</File>
			<File
				RelativePath=".\srchtest.cpp">
			</File>
			<File
				RelativePath=".\srchtest.h">
			</File>
			<File
				RelativePath="svccoll.cpp">
			</File>
			<File
				RelativePath="svccoll.h">
			</File>
			<File
				RelativePath=".\thcoll.cpp">
			</File>
			<File
				RelativePath=".\thcoll.h">
			</File>
			<File
				RelativePath=".\trcoll.cpp">
			</File>
			<File
				RelativePath=".\trcoll.h">
			</File>
			<File
				RelativePath=".\tscoll.cpp">
			</File>
			<File
				RelativePath=".\tscoll.h">
			</File>
			<File
				RelativePath=".\ucaconf.cpp">
			</File>
			<File
				RelativePath=".\ucaconf.h">
			</File>
		</Filter>
		<Filter
			Name="configuration"
			Filter="">
			<File
				RelativePath=".\strtest.cpp">
			</File>
			<File
				RelativePath=".\strtest.h">
			</File>
			<File
				RelativePath=".\tsmthred.cpp">
				<FileConfiguration
					Name="Debug|Win32">
					<Tool
						Name="VCCLCompilerTool"
						DisableLanguageExtensions="FALSE"/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|Win32">
					<Tool
						Name="VCCLCompilerTool"
						DisableLanguageExtensions="FALSE"/>
				</FileConfiguration>
			</File>
			<File
				RelativePath=".\tsmthred.h">
			</File>
			<File
				RelativePath=".\tsmutex.cpp">
			</File>
			<File
				RelativePath=".\tsmutex.h">
			</File>
			<File
				RelativePath=".\tsputil.cpp">
			</File>
			<File
				RelativePath=".\tsputil.h">
			</File>
		</Filter>
		<Filter
			Name="data &amp; memory"
			Filter="">
			<File
				RelativePath=".\uobjtest.cpp">
			</File>
			<File
				RelativePath=".\uobjtest.h">
			</File>
		</Filter>
		<Filter
			Name="formatting"
			Filter="">
			<File
				RelativePath=".\callimts.cpp">
			</File>
			<File
				RelativePath=".\callimts.h">
			</File>
			<File
				RelativePath=".\calregts.cpp">
			</File>
			<File
				RelativePath=".\calregts.h">
			</File>
			<File
				RelativePath=".\caltest.cpp">
			</File>
			<File
				RelativePath=".\caltest.h">
			</File>
			<File
				RelativePath=".\caltztst.cpp">
			</File>
			<File
				RelativePath=".\caltztst.h">
			</File>
			<File
				RelativePath=".\dcfmapts.cpp">
			</File>
			<File
				RelativePath=".\dcfmapts.h">
			</File>
			<File
				RelativePath=".\dtfmapts.cpp">
			</File>
			<File
				RelativePath=".\dtfmapts.h">
			</File>
			<File
				RelativePath=".\dtfmrgts.cpp">
			</File>
			<File
				RelativePath=".\dtfmrgts.h">
			</File>
			<File
				RelativePath=".\dtfmtrtts.cpp">
			</File>
			<File
				RelativePath=".\dtfmtrtts.h">
			</File>
			<File
				RelativePath=".\dtfmttst.cpp">
			</File>
			<File
				RelativePath=".\dtfmttst.h">
			</File>
			<File
				RelativePath=".\incaltst.cpp">
			</File>
			<File
				RelativePath=".\incaltst.h">
			</File>
			<File
				RelativePath=".\itformat.cpp">
			</File>
			<File
				RelativePath=".\itformat.h">
			</File>
			<File
				RelativePath=".\itrbnf.cpp">
			</File>
			<File
				RelativePath=".\itrbnf.h">
			</File>
			<File
				RelativePath=".\itrbnfrt.cpp">
			</File>
			<File
				RelativePath=".\itrbnfrt.h">
			</File>
			<File
				RelativePath=".\miscdtfm.cpp">
			</File>
			<File
				RelativePath=".\miscdtfm.h">
			</File>
			<File
				RelativePath=".\msfmrgts.cpp">
			</File>
			<File
				RelativePath=".\msfmrgts.h">
			</File>
			<File
				RelativePath=".\nmfmapts.cpp">
			</File>
			<File
				RelativePath=".\nmfmapts.h">
			</File>
			<File
				RelativePath=".\nmfmtrt.cpp">
			</File>
			<File
				RelativePath=".\nmfmtrt.h">
			</File>
			<File
				RelativePath=".\numfmtst.cpp">
			</File>
			<File
				RelativePath=".\numfmtst.h">
			</File>
			<File
				RelativePath=".\numrgts.cpp">
			</File>
			<File
				RelativePath=".\numrgts.h">
			</File>
			<File
				RelativePath=".\pptest.cpp">
			</File>
			<File
				RelativePath=".\pptest.h">
			</File>
			<File
				RelativePath=".\sdtfmtts.cpp">
			</File>
			<File
				RelativePath=".\sdtfmtts.h">
			</File>
			<File
				RelativePath=".\tchcfmt.cpp">
			</File>
			<File
				RelativePath=".\tchcfmt.h">
			</File>
			<File
				RelativePath=".\tfsmalls.cpp">
			</File>
			<File
				RelativePath=".\tfsmalls.h">
			</File>
			<File
				RelativePath=".\tmsgfmt.cpp">
			</File>
			<File
				RelativePath=".\tmsgfmt.h">
			</File>
			<File
				RelativePath=".\tsdate.cpp">
			</File>
			<File
				RelativePath=".\tsdate.h">
			</File>
			<File
				RelativePath=".\tsdcfmsy.cpp">
			</File>
			<File
				RelativePath=".\tsdcfmsy.h">
			</File>
			<File
				RelativePath=".\tsdtfmsy.cpp">
			</File>
			<File
				RelativePath=".\tsdtfmsy.h">
			</File>
			<File
				RelativePath=".\tsnmfmt.cpp">
			</File>
			<File
				RelativePath=".\tsnmfmt.h">
			</File>
			<File
				RelativePath=".\tzbdtest.cpp">
			</File>
			<File
				RelativePath=".\tzbdtest.h">
			</File>
			<File
				RelativePath=".\tzregts.cpp">
			</File>
			<File
				RelativePath=".\tzregts.h">
			</File>
			<File
				RelativePath=".\tztest.cpp">
			</File>
			<File
				RelativePath=".\tztest.h">
			</File>
		</Filter>
		<Filter
			Name="locales &amp; resources"
			Filter="">
			<File
				RelativePath=".\loctest.cpp">
			</File>
			<File
				RelativePath=".\loctest.h">
			</File>
			<File
				RelativePath=".\restest.cpp">
			</File>
			<File
				RelativePath=".\restest.h">
			</File>
			<File
				RelativePath=".\restsnew.cpp">
			</File>
			<File
				RelativePath=".\restsnew.h">
			</File>
		</Filter>
		<Filter
			Name="misc"
			Filter="">
			<File
				RelativePath=".\datamap.cpp">
			</File>
			<File
				RelativePath=".\datamap.h">
			</File>
			<File
				RelativePath=".\intltest.cpp">
			</File>
			<File
				RelativePath=".\intltest.h">
			</File>
			<File
				RelativePath=".\itmajor.cpp">
			</File>
			<File
				RelativePath=".\itmajor.h">
			</File>
			<File
				RelativePath=".\itutil.cpp">
			</File>
			<File
				RelativePath=".\itutil.h">
			</File>
			<File
				RelativePath=".\testdata.cpp">
			</File>
			<File
				RelativePath=".\testdata.h">
			</File>
			<File
				RelativePath=".\testutil.cpp">
			</File>
			<File
				RelativePath=".\testutil.h">
			</File>
			<File
				RelativePath=".\tstdtmod.cpp">
			</File>
			<File
				RelativePath=".\tstdtmod.h">
			</File>
		</Filter>
		<Filter
			Name="normalization"
			Filter="">
			<File
				RelativePath=".\canittst.cpp">
			</File>
			<File
				RelativePath=".\canittst.h">
			</File>
			<File
				RelativePath=".\normconf.cpp">
			</File>
			<File
				RelativePath=".\normconf.h">
			</File>
			<File
				RelativePath=".\tstnorm.cpp">
			</File>
			<File
				RelativePath=".\tstnorm.h">
			</File>
			<File
				RelativePath=".\tstnrapi.cpp">
			</File>
		</Filter>
		<Filter
			Name="properties &amp; sets"
			Filter="">
			<File
				RelativePath=".\ucdtest.cpp">
			</File>
			<File
				RelativePath=".\ucdtest.h">
			</File>
			<File
				RelativePath=".\usettest.cpp">
			</File>
			<File
				RelativePath=".\usettest.h">
			</File>
		</Filter>
		<Filter
			Name="regex"
			Filter="">
			<File
				RelativePath=".\regextst.cpp">
			</File>
			<File
				RelativePath=".\regextst.h">
			</File>
		</Filter>
		<Filter
			Name="registration"
			Filter="">
			<File
				RelativePath=".\icusvtst.cpp">
			</File>
			<File
				RelativePath=".\icusvtst.h">
			</File>
		</Filter>
		<Filter
			Name="strings"
			Filter="">
			<File
				RelativePath=".\citrtest.cpp">
			</File>
			<File
				RelativePath=".\citrtest.h">
			</File>
			<File
				RelativePath=".\reptest.cpp">
			</File>
			<File
				RelativePath=".\reptest.h">
			</File>
			<File
				RelativePath=".\sfwdchit.cpp">
			</File>
			<File
				RelativePath=".\sfwdchit.h">
			</File>
			<File
				RelativePath=".\strcase.cpp">
			</File>
			<File
				RelativePath=".\ustrtest.cpp">
			</File>
			<File
				RelativePath=".\ustrtest.h">
			</File>
		</Filter>
		<Filter
			Name="transforms"
			Filter="">
			<File
				RelativePath=".\cpdtrtst.cpp">
			</File>
			<File
				RelativePath=".\cpdtrtst.h">
			</File>
			<File
				RelativePath=".\hxuntrts.cpp">
			</File>
			<File
				RelativePath=".\hxuntrts.h">
			</File>
			<File
				RelativePath=".\ittrans.cpp">
			</File>
			<File
				RelativePath=".\ittrans.h">
			</File>
			<File
				RelativePath=".\jamotest.cpp">
			</File>
			<File
				RelativePath=".\jamotest.h">
			</File>
			<File
				RelativePath=".\transapi.cpp">
			</File>
			<File
				RelativePath=".\transapi.h">
			</File>
			<File
				RelativePath=".\transrt.cpp">
			</File>
			<File
				RelativePath=".\transrt.h">
			</File>
			<File
				RelativePath=".\transtst.cpp">
			</File>
			<File
				RelativePath=".\transtst.h">
			</File>
			<File
				RelativePath=".\trnserr.cpp">
			</File>
			<File
				RelativePath=".\trnserr.h">
			</File>
			<File
				RelativePath=".\ufltlgts.cpp">
			</File>
			<File
				RelativePath=".\ufltlgts.h">
			</File>
			<File
				RelativePath=".\unhxtrts.cpp">
			</File>
			<File
				RelativePath=".\unhxtrts.h">
			</File>
		</Filter>
		<Filter
			Name="idna"
			Filter="*.c,*.h">
			<File
				RelativePath=".\idnaref.cpp">
			</File>
			<File
				RelativePath=".\idnaref.h">
			</File>
			<File
				RelativePath=".\nptrans.cpp">
			</File>
			<File
				RelativePath=".\nptrans.h">
			</File>
			<File
				RelativePath=".\punyref.c">
			</File>
			<File
				RelativePath=".\punyref.h">
			</File>
			<File
				RelativePath=".\testidn.cpp">
			</File>
			<File
				RelativePath=".\testidna.cpp">
			</File>
			<File
				RelativePath=".\testidna.h">
			</File>
		</Filter>
		<Filter
			Name="collections"
			Filter="">
		</Filter>
	</Files>
	<Globals>
	</Globals>
</VisualStudioProject>





































--- NEW FILE: nptrans.cpp ---
/*
 *******************************************************************************
 *
 *   Copyright (C) 2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 *   file name:  nptrans.h
 *   encoding:   US-ASCII
 *   tab size:   8 (not used)
 *   indentation:4
 *
 *   created on: 2003feb1
 *   created by: Ram Viswanadha
 */

#include "unicode/utypes.h"

#if !UCONFIG_NO_TRANSLITERATION
#if !UCONFIG_NO_IDNA

#include "nptrans.h"
#include "unicode/resbund.h"
#include "unicode/uniset.h"
#include "sprpimpl.h"
#include "cmemory.h"
#include "ustr_imp.h"
#include "intltest.h"

#ifdef DEBUG 
#include <stdio.h>
#endif

const char NamePrepTransform::fgClassID=0;

//Factory method
NamePrepTransform* NamePrepTransform::createInstance(UParseError& parseError, UErrorCode& status){
    NamePrepTransform* transform = new NamePrepTransform(parseError, status);
    if(U_FAILURE(status)){
        delete transform;
        return NULL;
    }
    return transform;
}

//constructor
NamePrepTransform::NamePrepTransform(UParseError& parseError, UErrorCode& status)
: unassigned(), prohibited(), labelSeparatorSet(){
        
    mapping = NULL;
    bundle = NULL;


    const char* testDataName = IntlTest::loadTestData(status);
    
    if(U_FAILURE(status)){
        return;
    }
    
    bundle = ures_openDirect(testDataName,"idna_rules",&status);
    
    if(bundle != NULL && U_SUCCESS(status)){
        // create the mapping transliterator
        int32_t ruleLen = 0;
        const UChar* ruleUChar = ures_getStringByKey(bundle, "MapNFKC",&ruleLen, &status);
        UnicodeString rule(ruleUChar, ruleLen);
        
        mapping = Transliterator::createFromRules(UnicodeString("NamePrepTransform", ""), rule,
                                                   UTRANS_FORWARD, parseError,status);
        if(U_FAILURE(status)) {
          return;
        }

        //create the unassigned set
        int32_t patternLen =0;
        const UChar* pattern = ures_getStringByKey(bundle,"UnassignedSet",&patternLen, &status);
        unassigned.applyPattern(UnicodeString(pattern, patternLen), status);

        //create prohibited set
        patternLen=0;
        pattern =  ures_getStringByKey(bundle,"ProhibitedSet",&patternLen, &status);
        UnicodeString test(pattern,patternLen);
        prohibited.applyPattern(test,status);
#ifdef DEBUG
        if(U_FAILURE(status)){
            printf("Construction of Unicode set failed\n");
        }

        if(U_SUCCESS(status)){
            if(prohibited.contains((UChar) 0x644)){
                printf("The string contains 0x644 ... damn !!\n");
            }
            UnicodeString temp;
            prohibited.toPattern(temp,TRUE);

            for(int32_t i=0;i<temp.length();i++){
                printf("%c", (char)temp.charAt(i));
            }
            printf("\n");
        }
#endif
        
        //create label separator set
        patternLen=0;
        pattern =  ures_getStringByKey(bundle,"LabelSeparatorSet",&patternLen, &status);
        labelSeparatorSet.applyPattern(UnicodeString(pattern,patternLen),status);
    }

    if(U_SUCCESS(status) && 
        (mapping == NULL)
      ){
        status = U_MEMORY_ALLOCATION_ERROR;
        delete mapping;
        ures_close(bundle);
        mapping = NULL;
        bundle = NULL;
    }
        
}


UBool NamePrepTransform::isProhibited(UChar32 ch){ 
    return (UBool)(ch != ASCII_SPACE); 
}

NamePrepTransform::~NamePrepTransform(){
    delete mapping;
    mapping = NULL;
    
    //close the bundle
    ures_close(bundle);
    bundle = NULL;
}


int32_t NamePrepTransform::map(const UChar* src, int32_t srcLength, 
                        UChar* dest, int32_t destCapacity, 
                        UBool allowUnassigned,
                        UParseError* /*parseError*/,
                        UErrorCode& status ){

    if(U_FAILURE(status)){
        return 0;
    }
    //check arguments
    if(src==NULL || srcLength<-1 || (dest==NULL && destCapacity!=0)) {
        status=U_ILLEGAL_ARGUMENT_ERROR;
        return 0;
    }

    UnicodeString rsource(src,srcLength);
    // map the code points
    // transliteration also performs NFKC
    mapping->transliterate(rsource);
    
    const UChar* buffer = rsource.getBuffer();
    int32_t bufLen = rsource.length();
    // check if unassigned
    if(allowUnassigned == FALSE){
        int32_t bufIndex=0;
        UChar32 ch =0 ;
        for(;bufIndex<bufLen;){
            U16_NEXT(buffer, bufIndex, bufLen, ch);
            if(unassigned.contains(ch)){
                status = U_IDNA_UNASSIGNED_CODEPOINT_FOUND_ERROR;
                rsource.releaseBuffer();
                return 0;
            }
        }
    }
    // check if there is enough room in the output
    if(bufLen < destCapacity){
        uprv_memcpy(dest,buffer,bufLen*U_SIZEOF_UCHAR);
    }

    return u_terminateUChars(dest, destCapacity, bufLen, &status);
}


#define MAX_BUFFER_SIZE 300

int32_t NamePrepTransform::process( const UChar* src, int32_t srcLength, 
                                    UChar* dest, int32_t destCapacity, 
                                    UBool allowUnassigned,
                                    UParseError* parseError,
                                    UErrorCode& status ){
    // check error status
    if(U_FAILURE(status)){
        return 0;
    }
    
    //check arguments
    if(src==NULL || srcLength<-1 || (dest==NULL && destCapacity!=0)) {
        status=U_ILLEGAL_ARGUMENT_ERROR;
        return 0;
    }

    UChar b1Stack[MAX_BUFFER_SIZE];
    UChar *b1 = b1Stack;
    int32_t b1Len,b1Capacity = MAX_BUFFER_SIZE;

    int32_t b1Index = 0;
    UCharDirection direction=U_CHAR_DIRECTION_COUNT, firstCharDir=U_CHAR_DIRECTION_COUNT;
    UBool leftToRight=FALSE, rightToLeft=FALSE;

    b1Len = map(src,srcLength, b1, b1Capacity,allowUnassigned,parseError, status);

    if(status == U_BUFFER_OVERFLOW_ERROR){
        // redo processing of string
        /* we do not have enough room so grow the buffer*/
        if(!u_growBufferFromStatic(b1Stack,&b1,&b1Capacity,b1Len,0)){
            status = U_MEMORY_ALLOCATION_ERROR;
            goto CLEANUP;
        }

        status = U_ZERO_ERROR; // reset error
        
        b1Len = map(src,srcLength, b1, b1Len,allowUnassigned, parseError, status);
        
    }

    if(U_FAILURE(status)){
        goto CLEANUP;
    }


    for(; b1Index<b1Len; ){

        UChar32 ch = 0;

        U16_NEXT(b1, b1Index, b1Len, ch);

        if(prohibited.contains(ch) && ch!=0x0020){
            status = U_IDNA_PROHIBITED_CODEPOINT_FOUND_ERROR;
            goto CLEANUP;
        }

        direction = u_charDirection(ch);
        if(firstCharDir==U_CHAR_DIRECTION_COUNT){
            firstCharDir = direction;
        }
        if(direction == U_LEFT_TO_RIGHT){
            leftToRight = TRUE;
        }
        if(direction == U_RIGHT_TO_LEFT || direction == U_RIGHT_TO_LEFT_ARABIC){
            rightToLeft = TRUE;
        }
    }       
    
    // satisfy 2
    if( leftToRight == TRUE && rightToLeft == TRUE){
        status = U_IDNA_CHECK_BIDI_ERROR;
        goto CLEANUP;
    }

    //satisfy 3
    if( rightToLeft == TRUE && 
        !((firstCharDir == U_RIGHT_TO_LEFT || firstCharDir == U_RIGHT_TO_LEFT_ARABIC) &&
          (direction == U_RIGHT_TO_LEFT || direction == U_RIGHT_TO_LEFT_ARABIC))
       ){
        status = U_IDNA_CHECK_BIDI_ERROR;
        return FALSE;
    }

    if(b1Len <= destCapacity){
        uprv_memmove(dest,b1, b1Len*U_SIZEOF_UCHAR);
    }

CLEANUP:
    if(b1!=b1Stack){
        uprv_free(b1);
    }

    return u_terminateUChars(dest, destCapacity, b1Len, &status);
}

UBool NamePrepTransform::isLabelSeparator(UChar32 ch, UErrorCode& status){
    // check error status
    if(U_FAILURE(status)){
        return FALSE;
    }

    return labelSeparatorSet.contains(ch);
}

#endif /* #if !UCONFIG_NO_IDNA */
#endif /* #if !UCONFIG_NO_TRANSLITERATION */

--- NEW FILE: nptrans.h ---
/*
 *******************************************************************************
 *
 *   Copyright (C) 2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 *   file name:  nptrans.h
 *   encoding:   US-ASCII
 *   tab size:   8 (not used)
 *   indentation:4
 *
 *   created on: 2003feb1
 *   created by: Ram Viswanadha
 */

#ifndef NPTRANS_H
#define NPTRANS_H

#include "unicode/utypes.h"

#if !UCONFIG_NO_IDNA
#if !UCONFIG_NO_TRANSLITERATION

#include "strprep.h"
#include "unicode/uniset.h"
#include "unicode/ures.h"
#include "unicode/translit.h"



#define ASCII_SPACE 0x0020

class NamePrepTransform {

private :
    Transliterator *mapping;
    UnicodeSet unassigned;
    UnicodeSet prohibited;
    UnicodeSet labelSeparatorSet;
    UResourceBundle *bundle;
    NamePrepTransform(UParseError& parseError, UErrorCode& status);


public :

    static NamePrepTransform* createInstance(UParseError& parseError, UErrorCode& status);

    virtual ~NamePrepTransform();


    inline UBool isProhibited(UChar32 ch);
    
    /**
     * ICU "poor man's RTTI", returns a UClassID for the actual class.
     *
     * @draft ICU 2.6
     */
    inline UClassID getDynamicClassID() const { return getStaticClassID(); }

    /**
     * ICU "poor man's RTTI", returns a UClassID for this class.
     *
     * @draft ICU 2.6
     */
    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }

    /**
     * Map every character in input stream with mapping character 
     * in the mapping table and populate the output stream.
     * For any individual character the mapping table may specify 
     * that that a character be mapped to nothing, mapped to one 
     * other character or to a string of other characters.
     *
     * @param src           Pointer to UChar buffer containing a single label
     * @param srcLength     Number of characters in the source label
     * @param dest          Pointer to the destination buffer to receive the output
     * @param destCapacity  The capacity of destination array
     * @param allowUnassigned   Unassigned values can be converted to ASCII for query operations
     *                          If TRUE unassigned values are treated as normal Unicode code point.
     *                          If FALSE the operation fails with U_UNASSIGNED_CODE_POINT_FOUND error code.
     * @param status        ICU error code in/out parameter.
     *                      Must fulfill U_SUCCESS before the function call.
     * @return The number of UChars in the destination buffer
     *
     */
    int32_t map(const UChar* src, int32_t srcLength, 
                        UChar* dest, int32_t destCapacity, 
                        UBool allowUnassigned,
                        UParseError* parseError,
                        UErrorCode& status );

    /**
     * Prepare the input stream with for use. This operation maps, normalizes(NFKC),
     * checks for prohited and BiDi characters in the order defined by RFC 3454
     * 
     * @param src           Pointer to UChar buffer containing a single label
     * @param srcLength     Number of characters in the source label
     * @param dest          Pointer to the destination buffer to receive the output
     * @param destCapacity  The capacity of destination array
     * @param allowUnassigned   Unassigned values can be converted to ASCII for query operations
     *                          If TRUE unassigned values are treated as normal Unicode code point.
     *                          If FALSE the operation fails with U_UNASSIGNED_CODE_POINT error code.
     * @param status        ICU error code in/out parameter.
     *                      Must fulfill U_SUCCESS before the function call.
     * @return The number of UChars in the destination buffer
     */
    int32_t process(const UChar* src, int32_t srcLength, 
                            UChar* dest, int32_t destCapacity, 
                            UBool allowUnassigned,
                            UParseError* parseError,
                            UErrorCode& status );

    /**
     * Ascertain if the given code point is a label separator as specified by IDNA
     *
     * @return TRUE is the code point is a label separator
     *
     *
     */
    UBool isLabelSeparator(UChar32 ch, UErrorCode& status);

    
    inline UBool isLDHChar(UChar32 ch);
private:        
    /**
     * The address of this static class variable serves as this class's ID
     * for ICU "poor man's RTTI".
     */
    static const char fgClassID;
};

inline UBool NamePrepTransform::isLDHChar(UChar32 ch){
    // high runner case
    if(ch>0x007A){
        return FALSE;
    }
    //[\\u002D \\u0030-\\u0039 \\u0041-\\u005A \\u0061-\\u007A]
    if( (ch==0x002D) || 
        (0x0030 <= ch && ch <= 0x0039) ||
        (0x0041 <= ch && ch <= 0x005A) ||
        (0x0061 <= ch && ch <= 0x007A)
      ){
        return TRUE;
    }
    return FALSE;
}

#endif /* #if !UCONFIG_NO_TRANSLITERATION */
#else
class NamePrepTransform {
};
#endif /* #if !UCONFIG_NO_IDNA */

#endif

/*
 * Hey, Emacs, please set the following:
 *
 * Local Variables:
 * indent-tabs-mode: nil
 * End:
 *
 */







--- NEW FILE: punyref.c ---
/*
 *******************************************************************************
 *
 *   Copyright (C) 2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 *   file name:  nameprep.h
 *   encoding:   US-ASCII
 *   tab size:   8 (not used)
 *   indentation:4
 *
 *   created on: 2003feb1
 *   created by: Ram Viswanadha
 */

/*
Disclaimer and license

    Regarding this entire document or any portion of it (including
    the pseudocode and C code), the author makes no guarantees and
    is not responsible for any damage resulting from its use.  The
    author grants irrevocable permission to anyone to use, modify,
    and distribute it in any way that does not diminish the rights
    of anyone else to use, modify, and distribute it, provided that
    redistributed derivative works do not contain misleading author or
    version information.  Derivative works need not be licensed under
    similar terms.

punycode.c 0.4.0 (2001-Nov-17-Sat)
http://www.cs.berkeley.edu/~amc/idn/
Adam M. Costello
http://www.nicemice.net/amc/
*/

/**********************************************************/
/* Implementation (would normally go in its own .c file): */

#include <string.h>

#include "unicode/utypes.h"

#if !UCONFIG_NO_IDNA

#include "punyref.h"

/*** Bootstring parameters for Punycode ***/

enum { base = 36, tmin = 1, tmax = 26, skew = 38, damp = 700,
       initial_bias = 72, initial_n = 0x80, delimiter = 0x2D };

/* basic(cp) tests whether cp is a basic code point: */
#define basic(cp) ((punycode_uint)(cp) < 0x80)

/* delim(cp) tests whether cp is a delimiter: */
#define delim(cp) ((cp) == delimiter)

U_CDECL_BEGIN
/* decode_digit(cp) returns the numeric value of a basic code */
/* point (for use in representing integers) in the range 0 to */
/* base-1, or base if cp is does not represent a value.       */

static punycode_uint decode_digit(punycode_uint cp)
{
  return  cp - 48 < 10 ? cp - 22 :  cp - 65 < 26 ? cp - 65 :
          cp - 97 < 26 ? cp - 97 :  base;
}

/* encode_digit(d,flag) returns the basic code point whose value      */
/* (when used for representing integers) is d, which needs to be in   */
/* the range 0 to base-1.  The lowercase form is used unless flag is  */
/* nonzero, in which case the uppercase form is used.  The behavior   */
/* is undefined if flag is nonzero and digit d has no uppercase form. */

static char encode_digit(punycode_uint d, int flag)
{
  return (char) d + 22 + 75 * (d < 26) - ((flag != 0) << 5);
  /*  0..25 map to ASCII a..z or A..Z */
  /* 26..35 map to ASCII 0..9         */
}

/* flagged(bcp) tests whether a basic code point is flagged */
/* (uppercase).  The behavior is undefined if bcp is not a  */
/* basic code point.                                        */

#define flagged(bcp) ((punycode_uint)(bcp) - 65 < 26)

/* encode_basic(bcp,flag) forces a basic code point to lowercase */
/* if flag is zero, uppercase if flag is nonzero, and returns    */
/* the resulting code point.  The code point is unchanged if it  */
/* is caseless.  The behavior is undefined if bcp is not a basic */
/* code point.                                                   */

static char encode_basic(punycode_uint bcp, int flag)
{
  bcp -= (bcp - 97 < 26) << 5;
  return (char) bcp + ((!flag && (bcp - 65 < 26)) << 5);
}

/*** Platform-specific constants ***/

/* maxint is the maximum value of a punycode_uint variable: */
static const punycode_uint maxint = (punycode_uint) (-1);
/* Because maxint is unsigned, -1 becomes the maximum value. */

/*** Bias adaptation function ***/

static punycode_uint adapt(
  punycode_uint delta, punycode_uint numpoints, int firsttime )
{
  punycode_uint k;

  delta = firsttime ? delta / damp : delta >> 1;
  /* delta >> 1 is a faster way of doing delta / 2 */
  delta += delta / numpoints;

  for (k = 0;  delta > ((base - tmin) * tmax) / 2;  k += base) {
    delta /= base - tmin;
  }

  return k + (base - tmin + 1) * delta / (delta + skew);
}

/*** Main encode function ***/

enum punycode_status punycode_encode(
  punycode_uint input_length,
  const punycode_uint input[],
  const unsigned char case_flags[],
  punycode_uint *output_length,
  char output[] )
{
  punycode_uint n, delta, h, b, out, max_out, bias, j, m, q, k, t;

  /* Initialize the state: */

  n = initial_n;
  delta = out = 0;
  max_out = *output_length;
  bias = initial_bias;

  /* Handle the basic code points: */

  for (j = 0;  j < input_length;  ++j) {
    if (basic(input[j])) {
      if (max_out - out < 2) return punycode_big_output;
      output[out++] = (char)
        (case_flags ?  encode_basic(input[j], case_flags[j]) : input[j]);
    }
    /* else if (input[j] < n) return punycode_bad_input; */
    /* (not needed for Punycode with unsigned code points) */
  }

  h = b = out;

  /* h is the number of code points that have been handled, b is the  */
  /* number of basic code points, and out is the number of characters */
  /* that have been output.                                           */

  if (b > 0) output[out++] = delimiter;

  /* Main encoding loop: */

  while (h < input_length) {
    /* All non-basic code points < n have been     */
    /* handled already.  Find the next larger one: */

    for (m = maxint, j = 0;  j < input_length;  ++j) {
      /* if (basic(input[j])) continue; */
      /* (not needed for Punycode) */
      if (input[j] >= n && input[j] < m) m = input[j];
    }

    /* Increase delta enough to advance the decoder's    */
    /* <n,i> state to <m,0>, but guard against overflow: */

    if (m - n > (maxint - delta) / (h + 1)) return punycode_overflow;
    delta += (m - n) * (h + 1);
    n = m;

    for (j = 0;  j < input_length;  ++j) {
      /* Punycode does not need to check whether input[j] is basic: */
      if (input[j] < n /* || basic(input[j]) */ ) {
        if (++delta == 0) return punycode_overflow;
      }

      if (input[j] == n) {
        /* Represent delta as a generalized variable-length integer: */

        for (q = delta, k = base;  ;  k += base) {
          if (out >= max_out) return punycode_big_output;
          t = k <= bias /* + tmin */ ? tmin :     /* +tmin not needed */
              k >= bias + tmax ? tmax : k - bias;
          if (q < t) break;
          output[out++] = encode_digit(t + (q - t) % (base - t), 0);
          q = (q - t) / (base - t);
        }

        output[out++] = encode_digit(q, case_flags && case_flags[j]);
        bias = adapt(delta, h + 1, h == b);
        delta = 0;
        ++h;
      }
    }

    ++delta, ++n;
  }

  *output_length = out;
  return punycode_success;
}

/*** Main decode function ***/

enum punycode_status punycode_decode(
  punycode_uint input_length,
  const char input[],
  punycode_uint *output_length,
  punycode_uint output[],
  unsigned char case_flags[] )
{
  punycode_uint n, out, i, max_out, bias,
                 b, j, in, oldi, w, k, digit, t;

  /* Initialize the state: */

  n = initial_n;
  out = i = 0;
  max_out = *output_length;
  bias = initial_bias;

  /* Handle the basic code points:  Let b be the number of input code */
  /* points before the last delimiter, or 0 if there is none, then    */
  /* copy the first b code points to the output.                      */

  for (b = j = 0;  j < input_length;  ++j) if (delim(input[j])) b = j;
  if (b > max_out) return punycode_big_output;

  for (j = 0;  j < b;  ++j) {
    if (case_flags) case_flags[out] = flagged(input[j]);
    if (!basic(input[j])) return punycode_bad_input;
    output[out++] = input[j];
  }

  /* Main decoding loop:  Start just after the last delimiter if any  */
  /* basic code points were copied; start at the beginning otherwise. */

  for (in = b > 0 ? b + 1 : 0;  in < input_length;  ++out) {

    /* in is the index of the next character to be consumed, and */
    /* out is the number of code points in the output array.     */

    /* Decode a generalized variable-length integer into delta,  */
    /* which gets added to i.  The overflow checking is easier   */
    /* if we increase i as we go, then subtract off its starting */
    /* value at the end to obtain delta.                         */

    for (oldi = i, w = 1, k = base;  ;  k += base) {
      if (in >= input_length) return punycode_bad_input;
      digit = decode_digit(input[in++]);
      if (digit >= base) return punycode_bad_input;
      if (digit > (maxint - i) / w) return punycode_overflow;
      i += digit * w;
      t = k <= bias /* + tmin */ ? tmin :     /* +tmin not needed */
          k >= bias + tmax ? tmax : k - bias;
      if (digit < t) break;
      if (w > maxint / (base - t)) return punycode_overflow;
      w *= (base - t);
    }

    bias = adapt(i - oldi, out + 1, oldi == 0);

    /* i was supposed to wrap around from out+1 to 0,   */
    /* incrementing n each time, so we'll fix that now: */

    if (i / (out + 1) > maxint - n) return punycode_overflow;
    n += i / (out + 1);
    i %= (out + 1);

    /* Insert n at position i of the output: */

    /* not needed for Punycode: */
    /* if (decode_digit(n) <= base) return punycode_invalid_input; */
    if (out >= max_out) return punycode_big_output;

    if (case_flags) {
      memmove(case_flags + i + 1, case_flags + i, out - i);
      /* Case of last character determines uppercase flag: */
      case_flags[i] = flagged(input[in - 1]);
    }

    memmove(output + i + 1, output + i, (out - i) * sizeof *output);
    output[i++] = n;
  }

  *output_length = out;
  return punycode_success;
}

U_CDECL_END

#endif /* #if !UCONFIG_NO_IDNA */

--- NEW FILE: punyref.h ---
/*
 ******************************************************************************
 *
 *   Copyright (C) 2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 ******************************************************************************
 */
/*
punycode.c from draft-ietf-idn-punycode-03
http://www.nicemice.net/idn/
Adam M. Costello
http://www.nicemice.net/amc/

This is ANSI C code (C89) implementing
Punycode (draft-ietf-idn-punycode-03).

Disclaimer and license

    Regarding this entire document or any portion of it (including
    the pseudocode and C code), the author makes no guarantees and
    is not responsible for any damage resulting from its use.  The
    author grants irrevocable permission to anyone to use, modify,
    and distribute it in any way that does not diminish the rights
    of anyone else to use, modify, and distribute it, provided that
    redistributed derivative works do not contain misleading author or
    version information.  Derivative works need not be licensed under
    similar terms.

*/
#ifndef _PUNYREF_H
#define _PUNYREF_H

/************************************************************/
/* Public interface (would normally go in its own .h file): */

#include <limits.h>
#include "unicode/utypes.h"

#if !UCONFIG_NO_IDNA

enum punycode_status {
  punycode_success,
  punycode_bad_input,   /* Input is invalid.                       */
  punycode_big_output,  /* Output would exceed the space provided. */
  punycode_overflow     /* Input needs wider integers to process.  */
};


typedef uint32_t punycode_uint;

U_CDECL_BEGIN

enum punycode_status  punycode_encode(
  punycode_uint input_length,
  const punycode_uint input[],
  const unsigned char case_flags[],
  punycode_uint *output_length,
  char output[] );

    /* punycode_encode() converts Unicode to Punycode.  The input     */
    /* is represented as an array of Unicode code points (not code    */
    /* units; surrogate pairs are not allowed), and the output        */
    /* will be represented as an array of ASCII code points.  The     */
    /* output string is *not* null-terminated; it will contain        */
    /* zeros if and only if the input contains zeros.  (Of course     */
    /* the caller can leave room for a terminator and add one if      */
    /* needed.)  The input_length is the number of code points in     */
    /* the input.  The output_length is an in/out argument: the       */
    /* caller passes in the maximum number of code points that it     */
    /* can receive, and on successful return it will contain the      */
    /* number of code points actually output.  The case_flags array   */
    /* holds input_length boolean values, where nonzero suggests that */
    /* the corresponding Unicode character be forced to uppercase     */
    /* after being decoded (if possible), and zero suggests that      */
    /* it be forced to lowercase (if possible).  ASCII code points    */
    /* are encoded literally, except that ASCII letters are forced    */
    /* to uppercase or lowercase according to the corresponding       */
    /* uppercase flags.  If case_flags is a null pointer then ASCII   */
    /* letters are left as they are, and other code points are        */
    /* treated as if their uppercase flags were zero.  The return     */
    /* value can be any of the punycode_status values defined above   */
    /* except punycode_bad_input; if not punycode_success, then       */
    /* output_size and output might contain garbage.                  */

enum punycode_status punycode_decode(
  punycode_uint input_length,
  const char input[],
  punycode_uint *output_length,
  punycode_uint output[],
  unsigned char case_flags[] );

    /* punycode_decode() converts Punycode to Unicode.  The input is  */
    /* represented as an array of ASCII code points, and the output   */
    /* will be represented as an array of Unicode code points.  The   */
    /* input_length is the number of code points in the input.  The   */
    /* output_length is an in/out argument: the caller passes in      */
    /* the maximum number of code points that it can receive, and     */
    /* on successful return it will contain the actual number of      */
    /* code points output.  The case_flags array needs room for at    */
    /* least output_length values, or it can be a null pointer if the */
    /* case information is not needed.  A nonzero flag suggests that  */
    /* the corresponding Unicode character be forced to uppercase     */
    /* by the caller (if possible), while zero suggests that it be    */
    /* forced to lowercase (if possible).  ASCII code points are      */
    /* output already in the proper case, but their flags will be set */
    /* appropriately so that applying the flags would be harmless.    */
    /* The return value can be any of the punycode_status values      */
    /* defined above; if not punycode_success, then output_length,    */
    /* output, and case_flags might contain garbage.  On success, the */
    /* decoder will never need to write an output_length greater than */
    /* input_length, because of how the encoding is defined.          */
U_CDECL_END

#endif /* #if !UCONFIG_NO_IDNA */

#endif







--- NEW FILE: regextst.cpp ---
/********************************************************************
 * COPYRIGHT:
 * Copyright (c) 2002-2003, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

//
//   regextst.cpp
//
//      ICU Regular Expressions test, part of intltest.
//

#include "unicode/utypes.h"
#if !UCONFIG_NO_REGULAR_EXPRESSIONS

#include "unicode/uchar.h"
#include "unicode/ucnv.h"
#include "intltest.h"
#include "regextst.h"
[...1801 lines suppressed...]
    delete groupsPat;
    
    delete flagMat;
    delete flagPat;

    delete lineMat;
    delete linePat;
    
    delete fieldPat;
    delete [] testData;
    

    logln("%d tests skipped because of unimplemented regexp features.", skippedUnimplementedCount);

}



#endif  /* !UCONFIG_NO_REGULAR_EXPRESSIONS  */


--- NEW FILE: regextst.h ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 2002-2003, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/


#ifndef REGEXTST_H
#define REGEXTST_H

#include "unicode/utypes.h"
#if !UCONFIG_NO_REGULAR_EXPRESSIONS

#include "intltest.h"
#include "unicode/regex.h"


class RegexTest: public IntlTest {
public:
  
    RegexTest();
    virtual ~RegexTest();

    virtual void runIndexedTest(int32_t index, UBool exec, const char* &name, char* par = NULL );

    // The following are test functions that are visible from the intltest test framework.
    virtual void API_Match();
    virtual void API_Pattern();
    virtual void API_Replace();
    virtual void Basic();
    virtual void Extended();
    virtual void Errors();
    virtual void PerlTests();

    // The following functions are internal to the regexp tests.
    virtual UBool doRegexLMTest(const char *pat, const char *text, UBool looking, UBool match, int line);
    virtual void regex_find(const UnicodeString &pat, const UnicodeString &flags,
        const UnicodeString &input, int line);
    virtual void regex_err(const char *pat, int32_t errline, int32_t errcol,
                            UErrorCode expectedStatus, int line);
    virtual UChar *ReadAndConvertFile(const char *fileName, int &len, UErrorCode &status);
};

#endif   // !UCONFIG_NO_REGULAR_EXPRESSIONS
#endif













--- NEW FILE: strcase.cpp ---
/*
*******************************************************************************
*
*   Copyright (C) 2002-2003, International Business Machines
*   Corporation and others.  All Rights Reserved.
*
*******************************************************************************
*   file name:  strcase.cpp
*   encoding:   US-ASCII
*   tab size:   8 (not used)
*   indentation:4
*
*   created on: 2002mar12
*   created by: Markus W. Scherer
*
*   Test file for string casing C++ API functions.
*/

#include "unicode/utypes.h"
#include "unicode/uchar.h"
#include "unicode/unistr.h"
#include "unicode/ures.h"
#include "unicode/uloc.h"
#include "unicode/locid.h"
#include "unicode/ubrk.h"
#include "ustrtest.h"
#include "tstdtmod.h"

void
StringCaseTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char * /*par*/) {
    if (exec) logln("TestSuite StringCaseTest: ");
    switch (index) {
        case 0: name = "TestCaseConversion"; if (exec) TestCaseConversion(); break;
        case 1:
            name = "TestTitleCasing";
#if !UCONFIG_NO_BREAK_ITERATION
            if(exec) TestTitleCasing();
#endif
            break;

        default: name = ""; break; //needed to end loop
    }
}

void
StringCaseTest::TestCaseConversion()
{
    UChar uppercaseGreek[] =
        { 0x399, 0x395, 0x3a3, 0x3a5, 0x3a3, 0x20, 0x03a7, 0x3a1, 0x399, 0x3a3, 0x3a4,
        0x39f, 0x3a3, 0 };
        // "IESUS CHRISTOS"

    UChar lowercaseGreek[] = 
        { 0x3b9, 0x3b5, 0x3c3, 0x3c5, 0x3c2, 0x20, 0x03c7, 0x3c1, 0x3b9, 0x3c3, 0x3c4,
        0x3bf, 0x3c2, 0 };
        // "iesus christos"

    UChar lowercaseTurkish[] = 
        { 0x69, 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, 0x2c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 
        0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x0131, 0x6e, 0x6f, 0x70, 0x6c, 0x65, 0x21, 0 };

    UChar uppercaseTurkish[] = 
        { 0x54, 0x4f, 0x50, 0x4b, 0x41, 0x50, 0x49, 0x20, 0x50, 0x41, 0x4c, 0x41, 0x43, 0x45, 0x2c, 0x20,
        0x0130, 0x53, 0x54, 0x41, 0x4e, 0x42, 0x55, 0x4c, 0 };
    
    UnicodeString expectedResult;
    UnicodeString   test3;

    test3 += (UChar32)0x0130;
    test3 += "STANBUL, NOT CONSTANTINOPLE!";

    UnicodeString   test4(test3);
    test4.toLower();
    expectedResult = UnicodeString("i\\u0307stanbul, not constantinople!", "").unescape();
    if (test4 != expectedResult)
        errln("1. toLower failed: expected \"" + expectedResult + "\", got \"" + test4 + "\".");

    test4 = test3;
    test4.toLower(Locale("tr", "TR"));
    expectedResult = lowercaseTurkish;
    if (test4 != expectedResult)
        errln("2. toLower failed: expected \"" + expectedResult + "\", got \"" + test4 + "\".");

    test3 = "topkap";
    test3 += (UChar32)0x0131;
    test3 += " palace, istanbul";
    test4 = test3;

    test4.toUpper();
    expectedResult = "TOPKAPI PALACE, ISTANBUL";
    if (test4 != expectedResult)
        errln("toUpper failed: expected \"" + expectedResult + "\", got \"" + test4 + "\".");

    test4 = test3;
    test4.toUpper(Locale("tr", "TR"));
    expectedResult = uppercaseTurkish;
    if (test4 != expectedResult)
        errln("toUpper failed: expected \"" + expectedResult + "\", got \"" + test4 + "\".");

    test3 = CharsToUnicodeString("S\\u00FC\\u00DFmayrstra\\u00DFe");

    test3.toUpper(Locale("de", "DE"));
    expectedResult = CharsToUnicodeString("S\\u00DCSSMAYRSTRASSE");
    if (test3 != expectedResult)
        errln("toUpper failed: expected \"" + expectedResult + "\", got \"" + test3 + "\".");
    
    test4.replace(0, test4.length(), uppercaseGreek);

    test4.toLower(Locale("el", "GR"));
    expectedResult = lowercaseGreek;
    if (test4 != expectedResult)
        errln("toLower failed: expected \"" + expectedResult + "\", got \"" + test4 + "\".");
    
    test4.replace(0, test4.length(), lowercaseGreek);

    test4.toUpper();
    expectedResult = uppercaseGreek;
    if (test4 != expectedResult)
        errln("toUpper failed: expected \"" + expectedResult + "\", got \"" + test4 + "\".");

    // more string case mapping tests with the new implementation
    {
        static const UChar

        beforeLower[]= { 0x61, 0x42, 0x49,  0x3a3, 0xdf, 0x3a3, 0x2f, 0xd93f, 0xdfff },
        lowerRoot[]=   { 0x61, 0x62, 0x69,  0x3c3, 0xdf, 0x3c2, 0x2f, 0xd93f, 0xdfff },
        lowerTurkish[]={ 0x61, 0x62, 0x131, 0x3c3, 0xdf, 0x3c2, 0x2f, 0xd93f, 0xdfff },

        beforeUpper[]= { 0x61, 0x42, 0x69,  0x3c2, 0xdf,       0x3c3, 0x2f, 0xfb03,           0xfb03,           0xfb03,           0xd93f, 0xdfff },
        upperRoot[]=   { 0x41, 0x42, 0x49,  0x3a3, 0x53, 0x53, 0x3a3, 0x2f, 0x46, 0x46, 0x49, 0x46, 0x46, 0x49, 0x46, 0x46, 0x49, 0xd93f, 0xdfff },
        upperTurkish[]={ 0x41, 0x42, 0x130, 0x3a3, 0x53, 0x53, 0x3a3, 0x2f, 0x46, 0x46, 0x49, 0x46, 0x46, 0x49, 0x46, 0x46, 0x49, 0xd93f, 0xdfff },

        beforeMiniUpper[]=  { 0xdf, 0x61 },
        miniUpper[]=        { 0x53, 0x53, 0x41 };

        UnicodeString s;

        /* lowercase with root locale */
        s=UnicodeString(FALSE, beforeLower, (int32_t)(sizeof(beforeLower)/U_SIZEOF_UCHAR));
        s.toLower("");
        if( s.length()!=(sizeof(lowerRoot)/U_SIZEOF_UCHAR) ||
            s!=UnicodeString(FALSE, lowerRoot, s.length())
        ) {
            errln("error in toLower(root locale)=\"" + s + "\" expected \"" + UnicodeString(FALSE, lowerRoot, (int32_t)(sizeof(lowerRoot)/U_SIZEOF_UCHAR)) + "\"");
        }

        /* lowercase with turkish locale */
        s=UnicodeString(FALSE, beforeLower, (int32_t)(sizeof(beforeLower)/U_SIZEOF_UCHAR));
        s.setCharAt(0, beforeLower[0]).toLower(Locale("tr"));
        if( s.length()!=(sizeof(lowerTurkish)/U_SIZEOF_UCHAR) ||
            s!=UnicodeString(FALSE, lowerTurkish, s.length())
        ) {
            errln("error in toLower(turkish locale)=\"" + s + "\" expected \"" + UnicodeString(FALSE, lowerTurkish, (int32_t)(sizeof(lowerTurkish)/U_SIZEOF_UCHAR)) + "\"");
        }

        /* uppercase with root locale */
        s=UnicodeString(FALSE, beforeUpper, (int32_t)(sizeof(beforeUpper)/U_SIZEOF_UCHAR));
        s.setCharAt(0, beforeUpper[0]).toUpper();
        if( s.length()!=(sizeof(upperRoot)/U_SIZEOF_UCHAR) ||
            s!=UnicodeString(FALSE, upperRoot, s.length())
        ) {
            errln("error in toUpper(root locale)=\"" + s + "\" expected \"" + UnicodeString(FALSE, upperRoot, (int32_t)(sizeof(upperRoot)/U_SIZEOF_UCHAR)) + "\"");
        }

        /* uppercase with turkish locale */
        s=UnicodeString(FALSE, beforeUpper, (int32_t)(sizeof(beforeUpper)/U_SIZEOF_UCHAR));
        s.toUpper(Locale("tr"));
        if( s.length()!=(sizeof(upperTurkish)/U_SIZEOF_UCHAR) ||
            s!=UnicodeString(FALSE, upperTurkish, s.length())
        ) {
            errln("error in toUpper(turkish locale)=\"" + s + "\" expected \"" + UnicodeString(FALSE, upperTurkish, (int32_t)(sizeof(upperTurkish)/U_SIZEOF_UCHAR)) + "\"");
        }

        /* uppercase a short string with root locale */
        s=UnicodeString(FALSE, beforeMiniUpper, (int32_t)(sizeof(beforeMiniUpper)/U_SIZEOF_UCHAR));
        s.setCharAt(0, beforeMiniUpper[0]).toUpper("");
        if( s.length()!=(sizeof(miniUpper)/U_SIZEOF_UCHAR) ||
            s!=UnicodeString(FALSE, miniUpper, s.length())
        ) {
            errln("error in toUpper(root locale)=\"" + s + "\" expected \"" + UnicodeString(FALSE, miniUpper, (int32_t)(sizeof(miniUpper)/U_SIZEOF_UCHAR)) + "\"");
        }
    }

    // test some supplementary characters (>= Unicode 3.1)
    {
        UnicodeString t;

        UnicodeString
            deseretInput=UnicodeString("\\U0001043C\\U00010414", "").unescape(),
            deseretLower=UnicodeString("\\U0001043C\\U0001043C", "").unescape(),
            deseretUpper=UnicodeString("\\U00010414\\U00010414", "").unescape();
        (t=deseretInput).toLower();
        if(t!=deseretLower) {
            errln("error lowercasing Deseret (plane 1) characters");
        }
        (t=deseretInput).toUpper();
        if(t!=deseretUpper) {
            errln("error uppercasing Deseret (plane 1) characters");
        }
    }

    // test some more cases that looked like problems
    {
        UnicodeString t;

        UnicodeString
            ljInput=UnicodeString("ab'cD \\uFB00i\\u0131I\\u0130 \\u01C7\\u01C8\\u01C9 \\U0001043C\\U00010414", "").unescape(),
            ljLower=UnicodeString("ab'cd \\uFB00i\\u0131ii\\u0307 \\u01C9\\u01C9\\u01C9 \\U0001043C\\U0001043C", "").unescape(),
            ljUpper=UnicodeString("AB'CD FFIII\\u0130 \\u01C7\\u01C7\\u01C7 \\U00010414\\U00010414", "").unescape();
        (t=ljInput).toLower("en");
        if(t!=ljLower) {
            errln("error lowercasing LJ characters");
        }
        (t=ljInput).toUpper("en");
        if(t!=ljUpper) {
            errln("error uppercasing LJ characters");
        }
    }

#if !UCONFIG_NO_NORMALIZATION
    // some context-sensitive casing depends on normalization data being present

    // Unicode 3.1.1 SpecialCasing tests
    {
        UnicodeString t;

        // sigmas preceded and/or followed by cased letters
        UnicodeString
            sigmas=UnicodeString("i\\u0307\\u03a3\\u0308j \\u0307\\u03a3\\u0308j i\\u00ad\\u03a3\\u0308 \\u0307\\u03a3\\u0308 ", "").unescape(),
            sigmasLower=UnicodeString("i\\u0307\\u03c3\\u0308j \\u0307\\u03c3\\u0308j i\\u00ad\\u03c2\\u0308 \\u0307\\u03c3\\u0308 ", "").unescape(),
            sigmasUpper=UnicodeString("I\\u0307\\u03a3\\u0308J \\u0307\\u03a3\\u0308J I\\u00ad\\u03a3\\u0308 \\u0307\\u03a3\\u0308 ", "").unescape();

        (t=sigmas).toLower();
        if(t!=sigmasLower) {
            errln("error in sigmas.toLower()=\"" + t + "\" expected \"" + sigmasLower + "\"");
        }

        (t=sigmas).toUpper();
        if(t!=sigmasUpper) {
            errln("error in sigmas.toUpper()=\"" + t + "\" expected \"" + sigmasUpper + "\"");
        }

        // turkish & azerbaijani dotless i & dotted I
        // remove dot above if there was a capital I before and there are no more accents above
        UnicodeString
            dots=UnicodeString("I \\u0130 I\\u0307 I\\u0327\\u0307 I\\u0301\\u0307 I\\u0327\\u0307\\u0301", "").unescape(),
            dotsTurkish=UnicodeString("\\u0131 i i i\\u0327 \\u0131\\u0301\\u0307 i\\u0327\\u0301", "").unescape(),
            dotsDefault=UnicodeString("i i\\u0307 i\\u0307 i\\u0327\\u0307 i\\u0301\\u0307 i\\u0327\\u0307\\u0301", "").unescape();

        (t=dots).toLower("tr");
        if(t!=dotsTurkish) {
            errln("error in dots.toLower(tr)=\"" + t + "\" expected \"" + dotsTurkish + "\"");
        }

        (t=dots).toLower("de");
        if(t!=dotsDefault) {
            errln("error in dots.toLower(de)=\"" + t + "\" expected \"" + dotsDefault + "\"");
        }
    }

    // more Unicode 3.1.1 tests
    {
        UnicodeString t;

        // lithuanian dot above in uppercasing
        UnicodeString
            dots=UnicodeString("a\\u0307 \\u0307 i\\u0307 j\\u0327\\u0307 j\\u0301\\u0307", "").unescape(),
            dotsLithuanian=UnicodeString("A\\u0307 \\u0307 I J\\u0327 J\\u0301\\u0307", "").unescape(),
            dotsDefault=UnicodeString("A\\u0307 \\u0307 I\\u0307 J\\u0327\\u0307 J\\u0301\\u0307", "").unescape();

        (t=dots).toUpper("lt");
        if(t!=dotsLithuanian) {
            errln("error in dots.toUpper(lt)=\"" + t + "\" expected \"" + dotsLithuanian + "\"");
        }

        (t=dots).toUpper("de");
        if(t!=dotsDefault) {
            errln("error in dots.toUpper(de)=\"" + t + "\" expected \"" + dotsDefault + "\"");
        }

        // lithuanian adds dot above to i in lowercasing if there are more above accents
        UnicodeString
            i=UnicodeString("I I\\u0301 J J\\u0301 \\u012e \\u012e\\u0301 \\u00cc\\u00cd\\u0128", "").unescape(),
            iLithuanian=UnicodeString("i i\\u0307\\u0301 j j\\u0307\\u0301 \\u012f \\u012f\\u0307\\u0301 i\\u0307\\u0300i\\u0307\\u0301i\\u0307\\u0303", "").unescape(),
            iDefault=UnicodeString("i i\\u0301 j j\\u0301 \\u012f \\u012f\\u0301 \\u00ec\\u00ed\\u0129", "").unescape();

        (t=i).toLower("lt");
        if(t!=iLithuanian) {
            errln("error in i.toLower(lt)=\"" + t + "\" expected \"" + iLithuanian + "\"");
        }

        (t=i).toLower("de");
        if(t!=iDefault) {
            errln("error in i.toLower(de)=\"" + t + "\" expected \"" + iDefault + "\"");
        }
    }

#endif

    // test case folding
    {
        UnicodeString
            s=UnicodeString("A\\u00df\\u00b5\\ufb03\\U0001040c\\u0130\\u0131", "").unescape(),
            f=UnicodeString("ass\\u03bcffi\\U00010434i\\u0307\\u0131", "").unescape(),
            g=UnicodeString("ass\\u03bcffi\\U00010434i\\u0131", "").unescape(),
            t;

        (t=s).foldCase();
        if(f!=t) {
            errln("error in foldCase(\"" + s + "\", default)=\"" + t + "\" but expected \"" + f + "\"");
        }

        // alternate handling for dotted I/dotless i (U+0130, U+0131)
        (t=s).foldCase(U_FOLD_CASE_EXCLUDE_SPECIAL_I);
        if(g!=t) {
            errln("error in foldCase(\"" + s + "\", U_FOLD_CASE_EXCLUDE_SPECIAL_I)=\"" + t + "\" but expected \"" + g + "\"");
        }
    }
}

#if !UCONFIG_NO_BREAK_ITERATION

void
StringCaseTest::TestTitleCasing() {
  UErrorCode status = U_ZERO_ERROR;
  UBreakIterator *iter;
  char cLocaleID[100];
  UnicodeString locale, input, result;
  int32_t type;
  TestLog myLog;
  TestDataModule *driver = TestDataModule::getTestDataModule("casing", myLog, status);
  if(U_SUCCESS(status)) {
    TestData *casingTest = driver->createTestData("titlecasing", status);
    const DataMap *myCase = NULL;
    while(casingTest->nextCase(myCase, status)) {
      locale = myCase->getString("Locale", status);
      locale.extract(0, 0x7fffffff, cLocaleID, sizeof(cLocaleID), "");
      type = myCase->getInt("Type", status);
      

      input = myCase->getString("Input", status);
      if(type<0) {
          iter=0;
      } else {
          iter=ubrk_open((UBreakIteratorType)type, cLocaleID, input.getBuffer(), input.length(), &status);
      }

      if(U_FAILURE(status)) {
          errln("error: TestTitleCasing() ubrk_open(%d) failed for test case  from casing.res: %s", type,  u_errorName(status));
          status = U_ZERO_ERROR;
      } else {
          result=input;
          result.toTitle((BreakIterator *)iter, Locale(cLocaleID));
          if(result!=myCase->getString("Output", status)) {
              errln("error: TestTitleCasing() got a wrong result for test case from casing.res");
          }
      }
      ubrk_close(iter);
    }
    delete casingTest;
  }
  delete driver;

    // more tests for API coverage
    status=U_ZERO_ERROR;
    input=UNICODE_STRING_SIMPLE("sTrA\\u00dfE").unescape();
    (result=input).toTitle(NULL);
    if(result!=UNICODE_STRING_SIMPLE("Stra\\u00dfe").unescape()) {
        errln("UnicodeString::toTitle(BreakIterator *) failed");
    }

#if 0
    char cLocaleID[100];
    UnicodeString in, expect, result, localeID;
    UResourceBundle *casing, *titlecasing, *test, *res;
    UErrorCode errorCode;
    int32_t testIndex, type;

    errorCode=U_ZERO_ERROR;
    loadTestData(errorCode);
    casing=ures_openDirect("testdata", "casing", &errorCode);
    if(U_FAILURE(errorCode)) {
        errln("error: TestTitleCasing() is unable to open casing.res: %s", u_errorName(errorCode));
        return;
    }

    // titlecasing tests
    titlecasing=ures_getByKey(casing, "titlecasing", 0, &errorCode);
    if(U_FAILURE(errorCode)) {
        logln("TestTitleCasing() is unable to open get casing.res/titlecasing: %s", u_errorName(errorCode));
    } else {
        UBreakIterator *iter;

        for(testIndex=0;; ++testIndex) {
            // get test case
            test=ures_getByIndex(titlecasing, testIndex, 0, &errorCode);
            if(U_FAILURE(errorCode)) {
                break; // done
            }

            // get test case data
            in=ures_getUnicodeStringByIndex(test, 0, &errorCode);
            expect=ures_getUnicodeStringByIndex(test, 1, &errorCode);
            localeID=ures_getUnicodeStringByIndex(test, 2, &errorCode);

            res=ures_getByIndex(test, 3, 0, &errorCode);
            type=ures_getInt(res, &errorCode);
            ures_close(res);

            if(U_FAILURE(errorCode)) {
                errln("error: TestTitleCasing() is unable to get data for test case %ld from casing.res: %s", testIndex, u_errorName(errorCode));
                continue; // skip this test case
            }

            // run this test case
            localeID.extract(0, 0x7fffffff, cLocaleID, sizeof(cLocaleID), "");
            if(type<0) {
                iter=0;
            } else {
                iter=ubrk_open((UBreakIteratorType)type, cLocaleID, in.getBuffer(), in.length(), &errorCode);
            }

            if(U_FAILURE(errorCode)) {
                errln("error: TestTitleCasing() ubrk_open(%d) failed for test case %d from casing.res: %s", type, testIndex, u_errorName(errorCode));
            } else {
                result=in;
                result.toTitle((BreakIterator *)iter, Locale(cLocaleID));
                if(result!=expect) {
                    errln("error: TestTitleCasing() got a wrong result for test case %ld from casing.res", testIndex);
                }
            }

            // clean up
            ubrk_close(iter);
            ures_close(test);
        }
        ures_close(titlecasing);
        logln("TestTitleCasing() processed %ld test cases", testIndex);
    }

    ures_close(casing);
#endif
}
#endif



--- NEW FILE: svccoll.cpp ---
/*
 *******************************************************************************
 * Copyright (C) 2003, International Business Machines Corporation and         *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */

#include "unicode/utypes.h"

#if !UCONFIG_NO_COLLATION

#include "svccoll.h"
#include "unicode/coll.h"
#include "unicode/strenum.h"
#include "hash.h"

#include "ucol_imp.h" // internal api needed to test ucollator equality
#include "cstring.h" // internal api used to compare locale strings

void CollationServiceTest::TestRegister() 
{
  // register a singleton
    const Locale& FR = Locale::getFrance();
    const Locale& US = Locale::getUS();
    const Locale US_FOO("en", "US", "FOO");
    
    UErrorCode status = U_ZERO_ERROR;
    
    Collator* frcol = Collator::createInstance(FR, status);
    Collator* uscol = Collator::createInstance(US, status);
    if(U_FAILURE(status)) {
        errln("Failed to create collators with %s", u_errorName(status));
        delete frcol;
        delete uscol;
        return;
    }
    
    { // try override en_US collator
        URegistryKey key = Collator::registerInstance(frcol, US, status);
        
        Collator* ncol = Collator::createInstance(US_FOO, status);
        if (*frcol != *ncol) {
            errln("register of french collator for en_US failed on request for en_US_FOO");
        }
        // ensure original collator's params not touched
        Locale loc = frcol->getLocale(ULOC_REQUESTED_LOCALE, status);
        if (loc != FR) {
            errln(UnicodeString("fr collator's requested locale changed to ") + loc.getName());
        }
        loc = frcol->getLocale(ULOC_VALID_LOCALE, status);
        if (loc != FR) {
            errln(UnicodeString("fr collator's valid locale changed to ") + loc.getName());
        }
        
        loc = ncol->getLocale(ULOC_REQUESTED_LOCALE, status);
        if (loc != US_FOO) {
            errln(UnicodeString("requested locale for en_US_FOO is not en_US_FOO but ") + loc.getName());
        }
        loc = ncol->getLocale(ULOC_VALID_LOCALE, status);
        if (loc != US) {
            errln(UnicodeString("valid locale for en_US_FOO is not en_US but ") + loc.getName());
        }
        loc = ncol->getLocale(ULOC_ACTUAL_LOCALE, status);
        if (loc != US) {
            errln(UnicodeString("actual locale for en_US_FOO is not en_US but ") + loc.getName());
        }
        delete ncol; ncol = NULL;
        
        if (!Collator::unregister(key, status)) {
            errln("failed to unregister french collator");
        }
        // !!! frcol pointer is now invalid !!!
        
        ncol = Collator::createInstance(US, status);
        if (*uscol != *ncol) {
            errln("collator after unregister does not match original");
        }
        delete ncol; ncol = NULL;
    }
    
    // recreate frcol
    frcol = Collator::createInstance(FR, status);
    
    UCollator* frFR = ucol_open("fr_FR", &status);
    
    { // try create collator for new locale
        Locale fu_FU_FOO("fu", "FU", "FOO");
        Locale fu_FU("fu", "FU", "");
        
        Collator* fucol = Collator::createInstance(fu_FU, status);
        URegistryKey key = Collator::registerInstance(frcol, fu_FU, status);
        Collator* ncol = Collator::createInstance(fu_FU_FOO, status);
        if (*frcol != *ncol) {
            errln("register of fr collator for fu_FU failed");
        }
        
        UnicodeString locName = fu_FU.getName();
        StringEnumeration* localeEnum = Collator::getAvailableLocales();
        UBool found = FALSE;
        const UnicodeString* locStr;
        for (locStr = localeEnum->snext(status);
        !found && locStr != NULL;
        locStr = localeEnum->snext(status)) {
            //
            if (locName == *locStr) {
                found = TRUE;
            }
        }
        delete localeEnum;
        
        if (!found) {
            errln("new locale fu_FU not reported as supported locale");
        }
        
        UnicodeString displayName;
        Collator::getDisplayName(fu_FU, displayName);
        if (displayName != "fu (FU)") {
            errln(UnicodeString("found ") + displayName + " for fu_FU");
        }
        
        Collator::getDisplayName(fu_FU, fu_FU, displayName);
        if (displayName != "fu (FU)") {
            errln(UnicodeString("found ") + displayName + " for fu_FU");
        }
        
        // test ucol_open
        UCollator* fufu = ucol_open("fu_FU_FOO", &status);
        if (!fufu) {
            errln("could not open fu_FU_FOO with ucol_open");
        } else {
            if (!ucol_equals(fufu, frFR)) {
                errln("collator fufu != collator frFR");
            }
        }
        
        if (!Collator::unregister(key, status)) {
            errln("failed to unregister french collator");
        }
        // !!! note frcoll invalid again, but we're no longer using it
        
        // other collators should still work ok
        Locale nloc = ncol->getLocale(ULOC_VALID_LOCALE, status);
        if (nloc != fu_FU) {
            errln(UnicodeString("asked for nloc valid locale after close and got") + nloc.getName());
        }
        delete ncol; ncol = NULL;
        
        if (fufu) {
            const char* nlocstr = ucol_getLocale(fufu, ULOC_VALID_LOCALE, &status);
            if (uprv_strcmp(nlocstr, "fu_FU") != 0) {
                errln(UnicodeString("asked for uloc valid locale after close and got ") + nlocstr);
            }
            ucol_close(fufu);
        }
        ucol_close(frFR);
        
        ncol = Collator::createInstance(fu_FU, status);
        if (*fucol != *ncol) {
            errln("collator after unregister does not match original fu_FU");
        }
        delete uscol; uscol = NULL;
        delete ncol; ncol = NULL;
        delete fucol; fucol = NULL;
    }
}

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

struct CollatorInfo {
  Locale locale;
  Collator* collator;
  Hashtable* displayNames; // locale name -> string

  CollatorInfo(const Locale& locale, Collator* collatorToAdopt, Hashtable* displayNamesToAdopt);
  ~CollatorInfo();
  UnicodeString& getDisplayName(const Locale& displayLocale, UnicodeString& name) const;
};

CollatorInfo::CollatorInfo(const Locale& _locale, Collator* _collator, Hashtable* _displayNames)
  : locale(_locale)
  , collator(_collator)
  , displayNames(_displayNames)
{
}

CollatorInfo::~CollatorInfo() {
  delete collator;
  delete displayNames;
}

UnicodeString& 
CollatorInfo::getDisplayName(const Locale& displayLocale, UnicodeString& name) const {
  if (displayNames) {
    UnicodeString* val = (UnicodeString*)displayNames->get(displayLocale.getName());
    if (val) {
      name = *val;
      return name;
    }
  }

  return locale.getDisplayName(displayLocale, name);
}

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

class TestFactory : public CollatorFactory {
  CollatorInfo** info;
  int32_t count;
  UnicodeString* ids;

  const CollatorInfo* getInfo(const Locale& loc) const {
    for (CollatorInfo** p = info; *p; ++p) {
      if (loc == (**p).locale) {
        return *p;
      }
    }
    return NULL;
  }

public:       
  TestFactory(CollatorInfo** _info) 
    : info(_info)
    , count(0)
    , ids(NULL)
  {
    CollatorInfo** p;
    for (p = info; *p; ++p) {}
    count = p - info;
  }

  ~TestFactory() {
    for (CollatorInfo** p = info; *p; ++p) {
      delete *p;
    }
    delete[] info;
    delete[] ids;
  }

  virtual Collator* createCollator(const Locale& loc) {
    const CollatorInfo* ci = getInfo(loc);
    if (ci) {
      return ci->collator->clone();
    }
    return NULL;
  }

  virtual UnicodeString& getDisplayName(const Locale& objectLocale, 
                                        const Locale& displayLocale,
                                        UnicodeString& result)
  {
    const CollatorInfo* ci = getInfo(objectLocale);
    if (ci) {
      ci->getDisplayName(displayLocale, result);
    } else {
      result.setToBogus();
    }
    return result;
  }

  const UnicodeString* getSupportedIDs(int32_t& _count, UErrorCode& status) {
    if (U_SUCCESS(status)) {
      if (!ids) {
        ids = new UnicodeString[count];
        if (!ids) {
          status = U_MEMORY_ALLOCATION_ERROR;
          _count = 0;
          return NULL;
        }

        for (int i = 0; i < count; ++i) {
          ids[i] = info[i]->locale.getName();
        }
      }

      _count = count;
      return ids;
    }
    return NULL;
  }

  virtual inline UClassID getDynamicClassID() const {
    return (UClassID)&gClassID;
  }

  static UClassID getStaticClassID() {
    return (UClassID)&gClassID;
  }

private:
  static char gClassID;
};

char TestFactory::gClassID = 0;

void CollationServiceTest::TestRegisterFactory(void) 
{
    Locale fu_FU("fu", "FU", "");
    Locale fu_FU_FOO("fu", "FU", "FOO");
    
    UErrorCode status = U_ZERO_ERROR;
    
    Hashtable* fuFUNames = new Hashtable(FALSE, status);
    if (!fuFUNames) {
        errln("memory allocation error");
        return;
    }
    fuFUNames->setValueDeleter(uhash_deleteUnicodeString);
    
    fuFUNames->put(fu_FU.getName(), new UnicodeString("ze leetle bunny Fu-Fu"), status);
    fuFUNames->put(fu_FU_FOO.getName(), new UnicodeString("zee leetel bunny Foo-Foo"), status);
    fuFUNames->put(Locale::getUS().getName(), new UnicodeString("little bunny Foo Foo"), status);
    
    Collator* frcol = Collator::createInstance(Locale::getFrance(), status);
    Collator* gecol = Collator::createInstance(Locale::getGermany(), status);
    Collator* jpcol = Collator::createInstance(Locale::getJapan(), status);
    if(U_FAILURE(status)) {
      errln("Failed to create collators with %s", u_errorName(status));
      delete frcol;
      delete gecol;
      delete jpcol;
      delete fuFUNames;
      return;
    }
    
    CollatorInfo** info = new CollatorInfo*[4];
    if (!info) {
        errln("memory allocation error");
        return;
    }
    
    info[0] = new CollatorInfo(Locale::getUS(), frcol, NULL);
    info[1] = new CollatorInfo(Locale::getFrance(), gecol, NULL);
    info[2] = new CollatorInfo(fu_FU, jpcol, fuFUNames);
    info[3] = NULL;
    
    TestFactory* factory = new TestFactory(info);
    if (!factory) {
        errln("memory allocation error");
        return;
    }
    
    Collator* uscol = Collator::createInstance(Locale::getUS(), status);
    Collator* fucol = Collator::createInstance(fu_FU, status);
    
    {
        URegistryKey key = Collator::registerFactory(factory, status);
        Collator* ncol = Collator::createInstance(Locale::getUS(), status);
        if (*frcol != *ncol) {
            errln("frcoll for en_US failed");
        }
        delete ncol; ncol = NULL;
        
        ncol = Collator::createInstance(fu_FU_FOO, status);
        if (*jpcol != *ncol) {
            errln("jpcol for fu_FU_FOO failed");
        }
        
        Locale loc = ncol->getLocale(ULOC_REQUESTED_LOCALE, status);
        if (loc != fu_FU_FOO) {
            errln(UnicodeString("requested locale for fu_FU_FOO is not fu_FU_FOO but ") + loc.getName());
        }
        loc = ncol->getLocale(ULOC_VALID_LOCALE, status);
        if (loc != fu_FU) {
            errln(UnicodeString("valid locale for fu_FU_FOO is not fu_FU but ") + loc.getName());
        }
        delete ncol; ncol = NULL;
        
        UnicodeString locName = fu_FU.getName();
        StringEnumeration* localeEnum = Collator::getAvailableLocales();
        UBool found = FALSE;
        const UnicodeString* locStr;
        for (locStr = localeEnum->snext(status);
            !found && locStr != NULL;
            locStr = localeEnum->snext(status))
        {
            if (locName == *locStr) {
                found = TRUE;
            }
        }
        delete localeEnum;
        
        if (!found) {
            errln("new locale fu_FU not reported as supported locale");
        }
        
        UnicodeString name;
        Collator::getDisplayName(fu_FU, name);
        if (name != "little bunny Foo Foo") {
            errln(UnicodeString("found ") + name + " for fu_FU");
        }
        
        Collator::getDisplayName(fu_FU, fu_FU_FOO, name);
        if (name != "zee leetel bunny Foo-Foo") {
            errln(UnicodeString("found ") + name + " for fu_FU in fu_FU_FOO");
        }
        
        if (!Collator::unregister(key, status)) {
            errln("failed to unregister factory");
        }
        // ja, fr, ge collators no longer valid
        
        ncol = Collator::createInstance(fu_FU, status);
        if (*fucol != *ncol) {
            errln("collator after unregister does not match original fu_FU");
        }
	delete ncol;
    }
    
    delete fucol;
    delete uscol;
}

void CollationServiceTest::runIndexedTest(int32_t index, UBool exec, const char* &name, char* /*par */)
{
    if (exec) logln("TestSuite CollationServiceTest: ");
    switch (index) {
        TESTCASE(0, TestRegister);
        TESTCASE(1, TestRegisterFactory);
    default: name = ""; break;
    }
}

#endif

--- NEW FILE: svccoll.h ---
/********************************************************************
 * Copyright (c) 2003, International Business Machines Corporation
 * and others. All Rights Reserved.
 ********************************************************************/

/**
 * CollationServiceTest tests registration of collators.
 */

#ifndef _SVCCOLL
#define _SVCCOLL

#include "unicode/utypes.h"

#if !UCONFIG_NO_COLLATION

#include "intltest.h"

class CollationServiceTest: public IntlTest {
public:
    void runIndexedTest(int32_t index, UBool exec, const char* &name, char* /*par = NULL */);

    void TestRegister(void);
    void TestRegisterFactory(void);
};

/* #if !UCONFIG_NO_COLLATION */
#endif

/* #ifndef _SVCCOLL */
#endif



--- NEW FILE: testdata.cpp ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 2002, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

/* Created by weiv 05/09/2002 */

#include "testdata.h"

TestData::TestData(const char* name)
: name(name),
fInfo(NULL),
fCurrSettings(NULL),
fCurrCase(NULL),
fSettingsSize(0),
fCasesSize(0),
fCurrentSettings(0),
fCurrentCase(0)

{
}

TestData::~TestData() {
  if(fInfo != NULL) {
    delete fInfo;
  }
  if(fCurrSettings != NULL) {
    delete fCurrSettings;
  }
  if(fCurrCase != NULL) {
    delete fCurrCase;
  }
}

const char * TestData::getName() const
{
  return name;
}



RBTestData::RBTestData(const char* name)
: TestData(name),
fData(NULL),
fHeaders(NULL),
fSettings(NULL),
fCases(NULL)
{
}

RBTestData::RBTestData(UResourceBundle *data, UResourceBundle *headers, UErrorCode& status)
: TestData(ures_getKey(data)),
fData(data),
fHeaders(headers),
fSettings(NULL),
fCases(NULL)
{
  UErrorCode intStatus = U_ZERO_ERROR;
  UResourceBundle *currHeaders = ures_getByKey(data, "Headers", NULL, &intStatus);
  if(intStatus == U_ZERO_ERROR) {
    ures_close(fHeaders);
    fHeaders = currHeaders;
  } else {
    intStatus = U_ZERO_ERROR;
  }
  fSettings = ures_getByKey(data, "Settings", NULL, &intStatus);
  fSettingsSize = ures_getSize(fSettings);
  UResourceBundle *info = ures_getByKey(data, "Info", NULL, &intStatus);
  if(U_SUCCESS(intStatus)) {
    fInfo = new RBDataMap(info, status);
  } else {
    intStatus = U_ZERO_ERROR;
  }
  fCases = ures_getByKey(data, "Cases", NULL, &status);
  fCasesSize = ures_getSize(fCases);

  ures_close(info);
}


RBTestData::~RBTestData()
{
  ures_close(fData);
  ures_close(fHeaders);
  ures_close(fSettings);
  ures_close(fCases);
}

UBool RBTestData::getInfo(const DataMap *& info, UErrorCode &/*status*/) const
{
  if(fInfo) {
    info = fInfo;
    return TRUE;
  } else {
    info = NULL;
    return FALSE;
  }
}

UBool RBTestData::nextSettings(const DataMap *& settings, UErrorCode &status)
{
  UErrorCode intStatus = U_ZERO_ERROR;
  UResourceBundle *data = ures_getByIndex(fSettings, fCurrentSettings++, NULL, &intStatus);
  if(U_SUCCESS(intStatus)) {
    // reset the cases iterator
    fCurrentCase = 0;
    if(fCurrSettings == NULL) {
      fCurrSettings = new RBDataMap(data, status);
    } else {
      ((RBDataMap *)fCurrSettings)->init(data, status);
    }
    ures_close(data);
    settings = fCurrSettings;
    return TRUE;
  } else {
    settings = NULL;
    return FALSE;
  }
}

UBool RBTestData::nextCase(const DataMap *& nextCase, UErrorCode &status)
{
  UErrorCode intStatus = U_ZERO_ERROR;
  UResourceBundle *currCase = ures_getByIndex(fCases, fCurrentCase++, NULL, &intStatus);
  if(U_SUCCESS(intStatus)) {
    if(fCurrCase == NULL) {
      fCurrCase = new RBDataMap(fHeaders, currCase, status);
    } else {
      ((RBDataMap *)fCurrCase)->init(fHeaders, currCase, status);
    }
    ures_close(currCase);
    nextCase = fCurrCase;
    return TRUE;
  } else {
    nextCase = NULL;
    return FALSE;
  }
}


--- NEW FILE: testdata.h ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 2002, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

/* Created by weiv 05/09/2002 */

/* Base class for data driven tests */

#ifndef INTLTST_TESTDATA
#define INTLTST_TESTDATA

#include "tstdtmod.h"
#include "datamap.h"

 /** This is the class that abstracts one of the tests in a data file 
  *  It is usually instantiated using TestDataModule::CreateTestData method 
  *  This class provides two important methods: nextSettings and nextCase 
  *  Usually, one walks through all settings and executes all cases for 
  *  each setting. Each call to nextSettings resets the cases iterator.
  *  Individual test cases have to have the same number of fields as the
  *  number of entries in headers. Default headers can be specified in 
  *  the TestDataModule info section. The default headers will be overriden
  *  by per-test headers. 
  *  Example:                                             
  *  DataMap *settings = NULL;                            
  *  DataMap *cases = NULL;                               
  *  while(nextSettings(settings, status)) {              
  *    // set settings for the subtest                    
  *    while(nextCase(cases, status) {                    
  *      // process testcase                              
  *    }                                                  
  *   }                                                   
  */

class TestData {
  const char* name;

protected:
  DataMap *fInfo;
  DataMap *fCurrSettings;
  DataMap *fCurrCase;
  int32_t fSettingsSize;
  int32_t fCasesSize;
  int32_t fCurrentSettings;
  int32_t fCurrentCase;
  /** constructor - don't use */
  TestData(const char* name);

public:
  virtual ~TestData();

  const char* getName() const;

  /** Get a pointer to an object owned DataMap that contains more information on this
   *  TestData object.
   *  Usual fields is "Description".                                   
   *  @param info pass in a const DataMap pointer. If no info, it will be set to NULL
   */
  virtual UBool getInfo(const DataMap *& info, UErrorCode &status) const = 0;

  /** Gets the next set of settings for the test. Resets the cases iterator. 
   *  DataMap is owned by the object and should not be deleted. 
   *  @param settings a DataMap pointer provided by the user. Will be NULL if 
   *                  no more settings are available.
   *  @param status for reporting unexpected errors.
   *  @return A boolean, TRUE if there are settings, FALSE if there is no more 
   *          settings. 
   */
  virtual UBool nextSettings(const DataMap *& settings, UErrorCode &status) = 0;

  /** Gets the next test case. 
   *  DataMap is owned by the object and should not be deleted. 
   *  @param data a DataMap pointer provided by the user. Will be NULL if 
   *                  no more cases are available.
   *  @param status for reporting unexpected errors.
   *  @return A boolean, TRUE if there are cases, FALSE if there is no more 
   *          cases. 
   */
  virtual UBool nextCase(const DataMap *& data, UErrorCode &status) = 0;
};

// implementation of TestData that uses resource bundles

class RBTestData : public TestData {
  UResourceBundle *fData;
  UResourceBundle *fHeaders;
  UResourceBundle *fSettings;
  UResourceBundle *fCases;

public:
  RBTestData(const char* name);
  RBTestData(UResourceBundle *data, UResourceBundle *headers, UErrorCode& status);
private:
//  RBTestData() {};
//  RBTestData(const RBTestData& original) {};
  RBTestData& operator=(const RBTestData& /*original*/) {return *this;};

public:
  virtual ~RBTestData();

  virtual UBool getInfo(const DataMap *& info, UErrorCode &status) const;

  virtual UBool nextSettings(const DataMap *& settings, UErrorCode &status);
  virtual UBool nextCase(const DataMap *& nextCase, UErrorCode &status);
};

#endif

--- NEW FILE: testidn.cpp ---
/*
*******************************************************************************
*
*   Copyright (C) 2003, International Business Machines
*   Corporation and others.  All Rights Reserved.
*
*******************************************************************************
*   file name:  testidn.cpp
*   encoding:   US-ASCII
*   tab size:   8 (not used)
*   indentation:4
*
*   created on: 2003-02-06
*   created by: Ram Viswanadha
*
*   This program reads the rfc3454_*.txt files,
*   parses them, and extracts the data for Nameprep conformance.
*   It then preprocesses it and writes a binary file for efficient use
*   in various IDNA conversion processes.
*/

#include <stdio.h>
#include <stdlib.h>
#include "unicode/utypes.h"

#if !UCONFIG_NO_IDNA && !UCONFIG_NO_TRANSLITERATION

#include "unicode/uchar.h"
#include "unicode/putil.h"
#include "cmemory.h"
#include "cstring.h"
#include "unicode/udata.h"
#include "unewdata.h"
#include "uoptions.h"
#include "uparse.h"
#include "utrie.h"
#include "umutex.h"
#include "sprpimpl.h"
#include "testidna.h"

UBool beVerbose=FALSE, haveCopyright=TRUE;

/* prototypes --------------------------------------------------------------- */


static UBool isDataLoaded = FALSE;
static UTrie idnTrie={ 0,0,0,0,0,0,0 };
static UDataMemory *idnData=NULL;
static UErrorCode dataErrorCode =U_ZERO_ERROR;


static const uint16_t* mappingData = NULL;
static int32_t indexes[_IDNA_INDEX_TOP]={ 0 };


static void
parseMappings(const char *filename, UBool withNorm, UBool reportError,TestIDNA& test, UErrorCode *pErrorCode);

static void
parseTable(const char *filename, UBool isUnassigned, TestIDNA& test, UErrorCode *pErrorCode);

static UBool loadIDNData(UErrorCode &errorCode);

static UBool cleanup();

static void 
compareMapping(uint32_t codepoint, uint32_t* mapping, int32_t mapLength, 
               UBool withNorm);

static void
compareFlagsForRange(uint32_t start, uint32_t end,
                     UBool isUnassigned);

static void
testAllCodepoints(TestIDNA& test);

static TestIDNA* pTestIDNA =NULL;

static const char* fileNames[] = {
                                    "rfc3454_A_1.txt", /* contains unassigned code points */
                                    "rfc3454_C_X.txt", /* contains code points that are prohibited */
                                    "rfc3454_B_1.txt", /* contains case mappings when normalization is turned off */
                                    "rfc3454_B_2.txt", /* contains case mappings when normalization it turned on */
                                    /* "NormalizationCorrections.txt",contains NFKC case mappings whicha are not included in UTR 21  */
                                };
/* -------------------------------------------------------------------------- */

/* file definitions */
#define DATA_NAME "uidna"
#define DATA_TYPE "icu"

#define MISC_DIR "misc"

extern int
testData(TestIDNA& test) {
    char* filename = (char*) malloc(strlen(IntlTest::pathToDataDirectory())*3);
    //TODO get the srcDir dynamically 
    const char *srcDir=IntlTest::pathToDataDirectory();
    char *basename=NULL;
    UErrorCode errorCode=U_ZERO_ERROR;
    char *saveBasename =NULL;

    loadIDNData(errorCode);
    if(U_FAILURE(dataErrorCode)){
        test.errln( "Could not load data. Error: %s\n",u_errorName(dataErrorCode));
        return dataErrorCode;
    }
    
    //initialize
    pTestIDNA = &test;
    
    /* prepare the filename beginning with the source dir */
    if(uprv_strchr(srcDir,U_FILE_SEP_CHAR) == NULL){
        filename[0] = 0x2E;
        filename[1] = U_FILE_SEP_CHAR;
        uprv_strcpy(filename+2,srcDir);
    }else{
        uprv_strcpy(filename, srcDir);
    }
    basename=filename+uprv_strlen(filename);
    if(basename>filename && *(basename-1)!=U_FILE_SEP_CHAR) {
        *basename++=U_FILE_SEP_CHAR;
    }

    /* process unassigned */
    basename=filename+uprv_strlen(filename);
    if(basename>filename && *(basename-1)!=U_FILE_SEP_CHAR) {
        *basename++=U_FILE_SEP_CHAR;
    }
    
    /* first copy misc directory */
    saveBasename = basename;
    uprv_strcpy(basename,MISC_DIR);
    basename = basename + uprv_strlen(MISC_DIR);
    *basename++=U_FILE_SEP_CHAR;
    
    /* process unassigned */
    uprv_strcpy(basename,fileNames[0]);
    parseTable(filename,TRUE, test,&errorCode);
    if(U_FAILURE(errorCode)) {
        test.errln( "Could not open file %s for reading \n", filename);
        return errorCode;
    }
    /* process prohibited */
    uprv_strcpy(basename,fileNames[1]);
    parseTable(filename,FALSE, test, &errorCode);
    if(U_FAILURE(errorCode)) {
        test.errln( "Could not open file %s for reading \n", filename);
        return errorCode;
    }

    /* process mappings */
    uprv_strcpy(basename,fileNames[2]);
    parseMappings(filename, FALSE, FALSE,test, &errorCode);
    if(U_FAILURE(errorCode)) {
        test.errln( "Could not open file %s for reading \n", filename);
        return errorCode;
    }
    uprv_strcpy(basename,fileNames[3]);
    parseMappings(filename, TRUE, FALSE,test, &errorCode);
    if(U_FAILURE(errorCode)) {
        test.errln( "Could not open file %s for reading \n", filename);
        return errorCode;
    }

    testAllCodepoints(test);

    cleanup();
    pTestIDNA = NULL;
    free(filename);
    return errorCode;
}
U_CDECL_BEGIN
static void U_CALLCONV
caseMapLineFn(void *context,
              char *fields[][2], int32_t /*fieldCount*/,
              UErrorCode *pErrorCode) {
    uint32_t mapping[40];
    char *end, *s;
    uint32_t code;
    int32_t length;
    UBool* mapWithNorm = (UBool*) context;

    /* get the character code, field 0 */
    code=(uint32_t)uprv_strtoul(fields[0][0], &end, 16);
    if(end<=fields[0][0] || end!=fields[0][1]) {
        *pErrorCode=U_PARSE_ERROR;

    }

    s = fields[1][0];
    /* parse the mapping string */
    length=u_parseCodePoints(s, mapping, sizeof(mapping)/4, pErrorCode);

    /* store the mapping */

    compareMapping(code,mapping, length, *mapWithNorm);
}
U_CDECL_END

static void
parseMappings(const char *filename,UBool withNorm, UBool reportError, TestIDNA& test, UErrorCode *pErrorCode) {
    char *fields[3][2];

    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
        return;
    }

    u_parseDelimitedFile(filename, ';', fields, 3, caseMapLineFn, &withNorm, pErrorCode);

    //fprintf(stdout,"Number of code points that have mappings with length >1 : %i\n",len);

    if(U_FAILURE(*pErrorCode) && (reportError || *pErrorCode!=U_FILE_ACCESS_ERROR)) {
        test.errln( "testidn error: u_parseDelimitedFile(\"%s\") failed - %s\n", filename, u_errorName(*pErrorCode));
    }
}

/* parser for UnicodeData.txt ----------------------------------------------- */
U_CDECL_BEGIN

static void U_CALLCONV
unicodeDataLineFn(void *context,
                  char *fields[][2], int32_t /*fieldCount*/,
                  UErrorCode *pErrorCode) {
    uint32_t rangeStart=0,rangeEnd =0;
    UBool* isUnassigned = (UBool*) context;

    u_parseCodePointRange(fields[0][0], &rangeStart,&rangeEnd, pErrorCode);
    
    if(U_FAILURE(*pErrorCode)){
        *pErrorCode  = U_PARSE_ERROR;
        return;
    }


    compareFlagsForRange(rangeStart,rangeEnd,*isUnassigned);

}

U_CDECL_END

static void
parseTable(const char *filename,UBool isUnassigned,TestIDNA& test, UErrorCode *pErrorCode) {
    char *fields[2][2];
    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
        return;
    }

    u_parseDelimitedFile(filename, ';', fields, 1, unicodeDataLineFn, &isUnassigned, pErrorCode);


    if(U_FAILURE(*pErrorCode)) {
        test.errln( "testidn error: u_parseDelimitedFile(\"%s\") failed - %s\n", filename, u_errorName(*pErrorCode));
    }
}

static void
testAllCodepoints(TestIDNA& test){
    if(isDataLoaded){
        uint32_t i = 0;
        int32_t unassigned      = 0;
        int32_t prohibited      = 0;
        int32_t mappedWithNorm  = 0;
        int32_t mapped          = 0;
        int32_t noValueInTrie   = 0;


        for(i=0;i<=0x10FFFF;i++){
            uint32_t result = 0;
            UTRIE_GET16(&idnTrie,i, result);

            if(result != UIDNA_NO_VALUE ){
                if((result & 0x07) == UIDNA_UNASSIGNED){
                    unassigned++;
                }
                if((result & 0x07) == UIDNA_PROHIBITED){
                    prohibited++;
                }
                if((result>>5) == _IDNA_MAP_TO_NOTHING){
                    mapped++;
                }
                if((result & 0x07) == UIDNA_MAP_NFKC){
                    mappedWithNorm++;
                }
            }else{
                noValueInTrie++;
                if(result > 0){
                    test.errln("The return value for 0x%06X is wrong. %i\n",i,result);
                }
            }
        }

        test.logln("Number of Unassinged code points : %i \n",unassigned);
        test.logln("Number of Prohibited code points : %i \n",prohibited);
        test.logln("Number of Mapped code points : %i \n",mapped);
        test.logln("Number of Mapped with NFKC code points : %i \n",mappedWithNorm);
        test.logln("Number of code points that have no value in Trie: %i \n",noValueInTrie);

    }
}

static inline void getValues(uint32_t result, int8_t& flag, 
                             int8_t& length, int32_t& index){
    /* first 3 bits contain the flag */
    flag = (int8_t) (result & 0x07);
    /* next 2 bits contain the length */
    length = (int8_t) ((result>>3) & 0x03);
    /* next 11 bits contain the index */
    index  = (result>> 5);
}

static void 
compareMapping(uint32_t codepoint, uint32_t* mapping,int32_t mapLength, 
               UBool withNorm){
    if(isDataLoaded){
        uint32_t result = 0;
        UTRIE_GET16(&idnTrie,codepoint, result);

        int8_t flag, length;
        int32_t index;
        getValues(result,flag,length, index);


        if(withNorm){
            if(flag != UIDNA_MAP_NFKC){
                pTestIDNA->errln( "Did not get the assigned flag for codepoint 0x%08X. Expected: %i Got: %i\n",codepoint, UIDNA_MAP_NFKC, flag);
            }
        }else{
            if(flag==UIDNA_NO_VALUE || flag == UIDNA_PROHIBITED){
                if(index != _IDNA_MAP_TO_NOTHING ){
                    pTestIDNA->errln( "Did not get the assigned flag for codepoint 0x%08X. Expected: %i Got: %i\n", codepoint, _IDNA_MAP_TO_NOTHING, index);
                }
            }
        }
        if(length ==_IDNA_LENGTH_IN_MAPPING_TABLE){
            length = (int8_t)mappingData[index];
            index++;
        }
        int32_t realLength =0;
        /* figure out the real length */ 
        for(int32_t j=0; j<mapLength; j++){
            if(mapping[j] > 0xFFFF){
                realLength +=2;
            }else{
                realLength++;
            }      
        }

        if(realLength != length){
            pTestIDNA->errln( "Did not get the expected length. Expected: %i Got: %i\n", mapLength, length);
        }
        

        for(int8_t i =0; i< mapLength; i++){
            if(mapping[i] <= 0xFFFF){
                if(mappingData[index+i] != (uint16_t)mapping[i]){
                    pTestIDNA->errln("Did not get the expected result. Expected: 0x%04X Got: 0x%04X \n", mapping[i], mappingData[index+i]);
                }
            }else{
                UChar lead  = UTF16_LEAD(mapping[i]);
                UChar trail = UTF16_TRAIL(mapping[i]);
                if(mappingData[index+i] != lead ||
                    mappingData[index+i+1] != trail){
                    pTestIDNA->errln( "Did not get the expected result. Expected: 0x%04X 0x%04X  Got: 0x%04X 0x%04X", lead, trail, mappingData[index+i], mappingData[index+i+1]);
                }
            }
        }

    }

}

static void
compareFlagsForRange(uint32_t start, uint32_t end,
                     UBool isUnassigned){
    if(isDataLoaded){
        uint32_t result =0 ;
        while(start < end+1){
            UTRIE_GET16(&idnTrie,start, result);
            if(isUnassigned){
                if(result != UIDNA_UNASSIGNED){
                    pTestIDNA->errln( "UIDNA_UASSIGNED flag failed for 0x%06X. Expected: %04X Got: %04X\n",start,UIDNA_UNASSIGNED, result);
                }
            }else{
                if((result & 0x03) != UIDNA_PROHIBITED){
                    pTestIDNA->errln( "UIDNA_PROHIBITED flag failed for 0x%06X. Expected: %04X Got: %04X\n\n",start,UIDNA_PROHIBITED, result);
                }
            }
            start++;
        }
    }
}

UBool
cleanup() {
    if(idnData!=NULL) {
        udata_close(idnData);
        idnData=NULL;
    }
    dataErrorCode=U_ZERO_ERROR;
    isDataLoaded=FALSE;

    return TRUE;
}
U_CDECL_BEGIN
static UBool U_CALLCONV
isAcceptable(void * /* context */,
             const char * /* type */, const char * /* name */,
             const UDataInfo *pInfo) {
    if(
        pInfo->size>=20 &&
        pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
        pInfo->charsetFamily==U_CHARSET_FAMILY &&
        pInfo->dataFormat[0]==0x49 &&   /* dataFormat="IDNA" 0x49, 0x44, 0x4e, 0x41  */
        pInfo->dataFormat[1]==0x44 &&
        pInfo->dataFormat[2]==0x4e &&
        pInfo->dataFormat[3]==0x41 &&
        pInfo->formatVersion[0]==2 &&
        pInfo->formatVersion[2]==UTRIE_SHIFT &&
        pInfo->formatVersion[3]==UTRIE_INDEX_SHIFT
    ) {
        return TRUE;
    } else {
        return FALSE;
    }
}

/* idnTrie: the folding offset is the lead FCD value itself */
static int32_t U_CALLCONV
getFoldingOffset(uint32_t data) {
    if(data&0x8000) {
        return (int32_t)(data&0x7fff);
    } else {
        return 0;
    }
}
U_CDECL_END

static UBool
loadIDNData(UErrorCode &errorCode) {
    /* load Unicode normalization data from file */
    if(isDataLoaded==FALSE) {
        UTrie _idnTrie={ 0,0,0,0,0,0,0 };
        UDataMemory *data;
        const int32_t *p=NULL;
        const uint8_t *pb;
        if(&errorCode==NULL || U_FAILURE(errorCode)) {
            return 0;
        }

        /* open the data outside the mutex block */
        data=udata_openChoice(NULL, DATA_TYPE, DATA_NAME, isAcceptable, NULL, &errorCode);
        dataErrorCode=errorCode;
        if(U_FAILURE(errorCode)) {
            return isDataLoaded=FALSE;
        }

        p=(const int32_t *)udata_getMemory(data);
        pb=(const uint8_t *)(p+_IDNA_INDEX_TOP);
        utrie_unserialize(&_idnTrie, pb, p[_IDNA_INDEX_TRIE_SIZE], &errorCode);
        _idnTrie.getFoldingOffset=getFoldingOffset;


        if(U_FAILURE(errorCode)) {
            dataErrorCode=errorCode;
            udata_close(data);
            return isDataLoaded=FALSE;
        }

        /* in the mutex block, set the data for this process */
        umtx_lock(NULL);
        if(idnData==NULL) {
            idnData=data;
            data=NULL;
            uprv_memcpy(&indexes, p, sizeof(indexes));
            uprv_memcpy(&idnTrie, &_idnTrie, sizeof(UTrie));
        } else {
            p=(const int32_t *)udata_getMemory(idnData);
        }
        umtx_unlock(NULL);
        /* initialize some variables */
        mappingData=(uint16_t *)((uint8_t *)(p+_IDNA_INDEX_TOP)+indexes[_IDNA_INDEX_TRIE_SIZE]);

        isDataLoaded = TRUE;

        /* if a different thread set it first, then close the extra data */
        if(data!=NULL) {
            udata_close(data); /* NULL if it was set correctly */
        }
    }

    return isDataLoaded;
}

#endif /* #if !UCONFIG_NO_IDNA */

/*
 * Hey, Emacs, please set the following:
 *
 * Local Variables:
 * indent-tabs-mode: nil
 * End:
 *
 */

--- NEW FILE: testidna.cpp ---
/*
 *******************************************************************************
 *
 *   Copyright (C) 2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 *   file name:  testidna.cpp
 *   encoding:   US-ASCII
 *   tab size:   8 (not used)
 *   indentation:4
 *
 *   created on: 2003feb1
 *   created by: Ram Viswanadha
 */

#include "unicode/utypes.h"

#if !UCONFIG_NO_IDNA && !UCONFIG_NO_TRANSLITERATION
[...1538 lines suppressed...]
    testIDNToUnicode("idnaref_IDNToUnicode", idnaref_IDNToUnicode);
    testCompare("idnaref_compare",idnaref_compare);
    testErrorCases("idnaref_toASCII",idnaref_toASCII, "idnaref_IDNToASCII",idnaref_IDNToASCII,
                    "idnaref_IDNToUnicode",idnaref_IDNToUnicode);
    testChaining("idnaref_toASCII",idnaref_toASCII, "idnaref_toUnicode", idnaref_toUnicode);

    testRootLabelSeparator( "idnaref_compare",idnaref_compare,
                            "idnaref_IDNToASCII", idnaref_IDNToASCII,
                            "idnaref_IDNToUnicode",idnaref_IDNToUnicode
                            );
    testChaining("idnaref_toASCII",idnaref_toASCII, "idnaref_toUnicode", idnaref_toUnicode);
    delete TestIDNA::prep;
    TestIDNA::prep = NULL;
}

void TestIDNA::TestDataFile(){
     testData(*this);
}

#endif /* #if !UCONFIG_NO_IDNA */

--- NEW FILE: testidna.h ---
/*
 *******************************************************************************
 *
 *   Copyright (C) 2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 *   file name:  testidna.h
 *   encoding:   US-ASCII
 *   tab size:   8 (not used)
 *   indentation:4
 *
 *   created on: 2003feb1
 *   created by: Ram Viswanadha
 */

#ifndef TESTIDNA_H
#define TESTIDNA_H

#include "unicode/utypes.h"

#if !UCONFIG_NO_IDNA && !UCONFIG_NO_TRANSLITERATION

#include "sprpimpl.h"
#include "intltest.h"
#include "unicode/parseerr.h"

U_CDECL_BEGIN
typedef int32_t  
(*TestFunc) (   const UChar *src, int32_t srcLength,
                UChar *dest, int32_t destCapacity,
                int32_t options, UParseError *parseError,
                UErrorCode *status);
typedef int32_t  
(*CompareFunc) (const UChar *s1, int32_t s1Len,
                const UChar *s2, int32_t s2Len,
                int32_t options,
                UErrorCode *status);


U_CDECL_END

// test the API

class NamePrepTransform;

/**
 * @test
 * @summary General test of HexadecimalToUnicodeTransliterator
 */
class TestIDNA : public IntlTest {
public:
    void runIndexedTest(int32_t index, UBool exec, const char* &name, char* par=NULL);
    void TestDataFile();
    void TestToASCII();
    void TestToUnicode();
    void TestIDNToUnicode();
    void TestIDNToASCII();
    void TestCompare();
    void TestErrorCases();
    void TestChaining();
    void TestRootLabelSeparator();
    void TestCompareReferenceImpl();
    void TestRefIDNA();
    void TestIDNAMonkeyTest();
    void TestConformance();
    static NamePrepTransform* getInstance(UErrorCode& status);
    static NamePrepTransform* prep;
private:
    void testToASCII(const char* testName, TestFunc func);
    void testToUnicode(const char* testName, TestFunc func);
    void testIDNToUnicode(const char* testName, TestFunc func);
    void testIDNToASCII(const char* testName, TestFunc func);
    void testCompare(const char* testName, CompareFunc func);
    void testChaining(const char* toASCIIName, TestFunc toASCII,
                    const char* toUnicodeName, TestFunc toUnicode);

    // main testing functions
    void testAPI(const UChar *src, const UChar *expected, const char *testName, 
             UBool useSTD3ASCIIRules, UErrorCode expectedStatus,
             UBool doCompare, UBool testUnassigned, TestFunc func);

    void testCompare(const UChar* s1, int32_t s1Len,
                        const UChar* s2, int32_t s2Len,
                        const char* testName, CompareFunc func,
                        UBool isEqual);

    void testErrorCases(const char* toASCIIName, TestFunc toASCII,
                    const char* IDNToASCIIName, TestFunc IDNToASCII,
                    const char* IDNToUnicodeName, TestFunc IDNToUnicode);

    void testChaining(UChar* src,int32_t numIterations,const char* testName,
                  UBool useSTD3ASCIIRules, UBool caseInsensitive, TestFunc func);

    void testRootLabelSeparator(const char* testName, CompareFunc func, 
                            const char* IDNToASCIIName, TestFunc IDNToASCII,
                            const char* IDNToUnicodeName, TestFunc IDNToUnicode);

    void testCompareReferenceImpl(const UChar* src, int32_t srcLen);

    void testConformance(const char* toASCIIName, TestFunc toASCII,
                         const char* IDNToASCIIName, TestFunc IDNToASCII,
                         const char* IDNToUnicodeName, TestFunc IDNToUnicode,
                         const char* toUnicodeName, TestFunc toUnicode
                         );

};

// test the TRIE data structure
int testData(TestIDNA& test);

#endif /* #if !UCONFIG_NO_IDNA */

#endif



































--- NEW FILE: tstdtmod.cpp ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 2002, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

/* Created by weiv 05/09/2002 */

#include "tstdtmod.h"
#include "cmemory.h"

TestDataModule *TestDataModule::getTestDataModule(const char* name, TestLog& log, UErrorCode &status)
{
  if(U_FAILURE(status)) {
    return NULL;
  }
  TestDataModule *result = NULL;

  // TODO: probe for resource bundle and then for XML.
  // According to that, construct an appropriate driver object

  result = new RBTestDataModule(name, log, status);
  if(U_SUCCESS(status)) {
    return result;
  } else {
    delete result;
    return NULL;
  }
}

TestDataModule::TestDataModule(const char* name, TestLog& log, UErrorCode& /*status*/)
: testName(name),
fInfo(NULL),
fLog(log)
{
}

TestDataModule::~TestDataModule() {
  if(fInfo != NULL) {
    delete fInfo;
  }
}

const char * TestDataModule::getName() const
{
  return testName;
}



RBTestDataModule::~RBTestDataModule()
{
  ures_close(fTestData);
  ures_close(fModuleBundle);
  ures_close(fInfoRB);
  uprv_free(tdpath);
}

RBTestDataModule::RBTestDataModule(const char* name, TestLog& log, UErrorCode& status) 
: TestDataModule(name, log, status),
  fModuleBundle(NULL),
  fTestData(NULL),
  fInfoRB(NULL),
  tdpath(NULL)
{
  fNumberOfTests = 0;
  fDataTestValid = TRUE;
  fModuleBundle = getTestBundle(name, status);
  if(fDataTestValid) {
    fTestData = ures_getByKey(fModuleBundle, "TestData", NULL, &status);
    fNumberOfTests = ures_getSize(fTestData);
    fInfoRB = ures_getByKey(fModuleBundle, "Info", NULL, &status);
    if(status != U_ZERO_ERROR) {
      log.errln("Unable to initalize test data - missing mandatory description resources!");
      fDataTestValid = FALSE;
    } else {
      fInfo = new RBDataMap(fInfoRB, status);
    }
  }
}

UBool RBTestDataModule::getInfo(const DataMap *& info, UErrorCode &/*status*/) const
{
    info = fInfo;
    if(fInfo) {
        return TRUE;
    } else {
        return FALSE;
    }
}

TestData* RBTestDataModule::createTestData(int32_t index, UErrorCode &status) const 
{
  TestData *result = NULL;
  UErrorCode intStatus = U_ZERO_ERROR;

  if(fDataTestValid == TRUE) {
    // Both of these resources get adopted by a TestData object.
    UResourceBundle *DataFillIn = ures_getByIndex(fTestData, index, NULL, &status); 
    UResourceBundle *headers = ures_getByKey(fInfoRB, "Headers", NULL, &intStatus);
  
    if(U_SUCCESS(status)) {
      result = new RBTestData(DataFillIn, headers, status);

      if(U_SUCCESS(status)) {
        return result;
      } else {
        delete result;
      }
    } else {
      ures_close(DataFillIn);
      ures_close(headers);
    }
  } else {
    status = U_MISSING_RESOURCE_ERROR;
  }
  return NULL;
}

TestData* RBTestDataModule::createTestData(const char* name, UErrorCode &status) const
{
  TestData *result = NULL;
  UErrorCode intStatus = U_ZERO_ERROR;

  if(fDataTestValid == TRUE) {
    // Both of these resources get adopted by a TestData object.
    UResourceBundle *DataFillIn = ures_getByKey(fTestData, name, NULL, &status); 
    UResourceBundle *headers = ures_getByKey(fInfoRB, "Headers", NULL, &intStatus);
   
    if(U_SUCCESS(status)) {
      result = new RBTestData(DataFillIn, headers, status);
      if(U_SUCCESS(status)) {
        return result;
      } else {
        delete result;
      }
    } else {
      ures_close(DataFillIn);
      ures_close(headers);
    }
  } else {
    status = U_MISSING_RESOURCE_ERROR;
  }
  return NULL;
}



//Get test data from ResourceBundles
UResourceBundle* 
RBTestDataModule::getTestBundle(const char* bundleName, UErrorCode &status) 
{
  if(U_SUCCESS(status)) {
    UResourceBundle *testBundle = NULL;
    //const char* icu_data = (char*)loadTestData(status);
    const char* icu_data = IntlTest::loadTestData(status);
    if (testBundle == NULL) {
        testBundle = ures_openDirect(icu_data, bundleName, &status);
        if (status != U_ZERO_ERROR) {
            fLog.errln(UnicodeString("Failed: could not load test data from resourcebundle: ") + UnicodeString(bundleName));
            fDataTestValid = FALSE;
        }
    }
    return testBundle;
  } else {
    return NULL;
  }
}


--- NEW FILE: tstdtmod.h ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 2002, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

/* Created by weiv 05/09/2002 */

/* Base class for data driven tests */

#ifndef INTLTST_TESTMODULE
#define INTLTST_TESTMODULE

#include "unicode/utypes.h"
#include "unicode/unistr.h"
#include "intltest.h"
#include "unicode/ures.h"
#include "testdata.h"
#include "datamap.h"

/* This class abstracts the actual organization of the  
 * data for data driven tests                           
 */


class DataMap;
class TestData;

/** Facilitates internal logging of data driven test service 
 *  It would be interesting to develop this into a full      
 *  fledged control system as in Java.                       
 */
class TestLog : public IntlTest{
};


/** Main data driven test class. Corresponds to one named data 
 *  unit (such as a resource bundle. It is instantiated using  
 *  a factory method getTestDataModule 
 */
class TestDataModule {
  const char* testName;

protected:
  DataMap *fInfo;
  TestLog& fLog;

public:
  /** Factory method. 
   *  @param name name of the test module. Usually name of a resource bundle or a XML file 
   *  @param log a logging class, used for internal error reporting.                       
   *  @param status if something goes wrong, status will be set                            
   *  @return a TestDataModule object. Use it to get test data from it                     
   */
  static TestDataModule *getTestDataModule(const char* name, TestLog& log, UErrorCode &status);
  virtual ~TestDataModule();

protected:
  TestDataModule(const char* name, TestLog& log, UErrorCode& status);

public:
  /** Name of this TestData module. 
   *  @return a name 
   */
  const char * getName() const;

  /** Get a pointer to an object owned DataMap that contains more information on this module 
   *  Usual fields are "Description", "LongDescription", "Settings". Also, if containing a   
   *  field "Headers" these will be used as the default headers, so that you don't have to   
   *  to specify per test headers.                                                           
   *  @param info pass in a const DataMap pointer. If no info, it will be set to NULL
   */
  virtual UBool getInfo(const DataMap *& info, UErrorCode &status) const = 0;

  /** Create a test data object from an index. Helpful for integrating tests with current 
   *  intltest framework which addresses the tests by index.                              
   *  @param index index of the test to be instantiated                                   
   *  @return an instantiated TestData object, ready to provide settings and cases for    
   *          the tests.                                                                  
   */
  virtual TestData* createTestData(int32_t index, UErrorCode &status) const = 0;

  /** Create a test data object from a name.                              
   *  @param name name of the test to be instantiated                                     
   *  @return an instantiated TestData object, ready to provide settings and cases for    
   *          the tests.                                                                  
   */
  virtual TestData* createTestData(const char* name, UErrorCode &status) const = 0;
};

class RBTestDataModule : public TestDataModule {
public:
  virtual ~RBTestDataModule();

public:
  RBTestDataModule(const char* name, TestLog& log, UErrorCode& status);

public:
  virtual UBool getInfo(const DataMap *& info, UErrorCode &status) const;

  virtual TestData* createTestData(int32_t index, UErrorCode &status) const;
  virtual TestData* createTestData(const char* name, UErrorCode &status) const;

private:
  UResourceBundle *getTestBundle(const char* bundleName, UErrorCode &status);

private:
  UResourceBundle *fModuleBundle;
  UResourceBundle *fTestData;
  UResourceBundle *fInfoRB;
  UBool fDataTestValid;
  char *tdpath;

/* const char* fTestName;*/ /* See name */
  int32_t fNumberOfTests;

};


#endif



--- NEW FILE: tstnrapi.cpp ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 1997-2003, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

#include "unicode/utypes.h"
#include "unicode/uchar.h"
#include "unicode/normlzr.h"
#include "unicode/uniset.h"
#include "unicode/usetiter.h"
#include "unicode/schriter.h"
#include "tstnorm.h"

#if !UCONFIG_NO_NORMALIZATION

static UErrorCode status = U_ZERO_ERROR;

// test APIs that are not otherwise used - improve test coverage
void
BasicNormalizerTest::TestNormalizerAPI() {
    // instantiate a Normalizer from a CharacterIterator
    UnicodeString s=UnicodeString("a\\u0308\\uac00\\U0002f800", "").unescape();
    s.append(s); // make s a bit longer and more interesting
    StringCharacterIterator iter(s);
    Normalizer norm(iter, UNORM_NFC);
    if(norm.next()!=0xe4) {
        errln("error in Normalizer(CharacterIterator).next()");
    }

    // test copy constructor
    Normalizer copy(norm);
    if(copy.next()!=0xac00) {
        errln("error in Normalizer(Normalizer(CharacterIterator)).next()");
    }

    // test clone(), ==, and hashCode()
    Normalizer *clone=copy.clone();
    if(*clone!=copy) {
        errln("error in Normalizer(Normalizer(CharacterIterator)).clone()!=copy");
    }
    // clone must have the same hashCode()
    if(clone->hashCode()!=copy.hashCode()) {
        errln("error in Normalizer(Normalizer(CharacterIterator)).clone()->hashCode()!=copy.hashCode()");
    }
    if(clone->next()!=0x4e3d) {
        errln("error in Normalizer(Normalizer(CharacterIterator)).clone()->next()");
    }
    // position changed, must change hashCode()
    if(clone->hashCode()==copy.hashCode()) {
        errln("error in Normalizer(Normalizer(CharacterIterator)).clone()->next().hashCode()==copy.hashCode()");
    }
    delete clone;
    clone=0;

    // test compose() and decompose()
    UnicodeString tel, nfkc, nfkd;
    tel=UnicodeString(1, (UChar32)0x2121, 10);
    tel.insert(1, (UChar)0x301);

    UErrorCode errorCode=U_ZERO_ERROR;
    Normalizer::compose(tel, TRUE, 0, nfkc, errorCode);
    Normalizer::decompose(tel, TRUE, 0, nfkd, errorCode);
    if(U_FAILURE(errorCode)) {
        errln("error in Normalizer::(de)compose(): %s", u_errorName(errorCode));
    } else if(
        nfkc!=UnicodeString("TE\\u0139TELTELTELTELTELTELTELTELTEL", "").unescape() || 
        nfkd!=UnicodeString("TEL\\u0301TELTELTELTELTELTELTELTELTEL", "").unescape()
    ) {
        errln("error in Normalizer::(de)compose(): wrong result(s)");
    }

    // test setIndex()
    norm.setIndexOnly(3);
    if(norm.current()!=0x4e3d) {
        errln("error in Normalizer(CharacterIterator).setIndex(3)");
    }

    // test setText(CharacterIterator) and getText()
    UnicodeString out, out2;
    errorCode=U_ZERO_ERROR;
    copy.setText(iter, errorCode);
    if(U_FAILURE(errorCode)) {
        errln("error Normalizer::setText() failed: %s", u_errorName(errorCode));
    } else {
        copy.getText(out);
        iter.getText(out2);
        if( out!=out2 ||
            copy.startIndex()!=iter.startIndex() ||
            copy.endIndex()!=iter.endIndex()
        ) {
            errln("error in Normalizer::setText() or Normalizer::getText()");
        }
    }

    // test setText(UChar *), getUMode() and setMode()
    errorCode=U_ZERO_ERROR;
    copy.setText(s.getBuffer()+1, s.length()-1, errorCode);
    copy.setMode(UNORM_NFD);
    if(copy.getUMode()!=UNORM_NFD) {
        errln("error in Normalizer::setMode() or Normalizer::getUMode()");
    }
    if(copy.next()!=0x308 || copy.next()!=0x1100) {
        errln("error in Normalizer::setText(UChar *) or Normalizer::setMode()");
    }

    // test setText(UChar *, length=-1)
    errorCode=U_ZERO_ERROR;

    // NUL-terminate s
    s.append((UChar)0);         // append NUL
    s.truncate(s.length()-1);   // undo length change

    copy.setText(s.getBuffer()+1, -1, errorCode);
    if(copy.endIndex()!=s.length()-1) {
        errln("error in Normalizer::setText(UChar *, -1)");
    }

    // test setOption() and getOption()
    copy.setOption(0xaa0000, TRUE);
    copy.setOption(0x20000, FALSE);
    if(!copy.getOption(0x880000) || copy.getOption(0x20000)) {
        errln("error in Normalizer::setOption() or Normalizer::getOption()");
    }

    // test last()/previous() with an internal buffer overflow
    errorCode=U_ZERO_ERROR;
    copy.setText(UnicodeString(1000, (UChar32)0x308, 1000), errorCode);
    if(copy.last()!=0x308) {
        errln("error in Normalizer(1000*U+0308).last()");
    }

    // test UNORM_NONE
    norm.setMode(UNORM_NONE);
    if(norm.first()!=0x61 || norm.next()!=0x308 || norm.last()!=0x2f800) {
        errln("error in Normalizer(UNORM_NONE).first()/next()/last()");
    }
    Normalizer::normalize(s, UNORM_NONE, 0, out, status);
    if(out!=s) {
        errln("error in Normalizer::normalize(UNORM_NONE)");
    }

    // test that the same string can be used as source and destination
    s.setTo((UChar)0xe4);
    Normalizer::normalize(s, UNORM_NFD, 0, s, status);
    if(s.charAt(1)!=0x308) {
        errln("error in Normalizer::normalize(UNORM_NFD, self)");
    }
    Normalizer::normalize(s, UNORM_NFC, 0, s, status);
    if(s.charAt(0)!=0xe4) {
        errln("error in Normalizer::normalize(UNORM_NFC, self)");
    }
    Normalizer::decompose(s, FALSE, 0, s, status);
    if(s.charAt(1)!=0x308) {
        errln("error in Normalizer::decompose(self)");
    }
    Normalizer::compose(s, FALSE, 0, s, status);
    if(s.charAt(0)!=0xe4) {
        errln("error in Normalizer::compose(self)");
    }
    Normalizer::concatenate(s, s, s, UNORM_NFC, 0, status);
    if(s.charAt(1)!=0xe4) {
        errln("error in Normalizer::decompose(self)");
    }
}

#endif







--- NEW FILE: ucaconf.cpp ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 2002-2003, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

/**
 * UCAConformanceTest performs conformance tests defined in the data
 * files. ICU ships with stub data files, as the whole test are too 
 * long. To do the whole test, download the test files.
 */

#include "unicode/utypes.h"

#if !UCONFIG_NO_COLLATION

#include "ucaconf.h"
UCAConformanceTest::UCAConformanceTest() :
rbUCA(NULL),
testFile(NULL),
status(U_ZERO_ERROR)
{
  UCA = ucol_open("root", &status);
  if(U_FAILURE(status)) {
    errln("ERROR - UCAConformanceTest: Unable to open UCA collator!");
  }

  uprv_strcpy(testDataPath, IntlTest::loadTestData(status));
  if (U_FAILURE(status)) {
    errln("ERROR: could not open test data %s", u_errorName(status));
    return;
  }
  char* index = 0;
 
  index=strrchr(testDataPath,(char)U_FILE_SEP_CHAR);

  if((unsigned int)(index-testDataPath) != (strlen(testDataPath)-1)){
          *(index+1)=0;
  }
  uprv_strcat(testDataPath,".."U_FILE_SEP_STRING);
  uprv_strcat(testDataPath, "CollationTest_");
}

UCAConformanceTest::~UCAConformanceTest()
{
  ucol_close(UCA);
  if(rbUCA) {
    ucol_close(rbUCA);
  }
  if(testFile) {
    fclose(testFile);
  }
}

void UCAConformanceTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par */)
{
    if (exec) logln("TestSuite UCAConformanceTest: ");
    if(U_SUCCESS(status)) {
      switch (index) {
          case 0: name = "TestTableNonIgnorable"; if (exec)   TestTableNonIgnorable(/* par */); break;
          case 1: name = "TestTableShifted";      if (exec)   TestTableShifted(/* par */);      break;
          case 2: name = "TestRulesNonIgnorable"; if (exec)   TestRulesNonIgnorable(/* par */); break;
          case 3: name = "TestRulesShifted";      if (exec)   TestRulesShifted(/* par */);      break;
          default: name = ""; break;
      }
    } else {
      name = "";
    }
}

static const int BUFFER_SIZE_ = 330000;
static UChar buffer[BUFFER_SIZE_];

void UCAConformanceTest::initRbUCA() 
{
  if(!rbUCA) {
    UParseError parseError;
    UChar      *ucarules = buffer;
    int32_t size = ucol_getRulesEx(UCA, UCOL_FULL_RULES, ucarules, 
                                   BUFFER_SIZE_);
    if (size > BUFFER_SIZE_) {
        ucarules = (UChar *)malloc(size * sizeof(UChar));
        size = ucol_getRulesEx(UCA, UCOL_FULL_RULES, ucarules, size);
    }
    rbUCA = ucol_openRules(ucarules, size, UCOL_DEFAULT, UCOL_TERTIARY, 
                          &parseError, &status);
    if (U_FAILURE(status)) {
        errln("Failure creating UCA rule-based collator.");
        return;
    }
  }
}

void UCAConformanceTest::setCollNonIgnorable(UCollator *coll) 
{
  ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
  ucol_setAttribute(coll, UCOL_CASE_FIRST, UCOL_OFF, &status);
  ucol_setAttribute(coll, UCOL_CASE_LEVEL, UCOL_OFF, &status);
  ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_TERTIARY, &status);
  ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, &status);
}

void UCAConformanceTest::setCollShifted(UCollator *coll) 
{
  ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
  ucol_setAttribute(coll, UCOL_CASE_FIRST, UCOL_OFF, &status);
  ucol_setAttribute(coll, UCOL_CASE_LEVEL, UCOL_OFF, &status);
  ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_QUATERNARY, &status);
  ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
}

void UCAConformanceTest::openTestFile(const char *type)
{
  const char *ext = ".txt";
  if(testFile) {
    fclose(testFile);
  }
  char buffer[1024];
  uprv_strcpy(buffer, testDataPath);
  uprv_strcat(buffer, type);
  int32_t bufLen = uprv_strlen(buffer);

  // we try to open 3 files:
  // path/CollationTest_type.txt
  // path/CollationTest_type_SHORT.txt
  // path/CollationTest_type_STUB.txt
  // we are going to test with the first one that we manage to open.

  uprv_strcpy(buffer+bufLen, ext);

  testFile = fopen(buffer, "rb");

  if(testFile == 0) {
    uprv_strcpy(buffer+bufLen, "_SHORT");
    uprv_strcat(buffer, ext);
    testFile = fopen(buffer, "rb");

    if(testFile == 0) {
      uprv_strcpy(buffer+bufLen, "_STUB");
      uprv_strcat(buffer, ext);
      testFile = fopen(buffer, "rb");

      if (testFile == 0) {
        *(buffer+bufLen) = 0;
        errln("ERROR: could not open any of the conformance test files, tried opening base %s\n", buffer);
        return;        
      } else {
        infoln(
          "INFO: Working with the stub file.\n"
          "If you need the full conformance test, please\n"
          "download the appropriate data files from:\n"
          "http://oss.software.ibm.com/cvs/icu4j/unicodetools/com/ibm/text/data/");
      }
    }
  }
}

void UCAConformanceTest::testConformance(UCollator *coll) 
{
  if(testFile == 0) {
    return;
  }

  int32_t line = 0;

  UChar b1[1024], b2[1024];
  char lineB[1024];
  UChar *buffer = b1, *oldB = NULL;
  uint8_t sk1[1024], sk2[1024];
  uint8_t *oldSk = NULL, *newSk = sk1;
  int32_t resLen = 0, oldLen = 0;
  int32_t buflen = 0, oldBlen = 0;
  uint32_t first = 0;
  uint32_t offset = 0;


  while (fgets(lineB, 1024, testFile) != NULL) {
    offset = 0;

    line++;
    if(*lineB == 0 || lineB[0] == '#') {
      continue;
    }
    offset = u_parseString(lineB, buffer, 1024, &first, &status);
    buflen = offset;
    buffer[offset++] = 0;

    resLen = ucol_getSortKey(coll, buffer, buflen, newSk, 1024);

    int32_t res = 0, cmpres = 0, cmpres2 = 0;

    if(oldSk != NULL) {
      res = strcmp((char *)oldSk, (char *)newSk);
      cmpres = ucol_strcoll(coll, oldB, oldBlen, buffer, buflen);
      cmpres2 = ucol_strcoll(coll, buffer, buflen, oldB, oldBlen);

      if(cmpres != -cmpres2) {
        errln("Compare result not symmetrical on line %i", line);
      }

      if(((res&0x80000000) != (cmpres&0x80000000)) || (res == 0 && cmpres != 0) || (res != 0 && cmpres == 0)) {
        errln("Difference between ucol_strcoll and sortkey compare on line %i", line);
        logln("Data line %s", lineB);
      }

      if(res > 0) {
        errln("Line %i is not greater or equal than previous line", line);
        logln("Data line %s", lineB);
      } else if(res == 0) { /* equal */
        res = u_strcmpCodePointOrder(oldB, buffer);
        if (res == 0) {
          errln("Probable error in test file on line %i (comparing identical strings)", line);
          logln("Data line %s", lineB);
        } else if (res > 0) {
          errln("Sortkeys are identical, but code point comapare gives >0 on line %i", line);
          logln("Data line %s", lineB);
        }
      }
    }

    oldSk = newSk;
    oldLen = resLen;

    newSk = (newSk == sk1)?sk2:sk1;
    oldB = buffer;
    oldBlen = buflen;
    buffer = (buffer == b1)?b2:b1;
  }
}

void UCAConformanceTest::TestTableNonIgnorable(/* par */) {
  setCollNonIgnorable(UCA);
  openTestFile("NON_IGNORABLE");
  testConformance(UCA);
}

void UCAConformanceTest::TestTableShifted(/* par */) {
  setCollShifted(UCA);
  openTestFile("SHIFTED");
  testConformance(UCA);
}

void UCAConformanceTest::TestRulesNonIgnorable(/* par */) {
  initRbUCA();

  if(U_SUCCESS(status)) {
    setCollNonIgnorable(rbUCA);
    openTestFile("NON_IGNORABLE");
    testConformance(rbUCA);
  }
}

void UCAConformanceTest::TestRulesShifted(/* par */) {
  logln("This test is currently disabled, as it is impossible to "
    "wholly represent fractional UCA using tailoring rules.");
  return;

  initRbUCA();

  if(U_SUCCESS(status)) {
    setCollShifted(rbUCA);
    openTestFile("SHIFTED");
    testConformance(rbUCA);
  }
}

#endif /* #if !UCONFIG_NO_COLLATION */

--- NEW FILE: ucaconf.h ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 2002, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

/**
 * UCAConformanceTest performs conformance tests defined in the data
 * files. ICU ships with stub data files, as the whole test are too 
 * long. To do the whole test, download the test files.
 */

#ifndef _UCACONF_TST
#define _UCACONF_TST

#include "unicode/utypes.h"

#if !UCONFIG_NO_COLLATION

#include "unicode/tblcoll.h"
#include "unicode/ustring.h"
#include "tscoll.h"
#include "uparse.h"
#include "cstring.h"

#include <stdio.h>

class UCAConformanceTest: public IntlTestCollator {
public:
  UCAConformanceTest();
  virtual ~UCAConformanceTest();

  void runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par = NULL */);

  void TestTableNonIgnorable(/* par */);
  void TestTableShifted(/* par */);     
  void TestRulesNonIgnorable(/* par */);
  void TestRulesShifted(/* par */);     
private:
  void initRbUCA();
  void setCollNonIgnorable(UCollator *coll);
  void setCollShifted(UCollator *coll);
  void testConformance(UCollator *coll);
  void openTestFile(const char *type);

  UCollator *UCA;
  UCollator *rbUCA;
  FILE *testFile;
  UErrorCode status;
  char testDataPath[1024];
};

#endif /* #if !UCONFIG_NO_COLLATION */

#endif







--- NEW FILE: uobjtest.cpp ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 2002-2003, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

#include "uobjtest.h"
#include <string.h>

/**
 * 
 * Test for UObject, currently only the classID.
 *
 * Usage
 *   TESTCLASSID_ABSTRACT(Bar)
 *      --  Bar is expected to be abstract. Only the static ID will be tested.
 *
 *   TESTCLASSID_DEFAULT(Foo)
 *      --  Foo will be default-constructed.
 *
 *   TESTCLASSID_CTOR(Foo, (1, 2, 3, status))
 *      -- Second argument is (parenthesized) constructor argument.
 *          Will be called as:   new Foo ( 1, 2, 3, status)  [status is tested]
 *
 *   TESTCLASSID_FACTORY(Foo, fooCreateFunction(status) ) 
 *      -- call fooCreateFunction.  'status' will be tested & reset
 */


#define TESTCLASSID_FACTORY(c, f) { delete testClass(f, #c, #f, c ::getStaticClassID()); if(U_FAILURE(status)) { errln(UnicodeString(#c " - " #f " - got err status ") + UnicodeString(u_errorName(status))); status = U_ZERO_ERROR; } }
#define TESTCLASSID_TRANSLIT(c, t) { delete testClass(Transliterator::createInstance(UnicodeString(t), UTRANS_FORWARD,parseError,status), #c, "Transliterator: " #t, c ::getStaticClassID()); if(U_FAILURE(status)) { errln(UnicodeString(#c " - Transliterator: " #t " - got err status ") + UnicodeString(u_errorName(status))); status = U_ZERO_ERROR; } }
#define TESTCLASSID_CTOR(c, x) { delete testClass(new c x, #c, "new " #c #x, c ::getStaticClassID()); if(U_FAILURE(status)) { errln(UnicodeString(#c " - new " #x " - got err status ") + UnicodeString(u_errorName(status))); status = U_ZERO_ERROR; } }
#define TESTCLASSID_DEFAULT(c) delete testClass(new c, #c, "new " #c , c::getStaticClassID())
#define TESTCLASSID_ABSTRACT(c) testClass(NULL, #c, NULL, c::getStaticClassID())

#define MAX_CLASS_ID 200

UClassID    ids[MAX_CLASS_ID];
const char *ids_factory[MAX_CLASS_ID];
const char *ids_class[MAX_CLASS_ID];
uint32_t    ids_count = 0;

UObject *UObjectTest::testClass(UObject *obj,
				const char *className, const char *factory, 
				UClassID staticID)
{
  uint32_t i;
  UnicodeString what = UnicodeString(className) + " * x= " + UnicodeString(factory?factory:" ABSTRACT ") + "; ";
  UClassID dynamicID = NULL;

  if(ids_count >= MAX_CLASS_ID) {
    char count[100];
    sprintf(count, " (currently %d) ", MAX_CLASS_ID);
    errln("FAIL: Fatal: Ran out of IDs! Increase MAX_CLASS_ID." + UnicodeString(count) + what);
    return obj;
  }

  if(obj) {
    dynamicID = obj->getDynamicClassID();
  }    

  {
    char tmp[500];
    sprintf(tmp, " [static=%p, dynamic=%p] ", staticID, dynamicID);
    logln(what + tmp);
  }

  if(staticID == NULL) {
    errln(  "FAIL: staticID == NULL!" + what);
  }

  if(factory != NULL) {  /* NULL factory means: abstract */
    if(!obj) {
      errln( "FAIL: ==NULL!" + what);
      return obj;
    }

    if(dynamicID == NULL) {
      errln("FAIL: dynamicID == NULL!" + what);
    }
    
    if(dynamicID != staticID) {
      errln("FAIL: dynamicID != staticID!" + what );
    }
  }

  // Bail out if static ID is null
  if(staticID == NULL) {
    return obj;
  }

  for(i=0;i<ids_count;i++) {
    if(staticID == ids[i]) {
      if(!strcmp(ids_class[i], className)) {
	logln("OK: ID found is the same as " + UnicodeString(ids_class[i]) + UnicodeString(" *y= ") + ids_factory[i] + what);
	return obj; 
      } else {
	errln("FAIL: ID is the same as " + UnicodeString(ids_class[i]) + UnicodeString(" *y= ") + ids_factory[i] + what);
	return obj;
      }
    }
  }

  ids[ids_count] = staticID;
  ids_factory[ids_count] = factory;
  ids_class[ids_count] = className;
  ids_count++;

  return obj;
}


// begin actual #includes for things to be tested
// 
// The following script will generate the #includes needed here:
//
//    find common i18n -name '*.h' -print | xargs fgrep ClassID | cut -d: -f1 | cut -d\/ -f2-  | sort | uniq | sed -e 's%.*%#include "&"%'


#include "unicode/utypes.h"

// Things we Patch
#define protected public   /* to access private factory function */
#include "iculserv.h"
#undef protected

// Internal Things (woo)
#include "cpdtrans.h"
#include "rbt.h"
#include "rbt_data.h"
#include "hextouni.h"
#include "unitohex.h"
#include "nultrans.h"
#include "anytrans.h"
#include "digitlst.h"
#include "esctrn.h"
#include "funcrepl.h"
#include "icunotif.h"
#include "icuserv.h"
#include "name2uni.h"
#include "nfsubs.h"
#include "nortrans.h"
#include "quant.h"
#include "remtrans.h"
#include "strmatch.h"
#include "strrepl.h"
#include "titletrn.h"
#include "tolowtrn.h"
#include "toupptrn.h"
#include "unesctrn.h"
#include "uni2name.h"
#include "uvector.h"

// External Things
#include "unicode/brkiter.h"
#include "unicode/calendar.h"
#include "unicode/caniter.h"
#include "unicode/chariter.h"
#include "unicode/choicfmt.h"
#include "unicode/coleitr.h"
#include "unicode/coll.h"
#include "unicode/datefmt.h"
#include "unicode/dbbi.h"
#include "unicode/dcfmtsym.h"
#include "unicode/decimfmt.h"
#include "unicode/dtfmtsym.h"
#include "unicode/fieldpos.h"
#include "unicode/fmtable.h"
#include "unicode/format.h"
#include "unicode/gregocal.h"
#include "unicode/locid.h"
#include "unicode/msgfmt.h"
#include "unicode/normlzr.h"
#include "unicode/numfmt.h"
#include "unicode/parsepos.h"
#include "unicode/rbbi.h"
#include "unicode/rbnf.h"
#include "unicode/regex.h"
#include "unicode/resbund.h"
#include "unicode/schriter.h"
#include "unicode/simpletz.h"
#include "unicode/smpdtfmt.h"
#include "unicode/sortkey.h"
#include "unicode/stsearch.h"
#include "unicode/tblcoll.h"
#include "unicode/timezone.h"
#include "unicode/translit.h"
#include "unicode/uchriter.h"
#include "unicode/unifilt.h"
#include "unicode/unifunct.h"
#include "unicode/uniset.h"
#include "unicode/unistr.h"
#include "unicode/uobject.h"
#include "unicode/usetiter.h"
//#include "unicode/bidi.h"
//#include "unicode/convert.h"

// END includes =============================================================

#define UOBJTEST_TEST_INTERNALS 0   /* do NOT test Internal things - their functions aren't exported on Win32 */

void UObjectTest::testIDs()
{
    ids_count = 0;

#if !UCONFIG_NO_TRANSLITERATION
    UParseError parseError;
#endif
    UErrorCode status = U_ZERO_ERROR;
   

    
    //TESTCLASSID_DEFAULT(AbbreviatedUnicodeSetIterator);
    //TESTCLASSID_DEFAULT(AnonymousStringFactory);

    
#if !UCONFIG_NO_NORMALIZATION
    TESTCLASSID_FACTORY(CanonicalIterator, new CanonicalIterator(UnicodeString("abc"), status));
#endif
    //TESTCLASSID_DEFAULT(CollationElementIterator);
#if !UCONFIG_NO_COLLATION
    TESTCLASSID_DEFAULT(CollationKey);
#endif
    //TESTCLASSID_FACTORY(CompoundTransliterator, Transliterator::createInstance(UnicodeString("Any-Jex;Hangul-Jamo"), UTRANS_FORWARD, parseError, status));
    
#if !UCONFIG_NO_FORMATTING
    /* TESTCLASSID_FACTORY(NFSubstitution,  NFSubstitution::makeSubstitution(8, */
    /* TESTCLASSID_DEFAULT(DigitList);  UMemory but not UObject*/
    TESTCLASSID_ABSTRACT(NumberFormat);
    TESTCLASSID_CTOR(DateFormatSymbols, (status));
    TESTCLASSID_CTOR(DecimalFormatSymbols, (status));
#if UOBJTEST_TEST_INTERNALS
    TESTCLASSID_CTOR(FunctionReplacer, (NULL,NULL) ); /* don't care */
#endif
    TESTCLASSID_DEFAULT(FieldPosition);
    TESTCLASSID_DEFAULT(Formattable);
    TESTCLASSID_CTOR(GregorianCalendar, (status));
#endif

#if !UCONFIG_NO_BREAK_ITERATION
    /* TESTCLASSID_ABSTRACT(BreakIterator); No staticID!  */
    TESTCLASSID_FACTORY(RuleBasedBreakIterator, BreakIterator::createLineInstance("mt",status));
    TESTCLASSID_FACTORY(DictionaryBasedBreakIterator, BreakIterator::createLineInstance("th",status));
#endif
    
    //TESTCLASSID_DEFAULT(EscapeTransliterator);
        
    //TESTCLASSID_DEFAULT(GregorianCalendar);
    
#if !UCONFIG_NO_TRANSLITERATION

    
    TESTCLASSID_DEFAULT(HexToUnicodeTransliterator);
    TESTCLASSID_DEFAULT(UnicodeToHexTransliterator);
    TESTCLASSID_TRANSLIT(AnyTransliterator, "Any-Latin");
    TESTCLASSID_TRANSLIT(CompoundTransliterator, "Latin-Greek");
    TESTCLASSID_TRANSLIT(EscapeTransliterator, "Any-Hex");
    TESTCLASSID_TRANSLIT(LowercaseTransliterator, "Lower");
    TESTCLASSID_TRANSLIT(NameUnicodeTransliterator, "Name-Any");
    TESTCLASSID_TRANSLIT(NormalizationTransliterator, "NFD");
    TESTCLASSID_TRANSLIT(NullTransliterator, "Null");
    TESTCLASSID_TRANSLIT(RemoveTransliterator, "Remove");
    TESTCLASSID_CTOR(RuleBasedTransliterator, (UnicodeString("abcd"), UnicodeString("a>b;"), status));
    TESTCLASSID_TRANSLIT(TitlecaseTransliterator, "Title");
    TESTCLASSID_TRANSLIT(UnescapeTransliterator, "Hex-Any");
    TESTCLASSID_TRANSLIT(UnicodeNameTransliterator, "Any-Name");
    TESTCLASSID_TRANSLIT(UppercaseTransliterator, "Upper");
#endif
        
    TESTCLASSID_FACTORY(Locale, new Locale("123"));
    
    //TESTCLASSID_DEFAULT(Normalizer);

    //TESTCLASSID_DEFAULT(NumeratorSubstitution);
    
#if !UCONFIG_NO_TRANSLITERATION
    TESTCLASSID_DEFAULT(ParsePosition);
    //TESTCLASSID_DEFAULT(Quantifier);
#endif
    

// NO_REG_EX
    //TESTCLASSID_DEFAULT(RegexCompile);
    //TESTCLASSID_DEFAULT(RegexMatcher);
    //TESTCLASSID_DEFAULT(RegexPattern);

    //TESTCLASSID_DEFAULT(ReplaceableGlue);
    TESTCLASSID_FACTORY(ResourceBundle, new ResourceBundle(UnicodeString(), status) );
    //TESTCLASSID_DEFAULT(RuleBasedTransliterator);
    
    //TESTCLASSID_DEFAULT(SimpleFwdCharIterator);
    //TESTCLASSID_DEFAULT(StringReplacer);
    //TESTCLASSID_DEFAULT(StringSearch);
    
    //TESTCLASSID_DEFAULT(TempSearch);
    //TESTCLASSID_DEFAULT(TestMultipleKeyStringFactory);
    //TESTCLASSID_DEFAULT(TestReplaceable);
#if !UCONFIG_NO_FORMATTING
    TESTCLASSID_ABSTRACT(TimeZone);
#endif

#if !UCONFIG_NO_TRANSLITERATION
    TESTCLASSID_FACTORY(TitlecaseTransliterator,  Transliterator::createInstance(UnicodeString("Any-Title"), UTRANS_FORWARD, parseError, status));
    TESTCLASSID_ABSTRACT(Transliterator);

#if UOBJTEST_TEST_INTERNALS
    TESTCLASSID_CTOR(StringMatcher, (UnicodeString("x"), 0,0,0,TransliterationRuleData(status)));
    TESTCLASSID_CTOR(StringReplacer,(UnicodeString(),new TransliterationRuleData(status)));
#endif
#endif
    
    TESTCLASSID_DEFAULT(UnicodeString);
    TESTCLASSID_CTOR(UnicodeSet, (0, 1));
    TESTCLASSID_ABSTRACT(UnicodeFilter);
    TESTCLASSID_ABSTRACT(UnicodeFunctor);
    TESTCLASSID_CTOR(UnicodeSetIterator,(UnicodeSet(0,1)));
    TESTCLASSID_CTOR(UStack, (status));
    TESTCLASSID_CTOR(UVector, (status));

#if !UCONFIG_NO_SERVICE
    TESTCLASSID_CTOR(SimpleFactory, (NULL, UnicodeString("foo")));
    TESTCLASSID_DEFAULT(EventListener);
#if UOBJTEST_TEST_INTERNALS
    TESTCLASSID_DEFAULT(ICUResourceBundleFactory);
    //TESTCLASSID_DEFAULT(Key); // does ont exist?
    TESTCLASSID_CTOR(LocaleKey, (UnicodeString("baz"), UnicodeString("bat"), NULL, 92));
    TESTCLASSID_CTOR(LocaleKeyFactory, (42));
    TESTCLASSID_CTOR(SimpleLocaleKeyFactory, (NULL, UnicodeString("bar"), 8, 12) );
#endif
#endif

#if UOBJTEST_DUMP_IDS
    int i;
    for(i=0;i<ids_count;i++) {
        char junk[800];
        sprintf(junk, " %4d:\t%p\t%s\t%s\n", 
            i, ids[i], ids_class[i], ids_factory[i]);
        logln(UnicodeString(junk));
    }
#endif
}

/* --------------- */

#define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break;


void UObjectTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /* par */ )
{
    switch (index) {

    CASE(0, testIDs);

    default: name = ""; break; //needed to end loop
    }
}

--- NEW FILE: uobjtest.h ---
/********************************************************************
 * COPYRIGHT: 
 * Copyright (c) 2002, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/


#ifndef _UOBJECTTEST_
#define _UOBJECTTEST_

#include "intltest.h"

/** 
 * Test uobjtest.h
 **/
class UObjectTest : public IntlTest {
    // IntlTest override
    void runIndexedTest( int32_t index, UBool exec, const char* &name, char* par );
 private:
    // tests
    void testIDs();
    
    //helper
    
    /**
     * @param obj The UObject to be tested
     * @param className The name of the class being tested 
     * @param factory String version of obj, for exanple   "new UFoo(1,3,4)". NULL if object is abstract.
     * @param staticID The result of class :: getStaticClassID
     * @return Returns obj, suitable for deletion
     */
    UObject *testClass(UObject *obj,
		       const char *className, const char *factory, 
		       UClassID staticID);
		   
		   
};
 
#endif
//eof