solvespace/src/platform/unixutil.cpp
whitequark d12bf047b4 Update 58db06d8 to not even try to use std::fstream with Unicode paths.
Unfortunately there is no portable way to open an Unicode path with
std::fstream. On *nix, it is enough to call the const char*
constructor. On MSVC, it is enough to call a nonstandard
const wchar_t* constructor. However, on MinGW, there is no way at all
to construct an std::fstream with a wide path, not even using
undocumented APIs. (There used to be a const wchar_t* overload added
back in libstdc++ 4.7, but it got removed for a reason that I was not
able to find out.)
2016-10-09 20:00:02 +00:00

158 lines
4.0 KiB
C++

//-----------------------------------------------------------------------------
// Utility functions used by the Unix port. Notably, our memory allocation;
// we use two separate allocators, one for long-lived stuff and one for
// stuff that gets freed after every regeneration of the model, to save us
// the trouble of freeing the latter explicitly.
//
// Copyright 2008-2013 Jonathan Westhues.
// Copyright 2013 Daniel Richard G. <skunk@iSKUNK.ORG>
//-----------------------------------------------------------------------------
#include <time.h>
#include <execinfo.h>
#ifdef __APPLE__
# include <strings.h> // for strcasecmp
#endif
#include "solvespace.h"
namespace SolveSpace {
void dbp(const char *str, ...)
{
va_list f;
static char buf[1024*50];
va_start(f, str);
vsnprintf(buf, sizeof(buf), str, f);
va_end(f);
fputs(buf, stderr);
fputc('\n', stderr);
}
void assert_failure(const char *file, unsigned line, const char *function,
const char *condition, const char *message) {
fprintf(stderr, "File %s, line %u, function %s:\n", file, line, function);
fprintf(stderr, "Assertion '%s' failed: ((%s) == false).\n", message, condition);
#ifndef LIBRARY
static void *ptrs[1024] = {};
size_t nptrs = backtrace(ptrs, sizeof(ptrs) / sizeof(ptrs[0]));
char **syms = backtrace_symbols(ptrs, nptrs);
fprintf(stderr, "Backtrace:\n");
if(syms != NULL) {
for(size_t i = 0; i < nptrs; i++) {
fprintf(stderr, "%2zu: %s\n", i, syms[i]);
}
} else {
for(size_t i = 0; i < nptrs; i++) {
fprintf(stderr, "%2zu: %p\n", i, ptrs[i]);
}
}
#endif
abort();
}
bool PathEqual(const std::string &a, const std::string &b)
{
#if defined(__APPLE__)
// Case-sensitivity is actually per-volume on OS X,
// but it is tedious to implement and test for little benefit.
return !strcasecmp(a.c_str(), b.c_str());
#else
return a == b;
#endif
}
std::string PathSepPlatformToUnix(const std::string &filename)
{
return filename;
}
std::string PathSepUnixToPlatform(const std::string &filename)
{
return filename;
}
FILE *ssfopen(const std::string &filename, const char *mode)
{
ssassert(filename.length() == strlen(filename.c_str()),
"Unexpected null byte in middle of a path");
return fopen(filename.c_str(), mode);
}
void ssremove(const std::string &filename)
{
ssassert(filename.length() == strlen(filename.c_str()),
"Unexpected null byte in middle of a path");
remove(filename.c_str());
}
//-----------------------------------------------------------------------------
// A separate heap, on which we allocate expressions. Maybe a bit faster,
// since fragmentation is less of a concern, and it also makes it possible
// to be sloppy with our memory management, and just free everything at once
// at the end.
//-----------------------------------------------------------------------------
typedef struct _AllocTempHeader AllocTempHeader;
typedef struct _AllocTempHeader {
AllocTempHeader *prev;
AllocTempHeader *next;
} AllocTempHeader;
static AllocTempHeader *Head = NULL;
void *AllocTemporary(size_t n)
{
AllocTempHeader *h =
(AllocTempHeader *)malloc(n + sizeof(AllocTempHeader));
h->prev = NULL;
h->next = Head;
if(Head) Head->prev = h;
Head = h;
memset(&h[1], 0, n);
return (void *)&h[1];
}
void FreeTemporary(void *p)
{
AllocTempHeader *h = (AllocTempHeader *)p - 1;
if(h->prev) {
h->prev->next = h->next;
} else {
Head = h->next;
}
if(h->next) h->next->prev = h->prev;
free(h);
}
void FreeAllTemporary(void)
{
AllocTempHeader *h = Head;
while(h) {
AllocTempHeader *f = h;
h = h->next;
free(f);
}
Head = NULL;
}
void *MemAlloc(size_t n) {
void *p = malloc(n);
ssassert(p != NULL, "Cannot allocate memory");
return p;
}
void MemFree(void *p) {
free(p);
}
void InitHeaps(void) {
/* nothing to do */
}
};