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

Last change on this file since 523 was 523, checked in by Maciej Komosinski, 8 years ago

No more overloading of fopen/fclose/... functions for the VirtFILE class. #define VIRTFILE_OVERLOADING to enable overloading only when necessary.

  • Property svn:eol-style set to native
File size: 4.7 KB
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
[196]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"
[375]11#include "log.h"
[220]12#include <assert.h>
[247]13#ifdef USE_VIRTFILE
[382]14#include <common/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
[319]23        int 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
[523]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        }
[523]91//      else
[247]92#endif
93        {
[257]94                MFILE *f = mfopen(filename, FOPEN_READ_BINARY);
95                if (f)
96                {
97                        int size = getFileSize(f);
98                        data.resize(size);
99                        int przeczytane = mfread(&data[0], size, 1, f);
100                        mfclose(f);
101                        ok = przeczytane == 1;
102                }
[180]103        }
104        if (warn_on_missing_file && !ok)
[375]105                logPrintf("stl-util", "readCompleteFile", LOG_WARN, "Couldn't open file '%s'", filename);
[180]106        return ok;
107}
108
109bool readCompleteFile(const char* filename, string& out, bool warn_on_missing_file)
110{
[246]111        vector<char> data;
112        if (readCompleteFile(filename, data, warn_on_missing_file))
[180]113        {
[246]114                out = string(&data[0], data.size());
[180]115                return true;
116        }
117        return false;
118}
119
120bool writeCompleteFile(const char* filename, const string& text, bool warn_on_fail)
121{
[523]122#ifdef USE_VIRTFILE
123        VirtFILE *f = Vfopen(filename, FOPEN_WRITE_BINARY);
124        bool ok = f != NULL;
125        if (f)
126        {
127                int zapisane = f->Vwrite(text.c_str(), text.length(), 1);
128                delete f;
129                ok &= zapisane == 1;
130        }
131#else
[246]132        MFILE *f = mfopen(filename, FOPEN_WRITE_BINARY);
133        bool ok = f != NULL;
[180]134        if (f)
135        {
[246]136                int zapisane = mfwrite(text.c_str(), text.length(), 1, f);
[180]137                mfclose(f);
[246]138                ok &= zapisane == 1;
[180]139        }
[523]140#endif
[180]141        if (warn_on_fail && !ok)
[523]142                logPrintf("stl-util", "writeCompleteFile", LOG_WARN, "Couldn't write file '%s'", filename);
[180]143        return ok;
144}
145
146bool writeCompleteFile(const char* filename, vector<char>& data, bool warn_on_fail)
147{
[246]148        string s(&data[0], data.size());
[180]149        return writeCompleteFile(filename, s, warn_on_fail);
150}
151
152
153
[246]154string stripExt(const string& filename)
[180]155{
[319]156        size_t dot = filename.rfind('.');
[246]157        if (dot == string::npos) return filename;
[319]158        size_t sep = filename.rfind(PATH_SEPARATOR_CHAR);
[246]159        if ((sep == string::npos) || (sep < dot))
160                return filename.substr(0, dot);
[180]161        return filename;
162}
163
[460]164string stripFileDir(const string& filename)
165{
166        size_t sep = filename.rfind(PATH_SEPARATOR_CHAR);
167        if (sep == string::npos) return filename;
168        return filename.substr(sep+1);
169}
170
[246]171string getFileExt(const string& filename)
[180]172{
[319]173        size_t dot = filename.rfind('.');
[246]174        if (dot == string::npos) return string("");
[319]175        size_t sep = filename.rfind(PATH_SEPARATOR_CHAR);
[246]176        if ((sep == string::npos) || (sep < dot))
[180]177                return filename.substr(dot);
178        return string("");
179}
[246]180
181string getFileDir(const string& filename)
182{
[319]183        size_t slash = filename.rfind(PATH_SEPARATOR_CHAR);
[246]184        if (slash == string::npos) return string("");
185        return filename.substr(0, slash);
186}
Note: See TracBrowser for help on using the repository browser.