<commit_before>/**
 * Copyright 2015 opencxa.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @author <NAME>
 */
#include "cxa_logger_implementation.h"


// ******** includes ********
#include <stdarg.h>
#include <string.h>
#include <inttypes.h>
#include <cxa_assert.h>
#include <cxa_numberUtils.h>
#include <cxa_stringUtils.h>
#include <cxa_timeBase.h>


// ******** local macro definitions ********
#ifndef CXA_LOGGER_BUFFERLEN_BYTES
	#define CXA_LOGGER_BUFFERLEN_BYTES			24
#endif

#define CXA_LOGGER_TRUNCATE_STRING			"..."


// ******** local type definitions ********


// ******** local function prototypes ********
static inline void checkSysLogInit(void);
static void writeField(const char *const stringIn, size_t maxFieldLenIn);
static void writeHeader(cxa_logger_t *const loggerIn, const uint8_t levelIn);


// ********  local variable declarations *********
static cxa_logger_t sysLog;
static bool isSysLogInit = false;

static cxa_ioStream_t* ioStream = NULL;
static size_t largestloggerName_bytes = 0;


// ******** global function implementations ********
void cxa_logger_setGlobalIoStream(cxa_ioStream_t *const ioStreamIn)
{
	checkSysLogInit();

	ioStream = ioStreamIn;

	cxa_ioStream_writeBytes(ioStream, (void*)CXA_LINE_ENDING, sizeof(CXA_LINE_ENDING));
	cxa_ioStream_writeBytes(ioStream, (void*)CXA_LINE_ENDING, sizeof(CXA_LINE_ENDING));
	cxa_logger_vlog(&sysLog, CXA_LOG_LEVEL_INFO, "logging ioStream @ %p", ioStreamIn);
}


void cxa_logger_init(cxa_logger_t *const loggerIn, const char *nameIn)
{
	cxa_assert(loggerIn);
	cxa_assert(nameIn);
	checkSysLogInit();

	// copy our name (and make sure it will be null terminated)
	strncpy(loggerIn->name, nameIn, CXA_LOGGER_MAX_NAME_LEN_CHARS);
	loggerIn->name[CXA_LOGGER_MAX_NAME_LEN_CHARS-1] = 0;

	size_t nameLen_bytes = strlen(loggerIn->name);
	if( nameLen_bytes > largestloggerName_bytes ) largestloggerName_bytes = nameLen_bytes;
}


void cxa_logger_vinit(cxa_logger_t *const loggerIn, const char *nameFmtIn, ...)
{
	cxa_assert(loggerIn);
	cxa_assert(nameFmtIn);
	checkSysLogInit();

	va_list varArgs;
	va_start(varArgs, nameFmtIn);
	vsnprintf(loggerIn->name, CXA_LOGGER_MAX_NAME_LEN_CHARS, nameFmtIn, varArgs);
	loggerIn->name[CXA_LOGGER_MAX_NAME_LEN_CHARS-1] = 0;
	va_end(varArgs);

	size_t nameLen_bytes = strlen(loggerIn->name);
	if( nameLen_bytes > largestloggerName_bytes ) largestloggerName_bytes = nameLen_bytes;
}


cxa_logger_t* cxa_logger_getSysLog(void)
{
	return &sysLog;
}


void cxa_logger_log_untermString(cxa_logger_t *const loggerIn, const uint8_t levelIn, const char* prefixIn, const char* untermStringIn, size_t untermStrLen_bytesIn, const char* postFixIn)
{
	cxa_assert(loggerIn);
	cxa_assert(loggerIn);
	cxa_assert( (levelIn == CXA_LOG_LEVEL_ERROR) ||
				(levelIn == CXA_LOG_LEVEL_WARN) ||
				(levelIn == CXA_LOG_LEVEL_INFO) ||
				(levelIn == CXA_LOG_LEVEL_DEBUG) ||
				(levelIn == CXA_LOG_LEVEL_TRACE) );
	cxa_assert(untermStringIn);
	checkSysLogInit();

	// if we don't have an ioStream, don't worry about it!
	if( ioStream == NULL ) return;

	// common header
	writeHeader(loggerIn, levelIn);

	if( prefixIn != NULL ) cxa_ioStream_writeString(ioStream, (char *const)prefixIn);
	cxa_ioStream_writeBytes(ioStream, (void *const)untermStringIn, untermStrLen_bytesIn);
	if( postFixIn != NULL ) cxa_ioStream_writeString(ioStream, (char *const)postFixIn);

	// print EOL
	cxa_ioStream_writeBytes(ioStream, (void*)CXA_LINE_ENDING, strlen(CXA_LINE_ENDING));
}


void cxa_logger_stepDebug_vlog(const char* fileIn, const int lineNumIn, const char* formatIn, ...)
{
	cxa_assert(fileIn);

	// if we don't have an ioStream, don't worry about it!
	if( ioStream == NULL ) return;

	// shorten our file name
	char *file_sep = strrchr(fileIn, '/');
	if(file_sep) fileIn = file_sep+1;

	// common header
	writeHeader(&sysLog, CXA_LOG_LEVEL_DEBUG);

	// our buffer for this go-round
	char buff[CXA_LOGGER_BUFFERLEN_BYTES];

	// print our location
	size_t expectedNumBytesWritten = snprintf(buff, sizeof(buff), ((formatIn != NULL) ? "%s::%d - " : "%s::%d"), fileIn, lineNumIn);
	cxa_ioStream_writeBytes(ioStream, buff, CXA_MIN(expectedNumBytesWritten, sizeof(buff)));
	if( sizeof(buff) < expectedNumBytesWritten )
	{
		cxa_ioStream_writeBytes(ioStream, (void*)CXA_LOGGER_TRUNCATE_STRING, strlen(CXA_LOGGER_TRUNCATE_STRING));
	}

	// now do our VARARGS
	va_list varArgs;
	va_start(varArgs, formatIn);
	expectedNumBytesWritten = vsnprintf(buff, sizeof(buff), formatIn, varArgs);
	cxa_ioStream_writeBytes(ioStream, buff, CXA_MIN(expectedNumBytesWritten, sizeof(buff)));
	if( sizeof(buff) < expectedNumBytesWritten )
	{
		cxa_ioStream_writeBytes(ioStream, (void*)CXA_LOGGER_TRUNCATE_STRING, strlen(CXA_LOGGER_TRUNCATE_STRING));
	}
	va_end(varArgs);

	// print EOL
	cxa_ioStream_writeBytes(ioStream, (void*)CXA_LINE_ENDING, strlen(CXA_LINE_ENDING));
}


void cxa_logger_vlog(cxa_logger_t *const loggerIn, const uint8_t levelIn, const char *formatIn, ...)
{
	cxa_assert(loggerIn);
	cxa_assert( (levelIn == CXA_LOG_LEVEL_ERROR) ||
				(levelIn == CXA_LOG_LEVEL_WARN) ||
				(levelIn == CXA_LOG_LEVEL_INFO) ||
				(levelIn == CXA_LOG_LEVEL_DEBUG) ||
				(levelIn == CXA_LOG_LEVEL_TRACE) );
	cxa_assert(formatIn);
	checkSysLogInit();

	// if we don't have an ioStream, don't worry about it!
	if( ioStream == NULL ) return;

	// common header
	writeHeader(loggerIn, levelIn);

	// our buffer for this go-round
	char buff[CXA_LOGGER_BUFFERLEN_BYTES];

	// now do our VARARGS
	va_list varArgs;
	va_start(varArgs, formatIn);
	size_t expectedNumBytesWritten = vsnprintf(buff, sizeof(buff), formatIn, varArgs);
	cxa_ioStream_writeBytes(ioStream, buff, CXA_MIN(expectedNumBytesWritten, sizeof(buff)));
	if( sizeof(buff) < expectedNumBytesWritten )
	{
		cxa_ioStream_writeBytes(ioStream, (void*)CXA_LOGGER_TRUNCATE_STRING, strlen(CXA_LOGGER_TRUNCATE_STRING));
	}
	va_end(varArgs);

	// print EOL
	cxa_ioStream_writeBytes(ioStream, (void*)CXA_LINE_ENDING, strlen(CXA_LINE_ENDING));
}


// ******** local function implementations ********
static inline void checkSysLogInit(void)
{
	if( !isSysLogInit )
	{
		// mark init first since we'll have a stack overflow (recursive call if not)
		isSysLogInit = true;
		cxa_logger_init(&sysLog, "sysLog");
	}
}


static void writeField(const char *const stringIn, size_t maxFieldLenIn)
{<commit_msg>added critical sections for better logging from multiple threads (freeRTOS)<commit_after>/**
 * Copyright 2015 opencxa.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @author <NAME>
 */
#include "cxa_logger_implementation.h"


// ******** includes ********
#include <stdarg.h>
#include <string.h>
#include <inttypes.h>
#include <cxa_assert.h>
#include <cxa_criticalSection.h>
#include <cxa_numberUtils.h>
#include <cxa_stringUtils.h>
#include <cxa_timeBase.h>


// ******** local macro definitions ********
#ifndef CXA_LOGGER_BUFFERLEN_BYTES
	#define CXA_LOGGER_BUFFERLEN_BYTES			24
#endif

#define CXA_LOGGER_TRUNCATE_STRING			"..."


// ******** local type definitions ********


// ******** local function prototypes ********
static inline void checkSysLogInit(void);
static void writeField(const char *const stringIn, size_t maxFieldLenIn);
static void writeHeader(cxa_logger_t *const loggerIn, const uint8_t levelIn);


// ********  local variable declarations *********
static cxa_logger_t sysLog;
static bool isSysLogInit = false;

static cxa_ioStream_t* ioStream = NULL;
static size_t largestloggerName_bytes = 0;


// ******** global function implementations ********
void cxa_logger_setGlobalIoStream(cxa_ioStream_t *const ioStreamIn)
{
	checkSysLogInit();

	ioStream = ioStreamIn;

	cxa_ioStream_writeBytes(ioStream, (void*)CXA_LINE_ENDING, sizeof(CXA_LINE_ENDING));
	cxa_ioStream_writeBytes(ioStream, (void*)CXA_LINE_ENDING, sizeof(CXA_LINE_ENDING));
	cxa_logger_vlog(&sysLog, CXA_LOG_LEVEL_INFO, "logging ioStream @ %p", ioStreamIn);
}


void cxa_logger_init(cxa_logger_t *const loggerIn, const char *nameIn)
{
	cxa_assert(loggerIn);
	cxa_assert(nameIn);
	checkSysLogInit();

	// copy our name (and make sure it will be null terminated)
	strncpy(loggerIn->name, nameIn, CXA_LOGGER_MAX_NAME_LEN_CHARS);
	loggerIn->name[CXA_LOGGER_MAX_NAME_LEN_CHARS-1] = 0;

	size_t nameLen_bytes = strlen(loggerIn->name);
	if( nameLen_bytes > largestloggerName_bytes ) largestloggerName_bytes = nameLen_bytes;
}


void cxa_logger_vinit(cxa_logger_t *const loggerIn, const char *nameFmtIn, ...)
{
	cxa_assert(loggerIn);
	cxa_assert(nameFmtIn);
	checkSysLogInit();

	va_list varArgs;
	va_start(varArgs, nameFmtIn);
	vsnprintf(loggerIn->name, CXA_LOGGER_MAX_NAME_LEN_CHARS, nameFmtIn, varArgs);
	loggerIn->name[CXA_LOGGER_MAX_NAME_LEN_CHARS-1] = 0;
	va_end(varArgs);

	size_t nameLen_bytes = strlen(loggerIn->name);
	if( nameLen_bytes > largestloggerName_bytes ) largestloggerName_bytes = nameLen_bytes;
}


cxa_logger_t* cxa_logger_getSysLog(void)
{
	return &sysLog;
}


void cxa_logger_log_untermString(cxa_logger_t *const loggerIn, const uint8_t levelIn, const char* prefixIn, const char* untermStringIn, size_t untermStrLen_bytesIn, const char* postFixIn)
{
	cxa_assert(loggerIn);
	cxa_assert(loggerIn);
	cxa_assert( (levelIn == CXA_LOG_LEVEL_ERROR) ||
				(levelIn == CXA_LOG_LEVEL_WARN) ||
				(levelIn == CXA_LOG_LEVEL_INFO) ||
				(levelIn == CXA_LOG_LEVEL_DEBUG) ||
				(levelIn == CXA_LOG_LEVEL_TRACE) );
	cxa_assert(untermStringIn);
	checkSysLogInit();

	// if we don't have an ioStream, don't worry about it!
	if( ioStream == NULL ) return;


	cxa_criticalSection_enter();


	// common header
	writeHeader(loggerIn, levelIn);

	if( prefixIn != NULL ) cxa_ioStream_writeString(ioStream, (char *const)prefixIn);
	cxa_ioStream_writeBytes(ioStream, (void *const)untermStringIn, untermStrLen_bytesIn);
	if( postFixIn != NULL ) cxa_ioStream_writeString(ioStream, (char *const)postFixIn);

	// print EOL
	cxa_ioStream_writeBytes(ioStream, (void*)CXA_LINE_ENDING, strlen(CXA_LINE_ENDING));


	cxa_criticalSection_exit();
}


void cxa_logger_stepDebug_vlog(const char* fileIn, const int lineNumIn, const char* formatIn, ...)
{
	cxa_assert(fileIn);

	// if we don't have an ioStream, don't worry about it!
	if( ioStream == NULL ) return;

	// shorten our file name
	char *file_sep = strrchr(fileIn, '/');
	if(file_sep) fileIn = file_sep+1;


	cxa_criticalSection_enter();


	// common header
	writeHeader(&sysLog, CXA_LOG_LEVEL_DEBUG);

	// our buffer for this go-round
	char buff[CXA_LOGGER_BUFFERLEN_BYTES];

	// print our location
	size_t expectedNumBytesWritten = snprintf(buff, sizeof(buff), ((formatIn != NULL) ? "%s::%d - " : "%s::%d"), fileIn, lineNumIn);
	cxa_ioStream_writeBytes(ioStream, buff, CXA_MIN(expectedNumBytesWritten, sizeof(buff)));
	if( sizeof(buff) < expectedNumBytesWritten )
	{
		cxa_ioStream_writeBytes(ioStream, (void*)CXA_LOGGER_TRUNCATE_STRING, strlen(CXA_LOGGER_TRUNCATE_STRING));
	}

	// now do our VARARGS
	va_list varArgs;
	va_start(varArgs, formatIn);
	expectedNumBytesWritten = vsnprintf(buff, sizeof(buff), formatIn, varArgs);
	cxa_ioStream_writeBytes(ioStream, buff, CXA_MIN(expectedNumBytesWritten, sizeof(buff)));
	if( sizeof(buff) < expectedNumBytesWritten )
	{
		cxa_ioStream_writeBytes(ioStream, (void*)CXA_LOGGER_TRUNCATE_STRING, strlen(CXA_LOGGER_TRUNCATE_STRING));
	}
	va_end(varArgs);

	// print EOL
	cxa_ioStream_writeBytes(ioStream, (void*)CXA_LINE_ENDING, strlen(CXA_LINE_ENDING));


	cxa_criticalSection_exit();
}


void cxa_logger_vlog(cxa_logger_t *const loggerIn, const uint8_t levelIn, const char *formatIn, ...)
{
	cxa_assert(loggerIn);
	cxa_assert( (levelIn == CXA_LOG_LEVEL_ERROR) ||
				(levelIn == CXA_LOG_LEVEL_WARN) ||
				(levelIn == CXA_LOG_LEVEL_INFO) ||
				(levelIn == CXA_LOG_LEVEL_DEBUG) ||
				(levelIn == CXA_LOG_LEVEL_TRACE) );
	cxa_assert(formatIn);
	checkSysLogInit();

	// if we don't have an ioStream, don't worry about it!
	if( ioStream == NULL ) return;


	cxa_criticalSection_enter();


	// common header
	writeHeader(loggerIn, levelIn);

	// our buffer for this go-round
	char buff[CXA_LOGGER_BUFFERLEN_BYTES];

	// now do our VARARGS
	va_list varArgs;
	va_start(varArgs, formatIn);
	size_t expectedNumBytesWritten = vsnprintf(buff, sizeof(buff), formatIn, varArgs);
	cxa_ioStream_writeBytes(ioStream, buff, CXA_MIN(expectedNumBytesWritten, sizeof(buff)));
	if( sizeof(buff) < expectedNumBytesWritten )
	{
		cxa_ioStream_writeBytes(ioStream, (void*)CXA_LOGGER_TRUNCATE_STRING, strlen(CXA_LOGGER_TRUNCATE_STRING));
	}
	va_end(varArgs);

	// print EOL
	cxa_ioStream_writeBytes(ioStream, (void*)CXA_LINE_ENDING, strlen(CXA_LINE_ENDING));


	cxa_criticalSection_exit();
}


// ******** local function implementations ********
static inline void checkSysLogInit(void)
{
	if( !isSysLogInit )
	{
		// mark init first since we'll have a stack overflow (recursive call if not)
		isSysLogInit = true;
		cxa_logger_init(&sysLog, "sysLog");
	}
}


static void writeField(const char *const stringIn, size_t maxFieldLenIn)
{
{'fraction_non_alphanumeric': 0.1218303282810143, 'fraction_numerical': 0.0027296889591264997, 'mean_word_length': 5.961, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '6239230', 'n_tokens_mistral': 5268, 'n_tokens_neox': 4972, 'n_words': 1073}