1 Star 0 Fork 0

vsf-linux / sdlpal

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
util.c 20.41 KB
一键复制 编辑 原始数据 按行查看 历史
Wei Mingzhi 提交于 2022-01-09 17:30 . Update copyright.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007
/* -*- mode: c; tab-width: 4; c-basic-offset: 4; c-file-style: "linux" -*- */
//
// Copyright (c) 2009-2011, Wei Mingzhi <whistler_wmz@users.sf.net>.
// Copyright (c) 2011-2022, SDLPAL development team.
// All rights reserved.
//
// This file is part of SDLPAL.
//
// SDLPAL is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include "util.h"
#include "input.h"
#include "global.h"
#include "palcfg.h"
#include <errno.h>
#include "midi.h"
#if SDL_VERSION_ATLEAST(2, 0, 0)
#include "SDL_video.h"
#include "SDL_messagebox.h"
#endif
static char internal_buffer[PAL_MAX_GLOBAL_BUFFERS + 1][PAL_GLOBAL_BUFFER_SIZE];
#define INTERNAL_BUFFER_SIZE_ARGS internal_buffer[PAL_MAX_GLOBAL_BUFFERS], PAL_GLOBAL_BUFFER_SIZE
void UTIL_MsgBox(char *string)
{
#if SDL_VERSION_ATLEAST(2, 0, 0)
extern SDL_Window *gpWindow;
char buffer[300];
SDL_MessageBoxButtonData buttons[] = { { 0, 0, "OK" } };
SDL_MessageBoxData mbd = { SDL_MESSAGEBOX_WARNING, gpWindow, "Alert",buffer, 1, buttons, NULL };
int btnid;
sprintf(buffer, "%s\n", string);
SDL_ShowMessageBox(&mbd, &btnid);
#endif
}
long
flength(
FILE *fp
)
{
long old_pos = ftell(fp), length;
if (old_pos == -1) return -1;
if (fseek(fp, 0, SEEK_END) == -1) return -1;
length = ftell(fp); fseek(fp, old_pos, SEEK_SET);
return length;
}
void
trim(
char *str
)
/*++
Purpose:
Remove the leading and trailing spaces in a string.
Parameters:
str - the string to proceed.
Return value:
None.
--*/
{
int pos = 0;
char *dest = str;
//
// skip leading blanks
//
while (str[pos] <= ' ' && str[pos] > 0)
pos++;
while (str[pos])
{
*(dest++) = str[pos];
pos++;
}
*(dest--) = '\0'; // store the null
//
// remove trailing blanks
//
while (dest >= str && *dest <= ' ' && *dest > 0)
*(dest--) = '\0';
}
char *
UTIL_va(
char *buffer,
int buflen,
const char *format,
...
)
{
if (buflen > 0 && buffer)
{
va_list argptr;
va_start(argptr, format);
vsnprintf(buffer, buflen, format, argptr);
va_end(argptr);
return buffer;
}
else
{
return NULL;
}
}
/*
* RNG code based on RACC by Pierre-Marie Baty.
* http://racc.bots-united.com
*
* Copyright (c) 2004, Pierre-Marie Baty
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* Neither the name of the RACC nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
//
// Our random number generator's seed.
//
static int glSeed = 0;
static void
lsrand(
unsigned int iInitialSeed
)
/*++
Purpose:
This function initializes the random seed based on the initial seed value passed in the
iInitialSeed parameter.
Parameters:
[IN] iInitialSeed - The initial random seed.
Return value:
None.
--*/
{
//
// fill in the initial seed of the random number generator
//
glSeed = 1664525L * iInitialSeed + 1013904223L;
}
static int
lrand(
void
)
/*++
Purpose:
This function is the equivalent of the rand() standard C library function, except that
whereas rand() works only with short integers (i.e. not above 32767), this function is
able to generate 32-bit random numbers.
Parameters:
None.
Return value:
The generated random number.
--*/
{
if (glSeed == 0) // if the random seed isn't initialized...
lsrand((unsigned int)time(NULL)); // initialize it first
glSeed = 1664525L * glSeed + 1013904223L; // do some twisted math (infinite suite)
return ((glSeed >> 1) + 1073741824L); // and return the result.
}
int
RandomLong(
int from,
int to
)
/*++
Purpose:
This function returns a random integer number between (and including) the starting and
ending values passed by parameters from and to.
Parameters:
from - the starting value.
to - the ending value.
Return value:
The generated random number.
--*/
{
if (to <= from)
return from;
return from + lrand() / (INT_MAX / (to - from + 1));
}
float
RandomFloat(
float from,
float to
)
/*++
Purpose:
This function returns a random floating-point number between (and including) the starting
and ending values passed by parameters from and to.
Parameters:
from - the starting value.
to - the ending value.
Return value:
The generated random number.
--*/
{
if (to <= from)
return from;
return from + (float)lrand() / (INT_MAX / (to - from));
}
void
UTIL_Delay(
unsigned int ms
)
{
unsigned int t = SDL_GetTicks() + ms;
PAL_ProcessEvent();
while (!SDL_TICKS_PASSED(SDL_GetTicks(), t))
{
SDL_Delay(1);
PAL_ProcessEvent();
}
}
void
TerminateOnError(
const char *fmt,
...
)
// This function terminates the game because of an error and
// prints the message string pointed to by fmt both in the
// console and in a messagebox.
{
va_list argptr;
char string[256];
extern VOID PAL_Shutdown(int);
// concatenate all the arguments in one string
va_start(argptr, fmt);
vsnprintf(string, sizeof(string), fmt, argptr);
va_end(argptr);
fprintf(stderr, "\nFATAL ERROR: %s\n", string);
#if SDL_VERSION_ATLEAST(2, 0, 0)
{
extern SDL_Window *gpWindow;
char buffer[300];
SDL_MessageBoxButtonData buttons[2] = { { 0, 0, "Yes" },{ 0, 1, "No" } };
SDL_MessageBoxData mbd = { SDL_MESSAGEBOX_ERROR, gpWindow, "FATAL ERROR", buffer, 2, buttons, NULL };
int btnid;
#if PAL_HAS_CONFIG_PAGE
sprintf(buffer, "%sLaunch setting dialog on next start?\n", string);
if (SDL_ShowMessageBox(&mbd, &btnid) == 0 && btnid == 0)
{
gConfig.fLaunchSetting = TRUE;
PAL_SaveConfig();
}
#else
sprintf(buffer, "%s\n", string);
mbd.numbuttons=1;
SDL_ShowMessageBox(&mbd, &btnid);
#endif
PAL_Shutdown(255);
}
#else
PAL_FATAL_OUTPUT(string);
#endif
#ifdef _DEBUG
assert(!"TerminateOnError()"); // allows jumping to debugger
#endif
PAL_Shutdown(255);
}
void *
UTIL_malloc(
size_t buffer_size
)
{
// handy wrapper for operations we always forget, like checking malloc's returned pointer.
void *buffer;
// first off, check if buffer size is valid
if (buffer_size == 0)
TerminateOnError("UTIL_malloc() called with invalid buffer size: %d\n", buffer_size);
buffer = malloc(buffer_size); // allocate real memory space
// last check, check if malloc call succeeded
if (buffer == NULL)
TerminateOnError("UTIL_malloc() failure for %d bytes (out of memory?)\n", buffer_size);
return buffer; // nothing went wrong, so return buffer pointer
}
void *
UTIL_calloc(
size_t n,
size_t size
)
{
// handy wrapper for operations we always forget, like checking calloc's returned pointer.
void *buffer;
// first off, check if buffer size is valid
if (n == 0 || size == 0)
TerminateOnError ("UTIL_calloc() called with invalid parameters\n");
buffer = calloc(n, size); // allocate real memory space
// last check, check if malloc call succeeded
if (buffer == NULL)
TerminateOnError("UTIL_calloc() failure for %d bytes (out of memory?)\n", size * n);
return buffer; // nothing went wrong, so return buffer pointer
}
FILE *
UTIL_OpenRequiredFile(
LPCSTR lpszFileName
)
/*++
Purpose:
Open a required file. If fails, quit the program.
Parameters:
[IN] lpszFileName - file name to open.
Return value:
Pointer to the file.
--*/
{
return UTIL_OpenRequiredFileForMode(lpszFileName, "rb");
}
FILE *
UTIL_OpenRequiredFileForMode(
LPCSTR lpszFileName,
LPCSTR szMode
)
/*++
Purpose:
Open a required file. If fails, quit the program.
Parameters:
[IN] lpszFileName - file name to open.
[IN] szMode - file open mode.
Return value:
Pointer to the file.
--*/
{
FILE *fp = UTIL_OpenFileForMode(lpszFileName, szMode);
if (fp == NULL)
{
fp = fopen(lpszFileName, szMode);
}
if (fp == NULL)
{
TerminateOnError("File open error(%d): %s!\n", errno, lpszFileName);
}
return fp;
}
FILE *
UTIL_OpenFile(
LPCSTR lpszFileName
)
/*++
Purpose:
Open a file. If fails, return NULL.
Parameters:
[IN] lpszFileName - file name to open.
Return value:
Pointer to the file.
--*/
{
return UTIL_OpenFileForMode(lpszFileName, "rb");
}
FILE *
UTIL_OpenFileForMode(
LPCSTR lpszFileName,
LPCSTR szMode
)
/*++
Purpose:
Open a file. If fails, return NULL.
Parameters:
[IN] lpszFileName - file name to open.
[IN] szMode - file open mode.
Return value:
Pointer to the file.
--*/
{
//
// If lpszFileName is an absolute path, use its last element as filename
//
if (UTIL_IsAbsolutePath(lpszFileName))
{
char *temp = strdup(lpszFileName), *filename = temp;
FILE *fp = NULL;
for (char *next = strpbrk(filename, PAL_PATH_SEPARATORS); next; next = strpbrk(filename = next + 1, PAL_PATH_SEPARATORS));
if (*filename)
{
filename[-1] = '\0';
fp = UTIL_OpenFileAtPathForMode(*temp ? temp : "/", filename, szMode);
}
free(temp);
return fp;
}
return UTIL_OpenFileAtPathForMode(gConfig.pszGamePath, lpszFileName, szMode);
}
FILE *
UTIL_OpenFileAtPath(
LPCSTR lpszPath,
LPCSTR lpszFileName
)
{
return UTIL_OpenFileAtPathForMode(lpszPath, lpszFileName, "rb");
}
FILE *
UTIL_OpenFileAtPathForMode(
LPCSTR lpszPath,
LPCSTR lpszFileName,
LPCSTR szMode
)
{
if (!lpszPath || !lpszFileName || !szMode) return NULL;
//
// Construct full path according to lpszPath and lpszFileName
//
const char *path = UTIL_GetFullPathName(INTERNAL_BUFFER_SIZE_ARGS, lpszPath, lpszFileName);
//
// If no matching path, check the open mode
//
if (path)
{
return fopen(path, szMode);
}
else if (szMode[0] != 'r')
{
return fopen(UTIL_CombinePath(INTERNAL_BUFFER_SIZE_ARGS, 2, lpszPath, lpszFileName), szMode);
}
else
{
return NULL;
}
}
VOID
UTIL_CloseFile(
FILE *fp
)
/*++
Purpose:
Close a file.
Parameters:
[IN] fp - file handle to be closed.
Return value:
None.
--*/
{
if (fp != NULL)
{
fclose(fp);
}
}
BOOL
UTIL_IsFileExist(
const char *path
)
{
if( UTIL_IsAbsolutePath(path) )
return UTIL_GetFullPathName(INTERNAL_BUFFER_SIZE_ARGS, "", path) != NULL;
else
return UTIL_GetFullPathName(INTERNAL_BUFFER_SIZE_ARGS, gConfig.pszGamePath, path) != NULL;
}
const char *
UTIL_GetFullPathName(
char *buffer,
size_t buflen,
const char *basepath,
const char *subpath
)
{
if (!buffer || !basepath || !subpath || buflen == 0) return NULL;
int sublen = strlen(subpath);
if (sublen == 0) return NULL;
char *_base = strdup(basepath), *_sub = strdup(subpath);
const char *result = NULL;
if (access(UTIL_CombinePath(INTERNAL_BUFFER_SIZE_ARGS, 2, _base, _sub), 0) == 0)
{
result = internal_buffer[PAL_MAX_GLOBAL_BUFFERS];
}
#ifndef __EMSCRIPTEN__
#if !defined(PAL_FILESYSTEM_IGNORE_CASE) || !PAL_FILESYSTEM_IGNORE_CASE
if (result == NULL)
{
size_t pos = strspn(_sub, PAL_PATH_SEPARATORS);
if (pos < sublen)
{
char *start = _sub + pos;
char *end = strpbrk(start, PAL_PATH_SEPARATORS);
if (end) *end = '\0';
//
// try to find the matching file in the directory.
//
struct dirent **list;
int n = scandir(_base, &list, 0, alphasort);
while (n-- > 0)
{
if (!result && SDL_strcasecmp(list[n]->d_name, start) == 0)
{
result = UTIL_CombinePath(INTERNAL_BUFFER_SIZE_ARGS, 2, _base, list[n]->d_name);
if (end)
result = UTIL_GetFullPathName(INTERNAL_BUFFER_SIZE_ARGS, result, end + 1);
else if (access(result, 0) != 0)
result = NULL;
}
free(list[n]);
}
free(list);
}
}
#endif
#endif
if (result != NULL)
{
size_t dstlen = min(buflen - 1, strlen(result));
result = (char *)memmove(buffer, result, dstlen);
buffer[dstlen] = '\0';
}
free(_base);
free(_sub);
return result;
}
const char *
UTIL_CombinePath(
char *buffer,
size_t buflen,
int numentry,
...
)
{
if (buffer && buflen > 0 && numentry > 0)
{
const char *retval = buffer;
va_list argptr;
va_start(argptr, numentry);
for (int i = 0; i < numentry && buflen > 1; i++)
{
const char *path = va_arg(argptr, const char *);
int path_len = path ? strlen(path) : 0;
int append_delim = (i < numentry - 1 && path_len > 0 && !PAL_IS_PATH_SEPARATOR(path[path_len - 1]));
for (int is_sep = 0, j = 0; j < path_len && buflen > (size_t)append_delim + 1; j++)
{
//
// Skip continuous path separators
//
if (PAL_IS_PATH_SEPARATOR(path[j]))
{
if (is_sep)
continue;
else
is_sep = 1;
}
else
{
is_sep = 0;
}
*buffer++ = path[j];
buflen--;
}
//
// Make sure a path delimeter is append to the destination if this is not the last entry
//
if (append_delim)
{
*buffer++ = PAL_PATH_SEPARATORS[0];
buflen--;
}
}
va_end(argptr);
*buffer = '\0';
return retval;
}
else
{
return NULL;
}
}
char *
UTIL_GlobalBuffer(
int index
)
{
return (index >= 0 && index < PAL_MAX_GLOBAL_BUFFERS) ? internal_buffer[index] : NULL;
}
PALFILE
UTIL_CheckResourceFiles(
const char *path,
const char *msgfile
)
{
const char *common_files[] = {
"abc.mkf", "ball.mkf", "data.mkf", "f.mkf",
"fbp.mkf", "fire.mkf", "gop.mkf", "map.mkf",
"mgo.mkf", "pat.mkf", "rgm.mkf", "rng.mkf",
"sss.mkf"
};
const char *msg_files[][2] = {
{ msgfile, "m.msg" },
{ msgfile, "word.dat" }
};
const char *sound_files[2] = { "voc.mkf", "sounds.mkf" };
const char *music_files[2] = { "midi.mkf", "mus.mkf" };
int msgidx = !(msgfile && *msgfile);
PALFILE retval = (PALFILE)0;
for (int i = 0; i < sizeof(common_files) / sizeof(common_files[0]); i++)
{
if (!UTIL_GetFullPathName(INTERNAL_BUFFER_SIZE_ARGS, path, common_files[i]))
{
retval |= (PALFILE)(1 << i);
}
}
for (int i = 0; i < sizeof(msg_files[0]) / sizeof(msg_files[0][0]); i++)
{
if (!UTIL_GetFullPathName(INTERNAL_BUFFER_SIZE_ARGS, path, msg_files[i][msgidx]))
{
retval |= (PALFILE)(1 << ((i + 1) * msgidx + 13));
}
}
for (int i = 0; i < sizeof(sound_files) / sizeof(sound_files[0]); i++)
{
if (!UTIL_GetFullPathName(INTERNAL_BUFFER_SIZE_ARGS, path, sound_files[i]))
{
retval |= (PALFILE)(1 << (i + 16));
}
}
for (int i = 0; i < sizeof(music_files) / sizeof(music_files[0]); i++)
{
if (!UTIL_GetFullPathName(INTERNAL_BUFFER_SIZE_ARGS, path, music_files[i]))
{
retval |= (PALFILE)(1 << (i + 18));
}
}
return retval;
}
#if !defined(PAL_HAS_PLATFORM_SPECIFIC_UTILS)
BOOL
UTIL_GetScreenSize(
DWORD *pdwScreenWidth,
DWORD *pdwScreenHeight
)
{
return FALSE;
}
BOOL
UTIL_IsAbsolutePath(
LPCSTR lpszFileName
)
{
return FALSE;
}
INT
UTIL_Platform_Init(
int argc,
char* argv[]
)
{
gConfig.fLaunchSetting = FALSE;
return 0;
}
VOID
UTIL_Platform_Quit(
VOID
)
{
}
#endif
/*
* Logging utilities
*/
#ifndef PAL_LOG_BUFFER_SIZE
# define PAL_LOG_BUFFER_SIZE 4096
#endif
#define PAL_LOG_BUFFER_EXTRA_SIZE 32+sizeof(_log_prelude)
static char _log_prelude[80];
static LOGCALLBACK _log_callbacks[PAL_LOG_MAX_OUTPUTS];
static LOGLEVEL _log_callback_levels[PAL_LOG_MAX_OUTPUTS];
static char _log_buffer[PAL_LOG_BUFFER_SIZE + PAL_LOG_BUFFER_EXTRA_SIZE];
static const char * const _loglevel_str[] = {
"[VERBOSE]",
" [DEBUG]",
" [INFO]",
"[WARNING]",
" [ERROR]",
" [FATAL]",
};
int
UTIL_LogAddOutputCallback(
LOGCALLBACK callback,
LOGLEVEL loglevel
)
{
if (!callback) return -1;
// De-duplication
for (int i = 0; i < PAL_LOG_MAX_OUTPUTS; i++)
{
if (!_log_callbacks[i])
{
_log_callbacks[i] = callback;
}
if (_log_callbacks[i] == callback)
{
_log_callback_levels[i] = loglevel;
return i;
}
}
return -1;
}
void
UTIL_LogRemoveOutputCallback(
int id
)
{
if (id < 0 || id >= PAL_LOG_MAX_OUTPUTS) return;
while (id < PAL_LOG_MAX_OUTPUTS - 1)
{
_log_callbacks[id] = _log_callbacks[id + 1];
_log_callback_levels[id] = _log_callback_levels[id + 1];
id++;
}
_log_callbacks[id] = NULL;
_log_callback_levels[id] = LOGLEVEL_MIN;
}
void
UTIL_LogOutput(
LOGLEVEL level,
const char *fmt,
...
)
{
va_list va;
time_t tv = time(NULL);
struct tm *tmval = localtime(&tv);
int id, n;
if (level > LOGLEVEL_MAX) level = LOGLEVEL_MAX;
snprintf(_log_buffer, PAL_LOG_BUFFER_EXTRA_SIZE,
"%04d-%02d-%02d %02d:%02d:%02d %s: ",
tmval->tm_year + 1900, tmval->tm_mon, tmval->tm_mday,
tmval->tm_hour, tmval->tm_min, tmval->tm_sec,
_loglevel_str[level]);
if( strlen(_log_prelude) > 0 )
strncat(_log_buffer, _log_prelude, PAL_LOG_BUFFER_EXTRA_SIZE);
va_start(va, fmt);
n = vsnprintf(_log_buffer + strnlen(_log_buffer, PAL_LOG_BUFFER_EXTRA_SIZE), PAL_LOG_BUFFER_SIZE, fmt, va);
va_end(va);
n = (n == -1) ? PAL_LOG_BUFFER_EXTRA_SIZE + PAL_LOG_BUFFER_SIZE - 1 : n + PAL_LOG_BUFFER_EXTRA_SIZE;
_log_buffer[n--] = '\0';
if (_log_buffer[n] != '\n') _log_buffer[n] = '\n';
if( level == LOGLEVEL_FATAL )
TerminateOnError(_log_buffer);
if (level < gConfig.iLogLevel || !_log_callbacks[0]) return;
for(id = 0; id < PAL_LOG_MAX_OUTPUTS && _log_callbacks[id]; id++)
{
if (level >= _log_callback_levels[id])
{
_log_callbacks[id](level, _log_buffer, _log_buffer + PAL_LOG_BUFFER_EXTRA_SIZE - 1);
}
}
}
void
UTIL_LogSetLevel(
LOGLEVEL minlevel
)
{
if (minlevel < LOGLEVEL_MIN)
gConfig.iLogLevel = LOGLEVEL_MIN;
else if (minlevel > LOGLEVEL_MAX)
gConfig.iLogLevel = LOGLEVEL_MAX;
else
gConfig.iLogLevel = minlevel;
}
void
UTIL_LogToFile(
LOGLEVEL _,
const char *string,
const char *__
)
{
FILE *fp = UTIL_OpenFileForMode(gConfig.pszLogFile, "a");
if (fp)
{
fputs(string, fp);
fclose(fp);
}
}
void
UTIL_LogSetPrelude(
const char *prelude
)
{
memset(_log_prelude, 0, sizeof(_log_prelude));
if( prelude )
strncpy(_log_prelude, prelude, sizeof(_log_prelude) - 1);
}
#if PAL_NEED_STRCASESTR
PAL_FORCE_INLINE char* stoupper(const char* s)
{
char* p = strdup(s);
char* p1 = p;
while (*p = toupper(*p)) p++;
return p1;
}
PAL_C_LINKAGE char* strcasestr(const char *a, const char *b) {
char *a1 = stoupper(a);
char *b1 = stoupper(b);
char *ptr = strstr(a1, b1);
if (ptr != NULL) ptr = (char*)a + (ptr - a1);
free(a1);
free(b1);
return ptr;
}
#endif
char basename_buf[256];
char *UTIL_basename(const char *filename) {
memset(basename_buf, 0, 256);
memcpy(basename_buf, filename, strlen(filename));
char *pos = NULL;
int broked = 0;
for( int i=0;i<strlen(PAL_PATH_SEPARATORS);i++)
if( (pos = strrchr(basename_buf,PAL_PATH_SEPARATORS[i])) != NULL )
*pos='\0', broked = 1;
if( !broked )
sprintf((char*)basename_buf, "./");
return (char*)basename_buf;
}
1
https://gitee.com/vsf-linux/sdlpal.git
git@gitee.com:vsf-linux/sdlpal.git
vsf-linux
sdlpal
sdlpal
master

搜索帮助

53164aa7 5694891 3bd8fe86 5694891