/**
 * \file BGDNetString.h
 * \brief Объявление класса String.
 */

#ifndef __BGDNetString_h__
#define __BGDNetString_h__

#include "BGDNetConfig.h"

#include <string>
#include "BGDNetShare.h"

namespace BGDNet
{

using std::string;

/**
 * \class StringImp
 * \brief Класс "Реализация строки"
 *
 * Этот класс используется в реализации класса String.
 */
class BGDNET_API StringImp : public Share
{
public:

  StringImp( const char* p, size_t len = -1 );
  /**<
   * \brief Конструктор
   * @param p Указатель на строку
   * @param len Длина строки
   */

  StringImp( const StringImp& imp );
  /**<
   * \brief Инициализатор копии
   */

  virtual ~StringImp( void );
  /**<
   * \brief Деструктор
   * Деструктор не вызывается напрямую, объект освобождается
   * через вызов release().
   */

  string* m_pStr; /**< Указатель на объект, реализующий строку */
};




#ifdef _MSC_VER
# pragma warning(disable:4231)
#endif

BGDNET_TEMPLATE(SharePtr<StringImp>);

#ifdef _MSC_VER
# pragma warning(default:4231)
#endif
  



/**
 * \class String
 * \brief Класс "Строка"
 *
 * С помощью данного класса осуществляется эффективная работа со строками.
 * Копии одной и той же строки используют общую область памяти для ее хранения
 * до тех пор, пока один из объектов не будет модифицирован. В этом случае он
 * получает "персональную" копию буфера. ВНИМАНИЕ: класс String не осущечтвляет
 * синхронизацию доступа, поэтому строки, созданные одним потоком, нельзя
 * передавать другому потоку.
 */
class BGDNET_API String
{
public:

  String( void );
  /**<
   * \brief Конструктор по умолчанию.
   */

  String( const String& s );
  /**<
   * \brief Инициализатор копии.
   */

  String( const char* p );
  /**<
   * \brief Конструктор.
   * @param p Указатель на буфер, содержащий строку.
   */

  String( const char* p, size_t len );
  /**<
   * \brief Конструктор.
   * @param p Указатель на буфер, содержащий строку.
   * @param len Длина строки.
   */

  String& operator =( const String& s );
  /**<
   * \brief Оператор присваивания.
   */

  String& operator =( const char* p );
  /**<
   * \brief Оператор присваивания.
   */

  String& operator +=( const String& s );
  /**<
   * \brief Оператор конкатенации.
   */

  String& operator +=( const char* s );
  /**<
   * \brief Оператор конкатенации.
   */

  String& operator +=( const char c );
  /**<
   * \brief Оператор конкатенации.
   */

  operator const char*( void ) const;
  /**<
   * \brief Оператор преобразования к типу константного указателя на строку.
   */

  const char* ptr( void ) const;
  /**<
   * \brief Явный доступ к указателю на строку
   * @return Указатель на строку
   */

  size_t length( void ) const;
  /**<
   * \brief Доступ к длине строки.
   * @return Длина строки.
   */

  friend bool operator ==( String s1, String s2 );

private:

  void append( const char* buf, size_t len );
  /**<
   * \brief Добавляет подстроку в конец строки.
   * @param buf Указатель на буфер, содержащий подстроку.
   * @param len Количество символов, которые необходимо добавить.
   */

  void freeze( void );
  /**<
   * \brief "Замораживает" строку - строка становится единоличным
   * владельцем своей реализации.
   */

  SharePtr<StringImp> m_pImp;
  /**<
   * \brief Указатель на разделяемую реализацию строки.
   */
};

/**
 * \brief Перегруженный оператор проверки строк на равенство
 */
inline bool operator ==( String s1, String s2 )
{
  return (*s1.m_pImp->m_pStr) == (*s2.m_pImp->m_pStr);
}

/**
 * \brief Перегруженный оператор проверки строк на неравенство
 */
inline bool operator !=( String s1, String s2 )
{
  return !(s1 == s2);
}

} // namespace BGDNet

#endif //__BGDNetString_h__
