source: cpp/common/Convert.cpp @ 281

Last change on this file since 281 was 281, checked in by Maciej Komosinski, 10 years ago

Support for wide char (unicode) names of files and directories under Windows, internally encoded as char* utf-8

  • Property svn:eol-style set to native
File size: 4.9 KB
Line 
1// This file is a part of the Framsticks GDK.
2// Copyright (C) 1999-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#include "Convert.h"
6
7#include <sstream>
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#include "threads.h"
77static pthread_mutex_t fix_unsafe_mutex = PTHREAD_MUTEX_INITIALIZER;
78#endif
79
80struct tm Convert::localtime(const time_t &timep)
81{
82#ifndef MULTITHREADED
83
84        return *::localtime(&timep);
85
86#else
87
88        struct tm ret;
89
90#if defined LINUX // || android?
91        return *::localtime_r(&timep,&ret);
92#elif defined _WIN32 && !defined __BORLANDC__
93        ::localtime_s(&ret, &timep);
94        return ret;
95#else //borland?
96        pthread_mutex_lock(&fix_unsafe_mutex);
97        ret=*::localtime(&timep);
98        pthread_mutex_unlock(&fix_unsafe_mutex);
99        return ret;
100#endif
101
102#endif
103}
104
105string Convert::asctime(const struct tm &tm)
106{
107        char *ret;
108#ifndef MULTITHREADED
109
110        ret=::asctime(&tm);
111
112#else //MULTITHREADED
113
114        char buf[26];
115#if defined LINUX // || android?
116        ret=::asctime_r(&tm,buf);
117#elif defined _WIN32 && !defined __BORLANDC__
118        asctime_s(buf, sizeof(buf), &tm);
119        ret = buf;
120#else //borland?
121        pthread_mutex_lock(&fix_unsafe_mutex);
122        strcpy(buf,::asctime(&tm));
123        ret=buf;
124        pthread_mutex_unlock(&fix_unsafe_mutex);
125#endif
126#endif
127
128        return string(ret, 24); //24 znaki z pominieciem ostatniego \n
129}
130
131string Convert::wstrToUtf8(const wchar_t *str)
132{
133        if (str == NULL) return "";
134        string res;
135        wchar_t *wcp = (wchar_t*)str;
136        while (*wcp != 0)
137        {
138                int c = *wcp;
139                if (c < 0x80) res += c;
140                else if (c < 0x800) { res += 192 + c / 64; res += 128 + c % 64; }
141                else if (c - 0xd800u < 0x800) res += "<ERROR-CHAR>";
142                else if (c < 0x10000) { res += 224 + c / 4096; res += 128 + c / 64 % 64; res += 128 + c % 64; }
143                else if (c < 0x110000) { res += 240 + c / 262144; res += 128 + c / 4096 % 64; res += 128 + c / 64 % 64; res += 128 + c % 64; }
144                else res += "<ERROR-CHAR>";
145                wcp++;
146        }
147        return res;
148}
149
150#ifdef _WIN32
151wstring Convert::utf8ToUtf16(const char *str)
152{
153        wstring wstr;
154        int nOffset = 0;
155        int nDataLen = strlen(str) + 1; //including ending \0
156        int nLenWide = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)(str + nOffset),
157                (int)(nDataLen - nOffset), NULL, 0);
158        wstr.resize(nLenWide);
159        if (MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)(str + nOffset),
160                (int)(nDataLen - nOffset),
161                &wstr[0], nLenWide) != nLenWide)
162        {
163                //ASSERT(false); //some conversion error
164                return wstr;
165        }
166        return wstr;
167}
168#endif
Note: See TracBrowser for help on using the repository browser.