<commit_before>/* log.c  -  Foundation library  -  Public Domain  -  2013 <NAME> / Rampant Pixels
 * 
 * This library provides a cross-platform foundation library in C11 providing basic support data types and
 * functions to write applications and games in a platform-independent fashion. The latest source code is
 * always available at
 * 
 * https://github.com/rampantpixels/foundation_lib
 * 
 * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions.
 *
 */

#include <foundation/foundation.h>
#include <foundation/internal.h>

#include <stdio.h>
#include <stdarg.h>

#if FOUNDATION_PLATFORM_WINDOWS
#include <foundation/windows.h>
#  define snprintf( p, s, ... ) _snprintf_s( p, s, _TRUNCATE, __VA_ARGS__ )
#  define vsnprintf( s, n, format, arg ) _vsnprintf_s( s, n, _TRUNCATE, format, arg )
__declspec(dllimport) void STDCALL OutputDebugStringA(LPCSTR);
#endif

#if FOUNDATION_PLATFORM_ANDROID
#  include <android/log.h>
#endif

#if FOUNDATION_PLATFORM_POSIX
#  include <foundation/posix.h>
#endif

static bool             _log_stdout           = true;
static bool             _log_prefix           = true;
static log_callback_fn  _log_callback         = 0;
static hashtable64_t*   _log_suppress         = 0;
static error_level_t    _log_suppress_default = ERRORLEVEL_NONE;

static char _log_warning_name[WARNING_LAST_BUILTIN][18] = {
	"performance",
	"deprecated",
	"bad data",
	"memory",
	"unsupported",
	"suspicious",
	"system call fail",
	"deadlock",
	"script"
};

static char _log_error_name[ERROR_LAST_BUILTIN][18] = {
	"none",
	"invalid value",
	"unsupported",
	"not implemented",
	"out of memory",
	"memory leak",
	"memory alignment",
	"internal failure",
	"access denied",
	"exception",
	"system call fail",
	"unknown type",
	"unknown resource",
	"deprecated",
	"assert",
	"script"
};


typedef struct _log_timestamp
{
	unsigned int   hours;
	unsigned int   minutes;
	unsigned int   seconds;
	unsigned int   milliseconds;
} log_timestamp_t;


static log_timestamp_t _log_make_timestamp( void )
{
	tick_t elapsed = time_current() - time_startup();
	tick_t ticks_per_sec = time_ticks_per_second();

	log_timestamp_t timestamp;
	
	uint64_t milliseconds = ( ( elapsed % ticks_per_sec ) * 1000ULL ) / ticks_per_sec;
	uint64_t seconds = elapsed / ticks_per_sec;
	uint64_t minutes = seconds / 60ULL;

	timestamp.milliseconds = (unsigned int)( milliseconds % 1000ULL );
	timestamp.seconds = (unsigned int)( seconds % 60ULL );
	timestamp.minutes = (unsigned int)( minutes % 60ULL );
	timestamp.hours = (unsigned int)( minutes / 24ULL );

	return timestamp;
}


#if BUILD_ENABLE_LOG || BUILD_ENABLE_DEBUG_LOG

#if FOUNDATION_PLATFORM_WINDOWS
#  define LOG_USE_VACOPY 0
#else
#  define LOG_USE_VACOPY 1
#endif

static void _log_outputf( uint64_t context, int severity, const char* prefix, const char* format, va_list list, void* std )
{
	log_timestamp_t timestamp = _log_make_timestamp();
	uint64_t tid = thread_id();
	unsigned int pid = thread_hardware();
	int need, more, remain, size = 383;
	char local_buffer[385];
	char* buffer = local_buffer;
	while(1)
	{
		//This is guaranteed to always fit in minimum size of 383 bytes defined above, so need is always > 0
		if( _log_prefix )
			need = snprintf( buffer, size, "[%u:%02u:%02u.%03u] <%" PRIx64 ":%d> %s", timestamp.hours, timestamp.minutes, timestamp.seconds, timestamp.milliseconds, tid, pid, prefix );
		else
			need = snprintf( buffer, size, "%s", prefix );

		remain = size - need;
#if LOG_USE_VACOPY
		{
			va_list clist;
			va_copy( clist, list );
			more = vsnprintf( buffer + need, remain, format, clist );
			va_end( clist );
		}
#else
		more = vsnprintf( buffer + need, remain, format, list );
#endif
			
		if( ( more > -1 ) && ( more < remain ) )
		{
			buffer[need+more] = '\n';
			buffer[need+more+1] = 0;

#if FOUNDATION_PLATFORM_WINDOWS
			OutputDebugStringA( buffer );
#endif

#if FOUNDATION_PLATFORM_ANDROID
			if( _log_stdout )
				__android_log_write( ANDROID_LOG_DEBUG + severity, environment_application()->short_name, buffer );
#else
			if( _log_stdout && std )
				fprintf( std, "%s", buffer );
#endif

			if( _log_callback )
				_log_callback( context, severity, buffer );

			break;
		}

		if( ( more > -1 ) && ( need > -1 ) )<commit_msg>properly set android log level from foundation level<commit_after>/* log.c  -  Foundation library  -  Public Domain  -  2013 <NAME> / Rampant Pixels
 * 
 * This library provides a cross-platform foundation library in C11 providing basic support data types and
 * functions to write applications and games in a platform-independent fashion. The latest source code is
 * always available at
 * 
 * https://github.com/rampantpixels/foundation_lib
 * 
 * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions.
 *
 */

#include <foundation/foundation.h>
#include <foundation/internal.h>

#include <stdio.h>
#include <stdarg.h>

#if FOUNDATION_PLATFORM_WINDOWS
#include <foundation/windows.h>
#  define snprintf( p, s, ... ) _snprintf_s( p, s, _TRUNCATE, __VA_ARGS__ )
#  define vsnprintf( s, n, format, arg ) _vsnprintf_s( s, n, _TRUNCATE, format, arg )
__declspec(dllimport) void STDCALL OutputDebugStringA(LPCSTR);
#endif

#if FOUNDATION_PLATFORM_ANDROID
#  include <android/log.h>
#endif

#if FOUNDATION_PLATFORM_POSIX
#  include <foundation/posix.h>
#endif

static bool             _log_stdout           = true;
static bool             _log_prefix           = true;
static log_callback_fn  _log_callback         = 0;
static hashtable64_t*   _log_suppress         = 0;
static error_level_t    _log_suppress_default = ERRORLEVEL_NONE;

static char _log_warning_name[WARNING_LAST_BUILTIN][18] = {
	"performance",
	"deprecated",
	"bad data",
	"memory",
	"unsupported",
	"suspicious",
	"system call fail",
	"deadlock",
	"script"
};

static char _log_error_name[ERROR_LAST_BUILTIN][18] = {
	"none",
	"invalid value",
	"unsupported",
	"not implemented",
	"out of memory",
	"memory leak",
	"memory alignment",
	"internal failure",
	"access denied",
	"exception",
	"system call fail",
	"unknown type",
	"unknown resource",
	"deprecated",
	"assert",
	"script"
};


typedef struct _log_timestamp
{
	unsigned int   hours;
	unsigned int   minutes;
	unsigned int   seconds;
	unsigned int   milliseconds;
} log_timestamp_t;


static log_timestamp_t _log_make_timestamp( void )
{
	tick_t elapsed = time_current() - time_startup();
	tick_t ticks_per_sec = time_ticks_per_second();

	log_timestamp_t timestamp;
	
	uint64_t milliseconds = ( ( elapsed % ticks_per_sec ) * 1000ULL ) / ticks_per_sec;
	uint64_t seconds = elapsed / ticks_per_sec;
	uint64_t minutes = seconds / 60ULL;

	timestamp.milliseconds = (unsigned int)( milliseconds % 1000ULL );
	timestamp.seconds = (unsigned int)( seconds % 60ULL );
	timestamp.minutes = (unsigned int)( minutes % 60ULL );
	timestamp.hours = (unsigned int)( minutes / 24ULL );

	return timestamp;
}


#if BUILD_ENABLE_LOG || BUILD_ENABLE_DEBUG_LOG

#if FOUNDATION_PLATFORM_WINDOWS
#  define LOG_USE_VACOPY 0
#else
#  define LOG_USE_VACOPY 1
#endif

static void _log_outputf( uint64_t context, int severity, const char* prefix, const char* format, va_list list, void* std )
{
	log_timestamp_t timestamp = _log_make_timestamp();
	uint64_t tid = thread_id();
	unsigned int pid = thread_hardware();
	int need, more, remain, size = 383;
	char local_buffer[385];
	char* buffer = local_buffer;
	while(1)
	{
		//This is guaranteed to always fit in minimum size of 383 bytes defined above, so need is always > 0
		if( _log_prefix )
			need = snprintf( buffer, size, "[%u:%02u:%02u.%03u] <%" PRIx64 ":%d> %s", timestamp.hours, timestamp.minutes, timestamp.seconds, timestamp.milliseconds, tid, pid, prefix );
		else
			need = snprintf( buffer, size, "%s", prefix );

		remain = size - need;
#if LOG_USE_VACOPY
		{
			va_list clist;
			va_copy( clist, list );
			more = vsnprintf( buffer + need, remain, format, clist );
			va_end( clist );
		}
#else
		more = vsnprintf( buffer + need, remain, format, list );
#endif
			
		if( ( more > -1 ) && ( more < remain ) )
		{
			buffer[need+more] = '\n';
			buffer[need+more+1] = 0;

#if FOUNDATION_PLATFORM_WINDOWS
			OutputDebugStringA( buffer );
#endif

#if FOUNDATION_PLATFORM_ANDROID
			if( _log_stdout )
				__android_log_write( ANDROID_LOG_DEBUG + severity - 1, environment_application()->short_name, buffer );
#else
			if( _log_stdout && std )
				fprintf( std, "%s", buffer );
#endif

			if( _log_callback )
				_log_callback( context, severity, buffer );

			break;
		}

		if( ( more > -1 ) && ( need > -1 ) )
{'fraction_non_alphanumeric': 0.1124287873503081, 'fraction_numerical': 0.015463318218811766, 'mean_word_length': 4.105044510385756, 'pattern_counts': {'":': 2, '<': 23, '<?xml version=': 0, '>': 31, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '299798', 'n_tokens_mistral': 3215, 'n_tokens_neox': 2936, 'n_words': 824}