// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
* Copyright (C) 1996-2014, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*/

/*
* File coleitr.cpp
*
* Created by: Helena Shih
*
* Modification History:
*
*  Date      Name        Description
*
*  6/23/97   helena      Adding comments to make code more readable.
* 08/03/98   erm         Synched with 1.2 version of CollationElementIterator.java
* 12/10/99   aliu        Ported Thai collation support from Java.
* 01/25/01   swquek      Modified to a C++ wrapper calling C APIs (ucoliter.h)
* 02/19/01   swquek      Removed CollationElementIterator() since it is 
*                        private constructor and no calls are made to it
* 2012-2014  markus      Rewritten in C++ again.
*/

#include "unicode/utypes.h"

#if !UCONFIG_NO_COLLATION

#include "unicode/chariter.h"
#include "unicode/coleitr.h"
#include "unicode/tblcoll.h"
#include "unicode/ustring.h"
#include "cmemory.h"
#include "collation.h"
#include "collationdata.h"
#include "collationiterator.h"
#include "collationsets.h"
#include "collationtailoring.h"
#include "uassert.h"
#include "uhash.h"
#include "utf16collationiterator.h"
#include "uvectr32.h"

/* Constants --------------------------------------------------------------- */

U_NAMESPACE_BEGIN

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationElementIterator)

/* CollationElementIterator public constructor/destructor ------------------ */

CollationElementIterator::CollationElementIterator(
                                         const CollationElementIterator& other) 
        : UObject(other), iter_(NULL), rbc_(NULL), otherHalf_(0), dir_(0), offsets_(NULL) {
    *this = other;
}

CollationElementIterator::~CollationElementIterator()
{
    delete iter_;
    delete offsets_;
}

/* CollationElementIterator public methods --------------------------------- */

namespace {

uint32_t getFirstHalf(uint32_t p, uint32_t lower32) {
    return (p & 0xffff0000) | ((lower32 >> 16) & 0xff00) | ((lower32 >> 8) & 0xff);
}
uint32_t getSecondHalf(uint32_t p, uint32_t lower32) {
    return (p << 16) | ((lower32 >> 8) & 0xff00) | (lower32 & 0x3f);
}
UBool ceNeedsTwoParts(int64_t ce) {
    return (ce & INT64_C(0xffff00ff003f)) != 0;
}

}  // namespace

int32_t CollationElementIterator::getOffset() const
{
    if (dir_ < 0 && offsets_ != NULL && !offsets_->isEmpty()) {
        // CollationIterator::previousCE() decrements the CEs length
        // while it pops CEs from its internal buffer.
        int32_t i = iter_->getCEsLength();
        if (otherHalf_ != 0) {
            // Return the trailing CE offset while we are in the middle of a 64-bit CE.
            ++i;
        }
        U_ASSERT(i < offsets_->size());
        return offsets_->elementAti(i);
    }
    return iter_->getOffset();
}

/**
* Get the ordering priority of the next character in the string.
* @return the next character's ordering. Returns NULLORDER if an error has 
*         occured or if the end of string has been reached
*/
int32_t CollationElementIterator::next(UErrorCode& status)
{
    if (U_FAILURE(status)) { return NULLORDER; }
    if (dir_ > 1) {
        // Continue forward iteration. Test this first.
        if (otherHalf_ != 0) {
            uint32_t oh = otherHalf_;
            otherHalf_ = 0;
            return oh;
        }
    } else if (dir_ == 1) {
        // next() after setOffset()
        dir_ = 2;
    } else if (dir_ == 0) {
        // The iter_ is already reset to the start of the text.
        dir_ = 2;
    } else /* dir_ < 0 */ {
        // illegal change of direction
        status = U_INVALID_STATE_ERROR;
        return NULLORDER;
    }
    // No need to keep all CEs in the buffer when we iterate.
    iter_->clearCEsIfNoneRemaining();
    int64_t ce = iter_->nextCE(status);
    if (ce == Collation::NO_CE) { return NULLORDER; }
    // Turn the 64-bit CE into two old-style 32-bit CEs, without quaternary bits.
    uint32_t p = (uint32_t)(ce >> 32);
    uint32_t lower32 = (uint32_t)ce;
    uint32_t firstHalf = getFirstHalf(p, lower32);
    uint32_t secondHalf = getSecondHalf(p, lower32);
    if (secondHalf != 0) {
        otherHalf_ = secondHalf | 0xc0;  // continuation CE
    }
    return firstHalf;
}

UBool CollationElementIterator::operator!=(
                                  const CollationElementIterator& other) const
{
    return !(*this == other);
}

UBool CollationElementIterator::operator==(
                                    const CollationElementIterator& that) const
{
    if (this == &that) {
        return TRUE;
    }

    return
        (rbc_ == that.rbc_ || *rbc_ == *that.rbc_) &&
        otherHalf_ == that.otherHalf_ &&
        normalizeDir() == that.normalizeDir() &&
        string_ == that.string_ &&
        *iter_ == *that.iter_;
}

/**
* Get the ordering priority of the previous collation element in the string.
* @param status the error code status.
* @return the previous element's ordering. Returns NULLORDER if an error has 
*         occured or if the start of string has been reached.
*/
int32_t CollationElementIterator::previous(UErrorCode& status)
{
    if (U_FAILURE(status)) { return NULLORDER; }
    if (dir_ < 0) {
        // Continue backwards iteration. Test this first.
        if (otherHalf_ != 0) {
            uint32_t oh = otherHalf_;
            otherHalf_ = 0;
            return oh;
        }
    } else if (dir_ == 0) {
        iter_->resetToOffset(string_.length());
        dir_ = -1;
    } else if (dir_ == 1) {
        // previous() after setOffset()
        dir_ = -1;
    } else /* dir_ > 1 */ {
        // illegal change of direction
        status = U_INVALID_STATE_ERROR;
        return NULLORDER;
    }
    if (offsets_ == NULL) {
        offsets_ = new UVector32(status);
        if (offsets_ == NULL) {
            status = U_MEMORY_ALLOCATION_ERROR;
            return NULLORDER;
        }
    }
    // If we already have expansion CEs, then we also have offsets.
    // Otherwise remember the trailing offset in case we need to
    // write offsets for an artificial expansion.
    int32_t limitOffset = iter_->getCEsLength() == 0 ? iter_->getOffset() : 0;
    int64_t ce = iter_->previousCE(*offsets_, status);
    if (ce == Collation::NO_CE) { return NULLORDER; }
    // Turn the 64-bit CE into two old-style 32-bit CEs, without quaternary bits.
    uint32_t p = (uint32_t)(ce >> 32);
    uint32_t lower32 = (uint32_t)ce;
    uint32_t firstHalf = getFirstHalf(p, lower32);
    uint32_t secondHalf = getSecondHalf(p, lower32);
    if (secondHalf != 0) {
        if (offsets_->isEmpty()) {
            // When we convert a single 64-bit CE into two 32-bit CEs,
            // we need to make this artificial expansion behave like a normal expansion.
            // See CollationIterator::previousCE().
            offsets_->addElement(iter_->getOffset(), status);
            offsets_->addElement(limitOffset, status);
        }
        otherHalf_ = firstHalf;
        return secondHalf | 0xc0;  // continuation CE
    }
    return firstHalf;
}

/**
* Resets the cursor to the beginning of the string.
*/
void CollationElementIterator::reset()
{
    iter_ ->resetToOffset(0);
    otherHalf_ = 0;
    dir_ = 0;
}

void CollationElementIterator::setOffset(int32_t newOffset, 
                                         UErrorCode& status)
{
    if (U_FAILURE(status)) { return; }
    if (0 < newOffset && newOffset < string_.length()) {
        int32_t offset = newOffset;
        do {
            UChar c = string_.charAt(offset);
            if (!rbc_->isUnsafe(c) ||
                    (U16_IS_LEAD(c) && !rbc_->isUnsafe(string_.char32At(offset)))) {
                break;
            }
            // Back up to before this unsafe character.
            --offset;
        } while (offset > 0);
        if (offset < newOffset) {
            // We might have backed up more than necessary.
            // For example, contractions "ch" and "cu" make both 'h' and 'u' unsafe,
            // but for text "chu" setOffset(2) should remain at 2
            // although we initially back up to offset 0.
            // Find the last safe offset no greater than newOffset by iterating forward.
            int32_t lastSafeOffset = offset;
            do {
                iter_->resetToOffset(lastSafeOffset);
                do {
                    iter_->nextCE(status);
                    if (U_FAILURE(status)) { return; }
                } while ((offset = iter_->getOffset()) == lastSafeOffset);
                if (offset <= newOffset) {
                    lastSafeOffset = offset;
                }
            } while (offset < newOffset);
            newOffset = lastSafeOffset;
        }
    }
    iter_->resetToOffset(newOffset);
    otherHalf_ = 0;
    dir_ = 1;
}

/**
* Sets the source to the new source string.
*/
void CollationElementIterator::setText(const UnicodeString& source,
                                       UErrorCode& status)
{
    if (U_FAILURE(status)) {
        return;
    }

    string_ = source;
    const UChar *s = string_.getBuffer();
    CollationIterator *newIter;
    UBool numeric = rbc_->settings->isNumeric();
    if (rbc_->settings->dontCheckFCD()) {
        newIter = new UTF16CollationIterator(rbc_->data, numeric, s, s, s + string_.length());
    } else {
        newIter = new FCDUTF16CollationIterator(rbc_->data, numeric, s, s, s + string_.length());
    }
    if (newIter == NULL) {
        status = U_MEMORY_ALLOCATION_ERROR;
        return;
    }
    delete iter_;
    iter_ = newIter;
    otherHalf_ = 0;
    dir_ = 0;
}

// Sets the source to the new character iterator.
void CollationElementIterator::setText(CharacterIterator& source, 
                                       UErrorCode& status)
{
    if (U_FAILURE(status)) 
        return;

    source.getText(string_);
    setText(string_, status);
}

int32_t CollationElementIterator::strengthOrder(int32_t order) const
{
    UColAttributeValue s = (UColAttributeValue)rbc_->settings->getStrength();
    // Mask off the unwanted differences.
    if (s == UCOL_PRIMARY) {
        order &= 0xffff0000;
    }
    else if (s == UCOL_SECONDARY) {
        order &= 0xffffff00;
    }

    return order;
}

/* CollationElementIterator private constructors/destructors --------------- */

/** 
* This is the "real" constructor for this class; it constructs an iterator
* over the source text using the specified collator
*/
CollationElementIterator::CollationElementIterator(
                                               const UnicodeString &source,
                                               const RuleBasedCollator *coll,
                                               UErrorCode &status)
        : iter_(NULL), rbc_(coll), otherHalf_(0), dir_(0), offsets_(NULL) {
    setText(source, status);
}

/** 
* This is the "real" constructor for this class; it constructs an iterator over 
* the source text using the specified collator
*/
CollationElementIterator::CollationElementIterator(
                                           const CharacterIterator &source,
                                           const RuleBasedCollator *coll,
                                           UErrorCode &status)
        : iter_(NULL), rbc_(coll), otherHalf_(0), dir_(0), offsets_(NULL) {
    // We only call source.getText() which should be const anyway.
    setText(const_cast<CharacterIterator &>(source), status);
}

/* CollationElementIterator private methods -------------------------------- */

const CollationElementIterator& CollationElementIterator::operator=(
                                         const CollationElementIterator& other)
{
    if (this == &other) {
        return *this;
    }

    CollationIterator *newIter;
    const FCDUTF16CollationIterator *otherFCDIter =
            dynamic_cast<const FCDUTF16CollationIterator *>(other.iter_);
    if(otherFCDIter != NULL) {
        newIter = new FCDUTF16CollationIterator(*otherFCDIter, string_.getBuffer());
    } else {
        const UTF16CollationIterator *otherIter =
                dynamic_cast<const UTF16CollationIterator *>(other.iter_);
        if(otherIter != NULL) {
            newIter = new UTF16CollationIterator(*otherIter, string_.getBuffer());
        } else {
            newIter = NULL;
        }
    }
    if(newIter != NULL) {
        delete iter_;
        iter_ = newIter;
        rbc_ = other.rbc_;
        otherHalf_ = other.otherHalf_;
        dir_ = other.dir_;

        string_ = other.string_;
    }
    if(other.dir_ < 0 && other.offsets_ != NULL && !other.offsets_->isEmpty()) {
        UErrorCode errorCode = U_ZERO_ERROR;
        if(offsets_ == NULL) {
            offsets_ = new UVector32(other.offsets_->size(), errorCode);
        }
        if(offsets_ != NULL) {
            offsets_->assign(*other.offsets_, errorCode);
        }
    }
    return *this;
}

namespace {

class MaxExpSink : public ContractionsAndExpansions::CESink {
public:
    MaxExpSink(UHashtable *h, UErrorCode &ec) : maxExpansions(h), errorCode(ec) {}
    virtual ~MaxExpSink();
    virtual void handleCE(int64_t /*ce*/) {}
    virtual void handleExpansion(const int64_t ces[], int32_t length) {
        if (length <= 1) {
            // We do not need to add single CEs into the map.
            return;
        }
        int32_t count = 0;  // number of CE "halves"
        for (int32_t i = 0; i < length; ++i) {
            count += ceNeedsTwoParts(ces[i]) ? 2 : 1;
        }
        // last "half" of the last CE
        int64_t ce = ces[length - 1];
        uint32_t p = (uint32_t)(ce >> 32);
        uint32_t lower32 = (uint32_t)ce;
        uint32_t lastHalf = getSecondHalf(p, lower32);
        if (lastHalf == 0) {
            lastHalf = getFirstHalf(p, lower32);
            U_ASSERT(lastHalf != 0);
        } else {
            lastHalf |= 0xc0;  // old-style continuation CE
        }
        if (count > uhash_igeti(maxExpansions, (int32_t)lastHalf)) {
            uhash_iputi(maxExpansions, (int32_t)lastHalf, count, &errorCode);
        }
    }

private:
    UHashtable *maxExpansions;
    UErrorCode &errorCode;
};

MaxExpSink::~MaxExpSink() {}

}  // namespace

UHashtable *
CollationElementIterator::computeMaxExpansions(const CollationData *data, UErrorCode &errorCode) {
    if (U_FAILURE(errorCode)) { return NULL; }
    UHashtable *maxExpansions = uhash_open(uhash_hashLong, uhash_compareLong,
                                           uhash_compareLong, &errorCode);
    if (U_FAILURE(errorCode)) { return NULL; }
    MaxExpSink sink(maxExpansions, errorCode);
    ContractionsAndExpansions(NULL, NULL, &sink, TRUE).forData(data, errorCode);
    if (U_FAILURE(errorCode)) {
        uhash_close(maxExpansions);
        return NULL;
    }
    return maxExpansions;
}

int32_t
CollationElementIterator::getMaxExpansion(int32_t order) const {
    return getMaxExpansion(rbc_->tailoring->maxExpansions, order);
}

int32_t
CollationElementIterator::getMaxExpansion(const UHashtable *maxExpansions, int32_t order) {
    if (order == 0) { return 1; }
    int32_t max;
    if(maxExpansions != NULL && (max = uhash_igeti(maxExpansions, order)) != 0) {
        return max;
    }
    if ((order & 0xc0) == 0xc0) {
        // old-style continuation CE
        return 2;
    } else {
        return 1;
    }
}

U_NAMESPACE_END

#endif /* #if !UCONFIG_NO_COLLATION */
