📄 util.c
字号:
/*
* CUnit - A Unit testing framework library for C.
* Copyright (C) 2001 Anil Kumar
* Copyright (C) 2004,2005,2006 Anil Kumar, Jerry St.Clair
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Generic (internal) utility functions used across CUnit.
* These were originally distributed across the other CUnit
* source files, but were consolidated here for consistency.
*
* 13/Oct/2001 Initial implementation (AK)
*
* 26/Jul/2003 Added a function to convert a string containing special
* characters into escaped character for XML/HTML usage. (AK)
*
* 16-Jul-2004 New interface, doxygen comments. (JDS)
*/
/** @file
* Utility functions (implementation).
*/
/** @addtogroup Framework
@{
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <string.h>
#include "CUnit.h"
#include "TestDB.h"
#include "Util.h"
/** Structure containing mappings of special characters to
* xml entity codes.
*/
static const struct {
char special_char;
char* replacement;
} bindings [] = {
{'&', "&"},
{'>', ">"},
{'<', "<"}
};
/*------------------------------------------------------------------------*/
/** Checks whether a character is a special xml character.
* This function performs a lookup of the specified character in
* the bindings structure. If it is a special character, its
* index into the bindings array is returned. If not, -1 is returned.
* @param ch The character to check
* @return Index into bindings if a special character, -1 otherwise.
*/
static int get_index(char ch)
{
int length = sizeof(bindings)/sizeof(bindings[0]);
int counter;
for (counter = 0; counter < length && bindings[counter].special_char != ch; ++counter) {
;
}
return (counter < length ? counter : -1);
}
/*------------------------------------------------------------------------*/
/** Convert special characters in the specified string to
* xml entity codes. The character-entity mappings are
* contained in the struct bindings. Note that conversion
* to entities increases the length of the converted string.
* The worst case conversion would be a string consisting
* entirely of entity characters of length CUNIT_MAX_ENTITY_LEN.
* If szDest does not have enough room to convert an entity,
* it will not be converted. It is the caller's responsibility
* to make sure there is sufficient room in szDest to hold the
* converted string.
* @param szSrc Source string to convert (non-NULL).
* @param szDest Location to hold the converted string (non-NULL).
* @param maxlen Maximum number of characters szDest can hold.
* @return The number of special characters converted.
* @todo Consider a function calculating and returning the
* converted length of a given string.
*/
int CU_translate_special_characters(const char* szSrc, char* szDest, size_t maxlen)
{
int count = 0;
size_t src = 0;
size_t dest = 0;
size_t length = strlen(szSrc);
int conv_index;
assert(NULL != szSrc);
assert(NULL != szDest);
memset(szDest, 0, maxlen);
while ((dest < maxlen) && (src < length)) {
if ((-1 != (conv_index = get_index(szSrc[src]))) &&
((dest + (int)strlen(bindings[conv_index].replacement)) <= maxlen)) {
strcat(szDest, bindings[conv_index].replacement);
dest += (int)strlen(bindings[conv_index].replacement);
++count;
} else {
szDest[dest++] = szSrc[src];
}
++src;
}
return count;
}
/*------------------------------------------------------------------------*/
/** Case-insensitive string comparison. Neither string pointer
* can be NULL (checked by asssertion).
* @param szSrc 1st string to compare (non-NULL).
* @param szDest 2nd string to compare (non-NULL).
* @return 0 if the strings are equal, non-zero otherwise.
*/
int CU_compare_strings(const char* szSrc, const char* szDest)
{
assert(NULL != szSrc);
assert(NULL != szDest);
while (('\0' != *szSrc) && ('\0' != *szDest) && (toupper(*szSrc) == toupper(*szDest))) {
szSrc++;
szDest++;
}
return (int)(*szSrc - *szDest);
}
/*------------------------------------------------------------------------*/
/** Trim leading and trailing whitespace from the specified string.
* @param szString The string to trim.
*/
void CU_trim(char* szString)
{
CU_trim_left(szString);
CU_trim_right(szString);
}
/*------------------------------------------------------------------------*/
/** Trim leading whitespace from the specified string.
* @param szString The string to trim.
*/
void CU_trim_left(char* szString)
{
int nOffset = 0;
char* szSrc = szString;
char* szDest = szString;
assert(NULL != szString);
/* Scan for the spaces in the starting of string. */
for (; '\0' != *szSrc; szSrc++, nOffset++) {
if (!isspace(*szSrc)) {
break;
}
}
for(; (0 != nOffset) && ('\0' != (*szDest = *szSrc)); szSrc++, szDest++) {
;
}
}
/*------------------------------------------------------------------------*/
/** Trim trailing whitespace from the specified string.
* @param szString The string to trim.
*/
void CU_trim_right(char* szString)
{
size_t nLength;
char* szSrc = szString;
assert(NULL != szString);
nLength = strlen(szString);
/*
* Scan for specs in the end of string.
*/
for (; (0 != nLength) && isspace(*(szSrc + nLength - 1)); nLength--) {
;
}
*(szSrc + nLength) = '\0';
}
/** @} */
#ifdef CUNIT_BUILD_TESTS
#include "test_cunit.h"
#define MAX_LEN 100
static void test_CU_translate_special_characters(void)
{
int nchars;
char dest[MAX_LEN];
/* empty src */
strcpy(dest, "random initialized string");
nchars = CU_translate_special_characters("", dest, MAX_LEN);
TEST(0 == nchars);
TEST(!strcmp(dest, ""));
/* 1 char src */
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("#", dest, 1);
TEST(0 == nchars);
TEST(!strcmp(dest, "#"));
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("&", dest, 1);
TEST(0 == nchars);
TEST(!strcmp(dest, "&"));
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("&", dest, 4);
TEST(0 == nchars);
TEST(!strcmp(dest, "&"));
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("&", dest, 5);
TEST(1 == nchars);
TEST(!strcmp(dest, "&"));
/* maxlen=0 */
strcpy(dest, "random initialized string");
nchars = CU_translate_special_characters("some <<string & another>", dest, 0);
TEST(0 == nchars);
TEST(!strcmp(dest, "random initialized string"));
/* maxlen < len(converted szSrc) */
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("some <<string & another>", dest, 1);
TEST(0 == nchars);
TEST(!strcmp(dest, "s"));
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("some <<string & another>", dest, 6);
TEST(0 == nchars);
TEST(!strcmp(dest, "some <"));
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("some <<string & another>", dest, 9);
TEST(1 == nchars);
TEST(!strcmp(dest, "some <"));
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("some <<string & another>", dest, 10);
TEST(1 == nchars);
TEST(!strcmp(dest, "some <<"));
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("some <<string & another>", dest, 13);
TEST(2 == nchars);
TEST(!strcmp(dest, "some <<"));
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("some <<string & another>", dest, 14);
TEST(2 == nchars);
TEST(!strcmp(dest, "some <<s"));
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("some <<string & another>", dest, 21);
TEST(2 == nchars);
TEST(!strcmp(dest, "some <<string &"));
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("some <<string & another>", dest, 22);
TEST(2 == nchars);
TEST(!strcmp(dest, "some <<string & "));
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("some <<string & another>", dest, 23);
TEST(2 == nchars);
TEST(!strcmp(dest, "some <<string & a"));
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("some <<string & another>", dest, 24);
TEST(2 == nchars);
TEST(!strcmp(dest, "some <<string & an"));
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("some <<string & another>", dest, 25);
TEST(3 == nchars);
TEST(!strcmp(dest, "some <<string &"));
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("some <<string & another>", dest, 26);
TEST(3 == nchars);
TEST(!strcmp(dest, "some <<string & "));
/* maxlen == len(converted szSrc) */
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("some <<string & another>", dest, 37);
TEST(4 == nchars);
TEST(!strcmp(dest, "some <<string & another>"));
/* maxlen > len(converted szSrc) */
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("some <<string & another>", dest, MAX_LEN);
TEST(4 == nchars);
TEST(!strcmp(dest, "some <<string & another>"));
/* no special characters */
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("some string or another", dest, MAX_LEN);
TEST(0 == nchars);
TEST(!strcmp(dest, "some string or another"));
/* only special characters */
memset(dest, 0, MAX_LEN);
nchars = CU_translate_special_characters("<><><<>>&&&", dest, MAX_LEN);
TEST(11 == nchars);
TEST(!strcmp(dest, "<><><<>>&&&"));
}
static void test_CU_compare_strings(void)
{
TEST(0 == CU_compare_strings("",""));
TEST(0 == CU_compare_strings("@","@"));
TEST(0 == CU_compare_strings("D","d"));
TEST(0 == CU_compare_strings("s1","s1"));
TEST(0 == CU_compare_strings("s1","S1"));
TEST(0 != CU_compare_strings("s1","s12"));
TEST(0 == CU_compare_strings("this is string 1","tHIS iS sTRING 1"));
TEST(0 == CU_compare_strings("i have \t a tab!","I have \t a tab!"));
TEST(0 != CU_compare_strings("not the same"," not the same"));
}
static void test_CU_trim(void)
{
char string[MAX_LEN];
strcpy(string, "");
CU_trim(string);
TEST(!strcmp("", string));
strcpy(string, " ");
CU_trim(string);
TEST(!strcmp("", string));
strcpy(string, " ");
CU_trim(string);
TEST(!strcmp("", string));
strcpy(string, " b");
CU_trim(string);
TEST(!strcmp("b", string));
strcpy(string, " B");
CU_trim(string);
TEST(!strcmp("B", string));
strcpy(string, "s ");
CU_trim(string);
TEST(!strcmp("s", string));
strcpy(string, "S ");
CU_trim(string);
TEST(!strcmp("S", string));
strcpy(string, " 5 ");
CU_trim(string);
TEST(!strcmp("5", string));
strcpy(string, "~ & ^ ( ^ ");
CU_trim(string);
TEST(!strcmp("~ & ^ ( ^", string));
strcpy(string, " ~ & ^ ( ^");
CU_trim(string);
TEST(!strcmp("~ & ^ ( ^", string));
strcpy(string, " ~ & ^ ( ^ ");
CU_trim(string);
TEST(!strcmp("~ & ^ ( ^", string));
}
static void test_CU_trim_left(void)
{
char string[MAX_LEN];
strcpy(string, "");
CU_trim_left(string);
TEST(!strcmp("", string));
strcpy(string, " ");
CU_trim_left(string);
TEST(!strcmp("", string));
strcpy(string, " ");
CU_trim_left(string);
TEST(!strcmp("", string));
strcpy(string, " b");
CU_trim_left(string);
TEST(!strcmp("b", string));
strcpy(string, " B");
CU_trim_left(string);
TEST(!strcmp("B", string));
strcpy(string, "s ");
CU_trim_left(string);
TEST(!strcmp("s ", string));
strcpy(string, "S ");
CU_trim_left(string);
TEST(!strcmp("S ", string));
strcpy(string, " 5 ");
CU_trim_left(string);
TEST(!strcmp("5 ", string));
strcpy(string, "~ & ^ ( ^ ");
CU_trim_left(string);
TEST(!strcmp("~ & ^ ( ^ ", string));
strcpy(string, " ~ & ^ ( ^");
CU_trim_left(string);
TEST(!strcmp("~ & ^ ( ^", string));
strcpy(string, " ~ & ^ ( ^ ");
CU_trim_left(string);
TEST(!strcmp("~ & ^ ( ^ ", string));
}
static void test_CU_trim_right(void)
{
char string[MAX_LEN];
strcpy(string, "");
CU_trim_right(string);
TEST(!strcmp("", string));
strcpy(string, " ");
CU_trim_right(string);
TEST(!strcmp("", string));
strcpy(string, " ");
CU_trim_right(string);
TEST(!strcmp("", string));
strcpy(string, " b");
CU_trim_right(string);
TEST(!strcmp(" b", string));
strcpy(string, " B");
CU_trim_right(string);
TEST(!strcmp(" B", string));
strcpy(string, "s ");
CU_trim_right(string);
TEST(!strcmp("s", string));
strcpy(string, "S ");
CU_trim_right(string);
TEST(!strcmp("S", string));
strcpy(string, " 5 ");
CU_trim_right(string);
TEST(!strcmp(" 5", string));
strcpy(string, "~ & ^ ( ^ ");
CU_trim_right(string);
TEST(!strcmp("~ & ^ ( ^", string));
strcpy(string, " ~ & ^ ( ^");
CU_trim_right(string);
TEST(!strcmp(" ~ & ^ ( ^", string));
strcpy(string, " ~ & ^ ( ^ ");
CU_trim_right(string);
TEST(!strcmp(" ~ & ^ ( ^", string));
}
void test_cunit_Util(void)
{
test_cunit_start_tests("Util.c");
test_CU_translate_special_characters();
test_CU_compare_strings();
test_CU_trim();
test_CU_trim_left();
test_CU_trim_right();
test_cunit_end_tests();
}
#endif /* CUNIT_BUILD_TESTS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -