From 62b5c602821cee8ac703ebe6362f3e1fc6d9ad3c Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Sat, 29 Mar 2014 20:08:31 -0400 Subject: misc: Add string utility functions. It's more readable to write "M_StringEndsWith(..." than doing a bunch of pointer arithmetic, and this is a common pattern. Also add M_StringStartsWith, M_StringJoin and M_StringCopy. The latter is a safe alternative for strcpy() that works the same as OpenBSD's strlcpy(). Use these functions in a few places where it makes sense. --- src/d_iwad.c | 9 ++--- src/doom/d_main.c | 20 +++++----- src/i_pcsound.c | 6 +-- src/i_sdlsound.c | 11 ++--- src/m_misc.c | 111 ++++++++++++++++++++++++++++++++++++++++++++------- src/m_misc.h | 4 ++ src/net_packet.c | 10 +++-- src/net_structrw.c | 6 +-- src/setup/mainmenu.c | 2 +- src/w_merge.c | 3 +- 10 files changed, 135 insertions(+), 47 deletions(-) diff --git a/src/d_iwad.c b/src/d_iwad.c index f4155349..293553a2 100644 --- a/src/d_iwad.c +++ b/src/d_iwad.c @@ -423,7 +423,7 @@ static char *CheckDirectoryHasIWAD(char *dir, char *iwadname) // As a special case, the "directory" may refer directly to an // IWAD file if the path comes from DOOMWADDIR or DOOMWADPATH. - + if (DirIsFile(dir, iwadname) && M_FileExists(dir)) { return strdup(dir); @@ -432,15 +432,14 @@ static char *CheckDirectoryHasIWAD(char *dir, char *iwadname) // Construct the full path to the IWAD if it is located in // this directory, and check if it exists. - filename = malloc(strlen(dir) + strlen(iwadname) + 3); - if (!strcmp(dir, ".")) { - strcpy(filename, iwadname); + filename = strdup(iwadname); } else { - sprintf(filename, "%s%c%s", dir, DIR_SEPARATOR, iwadname); + char sep[] = {DIR_SEPARATOR, '\0'}; + filename = M_StringJoin(dir, sep, iwadname); } if (M_FileExists(filename)) diff --git a/src/doom/d_main.c b/src/doom/d_main.c index e6b993c4..fa84bc3b 100644 --- a/src/doom/d_main.c +++ b/src/doom/d_main.c @@ -1352,19 +1352,19 @@ void D_DoomMain (void) if (p) { - if (!strcasecmp(myargv[p+1] + strlen(myargv[p+1]) - 4, ".lmp")) + if (M_StringEndsWith(myargv[p + 1], ".lmp")) { - strcpy(file, myargv[p + 1]); + M_StringCopy(file, myargv[p + 1], sizeof(file)); } else { - sprintf (file,"%s.lmp", myargv[p+1]); + snprintf(file, sizeof(file), "%s.lmp", myargv[p+1]); } - if (D_AddFile (file)) + if (D_AddFile(file)) { - strncpy(demolumpname, lumpinfo[numlumps - 1].name, 8); - demolumpname[8] = '\0'; + M_StringCopy(demolumpname, lumpinfo[numlumps - 1].name, + sizeof(demolumpname)); printf("Playing demo %s.\n", file); } @@ -1374,10 +1374,8 @@ void D_DoomMain (void) // the demo in the same way as Vanilla Doom. This makes // tricks like "-playdemo demo1" possible. - strncpy(demolumpname, myargv[p + 1], 8); - demolumpname[8] = '\0'; + M_StringCopy(demolumpname, myargv[p + 1], sizeof(demolumpname)); } - } I_AtExit((atexit_func_t) G_CheckDemoStatus, true); @@ -1686,8 +1684,8 @@ void D_DoomMain (void) if (startloadgame >= 0) { - strcpy(file, P_SaveGameFile(startloadgame)); - G_LoadGame (file); + M_StringCopy(file, P_SaveGameFile(startloadgame), sizeof(file)); + G_LoadGame(file); } if (gameaction != ga_loadgame ) diff --git a/src/i_pcsound.c b/src/i_pcsound.c index 655f5a8b..0303d2e4 100644 --- a/src/i_pcsound.c +++ b/src/i_pcsound.c @@ -30,7 +30,7 @@ #include "deh_str.h" #include "i_sound.h" - +#include "m_misc.h" #include "w_wad.h" #include "z_zone.h" @@ -253,11 +253,11 @@ static int I_PCS_GetSfxLumpNum(sfxinfo_t* sfx) if (use_sfx_prefix) { - sprintf(namebuf, "dp%s", DEH_String(sfx->name)); + snprintf(namebuf, sizeof(namebuf), "dp%s", DEH_String(sfx->name)); } else { - strcpy(namebuf, DEH_String(sfx->name)); + M_StringCopy(namebuf, DEH_String(sfx->name), sizeof(namebuf)); } return W_GetNumForName(namebuf); diff --git a/src/i_sdlsound.c b/src/i_sdlsound.c index e60e18e3..b35c83ea 100644 --- a/src/i_sdlsound.c +++ b/src/i_sdlsound.c @@ -43,6 +43,7 @@ #include "i_system.h" #include "i_swap.h" #include "m_argv.h" +#include "m_misc.h" #include "w_wad.h" #include "z_zone.h" @@ -717,7 +718,7 @@ static boolean CacheSFX(sfxinfo_t *sfxinfo) return true; } -static void GetSfxLumpName(sfxinfo_t *sfx, char *buf) +static void GetSfxLumpName(sfxinfo_t *sfx, char *buf, size_t buf_len) { // Linked sfx lumps? Get the lump number for the sound linked to. @@ -731,11 +732,11 @@ static void GetSfxLumpName(sfxinfo_t *sfx, char *buf) if (use_sfx_prefix) { - sprintf(buf, "ds%s", DEH_String(sfx->name)); + snprintf(buf, buf_len, "ds%s", DEH_String(sfx->name)); } else { - strcpy(buf, DEH_String(sfx->name)); + M_StringCopy(buf, DEH_String(sfx->name), buf_len); } } @@ -765,7 +766,7 @@ static void I_SDL_PrecacheSounds(sfxinfo_t *sounds, int num_sounds) fflush(stdout); } - GetSfxLumpName(&sounds[i], namebuf); + GetSfxLumpName(&sounds[i], namebuf, sizeof(buf)); sounds[i].lumpnum = W_CheckNumForName(namebuf); @@ -815,7 +816,7 @@ static int I_SDL_GetSfxLumpNum(sfxinfo_t *sfx) { char namebuf[9]; - GetSfxLumpName(sfx, namebuf); + GetSfxLumpName(sfx, namebuf, sizeof(namebuf)); return W_GetNumForName(namebuf); } diff --git a/src/m_misc.c b/src/m_misc.c index f3e11c36..7bab3f1b 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -298,55 +298,136 @@ char *M_StrCaseStr(char *haystack, char *needle) // // String replace function. -// Returns a Z_Malloc()ed string. // char *M_StringReplace(char *haystack, char *needle, char *replacement) { - char *result, *p, *dst; + char *result, *p; + char *dst; size_t needle_len = strlen(needle); - int n; + size_t result_len, dst_len; - // Count number of occurrences of 'p': + // Iterate through occurrences of 'needle' and calculate the size of + // the new string. + result_len = strlen(haystack) + 1; + p = haystack; - for (p = haystack, n = 0;; ++n) + for (;;) { p = strstr(p, needle); - if (p == NULL) { break; } p += needle_len; + result_len += strlen(replacement) - needle_len; } // Construct new string. - result = Z_Malloc(strlen(haystack) - + (strlen(replacement) - needle_len) * n - + 1, - PU_STATIC, NULL); + result = malloc(result_len); + if (result == NULL) + { + I_Error("M_StringReplace: Failed to allocate new string"); + return NULL; + } - dst = result; + dst = result; dst_len = result_len; p = haystack; while (*p != '\0') { if (!strncmp(p, needle, needle_len)) { - strcpy(dst, replacement); - dst += strlen(replacement); + M_StringCopy(dst, replacement, dst_len); p += needle_len; + dst += strlen(replacement); + dst_len -= strlen(replacement); } else { *dst = *p; - ++dst; + ++dst; --dst_len; ++p; } } - *dst = '\0'; + + return result; +} + +// Safe string copy function that works like OpenBSD's strlcpy(). +// Returns true if the string was not truncated. + +boolean M_StringCopy(char *dest, char *src, size_t dest_size) +{ + strncpy(dest, src, dest_size); + dest[dest_size - 1] = '\0'; + return strlen(dest) == strlen(src); +} + +// Returns true if 's' begins with the specified prefix. + +boolean M_StringStartsWith(char *s, char *prefix) +{ + return strlen(s) > strlen(prefix) + && strncmp(s, prefix, strlen(prefix)) == 0; +} + +// Returns true if 's' ends with the specified suffix. + +boolean M_StringEndsWith(char *s, char *suffix) +{ + return strlen(s) >= strlen(suffix) + && strcmp(s + strlen(s) - strlen(suffix), suffix) == 0; +} + +// Return a newly-malloced string with all the strings given as arguments +// concatenated together. + +char *M_StringJoin(char *s, ...) +{ + char *result, *v; + va_list args; + size_t result_len; + + result_len = strlen(s) + 1; + + va_start(args, s); + for (;;) + { + v = va_arg(args, char *); + if (v == NULL) + { + break; + } + + result_len += strlen(v); + } + va_end(args); + + result = malloc(result_len); + + if (result == NULL) + { + I_Error("M_StringJoin: Failed to allocate new string."); + return NULL; + } + + M_StringCopy(result, s, result_len); + + va_start(args, s); + for (;;) + { + v = va_arg(args, char *); + if (v == NULL) + { + break; + } + + strncat(result, v, result_len); + } + va_end(args); return result; } diff --git a/src/m_misc.h b/src/m_misc.h index e96e2383..f81d6dc8 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -43,7 +43,11 @@ boolean M_StrToInt(const char *str, int *result); void M_ExtractFileBase(char *path, char *dest); void M_ForceUppercase(char *text); char *M_StrCaseStr(char *haystack, char *needle); +boolean M_StringCopy(char *dest, char *src, size_t dest_size); char *M_StringReplace(char *haystack, char *needle, char *replacement); +char *M_StringJoin(char *s, ...); +boolean M_StringStartsWith(char *s, char *prefix); +boolean M_StringEndsWith(char *s, char *suffix); char *M_OEMToUTF8(const char *ansi); #endif diff --git a/src/net_packet.c b/src/net_packet.c index 86809167..f984ca1e 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -24,6 +24,7 @@ //----------------------------------------------------------------------------- #include +#include "m_misc.h" #include "net_packet.h" #include "z_zone.h" @@ -280,19 +281,22 @@ void NET_WriteInt32(net_packet_t *packet, unsigned int i) void NET_WriteString(net_packet_t *packet, char *string) { byte *p; + size_t string_size; + + string_size = strlen(string) + 1; // Increase the packet size until large enough to hold the string - while (packet->len + strlen(string) + 1 > packet->alloced) + while (packet->len + string_size > packet->alloced) { NET_IncreasePacket(packet); } p = packet->data + packet->len; - strcpy((char *) p, string); + M_StringCopy((char *) p, string, string_size); - packet->len += strlen(string) + 1; + packet->len += string_size; } diff --git a/src/net_structrw.c b/src/net_structrw.c index 10b035c0..fd5008de 100644 --- a/src/net_structrw.c +++ b/src/net_structrw.c @@ -27,7 +27,7 @@ #include #include "doomtype.h" - +#include "m_misc.h" #include "net_packet.h" #include "net_structrw.h" @@ -493,7 +493,7 @@ boolean NET_ReadWaitData(net_packet_t *packet, net_waitdata_t *data) return false; } - strcpy(data->player_names[i], s); + M_StringCopy(data->player_names[i], s, MAXPLAYERNAME); s = NET_ReadString(packet); @@ -502,7 +502,7 @@ boolean NET_ReadWaitData(net_packet_t *packet, net_waitdata_t *data) return false; } - strcpy(data->player_addrs[i], s); + M_StringCopy(data->player_addrs[i], s, MAXPLAYERNAME); } return NET_ReadSHA1Sum(packet, data->wad_sha1sum) diff --git a/src/setup/mainmenu.c b/src/setup/mainmenu.c index 8e5ebdad..81688b29 100644 --- a/src/setup/mainmenu.c +++ b/src/setup/mainmenu.c @@ -329,7 +329,7 @@ static void SetWindowTitle(void) TXT_SetDesktopTitle(title); - Z_Free(title); + free(title); } // Initialize the textscreen library. diff --git a/src/w_merge.c b/src/w_merge.c index 027c6c2c..e7ba224f 100644 --- a/src/w_merge.c +++ b/src/w_merge.c @@ -33,6 +33,7 @@ #include "doomtype.h" #include "i_system.h" +#include "m_misc.h" #include "w_merge.h" #include "w_wad.h" #include "z_zone.h" @@ -718,7 +719,7 @@ void W_NWTDashMerge(char *filename) // Replace this entry with an empty string. This is what // nwt -merge does. - strcpy(iwad_sprites.lumps[i].name, ""); + M_StringCopy(iwad_sprites.lumps[i].name, "", 8); } } -- cgit v1.2.3