const char* environment_variable( const char* var ) { #if FOUNDATION_PLATFORM_WINDOWS unsigned int required; wchar_t* key = wstring_allocate_from_string( var, 0 ); wchar_t val[FOUNDATION_MAX_PATHLEN]; val[0] = 0; if( ( required = GetEnvironmentVariableW( key, val, FOUNDATION_MAX_PATHLEN ) ) > FOUNDATION_MAX_PATHLEN ) { wchar_t* val_local = memory_allocate( sizeof( wchar_t ) * ( required + 2 ), 0, MEMORY_TEMPORARY ); val_local[0] = 0; GetEnvironmentVariableW( key, val_local, required + 1 ); if( _environment_var ) string_deallocate( _environment_var ); _environment_var = string_allocate_from_wstring( val_local, 0 ); memory_deallocate( val_local ); } else { if( _environment_var ) string_deallocate( _environment_var ); _environment_var = string_allocate_from_wstring( val, 0 ); } wstring_deallocate( key ); return _environment_var; #elif FOUNDATION_PLATFORM_POSIX return getenv( var ); #else # error Not implemented #endif }
void _config_shutdown( void ) { int isb, is, ikb, ik, ssize, ksize; config_section_t* section; config_key_t* key; for( isb = 0; isb < CONFIG_SECTION_BUCKETS; ++isb ) { section = _config_section[isb]; for( is = 0, ssize = array_size( section ); is < ssize; ++is ) { for( ikb = 0; ikb < CONFIG_KEY_BUCKETS; ++ikb ) { /*lint -e{613} array_size( section ) in loop condition does the null pointer guard */ key = section[is].key[ikb]; for( ik = 0, ksize = array_size( key ); ik < ksize; ++ik ) { /*lint --e{613} array_size( key ) in loop condition does the null pointer guard */ if( key[ik].expanded != key[ik].sval ) string_deallocate( key[ik].expanded ); if( ( key[ik].type != CONFIGVALUE_STRING_CONST ) && ( key[ik].type != CONFIGVALUE_STRING_CONST_VAR ) ) string_deallocate( key[ik].sval ); } array_deallocate( key ); } } array_deallocate( section ); } }
DECLARE_TEST( fs, directory ) { char* longpath; char* testpath = path_merge( environment_temporary_directory(), string_from_int_static( random64(), 0, 0 ) ); if( !fs_is_file( testpath ) ) fs_remove_file( testpath ); if( !fs_is_directory( testpath ) ) fs_make_directory( testpath ); EXPECT_TRUE( fs_is_directory( testpath ) ); fs_remove_directory( testpath ); EXPECT_FALSE( fs_is_directory( testpath ) ); longpath = path_merge( testpath, string_from_int_static( random64(), 0, 0 ) ); EXPECT_FALSE( fs_is_directory( longpath ) ); fs_make_directory( longpath ); EXPECT_TRUE( fs_is_directory( longpath ) ); fs_remove_directory( testpath ); EXPECT_FALSE( fs_is_directory( testpath ) ); EXPECT_FALSE( fs_is_directory( longpath ) ); string_deallocate( longpath ); string_deallocate( testpath ); return 0; }
int bin2hex_process_files( char const* const* input, char const* const* output, int columns ) { int result = BIN2HEX_RESULT_OK; unsigned int ifile, files_size; for( ifile = 0, files_size = array_size( input ); ( result == BIN2HEX_RESULT_OK ) && ( ifile < files_size ); ++ifile ) { char* input_filename = 0; char* output_filename = 0; stream_t* input_file = 0; stream_t* output_file = 0; input_filename = path_clean( string_clone( input[ifile] ), path_is_absolute( input[ifile] ) ); error_context_push( "parsing file", input_filename ); output_filename = path_clean( string_clone( output[ifile] ), path_is_absolute( output[ifile] ) ); log_infof( 0, "bin2hex %s -> %s", input_filename, output_filename ); input_file = stream_open( input_filename, STREAM_IN | STREAM_BINARY ); if( !input_file ) { log_warnf( 0, WARNING_BAD_DATA, "Unable to open input file: %s", input_filename ); result = BIN2HEX_RESULT_MISSING_INPUT_FILE; } else { output_file = stream_open( output_filename, STREAM_OUT ); if( !output_file ) { log_warnf( 0, WARNING_BAD_DATA, "Unable to open output file: %s", output_filename ); result = BIN2HEX_RESULT_UNABLE_TO_OPEN_OUTPUT_FILE; } } if( input_file && output_file ) result = bin2hex_process_file( input_file, output_file, columns ); stream_deallocate( input_file ); stream_deallocate( output_file ); string_deallocate( output_filename ); error_context_pop(); string_deallocate( input_filename ); } if( ( result == BIN2HEX_RESULT_OK ) && ( files_size > 0 ) ) log_info( 0, "All files generated" ); return result; }
void process_finalize(process_t* proc) { if (!(proc->flags & PROCESS_DETACHED)) process_wait(proc); stream_deallocate(proc->pipeout); stream_deallocate(proc->pipein); string_deallocate(proc->wd.str); string_deallocate(proc->path.str); string_array_deallocate(proc->args); #if FOUNDATION_PLATFORM_WINDOWS string_deallocate(proc->verb.str); #endif }
void config_set_real( hash_t section, hash_t key, real value ) { config_key_t* key_val = config_key( section, key, true ); if( !FOUNDATION_VALIDATE( key_val ) ) return; key_val->bval = !math_realzero( value ); key_val->ival = (int64_t)value; key_val->rval = value; if( key_val->expanded != key_val->sval ) string_deallocate( key_val->expanded ); if( ( key_val->type != CONFIGVALUE_STRING_CONST ) && ( key_val->type != CONFIGVALUE_STRING_CONST_VAR ) ) string_deallocate( key_val->sval ); key_val->sval = 0; key_val->expanded = 0; key_val->type = CONFIGVALUE_REAL; }
void config_set_int( hash_t section, hash_t key, int64_t value ) { config_key_t* key_val = config_key( section, key, true ); if( !FOUNDATION_VALIDATE( key_val ) ) return; key_val->bval = value ? true : false; key_val->ival = value; key_val->rval = (real)value; if( key_val->expanded != key_val->sval ) string_deallocate( key_val->expanded ); if( ( key_val->type != CONFIGVALUE_STRING_CONST ) && ( key_val->type != CONFIGVALUE_STRING_CONST_VAR ) ) string_deallocate( key_val->sval ); key_val->sval = 0; key_val->expanded = 0; key_val->type = CONFIGVALUE_INT; }
void config_set_bool( hash_t section, hash_t key, bool value ) { config_key_t* key_val = config_key( section, key, true ); if( !FOUNDATION_VALIDATE( key_val ) ) return; key_val->bval = value; key_val->ival = ( value ? 1 : 0 ); key_val->rval = ( value ? REAL_C( 1.0 ) : REAL_C( 0.0 ) ); if( key_val->expanded != key_val->sval ) string_deallocate( key_val->expanded ); if( ( key_val->type != CONFIGVALUE_STRING_CONST ) && ( key_val->type != CONFIGVALUE_STRING_CONST_VAR ) ) string_deallocate( key_val->sval ); key_val->sval = 0; key_val->expanded = 0; key_val->type = CONFIGVALUE_BOOL; }
void process_set_working_directory( process_t* proc, const char* path ) { if( !proc ) return; string_deallocate( proc->wd ); proc->wd = string_clone( path ); }
void process_set_executable_path( process_t* proc, const char* path ) { if( !proc ) return; string_deallocate( proc->path ); proc->path = string_clone( path ); }
void process_deallocate( process_t* proc ) { if( !proc ) return; if( !( proc->flags & PROCESS_DETACHED ) ) process_wait( proc ); stream_deallocate( proc->pipeout ); stream_deallocate( proc->pipein ); string_deallocate( proc->wd ); string_deallocate( proc->path ); string_array_deallocate( proc->args ); #if FOUNDATION_PLATFORM_WINDOWS string_deallocate( proc->verb ); #endif memory_deallocate( proc ); }
void blast_reader_close(blast_reader_t* reader) { //munmap(reader->data, reader->size); //close(reader->id); string_deallocate(reader->name.str); memory_deallocate(reader); }
const char* environment_temporary_directory( void ) { if( _environment_temp_dir[0] ) return _environment_temp_dir; #if FOUNDATION_PLATFORM_WINDOWS { char* path; wchar_t* wpath = memory_allocate_zero( sizeof( wchar_t ) * FOUNDATION_MAX_PATHLEN, 0, MEMORY_TEMPORARY ); GetTempPathW( FOUNDATION_MAX_PATHLEN, wpath ); path = path_clean( string_allocate_from_wstring( wpath, 0 ), true ); string_copy( _environment_temp_dir, path, FOUNDATION_MAX_PATHLEN ); string_deallocate( path ); memory_deallocate( wpath ); } #elif FOUNDATION_PLATFORM_POSIX string_copy( _environment_temp_dir, P_tmpdir, FOUNDATION_MAX_PATHLEN ); unsigned int len = string_length( _environment_temp_dir ); if( ( len > 1 ) && ( _environment_temp_dir[ len - 1 ] == '/' ) ) _environment_temp_dir[ len - 1 ] = 0; #else # error Not implemented #endif if( _environment_app.config_dir ) { unsigned int curlen = string_length( _environment_temp_dir ); unsigned int cfglen = string_length( _environment_app.config_dir ); if( ( curlen + cfglen + 2 ) < FOUNDATION_MAX_PATHLEN ) { _environment_temp_dir[curlen] = '/'; memcpy( _environment_temp_dir + curlen + 1, _environment_app.config_dir, cfglen + 1 ); } } return _environment_temp_dir; }
static void _memory_tracker_shutdown( void ) { if( _memory_table ) hashtable_deallocate( _memory_table ); if( _memory_tags ) { bool got_leaks = false; log_debug( "Checking for memory leaks" ); for( unsigned int it = 0; it < MAX_CONCURRENT_ALLOCATIONS; ++it ) { memory_tag_t* tag = _memory_tags + it; if( tag->address ) { char* trace = stacktrace_resolve( tag->trace, 14, 0 ); log_warnf( WARNING_MEMORY, "Memory leak: %d bytes @ " STRING_FORMAT_POINTER " : tag %d\n%s", (unsigned int)tag->size, tag->address, it, trace ); string_deallocate( trace ); got_leaks = true; } } memory_deallocate( _memory_tags ); if( !got_leaks ) log_debug( "No memory leaks detected" ); } }
DECLARE_TEST( uuid, string ) { uuid_t uuid, uuidref; char* str; uuidref = uuid_generate_random(); EXPECT_FALSE( uuid_is_null( uuidref ) ); str = string_from_uuid( uuidref ); EXPECT_NE( str, 0 ); uuid = string_to_uuid( str ); EXPECT_FALSE( uuid_is_null( uuid ) ); EXPECT_TRUE( uuid_equal( uuid, uuidref ) ); string_deallocate( str ); uuid = string_to_uuid( "" ); EXPECT_EQ_MSGFORMAT( uuid_is_null( uuid ), true, "empty string did not convert to null uuid: %s", string_from_uuid_static( uuid ) ); uuid = string_to_uuid( "0" ); EXPECT_EQ_MSGFORMAT( uuid_is_null( uuid ), true, "\"0\" string did not convert to null uuid: %s", string_from_uuid_static( uuid ) ); uuid = string_to_uuid( string_from_uuid_static( uuid_null() ) ); EXPECT_EQ_MSGFORMAT( uuid_is_null( uuid ), true, "null uuid reconvert through string did not convert to null uuid: %s", string_from_uuid_static( uuid ) ); return 0; }
const char* environment_current_working_directory( void ) { if( _environment_current_working_dir[0] ) return _environment_current_working_dir; #if FOUNDATION_PLATFORM_WINDOWS { char* path; wchar_t* wd = memory_allocate_zero( sizeof( wchar_t ) * FOUNDATION_MAX_PATHLEN, 0, MEMORY_TEMPORARY ); GetCurrentDirectoryW( FOUNDATION_MAX_PATHLEN-1, wd ); path = path_clean( string_allocate_from_wstring( wd, 0 ), true ); string_copy( _environment_current_working_dir, path, FOUNDATION_MAX_PATHLEN ); string_copy( _environment_current_working_dir, path, FOUNDATION_MAX_PATHLEN ); string_deallocate( path ); memory_deallocate( wd ); } #elif FOUNDATION_PLATFORM_POSIX char* path = memory_allocate_zero( FOUNDATION_MAX_PATHLEN, 0, MEMORY_TEMPORARY ); if( !getcwd( path, FOUNDATION_MAX_PATHLEN ) ) { log_errorf( ERROR_SYSTEM_CALL_FAIL, "Unable to get cwd: %s", system_error_message( 0 ) ); return ""; } path = path_clean( path, true ); string_copy( _environment_current_working_dir, path, FOUNDATION_MAX_PATHLEN ); memory_deallocate( path ); #else # error Not implemented #endif return _environment_current_working_dir; }
void _environment_shutdown( void ) { string_array_deallocate( _environment_argv ); #if FOUNDATION_PLATFORM_WINDOWS string_deallocate( _environment_var ); #endif }
void config_parse_commandline( const char* const* cmdline, unsigned int num ) { //TODO: Implement, format --section:key=value unsigned int arg; for( arg = 0; arg < num; ++arg ) { if( string_match_pattern( cmdline[arg], "--*:*=*" ) ) { unsigned int first_sep = string_find( cmdline[arg], ':', 0 ); unsigned int second_sep = string_find( cmdline[arg], '=', 0 ); if( ( first_sep != STRING_NPOS ) && ( second_sep != STRING_NPOS ) && ( first_sep < second_sep ) ) { unsigned int section_length = first_sep - 2; unsigned int end_pos = first_sep + 1; unsigned int key_length = second_sep - end_pos; const char* section_str = cmdline[arg] + 2; const char* key_str = pointer_offset_const( cmdline[arg], end_pos ); hash_t section = hash( section_str, section_length ); hash_t key = hash( key_str, key_length ); char* value = string_substr( cmdline[arg], second_sep + 1, STRING_NPOS ); char* set_value = value; unsigned int value_length = string_length( value ); if( !value_length ) config_set_string( section, key, "" ); else if( string_equal( value, "false" ) ) config_set_bool( section, key, false ); else if( string_equal( value, "true" ) ) config_set_bool( section, key, true ); else if( ( string_find( value, '.', 0 ) != STRING_NPOS ) && ( string_find_first_not_of( value, "0123456789.", 0 ) == STRING_NPOS ) && ( string_find( value, '.', string_find( value, '.', 0 ) + 1 ) == STRING_NPOS ) ) //Exactly one "." config_set_real( section, key, string_to_real( value ) ); else if( string_find_first_not_of( value, "0123456789", 0 ) == STRING_NPOS ) config_set_int( section, key, string_to_int64( value ) ); else { if( ( value_length > 1 ) && ( value[0] == '"' ) && ( value[ value_length - 1 ] == '"' ) ) { value[ value_length - 1 ] = 0; set_value = value + 1; config_set_string( section, key, set_value ); } else { config_set_string( section, key, value ); } } log_infof( HASH_CONFIG, "Config value from command line: %.*s:%.*s = %s", section_length, section_str, key_length, key_str, set_value ); string_deallocate( value ); } } } }
void process_set_verb( process_t* proc, const char* verb ) { if( !proc ) return; #if FOUNDATION_PLATFORM_WINDOWS string_deallocate( proc->verb ); proc->verb = string_clone( verb ); #endif }
void stream_deallocate( stream_t* stream ) { if( !stream ) return; if( stream->vtable && stream->vtable->deallocate ) stream->vtable->deallocate( stream ); string_deallocate( stream->path ); memory_deallocate( stream ); }
char* path_subdirectory_name( const char* path, const char* root ) { char* subpath; char* testpath; char* testroot; char* pathofpath; unsigned int pathprotocol, rootprotocol; char* cpath = string_clone( path ); char* croot = string_clone( root ); cpath = path_clean( cpath, path_is_absolute( cpath ) ); croot = path_clean( croot, path_is_absolute( croot ) ); pathofpath = path_directory_name( cpath ); testpath = pathofpath; pathprotocol = string_find_string( testpath, "://", 0 ); if( pathprotocol != STRING_NPOS ) testpath += pathprotocol + 2; // add two to treat as absolute path testroot = croot; rootprotocol = string_find_string( testroot, "://", 0 ); if( rootprotocol != STRING_NPOS ) testroot += rootprotocol + 2; if( ( rootprotocol != STRING_NPOS ) && ( ( pathprotocol == STRING_NPOS ) || ( pathprotocol != rootprotocol ) || !string_equal_substr( cpath, croot, rootprotocol ) ) ) subpath = string_allocate( 0 ); else if( !string_equal_substr( testpath, testroot, string_length( testroot ) ) ) subpath = string_allocate( 0 ); else { char* filename = path_file_name( cpath ); subpath = string_substr( testpath, string_length( testroot ), STRING_NPOS ); subpath = path_clean( path_append( subpath, filename ), false ); string_deallocate( filename ); } string_deallocate( pathofpath ); string_deallocate( cpath ); string_deallocate( croot ); return subpath; }
void stream_finalize(stream_t* stream) { if (stream->vtable && stream->vtable->finalize) stream->vtable->finalize(stream); string_deallocate(stream->path.str); stream->path = (string_t) { 0, 0 }; stream->type = STREAMTYPE_INVALID; }
DECLARE_TEST(environment, workingdir) { char buffer[BUILD_MAX_PATHLEN]; string_const_t working_dir = environment_current_working_directory(); string_const_t new_working_dir = path_directory_name(STRING_ARGS(working_dir)); string_t working_dir_copy = string_clone(STRING_ARGS(working_dir)); string_t new_working_dir_copy; if (string_equal(STRING_ARGS(working_dir), STRING_CONST("/"))) { string_t tmpwork = path_make_temporary(buffer, sizeof(buffer)); new_working_dir = path_directory_name(STRING_ARGS(tmpwork)); } new_working_dir_copy = string_clone(STRING_ARGS(new_working_dir)); new_working_dir = string_to_const(new_working_dir_copy); EXPECT_CONSTSTRINGNE(working_dir, new_working_dir); #if FOUNDATION_PLATFORM_PNACL EXPECT_FALSE(environment_set_current_working_directory(STRING_ARGS(new_working_dir))); EXPECT_CONSTSTRINGEQ(environment_current_working_directory(), string_const(STRING_ARGS(working_dir_copy))); #else EXPECT_TRUE(environment_set_current_working_directory(STRING_ARGS(new_working_dir))); EXPECT_CONSTSTRINGEQ(environment_current_working_directory(), new_working_dir); environment_set_current_working_directory(STRING_ARGS(working_dir_copy)); EXPECT_CONSTSTRINGEQ(environment_current_working_directory(), string_const(STRING_ARGS(working_dir_copy))); { log_enable_stdout(false); bool ret = environment_set_current_working_directory(STRING_CONST("/invalid/path/which/does/not/exist")); log_enable_stdout(true); EXPECT_FALSE(ret); } EXPECT_CONSTSTRINGEQ(environment_current_working_directory(), string_const(STRING_ARGS(working_dir_copy))); #endif string_deallocate(new_working_dir_copy.str); string_deallocate(working_dir_copy.str); return 0; }
bool system_message_box( const char* title, const char* message, bool cancel_button ) { if( environment_application()->flags & APPLICATION_UTILITY ) return true; #if FOUNDATION_PLATFORM_WINDOWS return ( MessageBoxA( 0, message, title, cancel_button ? MB_OKCANCEL : MB_OK ) == IDOK ); #elif FOUNDATION_PLATFORM_APPLE return _system_show_alert( title, message, cancel_button ? 1 : 0 ) > 0; #elif 0//FOUNDATION_PLATFORM_LINUX char* buf = string_format( "%s\n\n%s\n", title, message ); pid_t pid = fork(); switch( pid ) { case -1: //error string_deallocate( buf ); break; case 0: execlp( "xmessage", "xmessage", "-buttons", cancel_button ? "OK:101,Cancel:102" : "OK:101", "-default", "OK", "-center", buf, (char*)0 ); _exit( -1 ); break; default: { string_deallocate( buf ); int status; waitpid( pid, &status, 0 ); if( ( !WIFEXITED( status ) ) || ( WEXITSTATUS( status ) != 101 ) ) return false; return true; } } return false; #else //Not implemented return false; #endif }
void stream_write_format(stream_t* stream, const char* format, size_t format_length, ...) { va_list list; string_t buffer; va_start(list, format_length); buffer = string_allocate_vformat(format, format_length, list); va_end(list); stream_write_string(stream, buffer.str, buffer.length); string_deallocate(buffer.str); }
void config_set_string( hash_t section, hash_t key, const char* value ) { config_key_t* key_val = config_key( section, key, true ); if( !FOUNDATION_VALIDATE( key_val ) ) return; if( key_val->expanded != key_val->sval ) string_deallocate( key_val->expanded ); if( ( key_val->type != CONFIGVALUE_STRING_CONST ) && ( key_val->type != CONFIGVALUE_STRING_CONST_VAR ) ) string_deallocate( key_val->sval ); key_val->sval = string_clone( value ); key_val->expanded = 0; key_val->type = ( ( string_find_string( key_val->sval, "$(", 0 ) != STRING_NPOS ) ? CONFIGVALUE_STRING_VAR : CONFIGVALUE_STRING ); if( key_val->type == CONFIGVALUE_STRING ) { bool is_true = string_equal( key_val->sval, "true" ); key_val->bval = ( string_equal( key_val->sval, "false" ) || string_equal( key_val->sval, "0" ) || !string_length( key_val->sval ) ) ? false : true; key_val->ival = is_true ? 1 : _config_string_to_int( key_val->sval ); key_val->rval = is_true ? REAL_C(1.0) : _config_string_to_real( key_val->sval ); } }
static NOINLINE void _expand_string_val( hash_t section, config_key_t* key ) { bool is_true; FOUNDATION_ASSERT( key->sval ); if( key->expanded != key->sval ) string_deallocate( key->expanded ); key->expanded = _expand_string( section, key->sval ); is_true = string_equal( key->expanded, "true" ); key->bval = ( string_equal( key->expanded, "false" ) || string_equal( key->expanded, "0" ) || !string_length( key->expanded ) ) ? false : true; key->ival = is_true ? 1 : _config_string_to_int( key->expanded ); key->rval = is_true ? REAL_C(1.0) : _config_string_to_real( key->expanded ); }
void config_set_string_constant( hash_t section, hash_t key, const char* value ) { config_key_t* key_val = config_key( section, key, true ); if( !FOUNDATION_VALIDATE( key_val ) ) return; if( !FOUNDATION_VALIDATE( value ) ) return; if( key_val->expanded != key_val->sval ) string_deallocate( key_val->expanded ); if( ( key_val->type != CONFIGVALUE_STRING_CONST ) && ( key_val->type != CONFIGVALUE_STRING_CONST_VAR ) ) string_deallocate( key_val->sval ); //key_val->sval = (char*)value; memcpy( &key_val->sval, &value, sizeof( char* ) ); //Yeah yeah, we're storing a const pointer in a non-const var key_val->expanded = 0; key_val->type = ( ( string_find_string( key_val->sval, "$(", 0 ) != STRING_NPOS ) ? CONFIGVALUE_STRING_CONST_VAR : CONFIGVALUE_STRING_CONST ); if( key_val->type == CONFIGVALUE_STRING_CONST ) { bool is_true = string_equal( key_val->sval, "true" ); key_val->bval = ( string_equal( key_val->sval, "false" ) || string_equal( key_val->sval, "0" ) || !string_length( key_val->sval ) ) ? false : true; key_val->ival = is_true ? 1 : _config_string_to_int( key_val->sval ); key_val->rval = is_true ? REAL_C(1.0) : _config_string_to_real( key_val->sval ); } }
uint8_t stream_read_uint8( stream_t* stream ) { uint8_t value = 0; if( stream_is_binary( stream ) ) stream_read( stream, &value, 1 ); else { char* str = stream_read_string( stream ); value = (uint8_t)string_to_uint( str, false ); string_deallocate( str ); } return value; }
const char* environment_home_directory( void ) { if( _environment_home_dir[0] ) return _environment_home_dir; #if FOUNDATION_PLATFORM_WINDOWS { char* path; wchar_t* wpath = memory_allocate_zero( sizeof( wchar_t ) * FOUNDATION_MAX_PATHLEN, 0, MEMORY_TEMPORARY ); SHGetFolderPathW( 0, CSIDL_LOCAL_APPDATA, 0, 0, wpath ); path = path_clean( string_allocate_from_wstring( wpath, 0 ), true ); string_copy( _environment_home_dir, path, FOUNDATION_MAX_PATHLEN ); string_deallocate( path ); memory_deallocate( wpath ); } #elif FOUNDATION_PLATFORM_LINUX string_copy( _environment_home_dir, environment_variable( "HOME" ), FOUNDATION_MAX_PATHLEN ); #elif FOUNDATION_PLATFORM_APPLE if( environment_application()->flags & APPLICATION_UTILITY ) { CFStringRef home = NSHomeDirectory(); CFStringGetCString( home, _environment_home_dir, FOUNDATION_MAX_PATHLEN, kCFStringEncodingUTF8 ); } else { char bundle_identifier[FOUNDATION_MAX_PATHLEN+1]; environment_bundle_identifier( bundle_identifier ); char* path = path_append( path_merge( _environment_home_dir, "/Library/Application Support" ), bundle_identifier ); string_copy( _environment_home_dir, path, FOUNDATION_MAX_PATHLEN ); string_deallocate( path ); } #elif FOUNDATION_PLATFORM_ANDROID string_copy( _environment_home_dir, android_app()->activity->internalDataPath, FOUNDATION_MAX_PATHLEN ); #else # error Not implemented #endif return _environment_home_dir; }