matrix_thing/src/raii/util.cpp

132 lines
2.8 KiB
C++

/**
This file is a part of rexy's matrix client
Copyright (C) 2019-2020 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <rexy/string.hpp>
namespace raii{
namespace detail{
size_t _calc_escaped_len(const char* str){
size_t ret = 0;
for(const char* c = str;*c;++c){
switch(*c){
case '\\':
case '"':
case '/':
case '\n':
case '\r':
case '\b':
case '\f':
case '\t':
++ret;
break;
};
++ret;
}
return ret;
}
char _escape_to_letter(char escape){
switch(escape){
case '\n':
return 'n';
case '\r':
return 'r';
case '\b':
return 'b';
case '\f':
return 'f';
case '\t':
return 't';
};
return '\\';
}
size_t _sanitize_json_copy(char* dest, const char* in){
size_t pos = 0;
for(const char* c = in;*c;++c){
switch(*c){
case '"':
case '\\':
case '/':
dest[pos++] = '\\';
dest[pos++] = *c;
break;
case '\n':
case '\r':
case '\b':
case '\f':
case '\t':
dest[pos++] = '\\';
dest[pos++] = _escape_to_letter(*c);
break;
default:
dest[pos++] = *c;
};
}
dest[pos] = 0;
return pos;
}
}
rexy::string json_escape(const rexy::string_base& str){
size_t len = detail::_calc_escaped_len(str.get());
char* tmp = reinterpret_cast<char*>(rexy::string::allocator_type::allocate(len+1));
detail::_sanitize_json_copy(tmp, str);
tmp[len] = 0;
return rexy::string(tmp, len, len);
}
//shamelessly stolen from stackoverflow (of all the things to need to steal)
size_t intlen(int i){
if(i >= 100000){
if(i >= 10000000){
if(i >= 1000000000) return 10;
if(i >= 100000000) return 9;
return 8;
}
if(i >= 1000000) return 7;
return 6;
}else{
if(i >= 1000){
if(i >= 10000) return 5;
return 4;
}else{
if(i >= 100) return 3;
if(i >= 10) return 2;
return 1;
}
}
}
rexy::string itostr(int i){
if(i == 0)
return rexy::string("0");
int place = intlen(i);
rexy::string ret(place, place);
char* buf = ret.get();
buf[place] = 0;
while(i != 0){
int rem = i % 10;
buf[--place] = rem + '0';
i /= 10;
}
return ret;
}
}