/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#pragma once

#include <mars.h>

#include <cstring>

#include <ctype.h>

//! Obsolete caching string class (pre std::string)
/*! Although this class, based on libMars C functions \c strcache()
 *  and \c strfree(), is heavily used in Metview code, it is now
 *  considered obsolete and superceded by standard std::string class
 *  and the use of Cached in the new code is not recommended.
 *  This documentation is mainly for understanding the old code
 *  that still uses Cached.
 */
class Cached
{
    char* Str;

public:
    //! Constructor with a C string as argument
    Cached(const char* s = nullptr) { Str = strcache(s); }

    //! Copy constructor
    Cached(const Cached& c) { Str = strcache(c.Str); }

    //! Destructor
    ~Cached() { strfree(Str); }

    //! Operator to cast Cached into a C string
    operator const char*() const { return Str; }

    //! Assignment operator for a C string
    Cached& operator=(char* s)
    {
        strfree(Str);
        Str = strcache(s);
        return *this;
    }

    //! Assignment operator for Cached
    Cached& operator=(const Cached& c)
    {
        strfree(Str);
        Str = strcache(c.Str);
        return *this;
    }

    //! Operator to test the equality
    int operator==(const Cached& c) const { return Str == c.Str; }

    //! Method to extract a substring
    /*! Copies a substring of length \c Length, starting from
     *  position \c StartPos.
     *  The first character is in position \c 1. \n \n
     *  NOTE: \c Length is not checked against a possible overflow
     *  and for \c Length overflowing the original string the
     *  substring will contain bytes after the original string!
     */
    Cached subString(int StartPos, int Length) const;

    //! Method to convert text to upper case
    Cached toUpper();

    //! Method to convert text to lower case
    Cached toLower() const;

    //! Concatenation operator for \c int
    /*! The numeric value is first converted to a number string
     *  and the number string is concatenated to the original string.
     */
    Cached operator+(int) const;

    //! Concatenation operator for \c long
    /*! The numeric value is first converted to a number string
     *  and the number string is concatenated to the original string.
     */
    Cached operator+(long) const;

    //! Concatenation operator for \c double
    /*! The numeric value is first converted to a number string
     *  and the number string is concatenated to the original string.
     */
    Cached operator+(double) const;

    //! Comparision operator
    int operator<(const Cached& other) const
    {
        return strcmp(Str, other.Str) < 0;
    }

    //! Comparision operator
    bool less(const Cached& other) const
    {
        return (strcmp(Str, other.Str) < 0) ? true : false;
    }
};

//! Function to concatenate a \c long and \c Cached
Cached operator+(long, const Cached&);

//! Function to concatenate a \c double and \c Cached
Cached operator+(double, const Cached&);

//! Function to concatenate a C string (<PRE>const char*</PRE>) and \c Cached
Cached operator+(const char*, const Cached&);
