/* 
 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
#ifndef __PJPP_STRING_HPP__
#define __PJPP_STRING_HPP__

#include <pj/string.h>
#include <pj++/pool.hpp>
#include <pj/assert.h>

//
// String wrapper class for pj_str_t.
//
class Pj_String : public pj_str_t
{
public:
    //
    // Default constructor.
    //
    Pj_String() 
    { 
        pj_assert(sizeof(Pj_String) == sizeof(pj_str_t));
        ptr=NULL; 
        slen=0; 
    }

    //
    // Construct the buffer from a char* (use with care)
    //
    Pj_String(char *str) 
    { 
        set(str);
    }

    //
    // Construct from a const char*.
    //
    Pj_String(Pj_Pool &pool, const char *src)
    {
        set(pool, src);
    }

    //
    // Construct from pj_str_t&.
    //
    explicit Pj_String(pj_str_t &s)
    {
        ptr = s.ptr;
        slen = s.slen;
    }

    //
    // Construct from const pj_str_t& (use with care!).
    //
    explicit Pj_String(const pj_str_t &s)
    {
        ptr = (char*)s.ptr;
        slen = s.slen;
    }

    //
    // Construct by copying from const pj_str_t*.
    //
    Pj_String(Pj_Pool &pool, const pj_str_t *s)
    {
        set(pool, s);
    }

    //
    // Construct by copying from Pj_String
    //
    Pj_String(Pj_Pool &pool, const Pj_String &rhs)
    {
        set(pool, rhs);
    }

    //
    // Construct from another Pj_String, use with care!
    //
    explicit Pj_String(const Pj_String &rhs)
    {
        ptr = rhs.ptr;
        slen = rhs.slen;
    }

    //
    // Construct from a char* and a length.
    //
    Pj_String(char *str, pj_size_t len)
    {
        set(str, len);
    }

    //
    // Construct from pair of pointer.
    //
    Pj_String(char *begin, char *end)
    {
        pj_strset3(this, begin, end);
    }

    //
    // You can cast Pj_String to pj_str_t*
    //
    operator pj_str_t*()
    {
        return this;
    }

    //
    // You can cast const Pj_String to const pj_str_t*
    //
    operator const pj_str_t*() const
    {
        return this;
    }

    //
    // Get the length of the string.
    //
    pj_size_t length() const
    {
        return pj_strlen(this);
    }

    //
    // Get the length of the string.
    //
    pj_size_t size() const
    {
        return length();
    }

    //
    // Get the string buffer.
    //
    const char *buf() const
    {
        return ptr;
    }

    //
    // Initialize buffer from char*.
    //
    void set(char *str)
    {
        pj_strset2(this, str);
    }

    //
    // Initialize by copying from a const char*.
    //
    void set(Pj_Pool &pool, const char *s)
    {
        pj_strdup2(pool, this, s);
    }

    //
    // Initialize from pj_str_t*.
    //
    void set(pj_str_t *s)
    {
        pj_strassign(this, s);
    }

    //
    // Initialize by copying from const pj_str_t*.
    //
    void set(Pj_Pool &pool, const pj_str_t *s)
    {
        pj_strdup(pool, this, s);
    }

    //
    // Initialize from char* and length.
    //
    void set(char *str, pj_size_t len)
    {
        pj_strset(this, str, len);
    }

    //
    // Initialize from pair of pointers.
    //
    void set(char *begin, char *end)
    {
        pj_strset3(this, begin, end);
    }

    //
    // Initialize from other Pj_String.
    //
    void set(Pj_String &rhs)
    {
        pj_strassign(this, &rhs);
    }

    //
    // Initialize by copying from a Pj_String*.
    //
    void set(Pj_Pool &pool, const Pj_String *s)
    {
        pj_strdup(pool, this, s);
    }

    //
    // Initialize by copying from other Pj_String.
    //
    void set(Pj_Pool &pool, const Pj_String &s)
    {
        pj_strdup(pool, this, &s);
    }

    //
    // Copy the contents of other string.
    //
    void strcpy(const pj_str_t *s)
    {
        pj_strcpy(this, s);
    }

    //
    // Copy the contents of other string.
    //
    void strcpy(const Pj_String &rhs)
    {
        pj_strcpy(this, &rhs);
    }

    //
    // Copy the contents of other string.
    //
    void strcpy(const char *s)
    {
        pj_strcpy2(this, s);
    }

    //
    // Compare string.
    //
    int strcmp(const char *s) const
    {
        return pj_strcmp2(this, s);
    }

    //
    // Compare string.
    //
    int strcmp(const pj_str_t *s) const
    {
        return pj_strcmp(this, s);
    }

    //
    // Compare string.
    //
    int strcmp(const Pj_String &rhs) const
    {
        return pj_strcmp(this, &rhs);
    }

    //
    // Compare string.
    //
    int strncmp(const char *s, pj_size_t len) const
    {
        return pj_strncmp2(this, s, len);
    }

    //
    // Compare string.
    //
    int strncmp(const pj_str_t *s, pj_size_t len) const
    {
        return pj_strncmp(this, s, len);
    }

    //
    // Compare string.
    //
    int strncmp(const Pj_String &rhs, pj_size_t len) const
    {
        return pj_strncmp(this, &rhs, len);
    }

    //
    // Compare string.
    //
    int stricmp(const char *s) const
    {
        return pj_stricmp2(this, s);
    }

    //
    // Compare string.
    //
    int stricmp(const pj_str_t *s) const
    {
        return pj_stricmp(this, s);
    }

    //
    // Compare string.
    //
    int stricmp(const Pj_String &rhs) const
    {
        return stricmp(&rhs);
    }

    //
    // Compare string.
    //
    int strnicmp(const char *s, pj_size_t len) const
    {
        return pj_strnicmp2(this, s, len);
    }

    //
    // Compare string.
    //
    int strnicmp(const pj_str_t *s, pj_size_t len) const
    {
        return pj_strnicmp(this, s, len);
    }

    //
    // Compare string.
    //
    int strnicmp(const Pj_String &rhs, pj_size_t len) const
    {
        return strnicmp(&rhs, len);
    }

    //
    // Compare contents for equality.
    //
    bool operator==(const char *s) const
    {
        return strcmp(s) == 0;
    }

    //
    // Compare contents for equality.
    //
    bool operator==(const pj_str_t *s) const
    {
        return strcmp(s) == 0;
    }

    //
    // Compare contents for equality.
    //
    bool operator==(const Pj_String &rhs) const
    {
        return pj_strcmp(this, &rhs) == 0;
    }

    //
    // Assign from char*
    //
    Pj_String& operator=(char *s)
    {
        set(s);
        return *this;
    }

    ///
    // Assign from another Pj_String, use with care!
    //
    Pj_String& operator=(const Pj_String &rhs)
    {
        ptr = rhs.ptr;
        slen = rhs.slen;
        return *this;
    }

    //
    // Find a character in the string.
    //
    char *strchr(int chr)
    {
        return pj_strchr(this, chr);
    }

    //
    // Find a character in the string.
    //
    char *find(int chr)
    {
        return strchr(chr);
    }

    //
    // Concatenate string.
    //
    void strcat(const Pj_String &rhs)
    {
        pj_strcat(this, &rhs);
    }

    //
    // Left trim.
    //
    void ltrim()
    {
        pj_strltrim(this);
    }

    //
    // Right trim.
    //
    void rtrim()
    {
        pj_strrtrim(this);
    }

    //
    // Left and right trim.
    //
    void trim()
    {
        pj_strtrim(this);
    }

    //
    // Convert to unsigned long.
    //
    unsigned long to_ulong() const
    {
        return pj_strtoul(this);
    }

    //
    // Convert from unsigned long.
    //
    void from_ulong(unsigned long value)
    {
        slen = pj_utoa(value, ptr);
    }

    //
    // Convert from unsigned long with padding.
    //
    void from_ulong_with_pad(unsigned long value, int min_dig=0, int pad=' ')
    {
        slen = pj_utoa_pad(value, ptr, min_dig, pad);
    }

};

#endif  /* __PJPP_STRING_HPP__ */