/*
 *
 *   Copyright (C) 1998-1999, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 * @version	1.0 06/19/98
 * @author	Helena Shih
 * Based on Taligent international support for C++
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "cmemory.h"
#include "ucmp8.h"

#if U_IOSTREAM_SOURCE >= 199711
#include <iostream>
using namespace std;
#elif U_IOSTREAM_SOURCE >= 198506
#include <iostream.h>
#endif

CompactByteArray* charDirArray = 0;

static const UChar LAST_CHAR_CODE_IN_FILE = 0xFFFD;
const char charDirStrings[] = "L  R  EN ES ET AN CS B  S  WS ON LRELROAL RLERLOPDFNSMBN ";

int tagValues[] = { 
	0,  // kLeftToRight              = 0, 
	1,  // kRightToLeft              = 1,
	2,  // kEuropeanNumber           = 2,
	3,  // kEuropeanNumberSeparator  = 3,
	4,  // kEuropeanNumberTerminator = 4,
	5,  // kArabicNumber             = 5,
	6,  // kCommonNumberSeparator    = 6,
    7,  // kParagraphSeparator       = 7,
	8,  // kSegmentSeparator         = 8,
	9,  // kWhiteSpaceNeutral        = 9, 
	10, // kOtherNeutral             = 10,
	11, // kLeftToRightEmbedding     = 11,
	12, // kLeftToRightOverride      = 12,
	13, // kRightToLeftArabic        = 13,
	14, // kRightToLeftEmbedding     = 14,
	15, // kRightToLeftOverride      = 15,
	16, // kPopDirectionalFormat     = 16,
	17, // kNonSpacingMark           = 17,
	18  // kBoundaryNeutral          = 18,
	
};

int MakeProp(char* str) 
{
	int result = 0;
	char* matchPosition;
	matchPosition = strstr(charDirStrings, str);
	if (matchPosition == 0) fprintf(stderr, "unrecognized type letter %s\n", str);
	else result = ((matchPosition - charDirStrings) / 3);
	return result;
}

CompactByteArray*
getArray(FILE *input)
{
	if (charDirArray == 0) {
		char	buffer[1000];
		char*	bufferPtr;
        int  set = FALSE;

		try {
			charDirArray = ucmp8_open(0);
			int32_t unicode;
            char *next;
            char dir[4];
			while (TRUE) {
                // Clear buffer first.
				bufferPtr = fgets(buffer, 999, input);
				if (bufferPtr == NULL) break;
				if (bufferPtr[0] == '#' || bufferPtr[0] == '\n' || bufferPtr[0] == 0) continue;
				sscanf(bufferPtr, "%X", &unicode);
				assert(0 <= unicode && unicode < 65536);
                for (int i = 0; i < 4; i++) {
				    bufferPtr = strchr(bufferPtr, ';');
				    assert(bufferPtr != NULL);
				    bufferPtr++;
                }
				assert(bufferPtr != NULL);
    		    next = strchr(bufferPtr, ';');
                *next = 0;
               /* for (int j = 0; j < 3; j++) {
				   if (bufferPtr+j!= next)
                        dir[j] = bufferPtr[j];
                   else
                        dir[j] = ' ';
                }*/
				for(int j=0; bufferPtr+j != next; j++)
					dir[j] = bufferPtr[j];
				while(j<3)
				{
					dir[j] = ' ';
					j++;
				}
				dir[3] = 0;
				ucmp8_set(charDirArray, (UChar)unicode, (int8_t)tagValues[MakeProp(dir)]);
                }

			if (input) fclose(input);
			ucmp8_compact(charDirArray, 1);
		}
		catch (...) {
			fprintf(stderr, "Error Occured while parsing unicode data file.\n");
		}
	}
	return charDirArray;
}

void 
writeArrays()
{
	const int8_t* values = ucmp8_getArray(charDirArray);
	const uint16_t* indexes = ucmp8_getIndex(charDirArray);
	int32_t i;
    int32_t cnt = ucmp8_getCount(charDirArray);
    cout << "\nconst t_uint32 Unicode::fCharDirIndices[] = {\n    ";
    for (i = 0; i < ucmp8_getkIndexCount()-1; i++)
    {
        cout << "(uint16_t)" << ((indexes[i] >= 0) ? (int)indexes[i] : (int)(indexes[i]+ucmp8_getkUnicodeCount()))
                         << ", ";
        if (i != 0)
            if (i % 3 == 0)
                cout << "\n    ";
    }
    cout << "    (uint16_t)" << ((indexes[ucmp8_getkIndexCount()-1] >= 0) ? (int)indexes[i] : (int)(indexes[i]+ucmp8_getkUnicodeCount()))
                       << " };\n";
    cout << "\nconst int8_t Unicode::fCharDirValues[] = {\n    ";
    for (i = 0; i < cnt-1; i++)
    {
        cout << "(int8_t)" << (int)values[i] << ", ";
        if (i != 0)
            if (i % 5 == 0)
                cout << "\n    ";
    }
    cout << "    (int8_t)" << (int)values[cnt-1] << " }\n";
	cout << "const int32_t Unicode::fCharDirCount = " << cnt << ";\n";
}
/**
 * The main function builds the CharType data array and prints it to System.out
 */
void main(int argc, char** argv)
{
	CompactByteArray* arrays = 0;
    FILE *input = 0;
    if (argc != 2) {
        printf("Usage : chartype filename\n\n");
        exit(1);
    }
    input = fopen(argv[1], "r");
    if (input == 0) {
        printf("Cannot open the input file: %s\n\n", argv[1]);
        exit(1);
    }
	arrays = getArray(input);
	writeArrays();
}

