source: cpp/common/Convert.cpp @ 1203

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

Used std::min(), std::max() explicitly to avoid compiler confusion. Used std::size() explicitly instead of the equivalent macro

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