
//http://kevin.atkinson.dhs.org
// (C) Copyright Kevin Atkinson 2004. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.

#ifndef PARM_STRING__HPP
#define PARM_STRING__HPP

#include <dkutil/boost/config.hpp>
#include <string>
#include <cstring>
#include <cstdio>
#include <limits>
#include <dkutil/boost/assert.hpp>
#include <stdexcept>

//
// parm_string is a special string class that is designed to be used as
// a parameter for a function that is expecting a string.  It will allow
// either a "const char *" or "string" class to be passed in.  It will
// automatically convert to a "const char *".  The string can also be
// accesses via the "str" method.  Usage example:
//
// void foo(parm_string s1, parm_string s2) {
//   const char *  str0 = s1;
//   unsigned int size0 = s2.size()
//   if (s1 == s2 || s2 == "bar") {
//     ...
//   }
// }
// ...
// string s1 = "...";
// foo(s1);
// const char * s2 = "...";
// foo(s2);
//
// By using parm_string insead on "const char *" one avoids the need
// to have to use the c_str() member every time a string is passed
// into a function.  It is also more effect than just using "const
// char *" as the length information is passed in if it is known.
// It is also more efferent than just using "const string &" as that
// will involve creating an unnecessary temporary when a non string
// object is used.
//
// In my experence most functions that require a string as a paramater
// really only need the value of the string and possibly its length.
// They don't need the functionaliy of the full "string" class.
//

namespace boost {

class parm_string {
public:
  typedef std::size_t size_type;
	
	BOOST_STATIC_CONSTANT(size_type,max_value = 4294967295);

  parm_string() : str_(0) {}
  parm_string(const char * str, 
              //size_type sz = std::numeric_limits<size_type>::max()
							size_type sz = max_value
							)   : str_(str), size_(sz) {}
  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 char * () const {
    return str_;
  }
  const char * str () const {
    return str_;
  }
	//d金魚がちょっと改造 (std::stringインターフェイス？
	const char *c_str()const{
		return str_;
		}
	const char *data()const{
		return str_;
		}
	const char at(size_type pos)const{
		if(size() <= pos){
			throw std::length_error("parm_string::at length error");
		}
		return str_[pos];
	}
	char at(size_type pos){
		if(size() <= pos){
			throw std::length_error("parm_string::at length error");
		}
		return str_[pos];
		}

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

static inline bool operator== (parm_string s1, parm_string s2)
{
  if (s1.str() == 0 || s2.str() == 0)
    return s1.str() == s2.str();
  //return std::strcmp(s1,s2) == 0;
	return strcmp(s1,s2) == 0;
}
static inline bool operator!= (parm_string s1, parm_string s2)
{
  if (s1.str() == 0 || s2.str() == 0)
    return s1.str() != s2.str();
  //return std::strcmp(s1,s2) != 0;
	return strcmp(s1,s2) != 0;
}


}//end of boost namespace

namespace dkutil{//d金魚がちょっと改造
	using boost::parm_string;
}


#endif

