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

Last change on this file since 837 was 837, checked in by Maciej Komosinski, 5 years ago

Now C++Builder supports va_copy(to,from)

  • Property svn:eol-style set to native
File size: 4.5 KB
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
[837]2// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
[286]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
[180]16
[837]17
[180]18string ssprintf_va(const char* format, va_list ap)
19{
[220]20        string s; //clang crashed when this declaration was in s=buf
[319]21        int size = 256;
[180]22        char* buf;
[247]23        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)
24        // (does not apply to SString::sprintf, it does not have the va_list variant)
[220]25
26        //almost like SString::sprintf, but there is no common code to share because SString can use its directWrite to avoid double allocating/copying
27#ifdef USE_VSCPRINTF
[257]28        va_copy(ap_copy, ap);
[247]29        size = _vscprintf(format, ap_copy) + 1; //+1 for terminating null character
30        va_end(ap_copy);
[220]31#endif
32
[246]33        while (1)
34        {
35                buf = (char*)malloc(size);
36                assert(buf != NULL);
[257]37                va_copy(ap_copy, ap);
[247]38                int n = vsnprintf(buf, size, format, ap_copy);
39                va_end(ap_copy);
[246]40                if (n > -1 && n < size)
[220]41                {
[246]42                        s = buf;
[220]43                        free(buf);
44                        return s;
[246]45                }
[220]46#ifdef VSNPRINTF_RETURNS_REQUIRED_SIZE
47                if (n > -1)    /* glibc 2.1 */
48                        size = n+1; /* precisely what is needed */
49                else           /* glibc 2.0 */
50#endif
51                        size *= 2;  /* twice the old size */
52                free(buf);
[246]53        }
[180]54}
55
[257]56char* strmove(char *a, char *b) //strcpy that works well for overlapping strings ("Source and destination overlap")
57{
58        if (a == NULL || b == NULL)
59                return NULL;
60        memmove(a, b, strlen(b) + 1);
61        return a;
62}
63
[180]64string ssprintf(const char* format, ...)
65{
66        va_list ap;
67        va_start(ap, format);
[246]68        string ret = ssprintf_va(format, ap); //is it too wasteful? copying the string again... unless the compiler can handle it better
[180]69        va_end(ap);
70        return ret;
71}
72
73bool readCompleteFile(const char* filename, vector<char>& data, bool warn_on_missing_file)
74{
[257]75        bool ok = false;
[247]76#ifdef USE_VIRTFILE
[523]77//      if (!isAbsolutePath(filename))
[257]78        {
[247]79                VirtFILE *f=Vfopen(filename,FOPEN_READ_BINARY);
80                if (f)
[257]81                {
[247]82                        int size=f->getSize();
83                        data.resize(size);
84                        int przeczytane = f->Vread(&data[0], size, 1);
85                        ok = przeczytane == 1;
86                        delete f;
87                }
[257]88        }
[523]89//      else
[247]90#endif
91        {
[257]92                MFILE *f = mfopen(filename, FOPEN_READ_BINARY);
93                if (f)
94                {
95                        int size = getFileSize(f);
96                        data.resize(size);
97                        int przeczytane = mfread(&data[0], size, 1, f);
98                        mfclose(f);
99                        ok = przeczytane == 1;
100                }
[180]101        }
102        if (warn_on_missing_file && !ok)
[375]103                logPrintf("stl-util", "readCompleteFile", LOG_WARN, "Couldn't open file '%s'", filename);
[180]104        return ok;
105}
106
107bool readCompleteFile(const char* filename, string& out, bool warn_on_missing_file)
108{
[246]109        vector<char> data;
110        if (readCompleteFile(filename, data, warn_on_missing_file))
[180]111        {
[246]112                out = string(&data[0], data.size());
[180]113                return true;
114        }
115        return false;
116}
117
118bool writeCompleteFile(const char* filename, const string& text, bool warn_on_fail)
119{
[523]120#ifdef USE_VIRTFILE
121        VirtFILE *f = Vfopen(filename, FOPEN_WRITE_BINARY);
122        bool ok = f != NULL;
123        if (f)
124        {
125                int zapisane = f->Vwrite(text.c_str(), text.length(), 1);
126                delete f;
127                ok &= zapisane == 1;
128        }
129#else
[246]130        MFILE *f = mfopen(filename, FOPEN_WRITE_BINARY);
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        }
[523]138#endif
[180]139        if (warn_on_fail && !ok)
[523]140                logPrintf("stl-util", "writeCompleteFile", LOG_WARN, "Couldn't write file '%s'", filename);
[180]141        return ok;
142}
143
144bool writeCompleteFile(const char* filename, vector<char>& data, bool warn_on_fail)
145{
[246]146        string s(&data[0], data.size());
[180]147        return writeCompleteFile(filename, s, warn_on_fail);
148}
149
150
151
[246]152string stripExt(const string& filename)
[180]153{
[319]154        size_t dot = filename.rfind('.');
[246]155        if (dot == string::npos) return filename;
[319]156        size_t sep = filename.rfind(PATH_SEPARATOR_CHAR);
[246]157        if ((sep == string::npos) || (sep < dot))
158                return filename.substr(0, dot);
[180]159        return filename;
160}
161
[460]162string stripFileDir(const string& filename)
163{
164        size_t sep = filename.rfind(PATH_SEPARATOR_CHAR);
165        if (sep == string::npos) return filename;
166        return filename.substr(sep+1);
167}
168
[246]169string getFileExt(const string& filename)
[180]170{
[319]171        size_t dot = filename.rfind('.');
[246]172        if (dot == string::npos) return string("");
[319]173        size_t sep = filename.rfind(PATH_SEPARATOR_CHAR);
[246]174        if ((sep == string::npos) || (sep < dot))
[180]175                return filename.substr(dot);
176        return string("");
177}
[246]178
179string getFileDir(const string& filename)
180{
[319]181        size_t slash = filename.rfind(PATH_SEPARATOR_CHAR);
[246]182        if (slash == string::npos) return string("");
183        return filename.substr(0, slash);
184}
[837]185
Note: See TracBrowser for help on using the repository browser.