source: cpp/common/Convert.cpp @ 1025

Last change on this file since 1025 was 1005, checked in by Maciej Komosinski, 4 years ago

Higher conformance with C++17, but gave up after missing M_PI, M_PI_2, strdup() and more; other cosmetic improvements

  • Property svn:eol-style set to native
File size: 5.1 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#include "Convert.h"
6#include <sstream>
7
8#if defined __ANDROID__ || defined __BORLANDC__
9#include <ctype.h> //toupper, tolower
10#endif
11
12#ifdef SHP
13#include <cstdlib>
14#else
15#include <stdlib.h>
16#endif
17
18#include <stdio.h>
19
20
21int Convert::toInt(string s) { return atoi(s.c_str()); }
22float Convert::toFloat(string s) { return (float)atof(s.c_str()); }
23string Convert::toLowerCase(string s) { std::transform(s.begin(), s.end(), s.begin(), ::tolower);  return s; }
24string Convert::toUpperCase(string s) { std::transform(s.begin(), s.end(), s.begin(), ::toupper);  return s; }
25char Convert::toLowerCase(char c) { return (char)tolower(c); }
26char Convert::toUpperCase(char c) { return (char)toupper(c); }
27
28template<class T> const char* printf_format_for(const T& value) { return "unknown type"; }
29template<> const char* printf_format_for(const unsigned int& value) { return "%u"; }
30template<> const char* printf_format_for(const int& value) { return "%d"; }
31template<> const char* printf_format_for(const short& value) { return "%d"; }
32template<> const char* printf_format_for(const float& value) { return "%g"; }
33template<> const char* printf_format_for(const double& value) { return "%g"; }
34
35template<class T> string Convert::_toString(const T& value)
36{
37        char buf[30];
38        sprintf(buf, printf_format_for(value), value);
39        return string(buf);
40        /*
41        #ifndef MULTITHREADED
42        static
43        #endif
44        std::ostringstream oss; //pod VS tworzenie go trwa dlugo nawet w wersji release (szczegolnie jak np konwertuje sie cos setki tysiecy razy)
45        //dlatego robimy go raz (static) i potem tylko czyscimy
46        //ciekawostka: kiedy nie byl static, czasy wykonania bogatego w konwersje kawa³ka kodu oscylowa³y w trybie debug
47        //(5.5s lub 55s) a w release zawsze 57s. Po uzyciu static czas tego samego kodu jest zawsze debug: 0.72s release: 0.33s
48        oss.clear(); //clear error flag
49        oss.str(""); //set empty string
50        oss << value;
51        return oss.str();
52        */
53}
54
55string Convert::toString(unsigned int v) { return _toString(v); }
56string Convert::toString(int v) { return _toString(v); }
57string Convert::toString(short v) { return _toString(v); }
58string Convert::toString(float v) { return _toString(v); }
59string Convert::toString(double v) { return _toString(v); }
60
61uint32_t Convert::hexToInt(const string& col)
62{
63        uint32_t value;
64        std::istringstream iss(col);
65        iss >> std::hex >> value;
66        return value;
67}
68
69#ifdef MULTITHREADED
70//jezeli jest tu a nie jako static w funkcji, to inicjalizacja
71//nastapi na samym poczatku (w nieprzewidywalnym momencie, ale nie szkodzi(?))
72//gdyby byla w funkcji to teoretycznie dwa watki moglyby wejsc
73//do niej rownoczesnie i zaczac inicjalizacje po czym jeden korzystalby
74//z mutexa gdy drugi dalej by go inicjalizowal
75#if ! ((defined LINUX) || (defined _WIN32 && !defined __BORLANDC__ ))
76// only for the "borland?" cases in localtime() and asctime() below
77#include "threads.h"
78static pthread_mutex_t fix_unsafe_mutex = PTHREAD_MUTEX_INITIALIZER;
79#endif
80#endif
81
82struct tm Convert::localtime(const time_t &timep)
83{
84#ifndef MULTITHREADED
85
86        return *::localtime(&timep);
87
88#else
89
90        struct tm ret;
91#if defined LINUX // || android?
92        return *::localtime_r(&timep, &ret);
93#elif defined _WIN32 && !defined __BORLANDC__
94        ::localtime_s(&ret, &timep);
95        return ret;
96#else //borland?
97        pthread_mutex_lock(&fix_unsafe_mutex);
98        ret = *::localtime(&timep);
99        pthread_mutex_unlock(&fix_unsafe_mutex);
100        return ret;
101#endif
102
103#endif
104}
105
106string Convert::asctime(const struct tm &tm)
107{
108        char *ret;
109#ifndef MULTITHREADED
110
111        ret = ::asctime(&tm);
112
113#else //MULTITHREADED
114
115        char buf[26];
116#if defined LINUX // || android?
117        ret = ::asctime_r(&tm, buf);
118#elif defined _WIN32 && !defined __BORLANDC__
119        asctime_s(buf, sizeof(buf), &tm);
120        ret = buf;
121#else //borland?
122        pthread_mutex_lock(&fix_unsafe_mutex);
123        strcpy(buf, ::asctime(&tm));
124        ret = buf;
125        pthread_mutex_unlock(&fix_unsafe_mutex);
126#endif
127#endif
128
129        return string(ret, 24); //24 znaki z pominieciem ostatniego \n
130}
131
132string Convert::wstrToUtf8(const wchar_t *str)
133{
134        if (str == NULL) return "";
135        string res;
136        wchar_t *wcp = (wchar_t*)str;
137        while (*wcp != 0)
138        {
139                int c = *wcp;
140                if (c < 0x80) res += c;
141                else if (c < 0x800) { res += 192 + c / 64; res += 128 + c % 64; }
142                else if (c - 0xd800u < 0x800) res += "<ERROR-CHAR>";
143                else if (c < 0x10000) { res += 224 + c / 4096; res += 128 + c / 64 % 64; res += 128 + c % 64; }
144                else if (c < 0x110000) { res += 240 + c / 262144; res += 128 + c / 4096 % 64; res += 128 + c / 64 % 64; res += 128 + c % 64; }
145                else res += "<ERROR-CHAR>";
146                wcp++;
147        }
148        return res;
149}
150
151#ifdef _WIN32
152wstring Convert::utf8ToUtf16(const char *str)
153{
154        wstring wstr;
155        int nOffset = 0;
156        int nDataLen = strlen(str); //ending \0 is not converted, but resize() below sets the proper length of wstr
157        int nLenWide = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)(str + nOffset),
158                (int)(nDataLen - nOffset), NULL, 0);
159        wstr.resize(nLenWide);
160        if (MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)(str + nOffset),
161                (int)(nDataLen - nOffset),
162                &wstr[0], nLenWide) != nLenWide)
163        {
164                //ASSERT(false); //some conversion error
165                return wstr + L"<UTF8_CONV_ERROR>";
166        }
167        return wstr;
168}
169#endif
Note: See TracBrowser for help on using the repository browser.