eccodes/src/string_util.cc

239 lines
5.9 KiB
C++
Raw Normal View History

2016-11-25 14:46:14 +00:00
/*
2020-01-28 14:32:34 +00:00
* (C) Copyright 2005- ECMWF.
2016-11-25 14:46:14 +00:00
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
*
* In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
*/
#include "grib_api_internal.h"
/* Compare two strings ignoring case.
* strcasecmp is not in the C standard. However, it's defined by
* 4.4BSD, POSIX.1-2001. So we use our own
*/
2020-01-22 13:10:59 +00:00
int strcmp_nocase(const char* s1, const char* s2)
2016-11-25 14:46:14 +00:00
{
2020-01-22 13:10:59 +00:00
const unsigned char *us1 = (const unsigned char*)s1,
*us2 = (const unsigned char*)s2;
2016-12-06 15:58:55 +00:00
while (tolower(*us1) == tolower(*us2++)) {
2016-11-25 14:46:14 +00:00
if (*us1++ == '\0')
return (0);
2016-12-06 15:58:55 +00:00
}
return (tolower(*us1) - tolower(*--us2));
2016-11-25 14:46:14 +00:00
}
/* Strip whitespace from the end of a string */
2022-06-10 19:51:39 +00:00
void string_rtrim(char* s)
2016-11-25 14:46:14 +00:00
{
size_t len = 0;
2020-01-22 13:10:59 +00:00
if (!s)
return;
2016-11-25 14:46:14 +00:00
len = strlen(s);
while (len > 0 && isspace((unsigned char)s[len - 1]))
len--;
s[len] = '\0';
}
2022-06-10 19:51:39 +00:00
void string_lrtrim(char** x, int do_left, int do_right)
{
DebugAssert(do_left || do_right);
if (do_left) {
while (isspace(**x) && **x != '\0')
(*x)++;
}
if (**x == '\0')
return;
if (do_right) {
char* p = (*x) + strlen(*x) - 1;
while (isspace(*p)) {
*p = '\0';
p--;
}
if (isspace(*p))
*p = '\0';
}
}
2016-11-25 14:46:14 +00:00
/* Return the component after final slash */
/* "/tmp/x" -> "x" */
/* "/tmp/" -> "" */
const char* extract_filename(const char* filepath)
{
2019-12-11 14:16:19 +00:00
/* Note: Windows users could pass in fwd slashes!
* so have to check both separators
*/
const char* s = strrchr(filepath, '/');
2020-01-22 13:10:59 +00:00
if (!s)
s = strrchr(filepath, '\\');
if (!s)
return filepath;
else
return s + 1;
2016-11-25 14:46:14 +00:00
}
2019-09-05 12:28:47 +00:00
/* Returns an array of strings the last of which is NULL.
* Note: The delimiter here is a 'string' but must be ONE character!
* Splitting with several delimiters is not supported.
*/
2016-11-25 14:46:14 +00:00
char** string_split(char* inputString, const char* delimiter)
{
2020-01-22 13:10:59 +00:00
char** result = NULL;
char* p = inputString;
2016-11-25 14:46:14 +00:00
char* lastDelimiter = NULL;
2020-01-22 13:10:59 +00:00
char* aToken = NULL;
char* lasts = NULL;
2020-01-22 13:10:59 +00:00
size_t numTokens = 0;
size_t strLength = 0;
size_t index = 0;
char delimiterChar = 0;
2016-11-25 14:46:14 +00:00
DebugAssert(inputString);
2020-01-22 13:10:59 +00:00
DebugAssert(delimiter && (strlen(delimiter) == 1));
2016-11-25 14:46:14 +00:00
delimiterChar = delimiter[0];
while (*p) {
const char ctmp = *p;
if (ctmp == delimiterChar) {
++numTokens;
lastDelimiter = p;
}
p++;
}
strLength = strlen(inputString);
if (lastDelimiter < (inputString + strLength - 1)) {
++numTokens; /* there is a trailing token */
}
++numTokens; /* terminating NULL string to mark the end */
result = (char**)malloc(numTokens * sizeof(char*));
Assert(result);
/* Start tokenizing */
aToken = strtok_r(inputString, delimiter, &lasts);
2016-11-25 14:46:14 +00:00
while (aToken) {
Assert(index < numTokens);
*(result + index++) = strdup(aToken);
aToken = strtok_r(NULL, delimiter, &lasts);
2016-11-25 14:46:14 +00:00
}
Assert(index == numTokens - 1);
*(result + index) = NULL;
2016-11-25 14:46:14 +00:00
return result;
}
2018-02-22 14:46:21 +00:00
/* Return GRIB_SUCCESS if can convert input to an integer, GRIB_INVALID_ARGUMENT otherwise */
int string_to_long(const char* input, long* output)
{
const int base = 10;
2020-01-22 13:10:59 +00:00
char* endptr;
long val = 0;
2020-01-22 13:10:59 +00:00
if (!input)
return GRIB_INVALID_ARGUMENT;
2018-02-22 14:46:21 +00:00
errno = 0;
2020-01-22 13:10:59 +00:00
val = strtol(input, &endptr, base);
if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) ||
(errno != 0 && val == 0)) {
2018-02-22 14:46:21 +00:00
/*perror("strtol");*/
return GRIB_INVALID_ARGUMENT;
}
if (endptr == input) {
2018-02-22 14:46:21 +00:00
/*fprintf(stderr, "No digits were found. EXIT_FAILURE\n");*/
return GRIB_INVALID_ARGUMENT;
}
*output = val;
2018-02-22 14:46:21 +00:00
return GRIB_SUCCESS;
}
/* Return 1 if 's' ends with 'suffix', 0 otherwise */
int string_ends_with(const char* s, const char* suffix)
{
const size_t len1 = strlen(s);
const size_t len2 = strlen(suffix);
if (len2 > len1)
return 0;
if (strcmp(&s[len1 - len2], suffix) == 0)
return 1;
return 0;
}
2021-02-04 11:52:57 +00:00
2022-06-10 19:51:39 +00:00
int string_count_char(const char* str, char c)
2021-02-04 11:52:57 +00:00
{
int i = 0, count = 0;
DebugAssert(str);
for(i=0; str[i]; i++) {
if (str[i] == c) count++;
}
return count;
}
2022-03-15 16:52:54 +00:00
const char* codes_get_product_name(ProductKind product)
{
switch (product) {
case PRODUCT_GRIB:
return "GRIB";
case PRODUCT_BUFR:
return "BUFR";
case PRODUCT_METAR:
return "METAR";
case PRODUCT_GTS:
return "GTS";
case PRODUCT_TAF:
return "TAF";
case PRODUCT_ANY:
return "ANY";
}
return "unknown";
}
const char* grib_get_type_name(int type)
{
switch (type) {
case GRIB_TYPE_LONG:
return "long";
case GRIB_TYPE_STRING:
return "string";
case GRIB_TYPE_BYTES:
return "bytes";
case GRIB_TYPE_DOUBLE:
return "double";
case GRIB_TYPE_LABEL:
return "label";
case GRIB_TYPE_SECTION:
return "section";
}
return "unknown";
}
/* Replace all occurrences of character in string.
* Returns pointer to the NUL byte at the end of 's'
*/
2022-06-09 17:10:07 +00:00
char *string_replace_char(char *s, char oldc, char newc)
{
for (; *s; ++s)
2022-06-09 17:10:07 +00:00
if (*s == oldc)
*s = newc;
return s;
}
/* Remove all instances of character 'c' from 'str' */
void string_remove_char(char * str, char c)
{
size_t i, j;
size_t len = strlen(str);
for(i=0; i<len; i++) {
if(str[i] == c) {
for(j=i; j<len; j++) {
str[j] = str[j+1];
}
len--;
i--;
}
}
}