source: cpp/common/Convert.cpp @ 1341

Last change on this file since 1341 was 1339, checked in by Maciej Komosinski, 4 days ago

Added two helper conversion functions: toDouble(), toUInt()

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