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; }
objectmap_t* objectmap_allocate( unsigned int size ) { uint64_t bits; unsigned int ip; uintptr_t next_indexshift; objectmap_t* map; void** slot; FOUNDATION_ASSERT_MSG( size > 2, "Invalid objectmap size" ); if( size <= 2 ) size = 2; bits = math_round( math_log2( (real)size ) ); //Number of bits needed FOUNDATION_ASSERT_MSGFORMAT( bits < 50, "Invalid objectmap size %d", size ); //Top two bits unused for Lua compatibility map = memory_allocate_zero( sizeof( objectmap_t ) + ( sizeof( void* ) * size ), 16, MEMORY_PERSISTENT ); map->size_bits = bits; map->id_max = ((1ULL<<(62ULL-bits))-1); map->size = size; map->mask_index = ((1ULL<<bits)-1ULL); map->mask_id = ( 0x3FFFFFFFFFFFFFFFULL & ~map->mask_index ); atomic_store64( &map->free, 0 ); atomic_store64( &map->id, 1 ); slot = map->map; for( ip = 0, next_indexshift = 3; ip < ( size - 1 ); ++ip, next_indexshift += 2, ++slot ) *slot = (void*)next_indexshift; *slot = (void*)((uintptr_t)-1); return map; }
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; }
mutex_t* mutex_allocate( const char* name ) { mutex_t* mutex = memory_allocate_zero( sizeof( mutex_t ), 16, MEMORY_PERSISTENT ); _mutex_initialize( mutex, name ); return mutex; }
static int _memory_tracker_initialize( void ) { log_debug( "Initializing local memory tracker" ); if( !_memory_tags ) _memory_tags = memory_allocate_zero( sizeof( memory_tag_t ) * MAX_CONCURRENT_ALLOCATIONS, 16, MEMORY_PERSISTENT ); if( !_memory_table ) _memory_table = hashtable_allocate( MAX_CONCURRENT_ALLOCATIONS ); return 0; }
void memory_context_push( uint16_t context_id ) { memory_context_t* context = get_thread_memory_context(); if( !context ) { context = memory_allocate_zero( sizeof( memory_context_t ), 0, MEMORY_PERSISTENT ); set_thread_memory_context( context ); } FOUNDATION_ASSERT_MSG( context->depth < BUILD_SIZE_MEMORY_CONTEXT_DEPTH, "Memory context stack overflow" ); context->context[ context->depth ] = context_id; if( context->depth < BUILD_SIZE_MEMORY_CONTEXT_DEPTH-1 ) ++context->depth; }
void _error_context_push( const char* name, const char* data ) { error_context_t* context = get_thread_error_context(); if( !context ) { context = memory_allocate_zero( sizeof( error_context_t ), 0, MEMORY_PERSISTENT ); set_thread_error_context( context ); } FOUNDATION_ASSERT_MSG( context->depth < BUILD_SIZE_ERROR_CONTEXT_DEPTH, "Error context stack overflow" ); context->frame[ context->depth ].name = name; context->frame[ context->depth ].data = data; if( context->depth < BUILD_SIZE_ERROR_CONTEXT_DEPTH-1 ) ++context->depth; }
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; }
stream_t* ringbuffer_stream_allocate( unsigned int buffer_size, uint64_t total_size ) { ringbuffer_stream_t* bufferstream = memory_allocate_zero( sizeof( ringbuffer_stream_t ) + buffer_size, 0, MEMORY_PERSISTENT ); stream_t* stream = (stream_t*)bufferstream; _stream_initialize( stream, system_byteorder() ); stream->type = STREAMTYPE_RINGBUFFER; stream->sequential = 1; stream->path = string_format( "ringbuffer://" STRING_FORMAT_POINTER, stream ); stream->mode = STREAM_OUT | STREAM_IN | STREAM_BINARY; semaphore_initialize( &bufferstream->signal_read, 0 ); semaphore_initialize( &bufferstream->signal_write, 0 ); bufferstream->pending_read = 0; bufferstream->pending_write = 0; bufferstream->total_size = total_size; bufferstream->buffer_size = buffer_size; stream->vtable = &_ringbuffer_stream_vtable; return stream; }
process_t* process_allocate() { process_t* proc = memory_allocate_zero( sizeof( process_t ), 0, MEMORY_PERSISTENT ); proc->flags = PROCESS_ATTACHED; return proc; }
int process_spawn( process_t* proc ) { static char unescaped[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.:/\\"; int i, num_args; int size; #if FOUNDATION_PLATFORM_WINDOWS wchar_t* wcmdline; wchar_t* wwd; char* cmdline = 0; #endif if( !proc ) return PROCESS_INVALID_ARGS; proc->code = PROCESS_INVALID_ARGS; if( !string_length( proc->path ) ) return proc->code; //Always escape path on Windows platforms #if FOUNDATION_PLATFORM_POSIX if( string_find_first_not_of( proc->path, unescaped, 0 ) != STRING_NPOS ) #endif { if( proc->path[0] != '"' ) proc->path = string_prepend( proc->path, "\"" ); if( proc->path[ string_length( proc->path ) - 1 ] != '"' ) proc->path = string_append( proc->path, "\"" ); } size = array_size( proc->args ); for( i = 0, num_args = 0; i < size; ++i ) { char* arg = proc->args[i]; if( !string_length( arg ) ) continue; ++num_args; if( string_find_first_not_of( arg, unescaped, 0 ) != STRING_NPOS ) { if( arg[0] != '"' ) { //Check if we need to escape " characters unsigned int pos = string_find( arg, '"', 0 ); while( pos != STRING_NPOS ) { if( arg[ pos - 1 ] != '\\' ) { char* escarg = string_substr( arg, 0, pos ); char* left = string_substr( arg, pos, STRING_NPOS ); escarg = string_append( escarg, "\\" ); escarg = string_append( escarg, left ); string_deallocate( left ); string_deallocate( arg ); arg = escarg; } pos = string_find( arg, '"', pos + 2 ); } arg = string_prepend( arg, "\"" ); arg = string_append( arg, "\"" ); proc->args[i] = arg; } } } #if FOUNDATION_PLATFORM_WINDOWS # ifndef SEE_MASK_NOASYNC # define SEE_MASK_NOASYNC 0x00000100 # endif if( !( proc->flags & PROCESS_WINDOWS_USE_SHELLEXECUTE ) ) //Don't prepend exe path to parameters if using ShellExecute cmdline = string_clone( proc->path ); //Build command line string for( i = 0; i < size; ++i ) { char* arg = proc->args[i]; if( !string_length( arg ) ) continue; if( cmdline ) cmdline = string_append( cmdline, " " ); cmdline = string_append( cmdline, arg ); } if( !string_length( proc->wd ) ) proc->wd = string_clone( environment_current_working_directory() ); wcmdline = wstring_allocate_from_string( cmdline, 0 ); wwd = wstring_allocate_from_string( proc->wd, 0 ); if( proc->flags & PROCESS_WINDOWS_USE_SHELLEXECUTE ) { SHELLEXECUTEINFOW sei; wchar_t* wverb; wchar_t* wpath; wverb = ( proc->verb && string_length( proc->verb ) ) ? wstring_allocate_from_string( proc->verb, 0 ) : 0; wpath = wstring_allocate_from_string( proc->path, 0 ); ZeroMemory( &sei, sizeof( sei ) ); sei.cbSize = sizeof(SHELLEXECUTEINFOW); sei.hwnd = 0; sei.fMask = SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; sei.lpVerb = wverb; sei.lpFile = wpath; sei.lpParameters = wcmdline; sei.lpDirectory = wwd; sei.nShow = SW_SHOWNORMAL; if( !( proc->flags & PROCESS_CONSOLE ) ) sei.fMask |= SEE_MASK_NO_CONSOLE; if( proc->flags & PROCESS_STDSTREAMS ) log_warnf( 0, WARNING_UNSUPPORTED, "Unable to redirect standard in/out through pipes when using ShellExecute for process spawning" ); log_debugf( 0, "Spawn process (ShellExecute): %s %s", proc->path, cmdline ); if( !ShellExecuteExW( &sei ) ) { log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to spawn process (ShellExecute) for executable '%s': %s", proc->path, system_error_message( GetLastError() ) ); } else { proc->hp = sei.hProcess; proc->ht = 0; proc->code = 0; } wstring_deallocate( wverb ); wstring_deallocate( wpath ); } else { STARTUPINFOW si; PROCESS_INFORMATION pi; BOOL inherit_handles = FALSE; memset( &si, 0, sizeof( si ) ); memset( &pi, 0, sizeof( pi ) ); si.cb = sizeof( si ); if( proc->flags & PROCESS_STDSTREAMS ) { proc->pipeout = pipe_allocate(); proc->pipein = pipe_allocate(); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdOutput = pipe_write_handle( proc->pipeout ); si.hStdError = pipe_write_handle( proc->pipeout ); si.hStdInput = pipe_read_handle( proc->pipein ); //Don't inherit wrong ends of pipes SetHandleInformation( pipe_read_handle( proc->pipeout ), HANDLE_FLAG_INHERIT, 0 ); SetHandleInformation( pipe_write_handle( proc->pipein ), HANDLE_FLAG_INHERIT, 0 ); inherit_handles = TRUE; } log_debugf( 0, "Spawn process (CreateProcess): %s %s", proc->path, cmdline ); if( !CreateProcessW( 0/*wpath*/, wcmdline, 0, 0, inherit_handles, ( proc->flags & PROCESS_CONSOLE ) ? CREATE_NEW_CONSOLE : 0, 0, wwd, &si, &pi ) ) { log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to spawn process (CreateProcess) for executable '%s': %s", proc->path, system_error_message( GetLastError() ) ); stream_deallocate( proc->pipeout ); stream_deallocate( proc->pipein ); proc->pipeout = 0; proc->pipein = 0; } else { proc->hp = pi.hProcess; proc->ht = pi.hThread; proc->code = 0; } if( proc->pipeout ) pipe_close_write( proc->pipeout ); if( proc->pipein ) pipe_close_read( proc->pipein ); } wstring_deallocate( wcmdline ); wstring_deallocate( wwd ); string_deallocate( cmdline ); if( proc->code < 0 ) return proc->code; //Error #endif #if FOUNDATION_PLATFORM_MACOSX if( proc->flags & PROCESS_OSX_USE_OPENAPPLICATION ) { proc->pid = 0; LSApplicationParameters params; ProcessSerialNumber psn; FSRef* fsref = memory_allocate_zero( sizeof( FSRef ), 0, MEMORY_TEMPORARY ); memset( ¶ms, 0, sizeof( LSApplicationParameters ) ); memset( &psn, 0, sizeof( ProcessSerialNumber ) ); char* pathstripped = string_strip( string_clone( proc->path ), "\"" ); OSStatus status = 0; status = FSPathMakeRef( (uint8_t*)pathstripped, fsref, 0 ); if( status < 0 ) { pathstripped = string_append( pathstripped, ".app" ); status = FSPathMakeRef( (uint8_t*)pathstripped, fsref, 0 ); } CFStringRef* args = 0; for( i = 0, size = array_size( proc->args ); i < size; ++i ) //App gets executable path automatically, don't include array_push( args, CFStringCreateWithCString( 0, proc->args[i], kCFStringEncodingUTF8 ) ); CFArrayRef argvref = CFArrayCreate( 0, (const void**)args, (CFIndex)array_size( args ), 0 ); params.flags = kLSLaunchDefaults; params.application = fsref; params.argv = argvref; log_debugf( 0, "Spawn process (LSOpenApplication): %s", pathstripped ); status = LSOpenApplication( ¶ms, &psn ); if( status != 0 ) { proc->code = status; log_warnf( 0, WARNING_BAD_DATA, "Unable to spawn process for executable '%s': %s", proc->path, system_error_message( status ) ); } CFRelease( argvref ); for( i = 0, size = array_size( args ); i < size; ++i ) CFRelease( args[i] ); memory_deallocate( fsref ); string_deallocate( pathstripped ); if( status == 0 ) { pid_t pid = 0; GetProcessPID( &psn, &pid ); proc->pid = pid; //Always "detached" with LSOpenApplication, not a child process at all //Setup a kqueue to watch when process terminates so we can emulate a wait proc->kq = kqueue(); if( proc->kq < 0 ) { log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to create kqueue for process watch: %s (%d)", proc->kq, system_error_message( proc->kq ) ); proc->kq = 0; } else { struct kevent changes; EV_SET( &changes, (pid_t)pid, EVFILT_PROC, EV_ADD | EV_RECEIPT, NOTE_EXIT, 0, 0 ); int ret = kevent( proc->kq, &changes, 1, &changes, 1, 0 ); if( ret != 1 ) { log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to setup kqueue for process watch, failed to add event to kqueue (%d)", ret ); close( proc->kq ); proc->kq = 0; } } } goto exit; } #endif #if FOUNDATION_PLATFORM_POSIX //Insert executable arg at start and null ptr at end int argc = array_size( proc->args ) + 1; array_grow( proc->args, 2 ); for( int arg = argc - 1; arg > 0; --arg ) proc->args[arg] = proc->args[arg-1]; proc->args[0] = string_clone( proc->path ); proc->args[argc] = 0; if( proc->flags & PROCESS_STDSTREAMS ) { proc->pipeout = pipe_allocate(); proc->pipein = pipe_allocate(); } proc->pid = 0; pid_t pid = fork(); if( pid == 0 ) { //Child if( string_length( proc->wd ) ) { log_debugf( 0, "Spawned child process, setting working directory to %s", proc->wd ); environment_set_current_working_directory( proc->wd ); } log_debugf( 0, "Child process executing: %s", proc->path ); if( proc->flags & PROCESS_STDSTREAMS ) { pipe_close_read( proc->pipeout ); dup2( pipe_write_fd( proc->pipeout ), STDOUT_FILENO ); pipe_close_write( proc->pipein ); dup2( pipe_read_fd( proc->pipein ), STDIN_FILENO ); } int code = execv( proc->path, proc->args ); if( code < 0 ) //Will always be true since this point will never be reached if execve() is successful log_warnf( 0, WARNING_BAD_DATA, "Child process failed execve() : %s : %s", proc->path, system_error_message( errno ) ); //Error process_exit( -1 ); } if( pid > 0 ) { log_debugf( 0, "Child process forked, pid %d", pid ); proc->pid = pid; if( proc->pipeout ) pipe_close_write( proc->pipeout ); if( proc->pipein ) pipe_close_read( proc->pipein ); if( proc->flags & PROCESS_DETACHED ) { int cstatus = 0; pid_t err = waitpid( pid, &cstatus, WNOHANG ); if( err == 0 ) { //TODO: Ugly wait to make sure process spawned correctly thread_sleep( 500 ); err = waitpid( pid, &cstatus, WNOHANG ); } if( err > 0 ) { //Process exited, check code proc->code = (int)((char)WEXITSTATUS( cstatus )); log_debugf( 0, "Child process returned: %d", proc->code ); return proc->code; } } } else { //Error proc->code = errno; log_warnf( 0, WARNING_BAD_DATA, "Unable to spawn process: %s : %s", proc->path, system_error_message( proc->code ) ); if( proc->pipeout ) stream_deallocate( proc->pipeout ); if( proc->pipein ) stream_deallocate( proc->pipein ); proc->pipeout = 0; proc->pipein = 0; return proc->code; } #endif #if !FOUNDATION_PLATFORM_WINDOWS && !FOUNDATION_PLATFORM_POSIX FOUNDATION_ASSERT_FAIL( "Process spawning not supported on platform" ); #endif #if FOUNDATION_PLATFORM_MACOSX exit: #endif if( proc->flags & PROCESS_DETACHED ) return PROCESS_STILL_ACTIVE; return process_wait( proc ); }
DECLARE_TEST( ringbufferstream, threadedio ) { ringbufferstream_test_t test = {0}; uint32_t* srcbuffer; unsigned int si; unsigned int loop, loops; real elapsed, throughput; unsigned int mbytes; #if FOUNDATION_PLATFORM_ANDROID || FOUNDATION_PLATFORM_IOS mbytes = 16; loops = 32; #else mbytes = 256; loops = 16; #endif test.buffer_size = mbytes * 1024 * 1024; srcbuffer = memory_allocate( test.buffer_size, 0, MEMORY_PERSISTENT ); test.source_buffer = (void*)srcbuffer; test.dest_buffer = memory_allocate_zero( test.buffer_size, 0, MEMORY_PERSISTENT ); for( si = 0; si < ( test.buffer_size / 4 ); ++si ) srcbuffer[si] = random32(); elapsed = 0; for( loop = 0; loop < loops; ++loop ) { test.stream = ringbuffer_stream_allocate( 23477, test.buffer_size ); test.read_thread = thread_create( read_thread, "reader", THREAD_PRIORITY_NORMAL, 0 ); test.write_thread = thread_create( write_thread, "writer", THREAD_PRIORITY_NORMAL, 0 ); thread_start( test.read_thread, &test ); thread_start( test.write_thread, &test ); thread_sleep( 100 ); while( thread_is_running( test.read_thread ) || thread_is_running( test.write_thread ) ) thread_sleep( 10 ); thread_destroy( test.read_thread ); thread_destroy( test.write_thread ); for( si = 0; si < test.buffer_size; ++si ) EXPECT_EQ( test.source_buffer[si], test.dest_buffer[si] ); stream_deallocate( test.stream ); elapsed += time_ticks_to_seconds( time_diff( test.start_time, test.end_time ) ); } throughput = (real)( (float64_t)( mbytes * loops ) / (float64_t)elapsed ); log_infof( HASH_TEST, "Ringbuffer throughput: %d MiB in %.2f sec -> %.2f MiB/sec", ( loops * mbytes ), (float32_t)elapsed, (float32_t)throughput ); elapsed = 0; for( loop = 0; loop < loops; ++loop ) { test.start_time = time_current(); memcpy( test.dest_buffer, test.source_buffer, test.buffer_size ); test.end_time = time_current(); for( si = 0; si < test.buffer_size; ++si ) EXPECT_EQ( test.source_buffer[si], test.dest_buffer[si] ); elapsed += time_ticks_to_seconds( time_diff( test.start_time, test.end_time ) ); } throughput = (real)( (float64_t)( mbytes * loops ) / (float64_t)elapsed ); log_infof( HASH_TEST, "Memcpy throughput: %d MiB in %.2f sec -> %.2f MiB/sec", ( loops * mbytes ), (float32_t)elapsed, (float32_t)throughput ); memory_deallocate( test.source_buffer ); memory_deallocate( test.dest_buffer ); return 0; }
void config_parse( stream_t* stream, hash_t filter_section, bool overwrite ) { char* buffer; hash_t section = 0; hash_t key = 0; unsigned int line = 0; #if BUILD_ENABLE_DEBUG_CONFIG log_debugf( HASH_CONFIG, "Parsing config stream: %s", stream_path( stream ) ); #endif buffer = memory_allocate_zero( 1024ULL, 0, MEMORY_TEMPORARY ); while( !stream_eos( stream ) ) { ++line; stream_read_line_buffer( stream, buffer, 1024, '\n' ); string_strip( buffer, " \t\n\r" ); if( !string_length( buffer ) || ( buffer[0] == ';' ) || ( buffer[0] == '#' ) ) continue; if( buffer[0] == '[' ) { //Section declaration unsigned int endpos = string_rfind( buffer, ']', string_length( buffer ) - 1 ); if( ( endpos == STRING_NPOS ) || ( endpos < 1 ) ) { log_warnf( HASH_CONFIG, WARNING_BAD_DATA, "Invalid section declaration on line %d in config stream '%s'", line, stream_path( stream ) ); continue; } buffer[endpos] = 0; section = hash( buffer + 1, endpos - 1 ); #if BUILD_ENABLE_DEBUG_CONFIG log_debugf( HASH_CONFIG, " config: section set to '%s' (0x%llx)", buffer + 1, section ); #endif } else if( !filter_section || ( filter_section == section ) ) { //name=value declaration char* name; char* value; unsigned int separator = string_find( buffer, '=', 0 ); if( separator == STRING_NPOS ) { log_warnf( HASH_CONFIG, WARNING_BAD_DATA, "Invalid value declaration on line %d in config stream '%s', missing assignment operator '=': %s", line, stream_path( stream ), buffer ); continue; } name = string_strip_substr( buffer, " \t", separator ); value = string_strip( buffer + separator + 1, " \t" ); if( !string_length( name ) ) { log_warnf( HASH_CONFIG, WARNING_BAD_DATA, "Invalid value declaration on line %d in config stream '%s', empty name string", line, stream_path( stream ) ); continue; } key = hash( name, string_length( name ) ); if( overwrite || !config_key( section, key, false ) ) { #if BUILD_ENABLE_DEBUG_CONFIG log_debugf( HASH_CONFIG, " config: %s (0x%llx) = %s", name, key, value ); #endif if( !string_length( value ) ) 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 config_set_string( section, key, value ); } } } memory_deallocate( buffer ); }
ringbuffer_t* ringbuffer_allocate( unsigned int size ) { ringbuffer_t* buffer = memory_allocate_zero( sizeof( ringbuffer_t ) + size, 0, MEMORY_PERSISTENT ); buffer->buffer_size = size; return buffer; }
object_t library_load( const char* name ) { library_t* library; hash_t namehash; unsigned int i, size; uint64_t id; #if FOUNDATION_PLATFORM_WINDOWS char* dllname; HANDLE dll; #endif //Locate already loaded library library = 0; namehash = string_hash( name ); for( i = 0, size = objectmap_size( _library_map ); i < size; ++i ) { library = objectmap_raw_lookup( _library_map, i ); if( library && ( library->namehash == namehash ) ) { FOUNDATION_ASSERT( string_equal( library->name, name ) ); atomic_incr32( &library->ref ); return library->id; } } error_context_push( "loading library", name ); //Try loading library #if FOUNDATION_PLATFORM_WINDOWS dllname = string_format( "%s.dll", name ); dll = LoadLibraryA( dllname ); if( !dll ) { #if FOUNDATION_PLATFORM_ARCH_X86 string_deallocate( dllname ); dllname = string_format( "%s32.dll", name ); dll = LoadLibraryA( dllname ); #elif FOUNDATION_PLATFORM_ARCH_X86_64 string_deallocate( dllname ); dllname = string_format( "%s64.dll", name ); dll = LoadLibraryA( dllname ); #endif } string_deallocate( dllname ); if( !dll ) { log_warnf( 0, WARNING_SUSPICIOUS, "Unable to load DLL '%s': %s", name, system_error_message( 0 ) ); error_context_pop(); return 0; } #elif FOUNDATION_PLATFORM_POSIX # if FOUNDATION_PLATFORM_APPLE char* libname = string_format( "lib%s.dylib", name ); # else char* libname = string_format( "lib%s.so", name ); # endif void* lib = dlopen( libname, RTLD_LAZY ); string_deallocate( libname ); #if FOUNDATION_PLATFORM_ANDROID if( !lib ) { libname = string_format( "%s/lib%s.so", environment_executable_directory(), name ); lib = dlopen( libname, RTLD_LAZY ); string_deallocate( libname ); } #endif if( !lib ) { log_warnf( 0, WARNING_SUSPICIOUS, "Unable to load dynamic library '%s': %s", name, dlerror() ); error_context_pop(); return 0; } #else log_errorf( 0, ERROR_NOT_IMPLEMENTED, "Dynamic library loading not implemented for this platform: %s", name ); error_context_pop(); return 0; #endif id = objectmap_reserve( _library_map ); if( !id ) { #if FOUNDATION_PLATFORM_WINDOWS FreeLibrary( dll ); #elif FOUNDATION_PLATFORM_POSIX dlclose( lib ); #endif log_errorf( 0, ERROR_OUT_OF_MEMORY, "Unable to allocate new library '%s', map full", name ); error_context_pop(); return 0; } library = memory_allocate_zero( sizeof( library_t ), 0, MEMORY_PERSISTENT ); library->ref = 1; library->id = id; library->namehash = string_hash( name ); string_copy( library->name, name, 32 ); #if FOUNDATION_PLATFORM_WINDOWS library->dll = dll; #elif FOUNDATION_PLATFORM_POSIX library->lib = lib; #endif objectmap_set( _library_map, id, library ); error_context_pop(); return library->id; }
blowfish_t* blowfish_allocate( void ) { return memory_allocate_zero( (uint64_t)sizeof( blowfish_t ), 0U, MEMORY_PERSISTENT ); }