2013-10-28 13:28:42 +08:00
|
|
|
//-----------------------------------------------------------------------------
|
2015-03-17 23:09:59 +08:00
|
|
|
// Utility functions used by the Unix port. Notably, our memory allocation;
|
2013-10-28 13:28:42 +08:00
|
|
|
// 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>
|
|
|
|
//-----------------------------------------------------------------------------
|
Use the same code for loading resources in all executables.
All of our executables need resources; e.g. the vector font is
a resource and it is necessary for generation. Before this commit,
the GUI executable loaded the resources in a nice way, and everything
else did it in a very ad-hoc, fragile way.
After this commit, all executables are placed in <build>/bin and
follow the same algorithm:
* On Windows, resources are compiled and linked into every
executable.
* On Linux, resources are copied into <build>/res (which is
tried first) and <prefix>/share/solvespace (which is tried
second).
* On macOS, resources are copied into <build>/res (which is
tried first) and <build>/bin/solvespace.app/Contents/Resources
(which is tried second).
In practice this means that we can add as many executables as we want
without duplicating lots of code. In addition, on macOS, we can
place supplementary executables into the bundle, and they can use
resources from the bundle transparently.
2016-11-28 12:16:18 +08:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/stat.h>
|
2016-05-19 03:38:17 +08:00
|
|
|
#include <execinfo.h>
|
Abstract all (ex-OpenGL) drawing operations into a Canvas interface.
This has several desirable consequences:
* It is now possible to port SolveSpace to a later version of
OpenGL, such as OpenGLES 2, so that it runs on platforms that
only have that OpenGL version;
* The majority of geometry is now rendered without references to
the camera in C++ code, so a renderer can now submit it to
the video card once and re-rasterize with a different projection
matrix every time the projection is changed, avoiding expensive
reuploads;
* The DOGD (draw or get distance) interface is now
a straightforward Canvas implementation;
* There are no more direct references to SS.GW.(projection)
in sketch rendering code, which allows rendering to multiple
viewports;
* There are no more unnecessary framebuffer flips on CPU on Cocoa
and GTK;
* The platform-dependent GL code is now confined to rendergl1.cpp.
* The Microsoft and Apple headers required by it that are prone to
identifier conflicts are no longer included globally;
* The rendergl1.cpp implementation can now be omitted from
compilation to run SolveSpace headless or with a different
OpenGL version.
Note these implementation details of Canvas:
* GetCamera currently always returns a reference to the field
`Camera camera;`. This is so that a future renderer that caches
geometry in the video memory can define it as asserting, which
would provide assurance against code that could accidentally
put something projection-dependent in the cache;
* Line and triangle rendering is specified through a level of
indirection, hStroke and hFill. This is so that a future renderer
that batches geometry could cheaply group identical styles.
* DrawPixmap and DrawVectorText accept a (o,u,v) and not a matrix.
This is so that a future renderer into an output format that
uses 2d transforms (e.g. SVG) could easily derive those.
Some additional internal changes were required to enable this:
* Pixmap is now always passed as std::shared_ptr<{const ,}Pixmap>.
This is so that the renderer could cache uploaded textures
between API calls, which requires it to capture a (weak)
reference.
* The PlatformPathEqual function was properly extracted into
platform-specific code. This is so that the <windows.h> header
could be included only where needed (in platform/w32* as well
as rendergl1.cpp).
* The SBsp{2,3}::DebugDraw functions were removed. They can be
rewritten using the Canvas API if they are ever needed.
While no visual changes were originally intended, some minor fixes
happened anyway:
* The "emphasis" yellow line from top-left corner is now correctly
rendered much wider.
* The marquee rectangle is now pixel grid aligned.
* The hidden entities now do not clobber the depth buffer, removing
some minor artifacts.
* The workplane "tab" now scales with the font used to render
the workplane name.
* The workplane name font is now taken from the normals style.
* Workplane and constraint line stipple is insignificantly
different. This is so that it can reuse the existing stipple
codepaths; rendering of workplanes and constraints predates
those.
Some debug functionality was added:
* In graphics window, an fps counter that becomes red when
rendering under 60fps is drawn.
2016-05-31 08:55:13 +08:00
|
|
|
#ifdef __APPLE__
|
|
|
|
# include <strings.h> // for strcasecmp
|
Use the same code for loading resources in all executables.
All of our executables need resources; e.g. the vector font is
a resource and it is necessary for generation. Before this commit,
the GUI executable loaded the resources in a nice way, and everything
else did it in a very ad-hoc, fragile way.
After this commit, all executables are placed in <build>/bin and
follow the same algorithm:
* On Windows, resources are compiled and linked into every
executable.
* On Linux, resources are copied into <build>/res (which is
tried first) and <prefix>/share/solvespace (which is tried
second).
* On macOS, resources are copied into <build>/res (which is
tried first) and <build>/bin/solvespace.app/Contents/Resources
(which is tried second).
In practice this means that we can add as many executables as we want
without duplicating lots of code. In addition, on macOS, we can
place supplementary executables into the bundle, and they can use
resources from the bundle transparently.
2016-11-28 12:16:18 +08:00
|
|
|
# include <CoreFoundation/CFString.h>
|
|
|
|
# include <CoreFoundation/CFURL.h>
|
|
|
|
# include <CoreFoundation/CFBundle.h>
|
Abstract all (ex-OpenGL) drawing operations into a Canvas interface.
This has several desirable consequences:
* It is now possible to port SolveSpace to a later version of
OpenGL, such as OpenGLES 2, so that it runs on platforms that
only have that OpenGL version;
* The majority of geometry is now rendered without references to
the camera in C++ code, so a renderer can now submit it to
the video card once and re-rasterize with a different projection
matrix every time the projection is changed, avoiding expensive
reuploads;
* The DOGD (draw or get distance) interface is now
a straightforward Canvas implementation;
* There are no more direct references to SS.GW.(projection)
in sketch rendering code, which allows rendering to multiple
viewports;
* There are no more unnecessary framebuffer flips on CPU on Cocoa
and GTK;
* The platform-dependent GL code is now confined to rendergl1.cpp.
* The Microsoft and Apple headers required by it that are prone to
identifier conflicts are no longer included globally;
* The rendergl1.cpp implementation can now be omitted from
compilation to run SolveSpace headless or with a different
OpenGL version.
Note these implementation details of Canvas:
* GetCamera currently always returns a reference to the field
`Camera camera;`. This is so that a future renderer that caches
geometry in the video memory can define it as asserting, which
would provide assurance against code that could accidentally
put something projection-dependent in the cache;
* Line and triangle rendering is specified through a level of
indirection, hStroke and hFill. This is so that a future renderer
that batches geometry could cheaply group identical styles.
* DrawPixmap and DrawVectorText accept a (o,u,v) and not a matrix.
This is so that a future renderer into an output format that
uses 2d transforms (e.g. SVG) could easily derive those.
Some additional internal changes were required to enable this:
* Pixmap is now always passed as std::shared_ptr<{const ,}Pixmap>.
This is so that the renderer could cache uploaded textures
between API calls, which requires it to capture a (weak)
reference.
* The PlatformPathEqual function was properly extracted into
platform-specific code. This is so that the <windows.h> header
could be included only where needed (in platform/w32* as well
as rendergl1.cpp).
* The SBsp{2,3}::DebugDraw functions were removed. They can be
rewritten using the Canvas API if they are ever needed.
While no visual changes were originally intended, some minor fixes
happened anyway:
* The "emphasis" yellow line from top-left corner is now correctly
rendered much wider.
* The marquee rectangle is now pixel grid aligned.
* The hidden entities now do not clobber the depth buffer, removing
some minor artifacts.
* The workplane "tab" now scales with the font used to render
the workplane name.
* The workplane name font is now taken from the normals style.
* Workplane and constraint line stipple is insignificantly
different. This is so that it can reuse the existing stipple
codepaths; rendering of workplanes and constraints predates
those.
Some debug functionality was added:
* In graphics window, an fps counter that becomes red when
rendering under 60fps is drawn.
2016-05-31 08:55:13 +08:00
|
|
|
#endif
|
2013-10-28 13:28:42 +08:00
|
|
|
|
|
|
|
#include "solvespace.h"
|
Use the same code for loading resources in all executables.
All of our executables need resources; e.g. the vector font is
a resource and it is necessary for generation. Before this commit,
the GUI executable loaded the resources in a nice way, and everything
else did it in a very ad-hoc, fragile way.
After this commit, all executables are placed in <build>/bin and
follow the same algorithm:
* On Windows, resources are compiled and linked into every
executable.
* On Linux, resources are copied into <build>/res (which is
tried first) and <prefix>/share/solvespace (which is tried
second).
* On macOS, resources are copied into <build>/res (which is
tried first) and <build>/bin/solvespace.app/Contents/Resources
(which is tried second).
In practice this means that we can add as many executables as we want
without duplicating lots of code. In addition, on macOS, we can
place supplementary executables into the bundle, and they can use
resources from the bundle transparently.
2016-11-28 12:16:18 +08:00
|
|
|
#include "config.h"
|
2013-10-28 13:28:42 +08:00
|
|
|
|
2015-03-24 01:49:04 +08:00
|
|
|
namespace SolveSpace {
|
|
|
|
|
2013-10-28 13:28:42 +08:00
|
|
|
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);
|
2015-03-18 01:02:04 +08:00
|
|
|
fputc('\n', stderr);
|
2013-10-28 13:28:42 +08:00
|
|
|
}
|
|
|
|
|
2016-05-19 03:38:17 +08:00
|
|
|
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);
|
|
|
|
|
2016-07-19 23:40:52 +08:00
|
|
|
#ifndef LIBRARY
|
2016-05-19 03:38:17 +08:00
|
|
|
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]);
|
|
|
|
}
|
|
|
|
}
|
2016-07-19 23:40:52 +08:00
|
|
|
#endif
|
2016-05-19 03:38:17 +08:00
|
|
|
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
Abstract all (ex-OpenGL) drawing operations into a Canvas interface.
This has several desirable consequences:
* It is now possible to port SolveSpace to a later version of
OpenGL, such as OpenGLES 2, so that it runs on platforms that
only have that OpenGL version;
* The majority of geometry is now rendered without references to
the camera in C++ code, so a renderer can now submit it to
the video card once and re-rasterize with a different projection
matrix every time the projection is changed, avoiding expensive
reuploads;
* The DOGD (draw or get distance) interface is now
a straightforward Canvas implementation;
* There are no more direct references to SS.GW.(projection)
in sketch rendering code, which allows rendering to multiple
viewports;
* There are no more unnecessary framebuffer flips on CPU on Cocoa
and GTK;
* The platform-dependent GL code is now confined to rendergl1.cpp.
* The Microsoft and Apple headers required by it that are prone to
identifier conflicts are no longer included globally;
* The rendergl1.cpp implementation can now be omitted from
compilation to run SolveSpace headless or with a different
OpenGL version.
Note these implementation details of Canvas:
* GetCamera currently always returns a reference to the field
`Camera camera;`. This is so that a future renderer that caches
geometry in the video memory can define it as asserting, which
would provide assurance against code that could accidentally
put something projection-dependent in the cache;
* Line and triangle rendering is specified through a level of
indirection, hStroke and hFill. This is so that a future renderer
that batches geometry could cheaply group identical styles.
* DrawPixmap and DrawVectorText accept a (o,u,v) and not a matrix.
This is so that a future renderer into an output format that
uses 2d transforms (e.g. SVG) could easily derive those.
Some additional internal changes were required to enable this:
* Pixmap is now always passed as std::shared_ptr<{const ,}Pixmap>.
This is so that the renderer could cache uploaded textures
between API calls, which requires it to capture a (weak)
reference.
* The PlatformPathEqual function was properly extracted into
platform-specific code. This is so that the <windows.h> header
could be included only where needed (in platform/w32* as well
as rendergl1.cpp).
* The SBsp{2,3}::DebugDraw functions were removed. They can be
rewritten using the Canvas API if they are ever needed.
While no visual changes were originally intended, some minor fixes
happened anyway:
* The "emphasis" yellow line from top-left corner is now correctly
rendered much wider.
* The marquee rectangle is now pixel grid aligned.
* The hidden entities now do not clobber the depth buffer, removing
some minor artifacts.
* The workplane "tab" now scales with the font used to render
the workplane name.
* The workplane name font is now taken from the normals style.
* Workplane and constraint line stipple is insignificantly
different. This is so that it can reuse the existing stipple
codepaths; rendering of workplanes and constraints predates
those.
Some debug functionality was added:
* In graphics window, an fps counter that becomes red when
rendering under 60fps is drawn.
2016-05-31 08:55:13 +08:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2016-07-26 03:37:48 +08:00
|
|
|
std::string PathSepPlatformToUnix(const std::string &filename)
|
|
|
|
{
|
|
|
|
return filename;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string PathSepUnixToPlatform(const std::string &filename)
|
|
|
|
{
|
|
|
|
return filename;
|
|
|
|
}
|
|
|
|
|
2016-12-05 08:25:31 +08:00
|
|
|
std::string PathFromCurrentDirectory(const std::string &relFilename)
|
|
|
|
{
|
|
|
|
// On Unix we can just pass this to ssfopen directly.
|
|
|
|
return relFilename;
|
|
|
|
}
|
|
|
|
|
2015-12-27 16:09:00 +08:00
|
|
|
FILE *ssfopen(const std::string &filename, const char *mode)
|
|
|
|
{
|
2016-05-19 06:51:36 +08:00
|
|
|
ssassert(filename.length() == strlen(filename.c_str()),
|
|
|
|
"Unexpected null byte in middle of a path");
|
2015-12-27 16:09:00 +08:00
|
|
|
return fopen(filename.c_str(), mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ssremove(const std::string &filename)
|
|
|
|
{
|
2016-05-19 06:51:36 +08:00
|
|
|
ssassert(filename.length() == strlen(filename.c_str()),
|
|
|
|
"Unexpected null byte in middle of a path");
|
2015-12-27 16:09:00 +08:00
|
|
|
remove(filename.c_str());
|
|
|
|
}
|
|
|
|
|
Use the same code for loading resources in all executables.
All of our executables need resources; e.g. the vector font is
a resource and it is necessary for generation. Before this commit,
the GUI executable loaded the resources in a nice way, and everything
else did it in a very ad-hoc, fragile way.
After this commit, all executables are placed in <build>/bin and
follow the same algorithm:
* On Windows, resources are compiled and linked into every
executable.
* On Linux, resources are copied into <build>/res (which is
tried first) and <prefix>/share/solvespace (which is tried
second).
* On macOS, resources are copied into <build>/res (which is
tried first) and <build>/bin/solvespace.app/Contents/Resources
(which is tried second).
In practice this means that we can add as many executables as we want
without duplicating lots of code. In addition, on macOS, we can
place supplementary executables into the bundle, and they can use
resources from the bundle transparently.
2016-11-28 12:16:18 +08:00
|
|
|
static std::string ExpandPath(std::string path) {
|
|
|
|
char *expanded_c_path = realpath(path.c_str(), NULL);
|
2016-11-29 10:57:41 +08:00
|
|
|
if(expanded_c_path == NULL) return "";
|
|
|
|
|
Use the same code for loading resources in all executables.
All of our executables need resources; e.g. the vector font is
a resource and it is necessary for generation. Before this commit,
the GUI executable loaded the resources in a nice way, and everything
else did it in a very ad-hoc, fragile way.
After this commit, all executables are placed in <build>/bin and
follow the same algorithm:
* On Windows, resources are compiled and linked into every
executable.
* On Linux, resources are copied into <build>/res (which is
tried first) and <prefix>/share/solvespace (which is tried
second).
* On macOS, resources are copied into <build>/res (which is
tried first) and <build>/bin/solvespace.app/Contents/Resources
(which is tried second).
In practice this means that we can add as many executables as we want
without duplicating lots of code. In addition, on macOS, we can
place supplementary executables into the bundle, and they can use
resources from the bundle transparently.
2016-11-28 12:16:18 +08:00
|
|
|
std::string expanded_path = expanded_c_path;
|
|
|
|
free(expanded_c_path);
|
|
|
|
return expanded_path;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const std::string &FindLocalResourceDir() {
|
|
|
|
static std::string resourceDir;
|
|
|
|
static bool checked;
|
|
|
|
|
|
|
|
if(checked) return resourceDir;
|
|
|
|
checked = true;
|
|
|
|
|
|
|
|
// Getting path to your own executable is a total portability disaster.
|
|
|
|
// Good job *nix OSes; you're basically all awful here.
|
|
|
|
std::string selfPath;
|
|
|
|
#if defined(__linux__)
|
|
|
|
selfPath = "/proc/self/exe";
|
|
|
|
#elif defined(__NetBSD__)
|
|
|
|
selfPath = "/proc/curproc/exe"
|
2016-12-08 00:02:54 +08:00
|
|
|
#elif defined(__OpenBSD__) || defined(__FreeBSD__)
|
Use the same code for loading resources in all executables.
All of our executables need resources; e.g. the vector font is
a resource and it is necessary for generation. Before this commit,
the GUI executable loaded the resources in a nice way, and everything
else did it in a very ad-hoc, fragile way.
After this commit, all executables are placed in <build>/bin and
follow the same algorithm:
* On Windows, resources are compiled and linked into every
executable.
* On Linux, resources are copied into <build>/res (which is
tried first) and <prefix>/share/solvespace (which is tried
second).
* On macOS, resources are copied into <build>/res (which is
tried first) and <build>/bin/solvespace.app/Contents/Resources
(which is tried second).
In practice this means that we can add as many executables as we want
without duplicating lots of code. In addition, on macOS, we can
place supplementary executables into the bundle, and they can use
resources from the bundle transparently.
2016-11-28 12:16:18 +08:00
|
|
|
selfPath = "/proc/curproc/file";
|
|
|
|
#elif defined(__APPLE__)
|
|
|
|
CFURLRef cfUrl =
|
|
|
|
CFBundleCopyExecutableURL(CFBundleGetMainBundle());
|
|
|
|
CFStringRef cfPath = CFURLCopyFileSystemPath(cfUrl, kCFURLPOSIXPathStyle);
|
|
|
|
selfPath.resize(CFStringGetLength(cfPath) + 1); // reserve space for NUL
|
|
|
|
ssassert(CFStringGetCString(cfPath, &selfPath[0], selfPath.size(), kCFStringEncodingUTF8),
|
|
|
|
"Cannot convert CFString to C string");
|
|
|
|
selfPath.resize(selfPath.size() - 1);
|
|
|
|
CFRelease(cfUrl);
|
|
|
|
CFRelease(cfPath);
|
|
|
|
#else
|
|
|
|
// We don't know how to find the local resource directory on this platform,
|
|
|
|
// so use the global one (by returning an empty string).
|
|
|
|
return resourceDir;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
resourceDir = ExpandPath(selfPath);
|
|
|
|
if(!resourceDir.empty()) {
|
|
|
|
resourceDir.erase(resourceDir.rfind('/'));
|
|
|
|
resourceDir += "/../res";
|
|
|
|
resourceDir = ExpandPath(resourceDir);
|
|
|
|
}
|
|
|
|
if(!resourceDir.empty()) {
|
|
|
|
struct stat st;
|
|
|
|
if(stat(resourceDir.c_str(), &st)) {
|
|
|
|
// We looked at the path where the local resource directory ought to be,
|
|
|
|
// but there isn't one, so use the global one.
|
|
|
|
resourceDir = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return resourceDir;
|
|
|
|
}
|
|
|
|
|
|
|
|
const void *LoadResource(const std::string &name, size_t *size) {
|
|
|
|
static std::map<std::string, std::string> cache;
|
|
|
|
|
|
|
|
auto it = cache.find(name);
|
|
|
|
if(it == cache.end()) {
|
|
|
|
const std::string &resourceDir = FindLocalResourceDir();
|
|
|
|
|
|
|
|
std::string path;
|
|
|
|
if(resourceDir.empty()) {
|
|
|
|
#if defined(__APPLE__)
|
|
|
|
CFStringRef cfName =
|
|
|
|
CFStringCreateWithCString(kCFAllocatorDefault, name.c_str(),
|
|
|
|
kCFStringEncodingUTF8);
|
|
|
|
CFURLRef cfUrl =
|
|
|
|
CFBundleCopyResourceURL(CFBundleGetMainBundle(), cfName, NULL, NULL);
|
|
|
|
CFStringRef cfPath = CFURLCopyFileSystemPath(cfUrl, kCFURLPOSIXPathStyle);
|
|
|
|
path.resize(CFStringGetLength(cfPath) + 1); // reserve space for NUL
|
|
|
|
ssassert(CFStringGetCString(cfPath, &path[0], path.size(), kCFStringEncodingUTF8),
|
|
|
|
"Cannot convert CFString to C string");
|
|
|
|
path.resize(path.size() - 1);
|
|
|
|
CFRelease(cfName);
|
|
|
|
CFRelease(cfUrl);
|
|
|
|
CFRelease(cfPath);
|
|
|
|
#else
|
|
|
|
path = (UNIX_DATADIR "/") + name;
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
path = resourceDir + "/" + name;
|
|
|
|
}
|
|
|
|
|
|
|
|
ssassert(ReadFile(path, &cache[name]), "Cannot read resource");
|
|
|
|
it = cache.find(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
*size = (*it).second.size();
|
|
|
|
return static_cast<const void *>(&(*it).second[0]);
|
|
|
|
}
|
|
|
|
|
2013-10-28 13:28:42 +08:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// 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;
|
2015-09-08 07:41:25 +08:00
|
|
|
if(Head) Head->prev = h;
|
2013-10-28 13:28:42 +08:00
|
|
|
Head = h;
|
2014-04-08 09:51:55 +08:00
|
|
|
memset(&h[1], 0, n);
|
2013-10-28 13:28:42 +08:00
|
|
|
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);
|
2016-05-19 06:51:36 +08:00
|
|
|
ssassert(p != NULL, "Cannot allocate memory");
|
2013-10-28 13:28:42 +08:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemFree(void *p) {
|
|
|
|
free(p);
|
|
|
|
}
|
2013-11-18 15:31:23 +08:00
|
|
|
|
2016-12-05 08:25:31 +08:00
|
|
|
std::vector<std::string> InitPlatform(int argc, char **argv) {
|
|
|
|
std::vector<std::string> args;
|
|
|
|
for(int i = 0; i < argc; i++) {
|
|
|
|
args.push_back(argv[i]);
|
|
|
|
}
|
|
|
|
return args;
|
2013-11-18 15:31:23 +08:00
|
|
|
}
|
2015-03-24 01:49:04 +08:00
|
|
|
|
|
|
|
};
|