source: cpp/common/stl-util.cpp @ 282

Last change on this file since 282 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.6 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 "stl-util.h"
6#include <stdarg.h>
7#include <stdlib.h>
8#include "nonstd_stdio.h"
9#include "Convert.h"
10#include "nonstd.h"
11#include "framsg.h"
12#include <assert.h>
13#ifdef USE_VIRTFILE
14#include <frams/virtfile/virtfile.h>
15#endif
16#ifdef __BORLANDC__
17#define va_copy(to,from) to=from //borland does not have va_copy() at all; va_list is just a pointer in borland
18#endif
19
20string ssprintf_va(const char* format, va_list ap)
21{
22        string s; //clang crashed when this declaration was in s=buf
23        long size = 256;
24        char* buf;
25        va_list ap_copy; // "va_list ap" can only by used once by printf-type functions as they advance the current argument pointer (crashed on linux x86_64)
26        // (does not apply to SString::sprintf, it does not have the va_list variant)
27
28        //almost like SString::sprintf, but there is no common code to share because SString can use its directWrite to avoid double allocating/copying
29#ifdef USE_VSCPRINTF
30        va_copy(ap_copy, ap);
31        size = _vscprintf(format, ap_copy) + 1; //+1 for terminating null character
32        va_end(ap_copy);
33#endif
34
35        while (1)
36        {
37                buf = (char*)malloc(size);
38                assert(buf != NULL);
39                va_copy(ap_copy, ap);
40                int n = vsnprintf(buf, size, format, ap_copy);
41                va_end(ap_copy);
42                if (n > -1 && n < size)
43                {
44                        s = buf;
45                        free(buf);
46                        return s;
47                }
48#ifdef VSNPRINTF_RETURNS_REQUIRED_SIZE
49                if (n > -1)    /* glibc 2.1 */
50                        size = n+1; /* precisely what is needed */
51                else           /* glibc 2.0 */
52#endif
53                        size *= 2;  /* twice the old size */
54                free(buf);
55        }
56}
57
58char* strmove(char *a, char *b) //strcpy that works well for overlapping strings ("Source and destination overlap")
59{
60        if (a == NULL || b == NULL)
61                return NULL;
62        memmove(a, b, strlen(b) + 1);
63        return a;
64}
65
66string ssprintf(const char* format, ...)
67{
68        va_list ap;
69        va_start(ap, format);
70        string ret = ssprintf_va(format, ap); //is it too wasteful? copying the string again... unless the compiler can handle it better
71        va_end(ap);
72        return ret;
73}
74
75bool readCompleteFile(const char* filename, vector<char>& data, bool warn_on_missing_file)
76{
77        bool ok = false;
78#ifdef USE_VIRTFILE
79        if (!isAbsolutePath(filename))
80        {
81                VirtFILE *f=Vfopen(filename,FOPEN_READ_BINARY);
82                if (f)
83                {
84                        int size=f->getSize();
85                        data.resize(size);
86                        int przeczytane = f->Vread(&data[0], size, 1);
87                        ok = przeczytane == 1;
88                        delete f;
89                }
90        }
91        else
92#endif
93        {
94#ifdef _WIN32
95                MFILE *f = mfopen(Convert::utf8ToUtf16(filename).c_str(), Convert::strTOwstr(FOPEN_READ_BINARY).c_str());
96#else
97                MFILE *f = mfopen(filename, FOPEN_READ_BINARY);
98#endif
99                if (f)
100                {
101                        int size = getFileSize(f);
102                        data.resize(size);
103                        int przeczytane = mfread(&data[0], size, 1, f);
104                        mfclose(f);
105                        ok = przeczytane == 1;
106                }
107        }
108        if (warn_on_missing_file && !ok)
109                FMprintf("stl-util", "readCompleteFile", FMLV_WARN, "Couldn't open file '%s'", filename);
110        return ok;
111}
112
113bool readCompleteFile(const char* filename, string& out, bool warn_on_missing_file)
114{
115        vector<char> data;
116        if (readCompleteFile(filename, data, warn_on_missing_file))
117        {
118                out = string(&data[0], data.size());
119                return true;
120        }
121        return false;
122}
123
124bool writeCompleteFile(const char* filename, const string& text, bool warn_on_fail)
125{
126#ifdef _WIN32
127        MFILE *f = mfopen(Convert::utf8ToUtf16(filename).c_str(), Convert::strTOwstr(FOPEN_WRITE_BINARY).c_str());
128#else
129        MFILE *f = mfopen(filename, FOPEN_WRITE_BINARY);
130#endif
131        bool ok = f != NULL;
132        if (f)
133        {
134                int zapisane = mfwrite(text.c_str(), text.length(), 1, f);
135                mfclose(f);
136                ok &= zapisane == 1;
137        }
138        if (warn_on_fail && !ok)
139                FMprintf("stl-util", "writeCompleteFile", FMLV_WARN, "couldn't write file '%s'", filename);
140        return ok;
141}
142
143bool writeCompleteFile(const char* filename, vector<char>& data, bool warn_on_fail)
144{
145        string s(&data[0], data.size());
146        return writeCompleteFile(filename, s, warn_on_fail);
147}
148
149
150
151string stripExt(const string& filename)
152{
153        int dot = filename.rfind('.');
154        if (dot == string::npos) return filename;
155        int sep = filename.rfind(PATH_SEPARATOR_CHAR);
156        if ((sep == string::npos) || (sep < dot))
157                return filename.substr(0, dot);
158        return filename;
159}
160
161string getFileExt(const string& filename)
162{
163        int dot = filename.rfind('.');
164        if (dot == string::npos) return string("");
165        int sep = filename.rfind(PATH_SEPARATOR_CHAR);
166        if ((sep == string::npos) || (sep < dot))
167                return filename.substr(dot);
168        return string("");
169}
170
171string getFileDir(const string& filename)
172{
173        int slash = filename.rfind(PATH_SEPARATOR_CHAR);
174        if (slash == string::npos) return string("");
175        return filename.substr(0, slash);
176}
Note: See TracBrowser for help on using the repository browser.