# 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:
janwas 2007-04-22 16:43:54 +00:00
parent 853f13bf03
commit e8a0626248
13 changed files with 100 additions and 23 deletions

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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
/**

View File

@ -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)

View File

@ -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.

View File

@ -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);
}

View File

@ -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);

View File

@ -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"));

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -25,7 +25,6 @@
// misc routines
extern int chdir(const char*);
#undef getcwd
extern char* getcwd(char*, size_t);