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

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