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

Last change on this file since 284 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
RevLine 
[196]1// This file is a part of the Framsticks GDK.
[197]2// Copyright (C) 1999-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
[196]3// Refer to http://www.framsticks.com/ for further information.
4
[180]5#include "stl-util.h"
6#include <stdarg.h>
7#include <stdlib.h>
8#include "nonstd_stdio.h"
[281]9#include "Convert.h"
[180]10#include "nonstd.h"
11#include "framsg.h"
[220]12#include <assert.h>
[247]13#ifdef USE_VIRTFILE
[257]14#include <frams/virtfile/virtfile.h>
[247]15#endif
16#ifdef __BORLANDC__
[257]17#define va_copy(to,from) to=from //borland does not have va_copy() at all; va_list is just a pointer in borland
[247]18#endif
[180]19
20string ssprintf_va(const char* format, va_list ap)
21{
[220]22        string s; //clang crashed when this declaration was in s=buf
[246]23        long size = 256;
[180]24        char* buf;
[247]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)
[220]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
[257]30        va_copy(ap_copy, ap);
[247]31        size = _vscprintf(format, ap_copy) + 1; //+1 for terminating null character
32        va_end(ap_copy);
[220]33#endif
34
[246]35        while (1)
36        {
37                buf = (char*)malloc(size);
38                assert(buf != NULL);
[257]39                va_copy(ap_copy, ap);
[247]40                int n = vsnprintf(buf, size, format, ap_copy);
41                va_end(ap_copy);
[246]42                if (n > -1 && n < size)
[220]43                {
[246]44                        s = buf;
[220]45                        free(buf);
46                        return s;
[246]47                }
[220]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);
[246]55        }
[180]56}
57
[257]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
[180]66string ssprintf(const char* format, ...)
67{
68        va_list ap;
69        va_start(ap, format);
[246]70        string ret = ssprintf_va(format, ap); //is it too wasteful? copying the string again... unless the compiler can handle it better
[180]71        va_end(ap);
72        return ret;
73}
74
75bool readCompleteFile(const char* filename, vector<char>& data, bool warn_on_missing_file)
76{
[257]77        bool ok = false;
[247]78#ifdef USE_VIRTFILE
79        if (!isAbsolutePath(filename))
[257]80        {
[247]81                VirtFILE *f=Vfopen(filename,FOPEN_READ_BINARY);
82                if (f)
[257]83                {
[247]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                }
[257]90        }
[247]91        else
92#endif
93        {
[281]94#ifdef _WIN32
95                MFILE *f = mfopen(Convert::utf8ToUtf16(filename).c_str(), Convert::strTOwstr(FOPEN_READ_BINARY).c_str());
96#else
[257]97                MFILE *f = mfopen(filename, FOPEN_READ_BINARY);
[281]98#endif
[257]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                }
[180]107        }
108        if (warn_on_missing_file && !ok)
[246]109                FMprintf("stl-util", "readCompleteFile", FMLV_WARN, "Couldn't open file '%s'", filename);
[180]110        return ok;
111}
112
113bool readCompleteFile(const char* filename, string& out, bool warn_on_missing_file)
114{
[246]115        vector<char> data;
116        if (readCompleteFile(filename, data, warn_on_missing_file))
[180]117        {
[246]118                out = string(&data[0], data.size());
[180]119                return true;
120        }
121        return false;
122}
123
124bool writeCompleteFile(const char* filename, const string& text, bool warn_on_fail)
125{
[281]126#ifdef _WIN32
127        MFILE *f = mfopen(Convert::utf8ToUtf16(filename).c_str(), Convert::strTOwstr(FOPEN_WRITE_BINARY).c_str());
128#else
[246]129        MFILE *f = mfopen(filename, FOPEN_WRITE_BINARY);
[281]130#endif
[246]131        bool ok = f != NULL;
[180]132        if (f)
133        {
[246]134                int zapisane = mfwrite(text.c_str(), text.length(), 1, f);
[180]135                mfclose(f);
[246]136                ok &= zapisane == 1;
[180]137        }
138        if (warn_on_fail && !ok)
[246]139                FMprintf("stl-util", "writeCompleteFile", FMLV_WARN, "couldn't write file '%s'", filename);
[180]140        return ok;
141}
142
143bool writeCompleteFile(const char* filename, vector<char>& data, bool warn_on_fail)
144{
[246]145        string s(&data[0], data.size());
[180]146        return writeCompleteFile(filename, s, warn_on_fail);
147}
148
149
150
[246]151string stripExt(const string& filename)
[180]152{
[246]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);
[180]158        return filename;
159}
160
[246]161string getFileExt(const string& filename)
[180]162{
[246]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))
[180]167                return filename.substr(dot);
168        return string("");
169}
[246]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.