/**
 * \file BGDNetString.cpp
 * \brief Реализация класса String
 */

#include "BGDNetPch.h"

#include "BGDNetString.h"

#include <assert.h>
#include <string.h>

#ifdef BGDNET_USE_MFC
# ifdef _DEBUG
#   define new DEBUG_NEW
#   undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
# endif
#endif

namespace BGDNet
{

StringImp::StringImp( const char* p, size_t len )
{
  if (-1 == len)
    len = strlen(p);
  m_pStr = new string(p, len);
  /**
   * \todo Предусмотреть ситуацию с нехваткой памяти.
   */
}

StringImp::StringImp( const StringImp& imp )
{
  m_pStr = new string(*imp.m_pStr);
  /**
   * \todo Предусмотреть ситуацию с нехваткой памяти.
   */
}

StringImp::~StringImp( void )
{
  delete m_pStr;
}




String::String( void )
{
  m_pImp = new StringImp("", 0);
}

String::String( const String& s )
{
  m_pImp = s.m_pImp;
}

String::String( const char* p )
{
  m_pImp = new StringImp(p);
}

String::String( const char* p, size_t len )
{
  m_pImp = new StringImp(p, len);
}

String& String::operator =( const String& s )
{
  m_pImp = s.m_pImp;
  return *this;
}

String& String::operator =( const char* p )
{
  m_pImp = new StringImp(p);
  return *this;
}

String& String::operator +=( const String& s )
{
  append(s, s.length());
  return *this;
}

String& String::operator +=( const char* s )
{
  append(s, strlen(s));
  return *this;
}

String& String::operator +=( const char c )
{
  append(&c, 1);
  return *this;
}

String::operator const char*( void ) const
{
  return ptr();
}

const char* String::ptr( void ) const
{
  return m_pImp->m_pStr->c_str();
}

size_t String::length( void ) const
{
  return m_pImp->m_pStr->length();
}

void String::append( const char* s, size_t len )
{
  // Перед модификацией объекта необходимо получить собственную
  // копию реализацию чтобы не навредить другим объектам, ссылающимся
  // на нее.
  freeze();
  m_pImp->m_pStr->append(s, len);
}

void String::freeze( void )
{
  // Если на заголовок ссылается кто-то кроме нас,
  // необходимо получить копию строки в "личное" пользование:
  if (m_pImp->shared())
    m_pImp = new StringImp(*m_pImp);
}

} // namespace BGDNet
