https://gitlab.inria.fr/pm2/pm2
Tip revision: 2fbf19bb15f8ebded3c8661efc6c788dacc5507d authored by Alexandre Denis on 02 December 2009, 16:12:15 UTC
ajout de TBX_CRITICAL_SHARED pour le cas pthread
ajout de TBX_CRITICAL_SHARED pour le cas pthread
Tip revision: 2fbf19b
tbx_string_management.c
/*! \file tbx_string_management.c
* \brief TBX string object management routines.
*
* This file contains the TBX string object management functions.
*
*/
/*
* PM2: Parallel Multithreaded Machine
* Copyright (C) 2001 "the PM2 team" (see AUTHORS file)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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.
*/
/*
* tbx_string_management.c
* :::::::::::::::::::::::////////////////////////////////////////////////////
*/
#include "tbx.h"
#include <errno.h>
#include <string.h>
#include <limits.h>
/*
* Macros
* ___________________________________________________________________________
*/
#define MAX_NUMBER_LENGTH 256
/*
* Functions
* ___________________________________________________________________________
*/
/*
* Initialization
* --------------
*/
void
tbx_string_manager_init(void)
{
LOG_IN();
LOG_OUT();
}
void
tbx_string_manager_exit(void)
{
LOG_IN();
LOG_OUT();
}
char *
tbx_strdup(const char *src)
{
char *dst = NULL;
size_t length = 0;
LOG_IN();
length = strlen(src);
dst = TBX_MALLOC(length + 1);
strcpy(dst, src);
LOG_OUT();
return dst;
}
tbx_bool_t
tbx_streq(const char *s1,
const char *s2)
{
tbx_bool_t result = tbx_false;
LOG_IN();
if (!strcmp(s1, s2))
{
result = tbx_true;
}
LOG_OUT();
return result;
}
p_tbx_string_t
tbx_string_init(void)
{
p_tbx_string_t string = NULL;
LOG_IN();
string = TBX_CALLOC(1, sizeof(tbx_string_t));
string->length = 0;
string->allocated_length = 0;
string->data = NULL;
LOG_OUT();
return string;
}
void
tbx_string_free(p_tbx_string_t string)
{
LOG_IN();
tbx_string_reset(string);
TBX_FREE(string);
LOG_OUT();
}
size_t
tbx_string_length(p_tbx_string_t string)
{
size_t length = 0;
LOG_IN();
length = string->length;
LOG_OUT();
return length;
}
void
tbx_string_reset(p_tbx_string_t string)
{
LOG_IN();
if (string->allocated_length)
{
TBX_FREE(string->data);
}
string->length = 0;
string->allocated_length = 0;
string->data = NULL;
LOG_OUT();
}
char *
tbx_string_to_cstring(p_tbx_string_t string)
{
char *cstring = NULL;
size_t length = 0;
LOG_IN();
length = string->length;
cstring = TBX_MALLOC(length + 1);
if (length)
{
memcpy(cstring, string->data, length);
}
cstring[length] = '\0';
LOG_OUT();
return cstring;
}
char *
tbx_string_to_cstring_and_free(p_tbx_string_t string)
{
char *cstring = NULL;
LOG_IN();
cstring = tbx_string_to_cstring(string);
tbx_string_free(string);
LOG_OUT();
return cstring;
}
void
tbx_string_set_to_cstring(p_tbx_string_t string,
const char *cstring)
{
size_t length = 0;
LOG_IN();
tbx_string_reset(string);
if ((length = strlen(cstring)))
{
string->data = TBX_MALLOC(length);
memcpy(string->data, cstring, length);
string->length = length;
string->allocated_length = length;
}
LOG_OUT();
}
void
tbx_string_set_to_cstring_and_free(p_tbx_string_t string,
char *cstring)
{
LOG_IN();
tbx_string_set_to_cstring(string, cstring);
TBX_FREE(cstring);
LOG_OUT();
}
void
tbx_string_set_to_char(p_tbx_string_t string,
int data)
{
LOG_IN();
tbx_string_reset(string);
string->data = TBX_MALLOC(1);
string->data[0] = data;
string->length = 1;
string->allocated_length = 1;
LOG_OUT();
}
p_tbx_string_t
tbx_string_init_to_cstring(const char *cstring)
{
p_tbx_string_t string = NULL;
LOG_IN();
string = tbx_string_init();
tbx_string_set_to_cstring(string, cstring);
LOG_OUT();
return string;
}
p_tbx_string_t
tbx_string_init_to_cstring_and_free(char *cstring)
{
p_tbx_string_t string = NULL;
LOG_IN();
string = tbx_string_init();
tbx_string_set_to_cstring_and_free(string, cstring);
LOG_OUT();
return string;
}
p_tbx_string_t
tbx_string_init_to_char(const int data)
{
p_tbx_string_t string = NULL;
LOG_IN();
string = tbx_string_init();
tbx_string_set_to_char(string, data);
LOG_OUT();
return string;
}
void
tbx_string_append_cstring(p_tbx_string_t string,
const char *cstring)
{
LOG_IN();
if (string->allocated_length)
{
size_t length = 0;
if ((length = strlen(cstring)))
{
if (string->length + length > string->allocated_length)
{
string->allocated_length =
tbx_max(2 * (string->allocated_length + 1),
string->allocated_length + length);
string->data =
TBX_REALLOC(string->data, string->allocated_length);
}
memcpy(string->data + string->length, cstring, length);
string->length += length;
}
}
else
{
tbx_string_set_to_cstring(string, cstring);
}
LOG_OUT();
}
void
tbx_string_append_cstring_and_free(p_tbx_string_t string,
char *cstring)
{
LOG_IN();
tbx_string_append_cstring(string, cstring);
TBX_FREE(cstring);
LOG_OUT();
}
void
tbx_string_append_char(p_tbx_string_t string,
int data)
{
LOG_IN();
if (string->allocated_length)
{
string->length++;
if (string->length > string->allocated_length)
{
string->allocated_length = 2 * (string->allocated_length + 1);
string->data = TBX_REALLOC(string->data, string->allocated_length);
}
string->data[string->length - 1] = (char)data;
}
else
{
tbx_string_set_to_char(string, data);
}
LOG_OUT();
}
void
tbx_string_append_int(p_tbx_string_t string,
int data)
{
char temp[MAX_NUMBER_LENGTH + 1];
size_t offset = 0;
tbx_bool_t neg = (data < 0);
LOG_IN();
if (neg)
{
data = -data;
}
do
{
temp[offset++] = '0' + data % 10;
data /= 10;
}
while (data);
if (neg)
{
temp[offset++] = '-';
}
do
{
tbx_string_append_char(string, temp[--offset]);
}
while (offset);
LOG_OUT();
}
void
tbx_string_set_to_int(p_tbx_string_t string,
int data)
{
LOG_IN();
tbx_string_reset(string);
tbx_string_append_int(string, data);
LOG_OUT();
}
p_tbx_string_t
tbx_string_init_to_int(int data)
{
p_tbx_string_t string = NULL;
LOG_IN();
string = tbx_string_init();
tbx_string_set_to_int(string, data);
LOG_OUT();
return string;
}
void
tbx_string_append_uint(p_tbx_string_t string,
unsigned int data)
{
char temp[MAX_NUMBER_LENGTH + 1];
size_t offset = 0;
LOG_IN();
do
{
temp[offset++] = '0' + data % 10;
data /= 10;
}
while (data);
do
{
tbx_string_append_char(string, temp[--offset]);
}
while (offset);
LOG_OUT();
}
void
tbx_string_set_to_uint(p_tbx_string_t string,
unsigned int data)
{
LOG_IN();
tbx_string_reset(string);
tbx_string_append_uint(string, data);
LOG_OUT();
}
p_tbx_string_t
tbx_string_init_to_uint(unsigned int data)
{
p_tbx_string_t string = NULL;
LOG_IN();
string = tbx_string_init();
tbx_string_set_to_uint(string, data);
LOG_OUT();
return string;
}
void
tbx_string_reverse(p_tbx_string_t string)
{
size_t offset_left = 0;
size_t offset_right = string->length - 1;
LOG_IN();
while (offset_left < offset_right)
{
string->data[offset_left] ^= string->data[offset_right];
string->data[offset_right] ^= string->data[offset_left];
string->data[offset_left] ^= string->data[offset_right];
offset_left ++;
offset_right --;
}
LOG_OUT();
}
void
tbx_string_set_to_string(p_tbx_string_t dst_string,
p_tbx_string_t src_string)
{
LOG_IN();
tbx_string_reset(dst_string);
if (src_string->length)
{
dst_string->data = TBX_MALLOC(src_string->length);
memcpy(dst_string->data, src_string->data, src_string->length);
dst_string->length = src_string->length;
dst_string->allocated_length = src_string->length;
}
LOG_OUT();
}
void
tbx_string_set_to_string_and_free(p_tbx_string_t dst_string,
p_tbx_string_t src_string)
{
LOG_IN();
tbx_string_set_to_string(dst_string, src_string);
tbx_string_free(src_string);
LOG_OUT();
}
void
tbx_string_append_string(p_tbx_string_t dst_string,
p_tbx_string_t src_string)
{
LOG_IN();
if (src_string->length)
{
if (dst_string->allocated_length)
{
if (dst_string->length + src_string->length >
dst_string->allocated_length)
{
dst_string->allocated_length =
tbx_max(2 * (dst_string->allocated_length + 1),
dst_string->allocated_length + src_string->length);
dst_string->data =
TBX_REALLOC(dst_string->data, dst_string->allocated_length);
}
memcpy(dst_string->data + dst_string->length,
src_string->data, src_string->length);
dst_string->length += src_string->length;
}
else
{
tbx_string_set_to_string(dst_string, src_string);
}
}
LOG_OUT();
}
void
tbx_string_append_string_and_free(p_tbx_string_t dst_string,
p_tbx_string_t src_string)
{
LOG_IN();
tbx_string_append_string(dst_string, src_string);
tbx_string_free(src_string);
LOG_OUT();
}
p_tbx_string_t
tbx_string_init_to_string(p_tbx_string_t src_string)
{
p_tbx_string_t dst_string = NULL;
LOG_IN();
dst_string = tbx_string_init();
tbx_string_set_to_string(dst_string, src_string);
LOG_OUT();
return dst_string;
}
p_tbx_string_t
tbx_string_dup(p_tbx_string_t src_string)
{
p_tbx_string_t dst_string = NULL;
LOG_IN();
dst_string = tbx_string_init_to_string(src_string);
LOG_OUT();
return dst_string;
}
p_tbx_string_t
tbx_string_init_to_string_and_free(p_tbx_string_t src_string)
{
p_tbx_string_t dst_string = NULL;
LOG_IN();
dst_string = tbx_string_init_to_string(src_string);
tbx_string_free(src_string);
LOG_OUT();
return dst_string;
}
p_tbx_string_t
tbx_string_double_quote(p_tbx_string_t src_string)
{
char *src_data = src_string->data;
size_t src_length = src_string->length;
p_tbx_string_t dst_string = NULL;
size_t offset = 0;
LOG_IN();
// Leading double quote
dst_string = tbx_string_init_to_char('"');
while (offset < src_length)
{
switch (src_data[offset])
{
case '\\':
case '"':
{
tbx_string_append_char(dst_string, '\\');
}
break;
default:
{
tbx_string_append_char(dst_string, src_data[offset++]);
}
break;
}
}
// Trailing double quote
tbx_string_append_char(dst_string, '"');
LOG_OUT();
return dst_string;
}
p_tbx_string_t
tbx_string_double_quote_and_free(p_tbx_string_t src_string)
{
p_tbx_string_t dst_string = NULL;
LOG_IN();
dst_string = tbx_string_double_quote(src_string);
tbx_string_free(src_string);
LOG_OUT();
return dst_string;
}
p_tbx_string_t
tbx_string_single_quote(p_tbx_string_t src_string)
{
p_tbx_string_t dst_string = NULL;
LOG_IN();
dst_string = tbx_string_init_to_char('\'');
tbx_string_append_string(dst_string, src_string);
tbx_string_append_char(dst_string, '\'');
LOG_OUT();
return dst_string;
}
p_tbx_string_t
tbx_string_single_quote_free(p_tbx_string_t src_string)
{
p_tbx_string_t dst_string = NULL;
LOG_IN();
dst_string = tbx_string_single_quote(src_string);
tbx_string_free(src_string);
LOG_OUT();
return dst_string;
}
p_tbx_slist_t
tbx_string_split(p_tbx_string_t src_string,
const char *IFS)
{
p_tbx_slist_t slist = NULL;
slist = tbx_slist_nil();
LOG_IN();
if (src_string->length)
{
p_tbx_string_t dst_string = NULL;
char *data = src_string->data;
size_t length = src_string->length;
size_t offset = 0;
tbx_bool_t single_mode = tbx_false;
tbx_bool_t double_mode = tbx_false;
tbx_bool_t copy_mode = tbx_false;
tbx_bool_t quoting_mode = tbx_false;
IFS = (IFS)?:" \t\n";
do
{
if (copy_mode)
{
if (!single_mode && !double_mode && !quoting_mode)
{
const char *ptr = IFS;
while (*ptr)
{
if (*ptr == data[offset])
{
offset++;
copy_mode = tbx_false;
tbx_slist_append(slist, dst_string);
dst_string = NULL;
goto next_1;
}
ptr++;
}
}
switch (data[offset])
{
case '\\':
{
if (!single_mode)
{
quoting_mode = !quoting_mode;
}
}
break;
case '\'':
{
if (!quoting_mode && !double_mode)
{
single_mode = !single_mode;
}
}
break;
case '"':
{
if (!quoting_mode && !single_mode)
{
double_mode = !double_mode;
}
}
break;
default:
{
/* Nothing */
}
break;
}
tbx_string_append_char(dst_string, data[offset++]);
}
else
{
const char *ptr = IFS;
while (*ptr)
{
if (*ptr == data[offset])
{
offset++;
goto next_1;
}
ptr++;
}
dst_string = tbx_string_init();
copy_mode = tbx_true;
}
next_1:
;
}
while (offset < length);
if (dst_string)
{
tbx_slist_append(slist, dst_string);
dst_string = NULL;
}
}
LOG_OUT();
return slist;
}
p_tbx_slist_t
tbx_string_split_and_free(p_tbx_string_t src_string,
const char *IFS)
{
p_tbx_slist_t slist = NULL;
LOG_IN();
slist = tbx_string_split(src_string, IFS);
tbx_string_free(src_string);
LOG_OUT();
return slist;
}
p_tbx_string_t
tbx_string_extract_name_from_pathname(p_tbx_string_t path_name)
{
p_tbx_string_t name = NULL;
size_t idx = 0;
LOG_IN();
name = tbx_string_init();
idx = path_name->length;
if (idx)
{
while ((idx > 0) && (path_name->data[idx - 1] != '\\'))
{
idx--;
}
name->length = path_name->length - idx;
if (name->length)
{
name->allocated_length = name->length;
name->data = TBX_MALLOC(name->allocated_length);
memcpy(name->data, path_name->data + idx, name->length);
path_name->length = (idx > 0)?idx - 1:idx;
if (!path_name->length)
{
TBX_FREE(path_name->data);
path_name->data = NULL;
path_name->allocated_length = 0;
}
}
}
LOG_OUT();
return name;
}
long
tbx_cstr_to_long(const char *s) {
long val = 0;
char *p = NULL;
LOG_IN();
val = strtol(s, &p, 0);
if (p == s)
TBX_FAILUREF("failed to convert string '%s' to <long>", s);
if (val == LONG_MIN && errno == ERANGE)
TBX_FAILUREF("underflow error while converting string '%s' to <long>", s);
if (val == LONG_MAX && errno == ERANGE)
TBX_FAILUREF("overflow error while converting string '%s' to <long>", s);
LOG_OUT();
return val;
}
unsigned long
tbx_cstr_to_unsigned_long(const char *s) {
unsigned long val = 0;
char *p = NULL;
LOG_IN();
val = strtoul(s, &p, 0);
if (p == s)
TBX_FAILUREF("failed to convert string '%s' to <long>", s);
if (val == LONG_MAX && errno == ERANGE)
TBX_FAILUREF("overflow error while converting string '%s' to <long>", s);
LOG_OUT();
return val;
}