forked from 0ad/0ad
# improvements to foundation code
(merged in from thesis project branch) allocator: remember page-aligned size (prevent resize error) config, sysdep, lib: add implementation of wcsdup for macosX path_util: add path_package_copy and cleanup file: add dir_exists, dir_create uses _mkdir (avoids mode_t param) This was SVN commit r4984.
This commit is contained in:
parent
853f13bf03
commit
e8a0626248
@ -212,6 +212,7 @@ LibError da_alloc(DynArray* da, size_t max_size)
|
||||
da->base = p;
|
||||
da->max_size_pa = max_size_pa;
|
||||
da->cur_size = 0;
|
||||
da->cur_size_pa = 0;
|
||||
da->prot = PROT_READ|PROT_WRITE;
|
||||
da->pos = 0;
|
||||
CHECK_DA(da);
|
||||
@ -237,6 +238,7 @@ LibError da_wrap_fixed(DynArray* da, u8* p, size_t size)
|
||||
da->base = p;
|
||||
da->max_size_pa = round_up_to_page(size);
|
||||
da->cur_size = size;
|
||||
da->cur_size_pa = da->max_size_pa;
|
||||
da->prot = PROT_READ|PROT_WRITE|DA_NOT_OUR_MEM;
|
||||
da->pos = 0;
|
||||
CHECK_DA(da);
|
||||
@ -257,7 +259,7 @@ LibError da_free(DynArray* da)
|
||||
CHECK_DA(da);
|
||||
|
||||
u8* p = da->base;
|
||||
size_t size = da->max_size_pa;
|
||||
size_t size_pa = da->max_size_pa;
|
||||
bool was_wrapped = (da->prot & DA_NOT_OUR_MEM) != 0;
|
||||
|
||||
// wipe out the DynArray for safety
|
||||
@ -268,7 +270,7 @@ LibError da_free(DynArray* da)
|
||||
// (i.e. it doesn't actually own any memory). don't complain;
|
||||
// da_free is supposed to be called even in the above case.
|
||||
if(!was_wrapped)
|
||||
RETURN_ERR(mem_release(p, size));
|
||||
RETURN_ERR(mem_release(p, size_pa));
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
@ -296,7 +298,7 @@ LibError da_set_size(DynArray* da, size_t new_size)
|
||||
|
||||
// not enough memory to satisfy this expand request: abort.
|
||||
// note: do not complain - some allocators (e.g. file_cache)
|
||||
// egitimately use up all available space.
|
||||
// legitimately use up all available space.
|
||||
if(new_size_pa > da->max_size_pa)
|
||||
return ERR::LIMIT; // NOWARN
|
||||
|
||||
@ -311,6 +313,7 @@ LibError da_set_size(DynArray* da, size_t new_size)
|
||||
// (we don't want mem_* to have to handle size=0)
|
||||
|
||||
da->cur_size = new_size;
|
||||
da->cur_size_pa = new_size_pa;
|
||||
CHECK_DA(da);
|
||||
return INFO::OK;
|
||||
}
|
||||
@ -326,12 +329,9 @@ LibError da_set_size(DynArray* da, size_t new_size)
|
||||
*/
|
||||
LibError da_reserve(DynArray* da, size_t size)
|
||||
{
|
||||
// default to page size (the OS won't commit less anyway);
|
||||
// grab more if request requires it.
|
||||
const size_t expand_amount = MAX(4*KiB, size);
|
||||
|
||||
if(da->pos + size > da->cur_size)
|
||||
return da_set_size(da, da->cur_size + expand_amount);
|
||||
if(da->pos+size > da->cur_size_pa)
|
||||
RETURN_ERR(da_set_size(da, da->cur_size_pa+size));
|
||||
da->cur_size = std::max(da->cur_size, da->pos+size);
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
@ -355,7 +355,7 @@ LibError da_set_prot(DynArray* da, int prot)
|
||||
WARN_RETURN(ERR::LOGIC);
|
||||
|
||||
da->prot = prot;
|
||||
RETURN_ERR(mem_protect(da->base, da->cur_size, prot));
|
||||
RETURN_ERR(mem_protect(da->base, da->cur_size_pa, prot));
|
||||
|
||||
CHECK_DA(da);
|
||||
return INFO::OK;
|
||||
|
@ -73,6 +73,7 @@ struct DynArray
|
||||
u8* base;
|
||||
size_t max_size_pa; /// reserved
|
||||
size_t cur_size; /// committed
|
||||
size_t cur_size_pa;
|
||||
|
||||
/**
|
||||
* mprotect flags applied to newly committed pages
|
||||
|
@ -312,6 +312,13 @@
|
||||
# define HAVE_NPRINTF 1
|
||||
#endif
|
||||
|
||||
// strdup, wcsdup
|
||||
#define HAVE_STRDUP 1
|
||||
#if OS_MACOSX
|
||||
# undef HAVE_STRDUP
|
||||
# define HAVE_STRDUP 0
|
||||
#endif
|
||||
|
||||
// rint*, fminf, fpclassify (too few/diverse to make separate HAVE_ for each)
|
||||
#define HAVE_C99_MATH 0
|
||||
#if HAVE_C99
|
||||
|
@ -506,6 +506,7 @@ extern u16 fp_to_u16(double in);
|
||||
* showing up in searches)
|
||||
**/
|
||||
#define SAFE_STRCPY str##cpy
|
||||
#define SAFE_WCSCPY wcs##cpy
|
||||
|
||||
|
||||
/**
|
||||
|
@ -41,7 +41,7 @@ AT_STARTUP(\
|
||||
)
|
||||
|
||||
|
||||
static inline bool is_dir_sep(char c)
|
||||
bool path_is_dir_sep(char c)
|
||||
{
|
||||
// note: ideally path strings would only contain '/' or even SYS_DIR_SEP.
|
||||
// however, windows-specific code (e.g. the sound driver detection)
|
||||
@ -75,8 +75,8 @@ bool path_is_subpath(const char* s1, const char* s2)
|
||||
{
|
||||
// s1 matched s2 up until:
|
||||
if((c2 == '\0') || // its end (i.e. they're equal length) OR
|
||||
is_dir_sep(c2) || // start of next component OR
|
||||
is_dir_sep(last_c1)) // ", but both have a trailing slash
|
||||
path_is_dir_sep(c2) || // start of next component OR
|
||||
path_is_dir_sep(last_c1)) // ", but both have a trailing slash
|
||||
// => is subpath
|
||||
return true;
|
||||
}
|
||||
@ -170,8 +170,8 @@ LibError path_append(char* dst, const char* path1, const char* path2, uint flags
|
||||
const size_t len1 = strlen(path1);
|
||||
const size_t len2 = strlen(path2);
|
||||
size_t total_len = len1 + len2 + 1; // includes '\0'
|
||||
const bool no_end_slash1 = (len1 == 0 || !is_dir_sep(path1[len1-1]));
|
||||
const bool no_end_slash2 = (len2 == 0 || !is_dir_sep(path2[len2-1]));
|
||||
const bool no_end_slash1 = (len1 == 0 || !path_is_dir_sep(path1[len1-1]));
|
||||
const bool no_end_slash2 = (len2 == 0 || !path_is_dir_sep(path2[len2-1]));
|
||||
|
||||
// check if we need to add '/' between path1 and path2
|
||||
// notes:
|
||||
@ -222,7 +222,7 @@ LibError path_replace(char* dst, const char* src, const char* remove, const char
|
||||
// if removing will leave a separator at beginning of src, remove it
|
||||
// (example: "a/b"; removing "a" would yield "/b")
|
||||
const char* start = src+remove_len;
|
||||
if(is_dir_sep(*start))
|
||||
if(path_is_dir_sep(*start))
|
||||
start++;
|
||||
|
||||
// prepend replace.
|
||||
@ -392,7 +392,7 @@ LibError path_package_set_dir(PathPackage* pp, const char* dir)
|
||||
if(len != 0)
|
||||
{
|
||||
char* last_char = pp->path+len-1;
|
||||
if(!is_dir_sep(*last_char))
|
||||
if(!path_is_dir_sep(*last_char))
|
||||
{
|
||||
*(last_char+1) = '/';
|
||||
// note: need to 0-terminate because pp.path is uninitialized
|
||||
@ -409,6 +409,14 @@ LibError path_package_set_dir(PathPackage* pp, const char* dir)
|
||||
}
|
||||
|
||||
|
||||
void path_package_copy(PathPackage* pp_dst, const PathPackage* pp_src)
|
||||
{
|
||||
*pp_dst = *pp_src;
|
||||
const ptrdiff_t end_ofs = pp_src->end - pp_src->path;
|
||||
pp_dst->end = pp_dst->path + end_ofs;
|
||||
}
|
||||
|
||||
|
||||
// append the given filename to the directory established by the last
|
||||
// path_package_set_dir on this package. the whole path is accessible at pp->path.
|
||||
LibError path_package_append_file(PathPackage* pp, const char* path)
|
||||
|
@ -66,6 +66,13 @@ extern LibError path_validate(const char* path);
|
||||
**/
|
||||
extern LibError path_component_validate(const char* name);
|
||||
|
||||
/**
|
||||
* is the given character a path separator character?
|
||||
*
|
||||
* @param c character to test
|
||||
* @return bool
|
||||
**/
|
||||
extern bool path_is_dir_sep(char c);
|
||||
|
||||
/**
|
||||
* is s2 a subpath of s1, or vice versa? (equal counts as subpath)
|
||||
@ -222,6 +229,11 @@ struct PathPackage
|
||||
**/
|
||||
extern LibError path_package_set_dir(PathPackage* pp, const char* dir);
|
||||
|
||||
/**
|
||||
* copy one PathPackage into another (doing so directly is incorrect!)
|
||||
**/
|
||||
extern void path_package_copy(PathPackage* pp_dst, const PathPackage* pp_src);
|
||||
|
||||
/**
|
||||
* append the given filename to the directory established by the last
|
||||
* path_package_set_dir on this package. the whole path is accessible at pp->path.
|
||||
|
@ -38,6 +38,10 @@
|
||||
#include "lib/allocators.h"
|
||||
#include "file_internal.h"
|
||||
|
||||
#if OS_WIN
|
||||
#include <direct.h> // _mkdir
|
||||
#endif
|
||||
|
||||
|
||||
AT_STARTUP(\
|
||||
error_setDescription(ERR::FILE_ACCESS, "Insufficient access rights to open file");\
|
||||
@ -196,7 +200,26 @@ LibError dir_close(DirIterator* di)
|
||||
}
|
||||
|
||||
|
||||
LibError dir_create(const char* P_path, mode_t mode)
|
||||
bool dir_exists(const char* P_path)
|
||||
{
|
||||
// modified from file_stat_impl - we don't want errors to be raised here.
|
||||
char N_path[PATH_MAX];
|
||||
THROW_ERR(file_make_full_native_path(P_path, N_path));
|
||||
|
||||
// if path ends in slash, remove it (required by stat)
|
||||
char* last_char = N_path+strlen(N_path)-1;
|
||||
if(path_is_dir_sep(*last_char))
|
||||
*last_char = '\0';
|
||||
|
||||
struct stat s;
|
||||
if(stat(N_path, &s) != 0)
|
||||
return false;
|
||||
debug_assert(S_ISDIR(s.st_mode));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
LibError dir_create(const char* P_path)
|
||||
{
|
||||
char N_path[PATH_MAX];
|
||||
RETURN_ERR(file_make_full_native_path(P_path, N_path));
|
||||
@ -207,7 +230,7 @@ LibError dir_create(const char* P_path, mode_t mode)
|
||||
return INFO::ALREADY_EXISTS;
|
||||
|
||||
errno = 0;
|
||||
ret = mkdir(N_path, mode);
|
||||
ret = _mkdir(N_path);
|
||||
return LibError_from_posix(ret);
|
||||
}
|
||||
|
||||
|
@ -159,7 +159,8 @@ extern LibError dir_next_ent(DirIterator* d, DirEnt* ent);
|
||||
extern LibError dir_close(DirIterator* d);
|
||||
|
||||
|
||||
extern LibError dir_create(const char* P_path, mode_t mode);
|
||||
extern bool dir_exists(const char* P_path);
|
||||
extern LibError dir_create(const char* P_path);
|
||||
extern LibError dir_delete(const char* P_path);
|
||||
|
||||
|
||||
|
@ -102,7 +102,7 @@ public:
|
||||
void test_create_archive_with_random_files()
|
||||
{
|
||||
if(!file_exists("archivetest")) // don't get stuck if this test fails and never deletes the directory it created
|
||||
TS_ASSERT_OK(dir_create("archivetest", S_IRWXU|S_IRWXG|S_IRWXO));
|
||||
TS_ASSERT_OK(dir_create("archivetest"));
|
||||
|
||||
TS_ASSERT_OK(vfs_mount("", "archivetest"));
|
||||
|
||||
|
@ -897,7 +897,7 @@ LibError mount_create_real_dir(const char* V_path, const Mount* m)
|
||||
char P_path[PATH_MAX];
|
||||
RETURN_ERR(mount_realpath(V_path, m, P_path));
|
||||
|
||||
return dir_create(P_path, S_IRWXU|S_IRWXG|S_IRWXO);
|
||||
return dir_create(P_path);
|
||||
}
|
||||
|
||||
|
||||
|
@ -90,3 +90,23 @@ i64 i64_from_double(double d)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !HAVE_STRDUP
|
||||
|
||||
char* strdup(const char* str)
|
||||
{
|
||||
const size_t num_chars = strlen(str);
|
||||
char* new_str = malloc(num_chars*sizeof(char)+1);
|
||||
SAFE_STRCPY(new_str, str);
|
||||
return new_str;
|
||||
}
|
||||
|
||||
wchar_t* wcsdup(const wchar_t* str)
|
||||
{
|
||||
const size_t num_chars = wcslen(str);
|
||||
wchar_t* new_str = malloc(num_chars*sizeof(wchar_t)+1);
|
||||
SAFE_WCSCPY(new_str, str);
|
||||
return new_str;
|
||||
}
|
||||
|
||||
#endif // #if !HAVE_STRDUP
|
||||
|
@ -206,6 +206,11 @@ extern void* alloca(size_t size);
|
||||
# define __func__ "(unknown)"
|
||||
#endif
|
||||
|
||||
#if !HAVE_STRDUP
|
||||
extern char* strdup(const char* str);
|
||||
extern wchar_t* wcsdup(const wchar_t* str);
|
||||
#endif // #if !HAVE_STRDUP
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// sysdep API
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
// misc routines
|
||||
|
||||
extern int chdir(const char*);
|
||||
#undef getcwd
|
||||
extern char* getcwd(char*, size_t);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user