#ifndef KZ_BASE_H
#define KZ_BASE_H

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

using namespace std;


inline void replace_all( const char *src, const char *fstr, const char *repstr, string &retstr, size_t off = 0)
{
	size_t	flen = strlen(fstr);
	size_t	fnd;
	const string &str(src);
	retstr.clear();
	retstr.reserve(str.capacity());
	retstr.assign( src, src + off);
	while ( (fnd = str.find( fstr, off)) != string::npos ) {
		retstr.append( str.c_str() + off, (fnd - off));
		retstr.append( repstr);
 		off = fnd + flen;
	}
	retstr += (str.c_str() + off);
}

inline void replace_first( const char *src, const char *fstr, const char *repstr, string &retstr, size_t off = 0)
{
	size_t	flen = strlen(fstr);
	size_t	fnd;
	const string &str(src);
	retstr.clear();
	retstr.reserve(str.capacity());
	retstr.assign( src, src + off);
	if ( (fnd = str.find( fstr, off)) != string::npos ) {
		retstr.append( str.c_str() + off, (fnd - off));
		retstr.append( repstr);
 		off = fnd + flen;
	}
	retstr += (str.c_str() + off);
}

inline void replace_regex_all( const string &srcstr, const char *fstr, const char *repstr, string &dststr, size_t off = 0)
{
	string tmp;
	boost::regex fnd(fstr);
	ostringstream t(ios::out | ios::binary);
	ostream_iterator<char, char> oi(t);
    boost::regex_replace( oi, srcstr.begin() + off, srcstr.end(), fnd, repstr, boost::match_default | boost::format_all);
	dststr.assign( srcstr.begin(), srcstr.begin() + off);
	dststr += t.str();
}

inline void replace_regex_first( const string &srcstr, const char *fstr, const char *repstr, string &dststr, size_t off = 0)
{
	string tmp;
	boost::regex fnd(fstr);
	ostringstream t(ios::out | ios::binary);
	ostream_iterator<char, char> oi(t);
    boost::regex_replace( oi, srcstr.begin() + off, srcstr.end(), fnd, repstr, boost::match_default | boost::format_first_only);
	dststr.assign( srcstr.begin(), srcstr.begin() + off);
	dststr += t.str();
}

inline void str2json(const string &str, string &value_) {
	value_.push_back('"');
	for ( string::const_iterator i = str.begin(); i < str.end(); i++ ) {
		switch ( *i ) {
			case '"' :
				value_.push_back('\\');
				value_.push_back('"');
				break;
			case '\\' :
				value_.push_back('\\');
				value_.push_back('\\');
				break;
			case '\r' :
				value_.push_back('\\');
				value_.push_back('r');
				break;
			case '\n' :
				value_.push_back('\\');
				value_.push_back('n');
				break;
			default :
				if ( iscntrl(*i) ) {
					string buf = cformat("\\u%04x", *i); 
					value_ += buf;
				} else {
					value_.push_back(*i);
				}
		}
	}
	value_.push_back('"');
}

inline bool revcmp( string &src, const char *dst, size_t len)
{
	if ( src.size() < len ) return false;
	return strcmp( src.c_str() + src.size() - len, dst) == 0;
}

inline bool revcmp3( string &src, const char *dst1, const char *dst2, const char *dst3, size_t len)
{
	if ( src.size() < len ) return false;
	if ( strcmp( src.c_str() + src.size() - len, dst1) == 0 ) return true;
	if ( strcmp( src.c_str() + src.size() - len, dst2) == 0 ) return true;
	if ( strcmp( src.c_str() + src.size() - len, dst3) == 0 ) return true;
	return false;
}

#endif
