1 #ifndef PROTON_STRING_HEADER
2 #define PROTON_STRING_HEADER
8 #include <boost/algorithm/string/predicate.hpp>
9 #include <boost/algorithm/string/case_conv.hpp>
13 #include <type_traits>
15 #include <proton/pool.hpp>
25 template<
typename string>
string strip(
const string& x)
27 string spc =
" \t\n\r";
29 long i=x.find_first_not_of(spc);
30 long j=x.find_last_not_of(spc);
32 if(i<0 || j<0 || j < i )
35 return x.substr(i,j-i+1);
44 template<
typename string_list,
typename string>
void split(string_list& r,
const string& s,
string spc=
"",
int null_unite=-1)
46 long pos = 0, begin, end;
62 begin = s.find_first_not_of(spc,pos);
65 end = s.find_first_of(spc,begin);
68 r.push_back(s.substr(begin, end-begin).c_str());
71 while(pos < (
long)s.length());
75 begin = s.find_first_of(spc,pos);
77 r.push_back(s.substr(pos).c_str());
80 r.push_back(s.substr(pos, begin-pos).c_str());
82 if(pos>=(
long)s.length()){
90 template<
typename string_list,
typename string>
91 void split(string_list& r,
const string& s,
const char* spc,
int null_unite=-1)
93 return split(r, s,
string(spc), null_unite);
101 template<
typename string_list>
102 typename string_list::value_type
join(
const char* token,
const string_list& r)
108 typename string_list::const_iterator it=r.begin();
109 typename string_list::value_type res=*it;
111 for(;it!=r.end();++it){
118 template<
typename str1,
typename str2>
bool startswith(
const str1& s,
const str2& sub)
120 return boost::algorithm::starts_with(s, sub);
123 template<
typename str1,
typename str2>
bool istartswith(
const str1& s,
const str2& sub)
125 return boost::algorithm::istarts_with(s, sub);
128 template<
typename str1,
typename str2>
bool endswith(
const str1& s,
const str2& sub)
130 return boost::algorithm::ends_with(s, sub);
133 template<
typename str1,
typename str2>
bool iendswith(
const str1& s,
const str2& sub)
135 return boost::algorithm::iends_with(s, sub);
138 template<
typename ostream>
void set_base(ostream& s,
int base,
bool is_num=
false)
155 PROTON_LOG(0,
"unsupported base : " << base );
164 template<
typename string,
typename T>
string to_(T&& n,
int base=10)
166 std::basic_ostringstream<char, std::char_traits<char>,
typename string::allocator_type > s;
167 set_base(s, base,
true);
178 template<
typename int_t,
typename string>
bool get_int(int_t& r,
const string& s,
int base=10)
180 bool is_hex= (base==16);
182 if( iendswith(s,
"h") ){
183 v1=s.substr(0,s.length()-1);
186 else if( istartswith(s,
"0x") ){
193 std::basic_istringstream<char, std::char_traits<char>,
typename string::allocator_type >
198 if ( (!(i >> x)) || (i.get()>0) ){
205 template<
typename string>
string to_lower(
const string& s)
207 long length = s.size();
208 static typename string::allocator_type
alloc;
209 char* p = alloc.allocate(length);
212 const char* p0 = s.c_str();
215 for(
long i=0;i<length;++i){
220 r = string(q,length);
221 alloc.deallocate(q,length) ;
229 template<
typename string>
string to_upper(
const string& s)
231 long length = s.size();
232 static typename string::allocator_type
alloc;
233 char* p = alloc.allocate(length);
236 const char* p0 = s.c_str();
239 for(
long i=0;i<length;++i){
244 r = string(q,length);
245 alloc.deallocate(q,length) ;
254 template<
typename string>
string readline(std::istream& f,
char delim=
'\n')
257 std::ios::pos_type start=f.tellg(), end;
258 std::getline(f, r, delim);
260 if(end-start>(
long)r.length()){
269 template <
typename C,
typename T,
typename A>
270 C
get(
const std::basic_string<C,T,A>& x,
long i)
272 unsigned long s=x.size();
275 if(i<0 || (
unsigned long)i >= s )
276 PROTON_ERR(
"out of range: look up "<<i<<
" in vector whose size is " << s);
280 template <
typename C,
typename T,
typename A>
281 std::basic_string<C,T,A> sub(
const std::basic_string<C,T,A>& x,
long first)
283 unsigned long s=x.size();
288 if((
unsigned long)first >= s )
291 return x.substr(first);
294 template <
typename C,
typename T,
typename A>
295 std::basic_string<C,T,A> sub(
const std::basic_string<C,T,A>& x,
long first,
long last)
297 unsigned long s=x.size();
302 if((
unsigned long)first >= s )
310 if((
unsigned long)last>s)
312 return x.substr(first,last-first);
316 template<
typename cT>
struct vals;
318 template<>
struct vals<char>{
319 static constexpr
const char* nil=
"";
320 static constexpr
const char* spc=
" ";
321 static constexpr
const char* ws=
" \t\r\n";
322 static constexpr
const char* per=
"%";
323 static constexpr
const char* d=
"d";
324 static constexpr
const char* f=
"f";
325 static constexpr
const char* u=
"u";
326 static constexpr
const char* o=
"o";
327 static constexpr
const char* x=
"x";
328 static constexpr
const char* X=
"X";
329 static constexpr
const char* s=
"s";
331 static const char* find(
const char* s,
char x)
333 return std::strchr(s, x);
337 template<>
struct vals<wchar_t>{
338 static constexpr
const wchar_t* nil=L
"";
339 static constexpr
const wchar_t* spc=L
" ";
340 static constexpr
const wchar_t* ws=L
" \t\r\n";
341 static constexpr
const wchar_t* per=L
"%";
342 static constexpr
const wchar_t* d=L
"d";
343 static constexpr
const wchar_t* f=L
"f";
344 static constexpr
const wchar_t* u=L
"u";
345 static constexpr
const wchar_t* o=L
"o";
346 static constexpr
const wchar_t* x=L
"x";
347 static constexpr
const wchar_t* X=L
"X";
348 static constexpr
const wchar_t* s=L
"s";
350 static const wchar_t* find(
const wchar_t* s,
wchar_t x)
352 return std::wcschr(s,x);
359 class Traits = std::char_traits<CharT>,
360 class Allocator = smart_allocator<CharT>
361 >
class basic_string_;
365 template<
typename C,
typename T>
366 void output_prefix(std::basic_ostream<C,T>& o,
const C*& f)
371 const C* p=vals<C>::find(f, *vals<C>::per);
375 throw std::invalid_argument(
"incomplete format");
394 template<
typename C,
typename T,
typename V,
typename X>
397 template<
typename C,
typename T,
typename V>
398 struct format_t<C,T,V,typename std::enable_if<std::is_integral<V>::value, void>::type>
400 static void output(std::basic_ostream<C,T>& o,
const C* & f, V a)
405 throw std::invalid_argument(
"not all arguments converted during formatting");
417 o << std::hex << std::nouppercase << a;
420 o << std::hex << std::uppercase << a;
423 throw std::invalid_argument(
"unsupported format character");
429 template<
typename C,
typename T,
typename V>
430 struct format_t<C,T,V,typename std::enable_if<std::is_floating_point<V>::value, void>::type>
432 static void output(std::basic_ostream<C,T>& o,
const C* & f, V a)
437 throw std::invalid_argument(
"not all arguments converted during formatting");
445 o << std::dec << (
long long)(a);
448 o << std::oct << (
long long)(a);
451 o << std::hex << std::nouppercase << (
long long)(a);
454 o << std::hex << std::uppercase << (
long long)(a);
457 throw std::invalid_argument(
"unsupported format character");
464 template<
typename C,
typename T,
typename V>
465 struct format_t<C,T,V,typename std::enable_if<!(std::is_floating_point<V>::value ||
466 std::is_integral<V>::value), void>::type>{
467 static void output(std::basic_ostream<C,T>& o,
const C* & f,
const V& a)
472 throw std::invalid_argument(
"not all arguments converted during formatting");
482 throw std::invalid_argument(
"a number is required");
484 throw std::invalid_argument(
"unsupported format character");
490 template<
typename C,
typename T,
typename V>
491 struct format_output_t{
492 static void output(std::basic_ostream<C,T>& s,
const C* f,
const V& v)
494 format_t<C,T,V,void>::output(s, f, v);
497 throw std::invalid_argument(
"not enough arguments for format");
501 template<
typename C,
typename T,
typename A,
typename V>
502 basic_string_<C,T,A> str_format(
const C* f,
const V& v)
504 std::basic_ostringstream<C,T,A> o;
505 format_output_t<C,T,V>::output(o, f, v);
510 template<
typename C,
typename T,
typename V, std::
size_t I>
511 struct format_tuple {
512 static void output(std::basic_ostream<C,T>& s,
const C* & f,
const V& t)
514 format_tuple<C, T, V, I-1>::output(s, f, t);
515 typedef decltype(std::get<I-1>(t)) N;
516 typedef typename std::remove_reference<N>::type N1;
517 format_t<C,T,N1,
void>::output(s, f, std::get<I-1>(t));
521 template<typename C, typename T, typename V>
522 struct format_tuple<C, T, V, 1> {
523 static void output(std::basic_ostream<C,T>& s,
const C* & f,
const V& t)
525 typedef decltype(std::get<0>(t)) N;
526 typedef typename std::remove_reference<N>::type N1;
527 format_t<C,T,N1,
void>::output(s, f, std::get<0>(t));
531 template<typename C, typename T, typename V>
532 struct format_tuple<C, T, V, 0> {
533 static void output(std::basic_ostream<C,T>& s,
const C* & f,
const V& t)
538 template<
typename C,
typename T,
typename ...V>
539 struct format_output_t<C,T,std::tuple<V...> >{
540 static void output(std::basic_ostream<C,T>& s,
const C* f,
const std::tuple<V...> & t)
542 format_tuple<C, T,
const std::tuple<V...> &,
sizeof...(V) >::output(s,f,t);
543 detail::output_prefix(s, f);
545 throw std::invalid_argument(
"not enough arguments for format");
560 typedef std::basic_string<CharT,Traits,Allocator> baseT;
561 typedef typename baseT::difference_type offset_t;
563 offset_t __offset(offset_t i)
const
570 offset_t offset(offset_t i)
const
573 PROTON_THROW_IF(i<0 || (
size_t)i>=this->size(),
"out of range, offset is " << i
574 <<
" while size is " << this->size() );
578 int fix_offset(offset_t begin)
const
580 offset_t size=(offset_t)this->size();
581 begin=__offset(begin);
590 void fix_range(offset_t& begin, offset_t& end)
const
592 offset_t size=(offset_t)this->size();
593 begin=__offset(begin);
595 if(begin>=size || end<=0 || end<=begin){
630 basic_string_(baseT&& x)noexcept:baseT(x)
647 basic_string_& operator=(
const baseT& x)
653 basic_string_& operator=(baseT&& x)noexcept
659 template<
typename argT> basic_string_& operator=(argT&& a)
665 basic_string_& operator=(std::initializer_list<CharT> a)
673 template<
typename argT>
682 template<
typename argT>
695 return detail::str_format<CharT, Traits, Allocator>(this->c_str(), a);
702 return reinterpret_cast<baseT&
>(*this);
707 template<
typename A1>
708 operator std::basic_string<CharT,Traits,A1> ()
const
710 return this->c_str();
715 CharT& operator[](offset_t i)
717 return *(this->begin()+offset(i));
722 const CharT& operator[](offset_t i)
const
724 return *(this->begin()+offset(i));
731 auto begin=this->begin();
739 auto begin=this->begin();
750 r.reserve((j-i)/k+2);
751 auto it=this->begin()+i;
752 for(offset_t n=i; n<j; n+=k,it+=k)
759 size_t count(
const CharT& x)
const
761 return std::count(this->begin(), this->end(), x);
768 offset_t index(
const CharT& val)
const
770 auto begin=this->begin(), end=this->end();
771 auto it=std::find(begin, end, val);
773 throw std::invalid_argument(
"The given char doesn't exist in this sequence.");
783 offset_t i=this->find_first_not_of(spc);
784 offset_t j=this->find_last_not_of(spc);
786 if(i<0 || j<0 || j < i )
787 return detail::vals<CharT>::nil;
798 split(
const baseT& delim=baseT(),
int null_unite=-1)
const
800 long pos = 0, begin, end;
808 spc=detail::vals<CharT>::ws;
817 begin = this->find_first_not_of(spc,pos);
820 end = this->find_first_of(spc,begin);
823 r.push_back(this->substr(begin, end-begin));
826 while(pos < (
long)this->length());
830 begin = this->find_first_of(spc,pos);
832 r.push_back(this->substr(pos));
835 r.push_back(this->substr(pos, begin-pos));
837 if(pos>=(
long)this->length()){
838 r.push_back(detail::vals<CharT>::nil);
850 template<
typename string_list>
857 typename string_list::const_iterator it=r.begin();
860 for(;it!=r.end();++it){
870 template<
typename str2>
bool startswith(str2&& sub)
const
872 return boost::algorithm::starts_with(*
this, sub);
877 template<
typename str2>
bool istartswith(str2&& sub)
const
879 return boost::algorithm::istarts_with(*
this, sub);
884 template<
typename str2>
bool endswith(str2&& sub)
const
886 return boost::algorithm::ends_with(*
this, sub);
891 template<
typename str2>
bool iendswith(str2&& sub)
const
893 return boost::algorithm::iends_with(*
this, sub);
900 return boost::algorithm::to_lower_copy(*
this);
907 return boost::algorithm::to_upper_copy(*
this);
927 template<
typename T,
typename C,
typename A>
937 template<
typename C,
typename V>
945 template<
typename T,
typename C,
typename A>
949 r.reserve(s.size()*n+1);
950 for(
size_t i=0; i<n; i++)
957 template<
typename T,
typename C,
typename A>
965 template<
typename T,
typename C,
typename A>
971 template<
typename T,
typename C,
typename A>
972 const basic_string_<T,C,A>&
cast_(
const std::basic_string<T,C,A>& x)
974 return reinterpret_cast<const basic_string_<T,C,A>&
>(x);
977 template<
typename T,
typename C,
typename A>
978 basic_string_<T,C,A>&&
cast_(std::basic_string<T,C,A>&& x)
980 return reinterpret_cast<basic_string_<T,C,A>&&
>(x);
983 template<
typename T,
typename C,
typename A>
984 const basic_string_<T,C,A>&&
cast_(
const std::basic_string<T,C,A>&& x)
986 return reinterpret_cast<const basic_string_<T,C,A>&&
>(x);
997 template<
typename T,
typename C,
typename A>
998 struct hash<proton::basic_string_<T,C,A> >{
1000 typedef size_t result_type;
1004 return std::hash<std::basic_string<T> >()(
reinterpret_cast<const std::basic_string<T>&
>(s));
1009 #endif // PROTON_STRING_HEADER