/*
 **********************************************************************
 *   Copyright (C) 2003-2005, 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.
     *
     * @draft 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);

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;

    const Locale **fLocales;
};

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
