XUtils string related updates

- allow count out-parameter of String_split() to be NULL
- introduce xStrndup()
- do not allow NULL pointers passed to String_eq()
  it is not used in any code
- implement String_startsWith(), String_contains_i() and String_eq()
  as inline header functions
- adjust several conversion issues
This commit is contained in:
Christian Göttsche 2020-10-03 21:20:43 +02:00
parent 577416d1a9
commit 4c66eb6d4c
13 changed files with 77 additions and 65 deletions

View File

@ -7,6 +7,8 @@ Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "config.h" // IWYU pragma: keep
#include <stdbool.h> #include <stdbool.h>
#include <sys/types.h> #include <sys/types.h>

2
CRT.c
View File

@ -655,7 +655,7 @@ void CRT_init(int delay, int colorScheme, bool allowUnicode) {
setlocale(LC_CTYPE, ""); setlocale(LC_CTYPE, "");
#ifdef HAVE_LIBNCURSESW #ifdef HAVE_LIBNCURSESW
if (allowUnicode && strcmp(nl_langinfo(CODESET), "UTF-8") == 0) if (allowUnicode && String_eq(nl_langinfo(CODESET), "UTF-8"))
CRT_utf8 = true; CRT_utf8 = true;
else else
CRT_utf8 = false; CRT_utf8 = false;

View File

@ -5,6 +5,8 @@ Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "config.h" // IWYU pragma: keep
#include "FunctionBar.h" #include "FunctionBar.h"
#include <stdlib.h> #include <stdlib.h>

View File

@ -8,6 +8,8 @@ Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "config.h" // IWYU pragma: keep
#include <stdbool.h> #include <stdbool.h>
#include <sys/types.h> #include <sys/types.h>

View File

@ -7,6 +7,8 @@ Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "config.h" // IWYU pragma: keep
#include <stdbool.h> #include <stdbool.h>
#include <sys/time.h> #include <sys/time.h>

View File

@ -31,16 +31,14 @@ void Settings_delete(Settings* this) {
static void Settings_readMeters(Settings* this, char* line, int column) { static void Settings_readMeters(Settings* this, char* line, int column) {
char* trim = String_trim(line); char* trim = String_trim(line);
int nIds; char** ids = String_split(trim, ' ', NULL);
char** ids = String_split(trim, ' ', &nIds);
free(trim); free(trim);
this->columns[column].names = ids; this->columns[column].names = ids;
} }
static void Settings_readMeterModes(Settings* this, char* line, int column) { static void Settings_readMeterModes(Settings* this, char* line, int column) {
char* trim = String_trim(line); char* trim = String_trim(line);
int nIds; char** ids = String_split(trim, ' ', NULL);
char** ids = String_split(trim, ' ', &nIds);
free(trim); free(trim);
int len = 0; int len = 0;
for (int i = 0; ids[i]; i++) { for (int i = 0; ids[i]; i++) {
@ -94,8 +92,7 @@ static void Settings_defaultMeters(Settings* this, int initialCpuCount) {
static void readFields(ProcessField* fields, int* flags, const char* line) { static void readFields(ProcessField* fields, int* flags, const char* line) {
char* trim = String_trim(line); char* trim = String_trim(line);
int nIds; char** ids = String_split(trim, ' ', NULL);
char** ids = String_split(trim, ' ', &nIds);
free(trim); free(trim);
int i, j; int i, j;
*flags = 0; *flags = 0;
@ -126,7 +123,7 @@ static bool Settings_read(Settings* this, const char* fileName, int initialCpuCo
if (!line) { if (!line) {
break; break;
} }
int nOptions; size_t nOptions;
char** option = String_split(line, '=', &nOptions); char** option = String_split(line, '=', &nOptions);
free (line); free (line);
if (nOptions < 2) { if (nOptions < 2) {

View File

@ -5,6 +5,8 @@ Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include "config.h" // IWYU pragma: keep
#include "UsersTable.h" #include "UsersTable.h"
#include <pwd.h> #include <pwd.h>

View File

@ -54,11 +54,11 @@ void* xRealloc(void* ptr, size_t size) {
} }
char* String_cat(const char* s1, const char* s2) { char* String_cat(const char* s1, const char* s2) {
int l1 = strlen(s1); const size_t l1 = strlen(s1);
int l2 = strlen(s2); const size_t l2 = strlen(s2);
char* out = xMalloc(l1 + l2 + 1); char* out = xMalloc(l1 + l2 + 1);
memcpy(out, s1, l1); memcpy(out, s1, l1);
memcpy(out+l1, s2, l2+1); memcpy(out+l1, s2, l2);
out[l1 + l2] = '\0'; out[l1 + l2] = '\0';
return out; return out;
} }
@ -67,39 +67,24 @@ char* String_trim(const char* in) {
while (in[0] == ' ' || in[0] == '\t' || in[0] == '\n') { while (in[0] == ' ' || in[0] == '\t' || in[0] == '\n') {
in++; in++;
} }
int len = strlen(in);
size_t len = strlen(in);
while (len > 0 && (in[len-1] == ' ' || in[len-1] == '\t' || in[len-1] == '\n')) { while (len > 0 && (in[len-1] == ' ' || in[len-1] == '\t' || in[len-1] == '\n')) {
len--; len--;
} }
char* out = xMalloc(len+1);
strncpy(out, in, len); return xStrndup(in, len);
out[len] = '\0';
return out;
} }
inline int String_eq(const char* s1, const char* s2) { char** String_split(const char* s, char sep, size_t* n) {
if (s1 == NULL || s2 == NULL) { const unsigned int rate = 10;
if (s1 == NULL && s2 == NULL)
return 1;
else
return 0;
}
return (strcmp(s1, s2) == 0);
}
char** String_split(const char* s, char sep, int* n) {
*n = 0;
const int rate = 10;
char** out = xCalloc(rate, sizeof(char*)); char** out = xCalloc(rate, sizeof(char*));
int ctr = 0; size_t ctr = 0;
int blocks = rate; unsigned int blocks = rate;
char* where; const char* where;
while ((where = strchr(s, sep)) != NULL) { while ((where = strchr(s, sep)) != NULL) {
int size = where - s; size_t size = (size_t)(where - s);
char* token = xMalloc(size + 1); out[ctr] = xStrndup(s, size);
strncpy(token, s, size);
token[size] = '\0';
out[ctr] = token;
ctr++; ctr++;
if (ctr == blocks) { if (ctr == blocks) {
blocks += rate; blocks += rate;
@ -113,7 +98,10 @@ char** String_split(const char* s, char sep, int* n) {
} }
out = xRealloc(out, sizeof(char*) * (ctr + 1)); out = xRealloc(out, sizeof(char*) * (ctr + 1));
out[ctr] = NULL; out[ctr] = NULL;
*n = ctr;
if (n)
*n = ctr;
return out; return out;
} }
@ -121,28 +109,28 @@ void String_freeArray(char** s) {
if (!s) { if (!s) {
return; return;
} }
for (int i = 0; s[i] != NULL; i++) { for (size_t i = 0; s[i] != NULL; i++) {
free(s[i]); free(s[i]);
} }
free(s); free(s);
} }
char* String_getToken(const char* line, const unsigned short int numMatch) { char* String_getToken(const char* line, const unsigned short int numMatch) {
const unsigned short int len = strlen(line); const size_t len = strlen(line);
char inWord = 0; char inWord = 0;
unsigned short int count = 0; unsigned short int count = 0;
char match[50]; char match[50];
unsigned short int foundCount = 0; size_t foundCount = 0;
for (unsigned short int i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
char lastState = inWord; char lastState = inWord;
inWord = line[i] == ' ' ? 0:1; inWord = line[i] == ' ' ? 0:1;
if (lastState == 0 && inWord == 1) if (lastState == 0 && inWord == 1)
count++; count++;
if(inWord == 1){ if (inWord == 1){
if (count == numMatch && line[i] != ' ' && line[i] != '\0' && line[i] != '\n' && line[i] != (char)EOF) { if (count == numMatch && line[i] != ' ' && line[i] != '\0' && line[i] != '\n' && line[i] != (char)EOF) {
match[foundCount] = line[i]; match[foundCount] = line[i];
foundCount++; foundCount++;
@ -155,8 +143,8 @@ char* String_getToken(const char* line, const unsigned short int numMatch) {
} }
char* String_readLine(FILE* fd) { char* String_readLine(FILE* fd) {
const int step = 1024; const unsigned int step = 1024;
int bufSize = step; unsigned int bufSize = step;
char* buffer = xMalloc(step + 1); char* buffer = xMalloc(step + 1);
char* at = buffer; char* at = buffer;
for (;;) { for (;;) {
@ -213,3 +201,11 @@ char* xStrdup(const char* str) {
} }
return data; return data;
} }
char* xStrndup(const char* str, size_t len) {
char* data = strndup(str, len);
if (!data) {
fail();
}
return data;
}

View File

@ -9,6 +9,7 @@ in the source distribution for its full text.
#include "config.h" // IWYU pragma: keep #include "config.h" // IWYU pragma: keep
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> // IWYU pragma: keep #include <stdlib.h> // IWYU pragma: keep
#include <string.h> // IWYU pragma: keep #include <string.h> // IWYU pragma: keep
@ -24,25 +25,31 @@ void* xCalloc(size_t nmemb, size_t size);
void* xRealloc(void* ptr, size_t size); void* xRealloc(void* ptr, size_t size);
#define String_startsWith(s, match) (strncmp((s),(match),strlen(match)) == 0)
#define String_contains_i(s1, s2) (strcasestr(s1, s2) != NULL)
/* /*
* String_startsWith gives better performance if strlen(match) can be computed * String_startsWith gives better performance if strlen(match) can be computed
* at compile time (e.g. when they are immutable string literals). :) * at compile time (e.g. when they are immutable string literals). :)
*/ */
static inline bool String_startsWith(const char* s, const char* match) {
return strncmp(s, match, strlen(match)) == 0;
}
static inline bool String_contains_i(const char* s1, const char* s2) {
return strcasestr(s1, s2) != NULL;
}
static inline bool String_eq(const char* s1, const char* s2) {
return strcmp(s1, s2) == 0;
}
char* String_cat(const char* s1, const char* s2); char* String_cat(const char* s1, const char* s2);
char* String_trim(const char* in); char* String_trim(const char* in);
int String_eq(const char* s1, const char* s2); char** String_split(const char* s, char sep, size_t* n);
char** String_split(const char* s, char sep, int* n);
void String_freeArray(char** s); void String_freeArray(char** s);
char* String_getToken(const char* line, const unsigned short int numMatch); char* String_getToken(const char* line, unsigned short int numMatch);
char* String_readLine(FILE* fd); char* String_readLine(FILE* fd);
@ -54,4 +61,6 @@ int xSnprintf(char *buf, int len, const char* fmt, ...);
char* xStrdup(const char* str) ATTR_NONNULL; char* xStrdup(const char* str) ATTR_NONNULL;
char* xStrndup(const char* str, size_t len) ATTR_NONNULL;
#endif #endif

2
htop.c
View File

@ -122,7 +122,7 @@ static CommandLineSettings parseArguments(int argc, char** argv) {
exit(0); exit(0);
case 's': case 's':
assert(optarg); /* please clang analyzer, cause optarg can be NULL in the 'u' case */ assert(optarg); /* please clang analyzer, cause optarg can be NULL in the 'u' case */
if (strcmp(optarg, "help") == 0) { if (String_eq(optarg, "help")) {
for (int j = 1; j < Platform_numberOfFields; j++) { for (int j = 1; j < Platform_numberOfFields; j++) {
const char* name = Process_fields[j].name; const char* name = Process_fields[j].name;
if (name) printf ("%s\n", name); if (name) printf ("%s\n", name);

View File

@ -53,7 +53,7 @@ static unsigned long int parseBatInfo(const char *fileName, const unsigned short
if (!dirEntry) if (!dirEntry)
break; break;
char* entryName = dirEntry->d_name; char* entryName = dirEntry->d_name;
if (strncmp(entryName, "BAT", 3)) if (String_startsWith(entryName, "BAT"))
continue; continue;
batteries[nBatteries] = xStrdup(entryName); batteries[nBatteries] = xStrdup(entryName);
nBatteries++; nBatteries++;
@ -128,7 +128,7 @@ static ACPresence procAcpiCheck(void) {
char *isOnline = String_getToken(line, 2); char *isOnline = String_getToken(line, 2);
free(line); free(line);
if (strcmp(isOnline, "on-line") == 0) { if (String_eq(isOnline, "on-line")) {
isOn = AC_PRESENT; isOn = AC_PRESENT;
} else { } else {
isOn = AC_ABSENT; isOn = AC_ABSENT;

View File

@ -419,9 +419,9 @@ static void LinuxProcessList_readIoFile(LinuxProcess* process, const char* dirna
while ((line = strsep(&buf, "\n")) != NULL) { while ((line = strsep(&buf, "\n")) != NULL) {
switch (line[0]) { switch (line[0]) {
case 'r': case 'r':
if (line[1] == 'c' && strncmp(line+2, "har: ", 5) == 0) if (line[1] == 'c' && String_startsWith(line+2, "har: "))
process->io_rchar = strtoull(line+7, NULL, 10); process->io_rchar = strtoull(line+7, NULL, 10);
else if (strncmp(line+1, "ead_bytes: ", 11) == 0) { else if (String_startsWith(line+1, "ead_bytes: ")) {
process->io_read_bytes = strtoull(line+12, NULL, 10); process->io_read_bytes = strtoull(line+12, NULL, 10);
process->io_rate_read_bps = process->io_rate_read_bps =
((double)(process->io_read_bytes - last_read))/(((double)(now - process->io_rate_read_time))/1000); ((double)(process->io_read_bytes - last_read))/(((double)(now - process->io_rate_read_time))/1000);
@ -429,9 +429,9 @@ static void LinuxProcessList_readIoFile(LinuxProcess* process, const char* dirna
} }
break; break;
case 'w': case 'w':
if (line[1] == 'c' && strncmp(line+2, "har: ", 5) == 0) if (line[1] == 'c' && String_startsWith(line+2, "har: "))
process->io_wchar = strtoull(line+7, NULL, 10); process->io_wchar = strtoull(line+7, NULL, 10);
else if (strncmp(line+1, "rite_bytes: ", 12) == 0) { else if (String_startsWith(line+1, "rite_bytes: ")) {
process->io_write_bytes = strtoull(line+13, NULL, 10); process->io_write_bytes = strtoull(line+13, NULL, 10);
process->io_rate_write_bps = process->io_rate_write_bps =
((double)(process->io_write_bytes - last_write))/(((double)(now - process->io_rate_write_time))/1000); ((double)(process->io_write_bytes - last_write))/(((double)(now - process->io_rate_write_time))/1000);
@ -439,14 +439,14 @@ static void LinuxProcessList_readIoFile(LinuxProcess* process, const char* dirna
} }
break; break;
case 's': case 's':
if (line[4] == 'r' && strncmp(line+1, "yscr: ", 6) == 0) { if (line[4] == 'r' && String_startsWith(line+1, "yscr: ")) {
process->io_syscr = strtoull(line+7, NULL, 10); process->io_syscr = strtoull(line+7, NULL, 10);
} else if (strncmp(line+1, "yscw: ", 6) == 0) { } else if (String_startsWith(line+1, "yscw: ")) {
process->io_syscw = strtoull(line+7, NULL, 10); process->io_syscw = strtoull(line+7, NULL, 10);
} }
break; break;
case 'c': case 'c':
if (strncmp(line+1, "ancelled_write_bytes: ", 22) == 0) { if (String_startsWith(line+1, "ancelled_write_bytes: ")) {
process->io_cancelled_write_bytes = strtoull(line+23, NULL, 10); process->io_cancelled_write_bytes = strtoull(line+23, NULL, 10);
} }
} }
@ -598,7 +598,7 @@ static void LinuxProcessList_readOpenVZData(LinuxProcess* process, const char* d
switch(field) { switch(field) {
case 1: case 1:
foundEnvID = true; foundEnvID = true;
if(0 != strcmp(name_value_sep, process->ctid ? process->ctid : "")) { if(!String_eq(name_value_sep, process->ctid ? process->ctid : "")) {
free(process->ctid); free(process->ctid);
process->ctid = xStrdup(name_value_sep); process->ctid = xStrdup(name_value_sep);
} }
@ -762,7 +762,7 @@ static void LinuxProcessList_readSecattrData(LinuxProcess* process, const char*
char *newline = strchr(buffer, '\n'); char *newline = strchr(buffer, '\n');
if (newline) if (newline)
*newline = '\0'; *newline = '\0';
if (process->secattr && 0 == strcmp(process->secattr, buffer)) if (process->secattr && String_eq(process->secattr, buffer))
return; return;
free(process->secattr); free(process->secattr);
process->secattr = xStrdup(buffer); process->secattr = xStrdup(buffer);

View File

@ -376,7 +376,7 @@ void Platform_getNetworkIO(unsigned long int *bytesReceived,
&packetsTransmittedParsed) != 5) &packetsTransmittedParsed) != 5)
continue; continue;
if (0 == strcmp(interfaceName, "lo:")) if (String_eq(interfaceName, "lo:"))
continue; continue;
bytesReceivedSum += bytesReceivedParsed; bytesReceivedSum += bytesReceivedParsed;