/**
@file string.hpp
@brief 文字列系のコンテナや処理等のライブラリ
@note 
ys3/YTLのstring.hはys3_stringとして定義されています。


*/
#ifndef DKUTIL_STRING_HPP
#define DKUTIL_STRING_HPP


#include <dkutil/macro.hpp>
#include <string>

#include <dkutil/parser/string_util.hpp>
#include <ys3/YTL/string.h>
#include <dkutil/boost/parm_string.hpp>
//#include <dkutil/const_string.hpp>

namespace dkutil{



///boost::parm_stringをベースに
template<class T>
class basic_parm_string {
public:
  typedef std::size_t size_type;
	typedef T value_type;
	
	BOOST_STATIC_CONSTANT(size_type,max_value = 4294967295);

  basic_parm_string() : str_(0) {}
  basic_parm_string(const value_type * str, 
              //size_type sz = std::numeric_limits<size_type>::max()
							size_type sz = max_value
							)   : str_(str), size_(sz) {}
  basic_parm_string(const std::string & str)
    : str_(str.c_str()), size_(str.size()) {}
  
  bool empty() const {return str_ == 0 || str_[0] == '\0';}

  size_type size() const {
    //if (size_ != std::numeric_limits<size_type>::max()) return size_;
    if (size_ != max_value) return size_;
		else{
			//return size_ = std::strlen(str_);
			return size_ = strlen(str_);
		}
  }
  operator const value_type * () const {
    return str_;
  }
  const value_type * str () const {
    return str_;
  }
	//d金魚がちょっと改造 (std::stringインターフェイス？
	const value_type *c_str()const{
		return str_;
		}
	const value_type *data()const{
		return str_;
		}
	const value_type at(size_type pos)const{
		if(size() <= pos){
			throw std::length_error("basic_parm_string::at length error");
		}
		return str_[pos];
	}
	value_type at(size_type pos){
		if(size() <= pos){
			throw std::length_error("basic_parm_string::at length error");
		}
		return str_[pos];
		}

	value_type operator[](size_type i)const{
#	if defined(_DEBUG) || defined(DEBUG)
		return at(i);
#	else		
		return str_[i];
#	endif
	}
private:
  const value_type * str_;
  mutable size_type size_;
};

template<class T>
static inline bool operator== (basic_parm_string<T> s1, basic_parm_string<T> s2)
{
  if (s1.str() == 0 || s2.str() == 0)
    return s1.str() == s2.str();
  //return std::strcmp(s1,s2) == 0;
	return strcmp(s1,s2) == 0;
}
template<class T>
static inline bool operator!= (basic_parm_string<T> s1, basic_parm_string<T> s2)
{
  if (s1.str() == 0 || s2.str() == 0)
    return s1.str() != s2.str();
  //return std::strcmp(s1,s2) != 0;
	return strcmp(s1,s2) != 0;
}

typedef basic_parm_string<std::wstring::value_type> parm_wstring;

typedef ys3::YTL::YTLstring::string ys3_string;
///これは「UNICODEでもうまく動くといいなぁ．．ヽ(´Д｀)ノ」だそうです。
typedef ys3::YTL::YTLstring::basic_string<wchar_t> ys3_wstring;




}//end of dkutil namespace



#endif