1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2024-12-01 13:24:25 +01:00
HLMetaModOfficial/core-legacy/util.cpp
David Anderson 1d9949e1a0 Renamed core-1.4 to core-legacy.
--HG--
rename : core-1.4/CPlugin.cpp => core-legacy/CPlugin.cpp
rename : core-1.4/CPlugin.h => core-legacy/CPlugin.h
rename : core-1.4/CSmmAPI.cpp => core-legacy/CSmmAPI.cpp
rename : core-1.4/CSmmAPI.h => core-legacy/CSmmAPI.h
rename : core-1.4/IPluginManager.h => core-legacy/IPluginManager.h
rename : core-1.4/ISmmAPI.h => core-legacy/ISmmAPI.h
rename : core-1.4/ISmmPlugin.h => core-legacy/ISmmPlugin.h
rename : core-1.4/Makefile => core-legacy/Makefile
rename : core-1.4/concommands.cpp => core-legacy/concommands.cpp
rename : core-1.4/concommands.h => core-legacy/concommands.h
rename : core-1.4/convar_smm.h => core-legacy/convar_smm.h
rename : core-1.4/msvc7/sourcemm.sln => core-legacy/msvc7/sourcemm.sln
rename : core-1.4/msvc7/sourcemm.vcproj => core-legacy/msvc7/sourcemm.vcproj
rename : core-1.4/msvc8/sourcemm.sln => core-legacy/msvc8/sourcemm.sln
rename : core-1.4/msvc8/sourcemm.vcproj => core-legacy/msvc8/sourcemm.vcproj
rename : core-1.4/msvc9/sourcemm.sln => core-legacy/msvc9/sourcemm.sln
rename : core-1.4/msvc9/sourcemm.vcproj => core-legacy/msvc9/sourcemm.vcproj
rename : core-1.4/oslink.cpp => core-legacy/oslink.cpp
rename : core-1.4/oslink.h => core-legacy/oslink.h
rename : core-1.4/sourcehook.cpp => core-legacy/sourcehook.cpp
rename : core-1.4/sourcehook/FastDelegate.h => core-legacy/sourcehook/FastDelegate.h
rename : core-1.4/sourcehook/generate/FastDelegate.h => core-legacy/sourcehook/generate/FastDelegate.h
rename : core-1.4/sourcehook/generate/FastDelegate.hxx => core-legacy/sourcehook/generate/FastDelegate.hxx
rename : core-1.4/sourcehook/generate/generate => core-legacy/sourcehook/generate/generate
rename : core-1.4/sourcehook/generate/generate.bat => core-legacy/sourcehook/generate/generate.bat
rename : core-1.4/sourcehook/generate/sh_memfuncinfo.h => core-legacy/sourcehook/generate/sh_memfuncinfo.h
rename : core-1.4/sourcehook/generate/sh_memfuncinfo.hxx => core-legacy/sourcehook/generate/sh_memfuncinfo.hxx
rename : core-1.4/sourcehook/generate/shworker.bin => core-legacy/sourcehook/generate/shworker.bin
rename : core-1.4/sourcehook/generate/shworker.exe => core-legacy/sourcehook/generate/shworker.exe
rename : core-1.4/sourcehook/generate/shworker/Makefile => core-legacy/sourcehook/generate/shworker/Makefile
rename : core-1.4/sourcehook/generate/shworker/fd_hopter.cpp => core-legacy/sourcehook/generate/shworker/fd_hopter.cpp
rename : core-1.4/sourcehook/generate/shworker/msvc7/shworker.vcproj => core-legacy/sourcehook/generate/shworker/msvc7/shworker.vcproj
rename : core-1.4/sourcehook/generate/shworker/msvc8/shworker.vcproj => core-legacy/sourcehook/generate/shworker/msvc8/shworker.vcproj
rename : core-1.4/sourcehook/generate/shworker/shworker.cpp => core-legacy/sourcehook/generate/shworker/shworker.cpp
rename : core-1.4/sourcehook/generate/sourcehook.h => core-legacy/sourcehook/generate/sourcehook.h
rename : core-1.4/sourcehook/generate/sourcehook.hxx => core-legacy/sourcehook/generate/sourcehook.hxx
rename : core-1.4/sourcehook/sh_list.h => core-legacy/sourcehook/sh_list.h
rename : core-1.4/sourcehook/sh_memfuncinfo.h => core-legacy/sourcehook/sh_memfuncinfo.h
rename : core-1.4/sourcehook/sh_memory.h => core-legacy/sourcehook/sh_memory.h
rename : core-1.4/sourcehook/sh_stack.h => core-legacy/sourcehook/sh_stack.h
rename : core-1.4/sourcehook/sh_string.h => core-legacy/sourcehook/sh_string.h
rename : core-1.4/sourcehook/sh_tinyhash.h => core-legacy/sourcehook/sh_tinyhash.h
rename : core-1.4/sourcehook/sh_vector.h => core-legacy/sourcehook/sh_vector.h
rename : core-1.4/sourcehook/sourcehook.cpp => core-legacy/sourcehook/sourcehook.cpp
rename : core-1.4/sourcehook/sourcehook.h => core-legacy/sourcehook/sourcehook.h
rename : core-1.4/sourcehook/sourcehook_impl.h => core-legacy/sourcehook/sourcehook_impl.h
rename : core-1.4/sourcehook/test/Makefile => core-legacy/sourcehook/test/Makefile
rename : core-1.4/sourcehook/test/main.cpp => core-legacy/sourcehook/test/main.cpp
rename : core-1.4/sourcehook/test/msvc7/test.vcproj => core-legacy/sourcehook/test/msvc7/test.vcproj
rename : core-1.4/sourcehook/test/msvc8/test.vcproj => core-legacy/sourcehook/test/msvc8/test.vcproj
rename : core-1.4/sourcehook/test/sourcehook_test.h => core-legacy/sourcehook/test/sourcehook_test.h
rename : core-1.4/sourcehook/test/test1.cpp => core-legacy/sourcehook/test/test1.cpp
rename : core-1.4/sourcehook/test/test2.cpp => core-legacy/sourcehook/test/test2.cpp
rename : core-1.4/sourcehook/test/test3.cpp => core-legacy/sourcehook/test/test3.cpp
rename : core-1.4/sourcehook/test/test4.cpp => core-legacy/sourcehook/test/test4.cpp
rename : core-1.4/sourcehook/test/testbail.cpp => core-legacy/sourcehook/test/testbail.cpp
rename : core-1.4/sourcehook/test/testbail.h => core-legacy/sourcehook/test/testbail.h
rename : core-1.4/sourcehook/test/testbail2.cpp => core-legacy/sourcehook/test/testbail2.cpp
rename : core-1.4/sourcehook/test/testevents.h => core-legacy/sourcehook/test/testevents.h
rename : core-1.4/sourcehook/test/testlist.cpp => core-legacy/sourcehook/test/testlist.cpp
rename : core-1.4/sourcehook/test/testmanual.cpp => core-legacy/sourcehook/test/testmanual.cpp
rename : core-1.4/sourcehook/test/testmulti.cpp => core-legacy/sourcehook/test/testmulti.cpp
rename : core-1.4/sourcehook/test/testrecall.cpp => core-legacy/sourcehook/test/testrecall.cpp
rename : core-1.4/sourcehook/test/testreentr.cpp => core-legacy/sourcehook/test/testreentr.cpp
rename : core-1.4/sourcehook/test/testref.cpp => core-legacy/sourcehook/test/testref.cpp
rename : core-1.4/sourcehook/test/testrefret.cpp => core-legacy/sourcehook/test/testrefret.cpp
rename : core-1.4/sourcemm.cpp => core-legacy/sourcemm.cpp
rename : core-1.4/sourcemm.h => core-legacy/sourcemm.h
rename : core-1.4/svn_version.h => core-legacy/svn_version.h
rename : core-1.4/svn_version.tpl => core-legacy/svn_version.tpl
rename : core-1.4/util.cpp => core-legacy/util.cpp
rename : core-1.4/util.h => core-legacy/util.h
rename : core-1.4/version.rc => core-legacy/version.rc
rename : core-1.4/vsp_listener.cpp => core-legacy/vsp_listener.cpp
rename : core-1.4/vsp_listener.h => core-legacy/vsp_listener.h
2008-11-14 05:02:00 -06:00

425 lines
7.4 KiB
C++

/* ======== SourceMM ========
* Copyright (C) 2004-2008 Metamod:Source Development Team
* No warranties of any kind
*
* License: zlib/libpng
*
* Author(s): David "BAILOPAN" Anderson
* ============================
*/
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include "util.h"
#include "oslink.h"
/**
* @brief Utility functions
* @file util.cpp
*/
const char *UTIL_GetExtension(const char *file)
{
int len = strlen(file);
int i = 0;
for (i = len - 1; i >= 0; i--)
{
if (file[i] == '/' || file[i] == '\\')
{
return NULL;
}
if ((file[i] == '.') && (i != len - 1))
{
return (const char *)&(file[i + 1]);
}
}
return NULL;
}
void UTIL_TrimLeft(char *buffer)
{
/* Let's think of this as our iterator */
char *i = buffer;
/* Make sure the buffer isn't null */
if (i && *i)
{
/* Add up number of whitespace characters */
while(isspace((unsigned char) *i))
{
i++;
}
/* If whitespace chars in buffer then adjust string so first non-whitespace char is at start of buffer */
if (i != buffer)
{
memmove(buffer, i, (strlen(i) + 1) * sizeof(char));
}
}
}
void UTIL_TrimRight(char *buffer)
{
/* Make sure buffer isn't null */
if (buffer)
{
size_t len = strlen(buffer);
/* Loop through buffer backwards while replacing whitespace chars with null chars */
for (size_t i = len - 1; i >= 0; i--)
{
if (isspace((unsigned char) buffer[i]))
{
buffer[i] = '\0';
} else {
break;
}
}
}
}
/* :TODO: this should skip string literals */
void UTIL_TrimComments(char *buffer)
{
int num_sc = 0;
size_t len = strlen(buffer);
if (buffer)
{
for (int i = len - 1; i >= 0; i--)
{
if (buffer[i] == '/')
{
if (++num_sc >= 2 && i==0)
{
buffer[i] = '\0';
return;
}
} else {
if (num_sc >= 2)
{
buffer[i] = '\0';
return;
}
num_sc = 0;
}
/* size_t won't go below 0, manually break out */
if (i == 0)
{
break;
}
}
}
}
void UTIL_KeySplit(const char *str, char *buf1, size_t len1, char *buf2, size_t len2)
{
size_t start;
size_t len = strlen(str);
for (start = 0; start < len; start++)
{
if (!isspace(str[start]))
{
break;
}
}
size_t end;
for (end = start; end < len; end++)
{
if (isspace(str[end]))
{
break;
}
}
size_t i, c = 0;
for (i = start; i < end; i++, c++)
{
if (c >= len1)
{
break;
}
buf1[c] = str[i];
}
buf1[c] = '\0';
for (start = end; start < len; start++)
{
if (!isspace(str[start]))
{
break;
}
}
for (c = 0; start < len; start++, c++)
{
if (c >= len2)
{
break;
}
buf2[c] = str[start];
}
buf2[c] = '\0';
}
bool UTIL_PathCmp(const char *path1, const char *path2)
{
size_t pos1 = 0, pos2 = 0;
while (true)
{
if (path1[pos1] == '\0' || path2[pos2] == '\0')
{
return (path1[pos1] == path2[pos2]);
}
if (path1[pos1] == PATH_SEP_CHAR)
{
if (path2[pos2] != PATH_SEP_CHAR)
{
return false;
}
/* Look for extra path chars */
while (path1[++pos1])
{
if (path1[pos1] != PATH_SEP_CHAR)
{
break;
}
}
while (path2[++pos2])
{
if (path2[pos2] != PATH_SEP_CHAR)
{
break;
}
}
continue;
}
/* If we're at a different non-alphanumeric, the next character MUST match */
if (!isalpha(path1[pos1]) && (path1[pos1] != path2[pos2]))
{
return false;
}
#ifdef WIN32
if (toupper(path1[pos1]) != toupper(path2[pos2]))
#else
if (path1[pos1] != path2[pos2])
#endif
{
return false;
}
pos1++;
pos2++;
}
}
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
size_t len = vsnprintf(buffer, maxlength, fmt, ap);
va_end(ap);
if (len >= maxlength)
{
len = maxlength - 1;
buffer[len] = '\0';
}
return len;
}
inline bool pathchar_isalpha(char a)
{
return (((a & 1<<7) == 0) && isalpha(a));
}
inline bool pathchar_sep(char a)
{
#if defined WIN32
return (a == '/' || a == '\\');
#elif defined __linux__
return (a == '/');
#endif
}
inline bool pathstr_isabsolute(const char *str)
{
#if defined WIN32
return (pathchar_isalpha(str[0])
&& str[1] == ':'
&& pathchar_sep(str[2]));
#elif defined __linux__
return (str[0] == '/');
#endif
}
inline bool pathchar_cmp(char a, char b)
{
#if defined WIN32
if (pathchar_isalpha(a) && pathchar_isalpha(b))
{
return (tolower(a) == tolower(b));
}
/* Either path separator is acceptable */
if (pathchar_sep(a))
{
return pathchar_sep(b);
}
#endif
return (a == b);
}
/**
* @brief Forms a relative path given two absolute paths.
*
* @param buffer Buffer to store relative path in.
* @param maxlength Maximum length of the output buffer.
* @param relTo Destination folder to use as a working directory.
* Final folder name should not be pathchar-terminated.
* @param relFrom Source file or folder to use as a target.
* @return True on success, false on failure.
*/
bool UTIL_Relatize(char buffer[],
size_t maxlength,
const char *relTo,
const char *relFrom)
{
/* We don't allow relative paths in here, force
* the user to resolve these himself!
*/
if (!pathstr_isabsolute(relTo)
|| !pathstr_isabsolute(relFrom))
{
return false;
}
#if defined WIN32
/* Relative paths across drives are not possible */
if (!pathchar_cmp(relTo[0], relFrom[0]))
{
return false;
}
/* Get rid of the drive and semicolon part */
relTo = &relTo[2];
relFrom = &relFrom[2];
#endif
/* Eliminate the common root between the paths */
const char *rootTo = NULL;
const char *rootFrom = NULL;
while (*relTo != '\0' && *relFrom != '\0')
{
/* If we get to a new path sequence, start over */
if (pathchar_sep(*relTo)
&& pathchar_sep(*relFrom))
{
rootTo = relTo;
rootFrom = relFrom;
/* If the paths don't compare, stop looking for a common root */
} else if (!pathchar_cmp(*relTo, *relFrom)) {
break;
}
relTo++;
relFrom++;
}
/* NULLs shouldn't happen! */
if (rootTo == NULL
|| rootFrom == NULL)
{
return false;
}
size_t numLevels = 0;
/* The root case is special!
* Don't count anything from it.
*/
if (*(rootTo + 1) != '\0')
{
/* Search for how many levels we need to go up.
* Since the root pointer points to a '/', we increment
* the initial pointer by one.
*/
while (*rootTo != '\0')
{
if (pathchar_sep(*rootTo))
{
/* Check for an improper trailing slash,
* just to be nice even though the user
* should NOT have done this!
*/
if (*(rootTo + 1) == '\0')
{
break;
}
numLevels++;
}
rootTo++;
}
}
/* Now build the new relative path. */
size_t len, total = 0;
while (numLevels--)
{
len = _snprintf(&buffer[total], maxlength - total, ".." PATH_SEP_STR);
if (len >= maxlength - total)
{
/* Not enough space in the buffer */
return false;
}
total += len;
}
/* Add the absolute path. */
len = _snprintf(&buffer[total], maxlength - total, "%s", &rootFrom[1]);
if (len >= maxlength - total)
{
return false;
}
return true;
}
size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list params)
{
size_t len = vsnprintf(buffer, maxlength, fmt, params);
if (len >= maxlength)
{
len = maxlength - 1;
buffer[len] = '\0';
}
return len;
}
bool UTIL_VerifySignature(const void *addr, const char *sig, size_t len)
{
unsigned char *addr1 = (unsigned char *) addr;
unsigned char *addr2 = (unsigned char *) sig;
for (size_t i = 0; i < len; i++)
{
if (addr2[i] == '*')
continue;
if (addr1[i] != addr2[i])
return false;
}
return true;
}