// ZenLib::MemoryDebug - To debug memory allocation errors
// Copyright (C) 2002-2005 Jerome Martinez, Zen@MediaArea.net
//
// This software is provided 'as-is', without any express or implied
// warranty.  In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would be
//    appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
//    misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// More methods for std::(w)string
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 2005-007-18, Zen@MediaArea.net
// From_Number, Option : Ztring_NoZero
//
// 2005-03-15, Zen@MediaArea.net
// "Size" in From_XXX
// Count()
// Compare()
//
// 2005-03-08, Zen@MediaArea.net
// Delete automatic integers translation
// UTF8 and local encoded handling in Ansi version
//
// 2005-03-02, Zen@MediaArea.net
// UTF8 and local encoded handling in Unicode version
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//---------------------------------------------------------------------------
#ifndef ZenLib_ZtringH
#define ZenLib_ZtringH
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include <string>
#include <ZenLib/Conf.h>
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#ifdef __BORLANDC__
    #pragma warn -8027
#endif
//---------------------------------------------------------------------------


namespace ZenLib
{

//---------------------------------------------------------------------------
typedef std::basic_string<Char, std::char_traits<Char>, std::allocator<Char> > tstring;
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
/// @brief Options for Ztring methods
enum ztring_t
{
    Ztring_Nothing,
    Ztring_Rounded              = 1,            ///< if >.5, upper, else lower
    Ztring_CaseSensitive        = 2,            ///< Case sensitive ("A" and "a" are different)
    Ztring_AddLastItem          = 4,            ///< if Begin is found and End is not found, return between Begin and end of string
    Ztring_Recursive            = 8,            ///< Do all strings
    Ztring_NoZero               =16             ///> Doesn't keep Zero in the float number
};

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

//***************************************************************************
/// @brief String manipulation (based on std::(w)string)
//***************************************************************************

class Ztring : public tstring  //for details about undocumented methods see http://www.sgi.com/tech/stl/basic_string.html
{
public :
    //Constructor/destructor
    Ztring ()                                                                   : tstring(){};
    Ztring (const tstring& s, size_type pos=0, size_type n=npos)                : tstring(s.c_str(), pos, npos){};
    Ztring (const tstring* s, size_type pos=0, size_type n=npos)                : tstring(s->c_str(), pos, npos){};
    Ztring (const Char *s)                                                      : tstring(s){};
    Ztring (const Char *s, size_type n)                                         : tstring(s, n){};
    Ztring (size_type n, const Char s)                                          : tstring(n, s){};

    //Operators
    Char &operator () (size_t Pos); ///< Same as [], but resize the string if Pos doesn't exist yet

    //Conversions
        /// @brief convert an Unicode encoded string into Ztring
    Ztring& From_Unicode(const std::wstring &S)                                 {return From_Unicode(S.c_str());};
        /// @brief convert an Unicode encoded string into Ztring
    Ztring& From_Unicode(const wchar_t *s);
        /// @brief convert an Unicode encoded string into Ztring
    Ztring& From_Unicode(const wchar_t *s, size_t Length);
        /// @brief convert an UTF-8 encoded string into Ztring
    Ztring& From_UTF8   (const std::string &S)                                  {return From_UTF8(S.c_str());};
        /// @brief convert an UTF-8 encoded string into Ztring
    Ztring& From_UTF8   (const char *s);
        /// @brief convert an UTF-8 encoded string into Ztring
    Ztring& From_UTF8   (const char *s, size_t Length);
        /// @brief convert an Local encoded string into Ztring
    Ztring& From_Local  (const std::string &S)                                  {return From_Local(S.c_str());};
        /// @brief convert an Local encoded string into Ztring
    Ztring& From_Local  (const char *s);
        /// @brief convert an Local encoded string into Ztring
    Ztring& From_Local  (const char *s, size_t Length);
    Ztring& From_Number (const int8s,    intu Radix=10);
    Ztring& From_Number (const int8u,    intu Radix=10);
    Ztring& From_Number (const int16s,   intu Radix=10);
    Ztring& From_Number (const int16u,   intu Radix=10);
    Ztring& From_Number (const int32s,   intu Radix=10);
    Ztring& From_Number (const int32u,   intu Radix=10);
    #if (MAXTYPE_INT>=64)
	Ztring& From_Number (const int64s,   intu Radix=10);
	Ztring& From_Number (const int64u,   intu Radix=10);
    #endif
    Ztring& From_Number (const float32,  intu AfterComma=3, ztring_t Options=Ztring_Nothing);
    Ztring& From_Number (const float64,  intu AfterComma=3, ztring_t Options=Ztring_Nothing);
    Ztring& From_Number (const float128, intu AfterComma=3, ztring_t Options=Ztring_Nothing);
    std::wstring To_Unicode ();
        /// @brief Convert into char* (UTF-8 encoded)
        /// @return the string corresponding \n
    std::string To_UTF8 ();
        /// @brief Convert into char* (Local encoded)
        /// @return the string corresponding \n
    std::string To_Local ();
        /// @brief Convert into Int (32 bits)
        /// @return the value corresponding \n
        ///         0 if there is a problem
    int32s To_int32s(ztring_t Options=Ztring_Rounded) const;
        /// @brief Convert into unsigned Int (32 bits)
        /// @return the value corresponding
        ///         0 if there is a problem
    int32u To_int32u(ztring_t Options=Ztring_Rounded) const;
    #if (MAXTYPE_INT>=64)
        /// @brief Convert into Int (64 bits)
        /// @return the value corresponding \n
        ///         0 if there is a problem
    int64s To_int64s(ztring_t Options=Ztring_Rounded) const;
        /// @brief Convert into unsigned Int (64 bits)
        /// @return the value corresponding \n
        ///         0 if there is a problem
    int64u To_int64u(ztring_t Options=Ztring_Rounded) const;
    #endif
        /// @brief Convert into float
        /// @return the value corresponding \n
        ///         0 if there is a problem
    float32  To_float32 (ztring_t Options=Ztring_Nothing) const;
    float64  To_float64 (ztring_t Options=Ztring_Nothing) const;
    float128 To_float128(ztring_t Options=Ztring_Nothing) const;

    static Ztring ToZtring (const int8s   I,  intu Radix=10)                    {return Ztring().From_Number(I, Radix);};
    static Ztring ToZtring (const int8u   I,  intu Radix=10)                    {return Ztring().From_Number(I, Radix);};
    static Ztring ToZtring (const int16s  I,  intu Radix=10)                    {return Ztring().From_Number(I, Radix);};
    static Ztring ToZtring (const int16u  I,  intu Radix=10)                    {return Ztring().From_Number(I, Radix);};
    static Ztring ToZtring (const int32s  I,  intu Radix=10)                    {return Ztring().From_Number(I, Radix);};
    static Ztring ToZtring (const int32u  I,  intu Radix=10)                    {return Ztring().From_Number(I, Radix);};
    #if (MAXTYPE_INT>=64)
    static Ztring ToZtring (const int64s  I,  intu Radix=10)                    {return Ztring().From_Number(I, Radix);};
    static Ztring ToZtring (const int64u  I,  intu Radix=10)                    {return Ztring().From_Number(I, Radix);};
    #endif
    static Ztring ToZtring (const float32  F, intu AfterComma=3)                {return Ztring().From_Number(F, AfterComma);};
    static Ztring ToZtring (const float64  F, intu AfterComma=3)                {return Ztring().From_Number(F, AfterComma);};
    static Ztring ToZtring (const float128 F, intu AfterComma=3)                {return Ztring().From_Number(F, AfterComma);};

    //Edition
        /// @brief convert into lowercase
    Ztring* MakeLowerCase();
        /// @brief convert into uppercase
    Ztring* MakeUpperCase();
        /// @brief Remove leading whitespaces from a string
    Ztring* TrimLeft(Char ToTrim=_T(' '));
        /// @brief Remove trailing whitespaces from a string
    Ztring* TrimRight(Char ToTrim=_T(' '));
        /// @brief Remove leading and trailing whitespaces from a string
    Ztring* Trim(Char ToTrim=_T(' '));
        /// @brief Quotes a string
    Ztring* Quote(Char ToTrim=_T('\"'));
        /// @brief return a string between two strings
        /// @param Begin First string
        /// @param End Second string
        /// @param Pos Position to begin to scan string
        /// @param Options Options for searching \n
        ///                Available : Ztring_CaseSensitive
        /// @return The substring \n
        ///         "" if not found
    Ztring SubString (const tstring &Begin, const tstring &End, size_type Pos=0, ztring_t Options=Ztring_Nothing) const;
        /// @brief replace a string by another one
        /// @param ToFind string to find
        /// @param ToReplace string wich replace the string found
        /// @param Pos Position to begin to scan string
        /// @param Options Options for searching \n
        ///                Available : Ztring_CaseSensitive, Ztring_Recursive
        /// @return The count of replacements
    size_t FindAndReplace (const tstring &ToFind, const tstring &ReplaceBy, size_type Pos=0, ztring_t Options=Ztring_Nothing); //Remplace une chaine par une autre
        /// @brief Count the number of occurencies of a string in the string
        /// @param ToCount string to count
        /// @param Options Options for count \n
        ///                Available : Ztring_CaseSensitive
        /// @return the count

    //Information
    size_t Count (const Ztring &ToCount, ztring_t Options=Ztring_Nothing) const;
        /// @brief compare with another string
        /// @param ToCompare string to compare with
        /// @param Options Options for comaparing \n
        ///                Available : Ztring_CaseSensitive
        /// @return The result of comparasion
    bool Compare (const Ztring &ToCompare, const Ztring &Comparator, ztring_t Options=Ztring_Nothing) const;
};

} //NameSpace

//---------------------------------------------------------------------------
#ifdef __BORLANDC__
    #pragma warn .8027
#endif
//---------------------------------------------------------------------------

#endif


