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

#ifndef __RUNARRAYS_H

#define __RUNARRAYS_H

#include "layout/LETypes.h"
#include "layout/LEFontInstance.h"

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

/**
 * \file 
 * \brief C++ API: base class for building classes which represent data that is associated with runs of text.
 */
 
U_NAMESPACE_BEGIN

/**
 * The initial size of an array if it is unspecified.
 *
 * @stable ICU 3.2
 */
#define INITIAL_CAPACITY 16

/**
 * When an array needs to grow, it will double in size until
 * it becomes this large, then it will grow by this amount.
 *
 * @stable ICU 3.2
 */
#define CAPACITY_GROW_LIMIT 128

/**
 * The <code>RunArray</code> class is a base class for building classes
 * which represent data that is associated with runs of text. This class
 * maintains an array of limit indices into the text, subclasses
 * provide one or more arrays of data.
 *
 * @stable ICU 3.2
 */
class U_LAYOUTEX_API RunArray : public UObject
{
public:
    /**
     * Construct a <code>RunArray</code> object from a pre-existing
     * array of limit indices.
     *
     * @param limits is an array of limit indices. This array must remain
     *               valid until the <code>RunArray</code> object is destroyed.
     *
     * @param count is the number of entries in the limit array.
     *
     * @stable ICU 3.2
     */
    inline RunArray(const le_int32 *limits, le_int32 count);

    /**
     * Construct an empty <code>RunArray</code> object. Clients can add limit
     * indices array using the <code>add</code> method.
     *
     * @param initialCapacity is the initial size of the limit indices array. If
     *        this value is zero, no array will be allocated.
     *
     * @see add
     *
     * @stable ICU 3.2
     */
    RunArray(le_int32 initialCapacity);

    /**
     * The destructor; virtual so that subclass destructors are invoked as well.
     *
     * @stable ICU 3.2
     */
    virtual ~RunArray();

    /**
     * Get the number of entries in the limit indices array.
     *
     * @return the number of entries in the limit indices array.
     *
     * @stable ICU 3.2
     */
    inline le_int32 getCount() const;

    /**
     * Reset the limit indices array. This method sets the number of entries in the
     * limit indices array to zero. It does not delete the array.
     *
     * Note: Subclass arrays will also be reset and not deleted.
     *
     * @stable ICU 3.6
     */
    inline void reset();

    /**
     * Get the last limit index. This is the number of characters in
     * the text.
     *
     * @return the last limit index.
     *
     * @stable ICU 3.2
     */
    inline le_int32 getLimit() const;

    /**
     * Get the limit index for a particular run of text.
     *
     * @param run is the run. This is an index into the limit index array.
     *
     * @return the limit index for the run, or -1 if <code>run</code> is out of bounds.
     *
     * @stable ICU 3.2
     */
    inline le_int32 getLimit(le_int32 run) const;

    /**
     * Add a limit index to the limit indices array and return the run index
     * where it was stored. If the array does not exist, it will be created by
     * calling the <code>init</code> method. If it is full, it will be grown by
     * calling the <code>grow</code> method.
     *
     * If the <code>RunArray</code> object was created with a client-supplied
     * limit indices array, this method will return a run index of -1.
     *
     * Subclasses should not override this method. Rather they should provide
     * a new <code>add</code> method which takes a limit index along with whatever
     * other data they implement. The new <code>add</code> method should
     * first call this method to grow the data arrays, and use the return value
     * to store the data in their own arrays.
     *
     * @param limit is the limit index to add to the array.
     *
     * @return the run index where the limit index was stored, or -1 if the limit index cannt be stored.
     *
     * @see init
     * @see grow
     *
     * @stable ICU 3.2
     */
    le_int32 add(le_int32 limit);

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

    /**
     * ICU "poor man's RTTI", returns a UClassID for the actual class.
     *
     * @stable ICU 3.2
     */
    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }

protected:
    /**
     * Create a data array with the given initial size. This method will be
     * called by the <code>add</code> method if there is no limit indices
     * array. Subclasses which override this method must also call it from
     * the overriding method to create the limit indices array.
     *
     * @param capacity is the initial size of the data array.
     *
     * @see add
     *
     * @stable ICU 3.2
     */
    virtual void init(le_int32 capacity);

    /**
     * Grow a data array to the given initial size. This method will be
     * called by the <code>add</code> method if the limit indices
     * array is full. Subclasses which override this method must also call it from
     * the overriding method to grow the limit indices array.
     *
     * @param capacity is the initial size of the data array.
     *
     * @see add
     *
     * @stable ICU 3.2
     */
    virtual void grow(le_int32 capacity);

    /**
     * Set by the constructors to indicate whether
     * or not the client supplied the data arrays.
     * If they were supplied by the client, the 
     * <code>add</code> method won't change the arrays
     * and the destructor won't delete them.
     *
     * @stable ICU 3.2
     */
    le_bool fClientArrays;

private:
    /**
     * The address of this static class variable serves as this class's ID
     * for ICU "poor man's RTTI".
     */
    static const char fgClassID;

    le_int32 ensureCapacity();

    inline RunArray();
    inline RunArray(const RunArray & /*other*/);
    inline RunArray &operator=(const RunArray & /*other*/) { return *this; };

    const le_int32 *fLimits;
          le_int32  fCount;
          le_int32  fCapacity;
};

inline RunArray::RunArray()
    : UObject(), fClientArrays(FALSE), fLimits(NULL), fCount(0), fCapacity(0)
{
    // nothing else to do...
}

inline RunArray::RunArray(const RunArray & /*other*/)
    : UObject(), fClientArrays(FALSE), fLimits(NULL), fCount(0), fCapacity(0)
{
    // nothing else to do...
}

inline RunArray::RunArray(const le_int32 *limits, le_int32 count)
    : UObject(), fClientArrays(TRUE), fLimits(limits), fCount(count), fCapacity(count)
{
    // nothing else to do...
}

inline le_int32 RunArray::getCount() const
{
    return fCount;
}

inline void RunArray::reset()
{
    fCount = 0;
}

inline le_int32 RunArray::getLimit(le_int32 run) const
{
    if (run < 0 || run >= fCount) {
        return -1;
    }

    return fLimits[run];
}

inline le_int32 RunArray::getLimit() const
{
    return getLimit(fCount - 1);
}

/**
 * The <code>FontRuns</code> class associates pointers to <code>LEFontInstance</code>
 * objects with runs of text.
 *
 * @stable ICU 3.2
 */
class U_LAYOUTEX_API FontRuns : public RunArray
{
public:
    /**
     * Construct a <code>FontRuns</code> object from pre-existing arrays of fonts
     * and limit indices.
     *
     * @param fonts is the address of an array of pointers to <code>LEFontInstance</code> objects. This
     *              array, and the <code>LEFontInstance</code> objects to which it points must remain
     *              valid until the <code>FontRuns</code> object is destroyed.
     *
     * @param limits is the address of an array of limit indices. This array must remain valid until
     *               the <code>FontRuns</code> object is destroyed.
     *
     * @param count is the number of entries in the two arrays.
     *
     * @stable ICU 3.2
     */
    inline FontRuns(const LEFontInstance **fonts, const le_int32 *limits, le_int32 count);

    /**
     * Construct an empty <code>FontRuns</code> object. Clients can add font and limit
     * indices arrays using the <code>add</code> method.
     *
     * @param initialCapacity is the initial size of the font and limit indices arrays. If
     *        this value is zero, no arrays will be allocated.
     *
     * @see add
     *
     * @stable ICU 3.2
     */
    FontRuns(le_int32 initialCapacity);

    /**
     * The destructor; virtual so that subclass destructors are invoked as well.
     *
     * @stable ICU 3.2
     */
    virtual ~FontRuns();

    /**
     * Get the <code>LEFontInstance</code> object assoicated with the given run
     * of text. Use <code>RunArray::getLimit(run)</code> to get the corresponding
     * limit index.
     *
     * @param run is the index into the font and limit indices arrays.
     *
     * @return the <code>LEFontInstance</code> associated with the given text run.
     *
     * @see RunArray::getLimit
     *
     * @stable ICU 3.2
     */
    const LEFontInstance *getFont(le_int32 run) const;


    /**
     * Add an <code>LEFontInstance</code> and limit index pair to the data arrays and return
     * the run index where the data was stored. This  method calls
     * <code>RunArray::add(limit)</code> which will create or grow the arrays as needed.
     *
     * If the <code>FontRuns</code> object was created with a client-supplied
     * font and limit indices arrays, this method will return a run index of -1.
     *
     * Subclasses should not override this method. Rather they should provide a new <code>add</code>
     * method which takes a font and a limit index along with whatever other data they implement.
     * The new <code>add</code> method should first call this method to grow the font and limit indices
     * arrays, and use the returned run index to store data their own arrays.
     *
     * @param font is the address of the <code>LEFontInstance</code> to add. This object must
     *             remain valid until the <code>FontRuns</code> object is destroyed.
     *
     * @param limit is the limit index to add
     *
     * @return the run index where the font and limit index were stored, or -1 if the data cannot be stored.
     *
     * @stable ICU 3.2
     */
    le_int32 add(const LEFontInstance *font, le_int32 limit);

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

    /**
     * ICU "poor man's RTTI", returns a UClassID for the actual class.
     *
     * @stable ICU 3.2
     */
    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }

protected:
    virtual void init(le_int32 capacity);
    virtual void grow(le_int32 capacity);

private:

    inline FontRuns();
    inline FontRuns(const FontRuns &other);
    inline FontRuns &operator=(const FontRuns & /*other*/) { return *this; };

    /**
     * The address of this static class variable serves as this class's ID
     * for ICU "poor man's RTTI".
     */
    static const char fgClassID;

    const LEFontInstance **fFonts;
};

inline FontRuns::FontRuns()
    : RunArray(0), fFonts(NULL)
{
    // nothing else to do...
}

inline FontRuns::FontRuns(const FontRuns & /*other*/)
    : RunArray(0), fFonts(NULL)
{
    // nothing else to do...
}

inline FontRuns::FontRuns(const LEFontInstance **fonts, const le_int32 *limits, le_int32 count)
    : RunArray(limits, count), fFonts(fonts)
{
    // nothing else to do...
}

/**
 * The <code>LocaleRuns</code> class associates pointers to <code>Locale</code>
 * objects with runs of text.
 *
 * @stable ICU 3.2
 */
class U_LAYOUTEX_API LocaleRuns : public RunArray
{
public:
    /**
     * Construct a <code>LocaleRuns</code> object from pre-existing arrays of locales
     * and limit indices.
     *
     * @param locales is the address of an array of pointers to <code>Locale</code> objects. This array,
     *                and the <code>Locale</code> objects to which it points, must remain valid until
     *                the <code>LocaleRuns</code> object is destroyed.
     *
     * @param limits is the address of an array of limit indices. This array must remain valid until the
     *               <code>LocaleRuns</code> object is destroyed.
     *
     * @param count is the number of entries in the two arrays.
     *
     * @stable ICU 3.2
     */
    inline LocaleRuns(const Locale **locales, const le_int32 *limits, le_int32 count);

    /**
     * Construct an empty <code>LocaleRuns</code> object. Clients can add locale and limit
     * indices arrays using the <code>add</code> method.
     *
     * @param initialCapacity is the initial size of the locale and limit indices arrays. If
     *        this value is zero, no arrays will be allocated.
     *
     * @see add
     *
     * @stable ICU 3.2
     */
    LocaleRuns(le_int32 initialCapacity);

    /**
     * The destructor; virtual so that subclass destructors are invoked as well.
     *
     * @stable ICU 3.2
     */
    virtual ~LocaleRuns();

    /**
     * Get the <code>Locale</code> object assoicated with the given run
     * of text. Use <code>RunArray::getLimit(run)</code> to get the corresponding
     * limit index.
     *
     * @param run is the index into the font and limit indices arrays.
     *
     * @return the <code>Locale</code> associated with the given text run.
     *
     * @see RunArray::getLimit
     *
     * @stable ICU 3.2
     */
    const Locale *getLocale(le_int32 run) const;


    /**
     * Add a <code>Locale</code> and limit index pair to the data arrays and return
     * the run index where the data was stored. This  method calls
     * <code>RunArray::add(limit)</code> which will create or grow the arrays as needed.
     *
     * If the <code>LocaleRuns</code> object was created with a client-supplied
     * locale and limit indices arrays, this method will return a run index of -1.
     *
     * Subclasses should not override this method. Rather they should provide a new <code>add</code>
     * method which takes a locale and a limit index along with whatever other data they implement.
     * The new <code>add</code> method should first call this method to grow the font and limit indices
     * arrays, and use the returned run index to store data their own arrays.
     *
     * @param locale is the address of the <code>Locale</code> to add. This object must remain valid
     *               until the <code>LocaleRuns</code> object is destroyed.
     *
     * @param limit is the limit index to add
     *
     * @return the run index where the locale and limit index were stored, or -1 if the data cannot be stored.
     *
     * @stable ICU 3.2
     */
    le_int32 add(const Locale *locale, le_int32 limit);

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

    /**
     * ICU "poor man's RTTI", returns a UClassID for the actual class.
     *
     * @stable ICU 3.2
     */
    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }

protected:
    virtual void init(le_int32 capacity);
    virtual void grow(le_int32 capacity);

    /**
     * @internal
     */
    const Locale **fLocales;

private:

    inline LocaleRuns();
    inline LocaleRuns(const LocaleRuns &other);
    inline LocaleRuns &operator=(const LocaleRuns & /*other*/) { return *this; };

    /**
     * The address of this static class variable serves as this class's ID
     * for ICU "poor man's RTTI".
     */
    static const char fgClassID;
};

inline LocaleRuns::LocaleRuns()
    : RunArray(0), fLocales(NULL)
{
    // nothing else to do...
}

inline LocaleRuns::LocaleRuns(const LocaleRuns & /*other*/)
    : RunArray(0), fLocales(NULL)
{
    // nothing else to do...
}

inline LocaleRuns::LocaleRuns(const Locale **locales, const le_int32 *limits, le_int32 count)
    : RunArray(limits, count), fLocales(locales)
{
    // nothing else to do...
}

/**
 * The <code>ValueRuns</code> class associates integer values with runs of text.
 *
 * @stable ICU 3.2
 */
class U_LAYOUTEX_API ValueRuns : public RunArray
{
public:
    /**
     * Construct a <code>ValueRuns</code> object from pre-existing arrays of values
     * and limit indices.
     *
     * @param values is the address of an array of integer. This array must remain valid until
     *               the <code>ValueRuns</code> object is destroyed.
     *
     * @param limits is the address of an array of limit indices. This array must remain valid until
     *               the <code>ValueRuns</code> object is destroyed.
     *
     * @param count is the number of entries in the two arrays.
     *
     * @stable ICU 3.2
     */
    inline ValueRuns(const le_int32 *values, const le_int32 *limits, le_int32 count);

    /**
     * Construct an empty <code>ValueRuns</code> object. Clients can add value and limit
     * indices arrays using the <code>add</code> method.
     *
     * @param initialCapacity is the initial size of the value and limit indices arrays. If
     *        this value is zero, no arrays will be allocated.
     *
     * @see add
     *
     * @stable ICU 3.2
     */
    ValueRuns(le_int32 initialCapacity);

    /**
     * The destructor; virtual so that subclass destructors are invoked as well.
     *
     * @stable ICU 3.2
     */
    virtual ~ValueRuns();

    /**
     * Get the integer value assoicated with the given run
     * of text. Use <code>RunArray::getLimit(run)</code> to get the corresponding
     * limit index.
     *
     * @param run is the index into the font and limit indices arrays.
     *
     * @return the integer value associated with the given text run.
     *
     * @see RunArray::getLimit
     *
     * @stable ICU 3.2
     */
    le_int32 getValue(le_int32 run) const;


    /**
     * Add an integer value and limit index pair to the data arrays and return
     * the run index where the data was stored. This  method calls
     * <code>RunArray::add(limit)</code> which will create or grow the arrays as needed.
     *
     * If the <code>ValueRuns</code> object was created with a client-supplied
     * font and limit indices arrays, this method will return a run index of -1.
     *
     * Subclasses should not override this method. Rather they should provide a new <code>add</code>
     * method which takes an integer value and a limit index along with whatever other data they implement.
     * The new <code>add</code> method should first call this method to grow the font and limit indices
     * arrays, and use the returned run index to store data their own arrays.
     *
     * @param value is the integer value to add
     *
     * @param limit is the limit index to add
     *
     * @return the run index where the value and limit index were stored, or -1 if the data cannot be stored.
     *
     * @stable ICU 3.2
     */
    le_int32 add(le_int32 value, le_int32 limit);

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

    /**
     * ICU "poor man's RTTI", returns a UClassID for the actual class.
     *
     * @stable ICU 3.2
     */
    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }

protected:
    virtual void init(le_int32 capacity);
    virtual void grow(le_int32 capacity);

private:

    inline ValueRuns();
    inline ValueRuns(const ValueRuns &other);
    inline ValueRuns &operator=(const ValueRuns & /*other*/) { return *this; };

    /**
     * The address of this static class variable serves as this class's ID
     * for ICU "poor man's RTTI".
     */
    static const char fgClassID;

    const le_int32 *fValues;
};

inline ValueRuns::ValueRuns()
    : RunArray(0), fValues(NULL)
{
    // nothing else to do...
}

inline ValueRuns::ValueRuns(const ValueRuns & /*other*/)
    : RunArray(0), fValues(NULL)
{
    // nothing else to do...
}

inline ValueRuns::ValueRuns(const le_int32 *values, const le_int32 *limits, le_int32 count)
    : RunArray(limits, count), fValues(values)
{
    // nothing else to do...
}

U_NAMESPACE_END
#endif
