#include <stdio.h>
#include <sstream>
#include <functional>
#include <stdarg.h> // for va_start, etc
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include "Utils.h"
#include "Containers.h"
#include "Test.h"
BEGIN_NAMESPACE
std::string wstring_to_utf8(const std::wstring& utf16)
{
std::vector<char> utf8(100,'\0');
int len = WideCharToMultiByte(CP_UTF8, 0, utf16.c_str(), -1, NULL, 0, 0, 0);
if (len > 1)
{
utf8.resize(len + 1);
WideCharToMultiByte(CP_UTF8, 0, utf16.c_str(), -1, utf8.data(), len, 0, 0);
}
return utf8.data();
}
std::wstring utf8_to_wstring(const std::string& utf8)
{
std::vector<wchar_t> utf16(100,'\0');
int len = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0);
if (len>1)
{
utf16.resize(len + 1);
MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, utf16.data(), len);
}
return utf16.data();
}
#ifndef USE_STL_CONTAINERS
Vector<std::string> split(const std::string &s, char delim)
{
Vector<std::string> elems;
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
Vector<std::string> split(const std::string &s, const char* a_delim)
{
Vector<std::string> elems;
std::string delim = a_delim;
size_t start = 0U;
size_t end = s.find(delim);
while (end != std::string::npos)
{
elems.push_back(s.substr(start, end - start));
start = end + delim.length();
end = s.find(delim, start);
}
elems.push_back(s.substr(start, end));
return elems;
}
// returns everything to the left of match from the input string
std::string left(const std::string &str, const char* match)
{
std::size_t found = str.find(match);
if (found == std::string::npos)
return str; // Not found
return str.substr(0, found);
}
// returns everything to the right of match from the input string
std::string right(const std::string &str, const char* match)
{
std::size_t found = str.find(match);
if (found == std::string::npos)
return str; // Not found
return str.substr(found + strlen(match));
}
std::string string_format(const char* fmt, ...)
{
std::vector<char> str(100,'\0');
va_list ap;
while (1) {
va_start(ap, fmt);
int n = vsnprintf(str.data(), str.size(), fmt, ap);
va_end(ap);
if ((n > -1) && (size_t(n) < str.size())) {
return str.data();
}
if (n > -1)
str.resize(n + 1);
else
str.resize(str.size() * 2);
}
return str.data();
}
std::string to_string(uint32_t i)
{
std::stringstream ss;
ss << i;
return ss.str();
}
Vector<char> wideString_to_utf8(const std::wstring& utf16)
{
Vector<char> utf8(100,'\0');
int len = WideCharToMultiByte(CP_UTF8, 0, utf16.c_str(), -1, NULL, 0, 0, 0);
if (len > 1)
{
utf8.resize(len + 1);
WideCharToMultiByte(CP_UTF8, 0, utf16.c_str(), -1, utf8.data(), len, 0, 0);
}
return utf8;
}
String::String() {}
String::~String() {}
String::String(char a_val) { std::stringstream ss; ss << a_val; m_str = ss.str(); }
String::String(int8_t a_val) { std::stringstream ss; ss << a_val; m_str = ss.str(); }
String::String(uint8_t a_val) { std::stringstream ss; ss << a_val; m_str = ss.str(); }
String::String(int16_t a_val) { std::stringstream ss; ss << a_val; m_str = ss.str(); }
String::String(uint16_t a_val) { std::stringstream ss; ss << a_val; m_str = ss.str(); }
String::String(int32_t a_val) { std::stringstream ss; ss << a_val; m_str = ss.str(); }
String::String(uint32_t a_val) { std::stringstream ss; ss << a_val; m_str = ss.str(); }
String::String(int64_t a_val) { std::stringstream ss; ss << a_val; m_str = ss.str(); }
String::String(uint64_t a_val) { std::stringstream ss; ss << a_val; m_str = ss.str(); }
String::String(float a_val) { std::stringstream ss; ss << a_val; m_str = ss.str(); }
String::String(double a_val) { std::stringstream ss; ss << a_val; m_str = ss.str(); }
/*
String::String(const std::wstring& a_other) { m_str = wstring_to_utf8(a_other); }
*/
String::String(const std::string& a_other) { m_str = a_other; }
String::String(const wchar_t* a_wideString) { m_str = wstring_to_utf8(a_wideString); }
String::String(const String& a_other) { m_str = a_other.m_str; }
String String::replace(const char* a_match, const char* a_replacement)
{
size_t start_pos = 0;
String str = *this;
size_t len = strlen(a_replacement);
if (strlen(a_match) != len) // make sure a_match and a_replacement are the same length
return str;
while ((start_pos = find(a_match, start_pos)) != npos)
{
//str.replace(start_pos, a_match.toUtf8().length(), a_replacement.toUtf8());
memcpy((char*)str.data() + start_pos, a_replacement, len);
start_pos += len;
}
return str;
}
String String::left(const char* a_match) { return NAMESPACE::left(m_str, a_match); }
String String::right(const char* a_match) { return NAMESPACE::right(m_str, a_match); }
const std::string& String::toUtf8() const { return m_str; }
const std::wstring& String::toWString() const { m_wstr = utf8_to_wstring(m_str); return m_wstr; }
/*
*/
const char* String::data() const { return m_str.data(); }
const char* String::c_str() const { return m_str.data(); }
String::operator const char*() const { return c_str(); }
String& String::operator= (const String& a_other) { m_str = a_other.m_str; return *this; }
String& String::operator= (const char* a_str) { m_str = a_str; return *this; }
String& String::operator= (char a_ch) { m_str = a_ch; return *this; }
String& String::operator+=(const char* a_str) { m_str += a_str; return *this; }
String& String::operator+=(const String& a_other) { m_str += a_other.m_str; return *this; }
String& String::operator+=(char a_ch) { m_str += a_ch; return *this; }
bool String::operator==(const char* a_other) const { return (m_str == std::string(a_other)); }
//bool String::operator==(const std::string& a_other) const { return (m_str == a_other); }
bool String::operator==(const String& a_other) const { return (m_str == a_other.m_str); }
bool String::operator!=(const char* a_other) const { return (m_str != std::string(a_other)); }
//bool String::operator!=(const std::string& a_other) const { return (m_str != a_other); }
bool String::operator!=(const String& a_other) const { return (m_str != a_other.m_str); }
bool String::operator< (const String& a_other) const { return (m_str < a_other.m_str); }
bool String::operator> (const String& a_other) const { return (m_str > a_other.m_str); }
bool String::operator<=(const String& a_other) const { return (m_str <= a_other.m_str); }
bool String::operator>=(const String& a_other) const { return (m_str >= a_other.m_str); }
bool String::operator!() const { return m_str.size() ? false : true; }
const String operator+(const String& a_a, const String& a_b) { return String(a_a.m_str + a_b.m_str); }
const String operator+(const String& a_a, const char* a_b) { return String(a_a.m_str + a_b); }
const String operator+(const char* a_a, const String& a_b) { return String(a_a + a_b.m_str); }
const String operator+(char a_a, const String& a_b) { return String(a_a + a_b.m_str); }
const String operator+(const String& a_a, char a_b) { return String(a_a.m_str + a_b); }
bool operator==(const char* a_a, const String& a_b) { return a_a == a_b.m_str; }
bool operator!=(const char* a_a, const String& a_b) { return a_a != a_b.m_str; }
const size_t String::npos = -1;
static size_t hashFunc(const uint8_t *a_str, size_t a_count)
{
size_t val = 2166136261U;
for (size_t i = 0; i < a_count; i++)
{
val ^= (size_t)a_str[i];
val *= 16777619U;
}
//val ^= val >> 32;
return val;
}
size_t String::hash() const
{
return hashFunc((const uint8_t *)m_str.data(), m_str.size());
//return std::hash<std::string>()(m_str);
}
size_t String::find(const char* a_match, size_t a_start)
{
int len = strlen(a_match);
int siz = m_str.size();
const char* data = m_str.data();
if (siz < len)
return npos;
for (size_t i = a_start; i < (siz-len); i++)
{
size_t j = 0;
for (; j < len; j++)
if (data[i+j] != a_match[j])
break;
if (j == len)
return i;
}
return npos;
}
Vector<String> String::split(const char* a_deliminator)
{
Vector<String> elems;
size_t start = 0U;
size_t end = find(a_deliminator);
int len = strlen(a_deliminator);
while (end != npos)
{
elems.push_back(String(m_str.substr(start, end - start)));
start = end + len;
end = find(a_deliminator, start);
}
elems.push_back(String(m_str.substr(start, end)));
return elems;
}
String::String(const char* fmt, ...)
{
std::vector<char> str(50,'\0');
va_list ap;
int n = -1;
while ((n <= -1) || (size_t(n) >= str.size())) {
str.resize((n <= -1) ? (str.size() * 2) : (n + 1));
va_start(ap, fmt);
n = vsnprintf(str.data(), str.size(), fmt, ap);
va_end(ap);
}
m_str = str.data();
}
UNIT_TEST(StringTests, 0)
{
String str("blah/foo/bar");
Vector<String> strs = str.split("/");
CHECK(str == "blah/foo/bar");
CHECK(strs.size() == 3);
CHECK(strs[0] == "blah");
CHECK(strs[1] == "foo");
CHECK(strs[2] == "bar");
CHECK(str.left("foo") == "blah/");
CHECK(str.right("foo") == "/bar");
}
#else
const std::wstring& String::toWString() const
{
m_wstr = utf8_to_wstring(*this);
return m_wstr;
}
#endif
#if 0
// whole bunch of code trying to make cout and stdout write to visual studios output window
// only cout seems to be able to be made to do this, looks like nearly impossible to do to stdout
#include <iostream>
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
/// \brief This class is a derivate of basic_stringbuf which will output
/// all the written data using the OutputDebugString function
template<typename TChar, typename TTraits = std::char_traits<TChar>>
class OutputDebugStringBuf : public std::basic_stringbuf<TChar,TTraits> {
public:
explicit OutputDebugStringBuf() : _buffer(256) {
setg(nullptr, nullptr, nullptr);
setp(_buffer.data(), _buffer.data(), _buffer.data() + _buffer.size());
}
~OutputDebugStringBuf() {
int x = 0;
}
static_assert(std::is_same<TChar,char>::value || std::is_same<TChar,wchar_t>::value, "OutputDebugStringBuf only supports char and wchar_t types");
int sync() try {
MessageOutputer<TChar,TTraits>()(pbase(), pptr());
setp(_buffer.data(), _buffer.data(), _buffer.data() + _buffer.size());
return 0;
} catch(...) {
return -1;
}
int_type overflow(int_type c = TTraits::eof()) {
auto syncRet = sync();
if (c != TTraits::eof()) {
_buffer[0] = c;
setp(_buffer.data(), _buffer.data() + 1, _buffer.data() + _buffer.size());
}
return syncRet == -1 ? TTraits::eof() : 0;
}
private:
std::vector<TChar> _buffer;
template<typename TChar, typename TTraits>
struct MessageOutputer;
template<>
struct MessageOutputer<char,std::char_traits<char>> {
template<typename TIterator>
void operator()(TIterator begin, TIterator end) const {
std::string s(begin, end);
OutputDebugStringA(s.c_str());
}
};
template<>
struct MessageOutputer<wchar_t,std::char_traits<wchar_t>> {
template<typename TIterator>
void operator()(TIterator begin, TIterator end) const {
std::wstring s(begin, end);
OutputDebugStringW(s.c_str());
}
};
};
#include <cstdio>
void initDebugOutput()
{
static OutputDebugStringBuf<char> charDebugOutput;
std::cout.rdbuf(&charDebugOutput);
std::cerr.rdbuf(&charDebugOutput);
std::clog.rdbuf(&charDebugOutput);
std::ios_base::sync_with_stdio(true);
}
#endif
END_NAMESPACE