a firstworks project
Rudiments
About Documentation Download Licensing News

Using the charstring class


Introduction

The charstring class provides static methods for manipulating C-style character strings.

In addition to some unique methods, analogs for the standard C string functions are provided. However, unlike the standard C string functions, the charstring methods are NULL safe. Your application will not crash if a NULL is passed in, and instead, will give intuitive results.

Manipulating Character Strings

The charstring class provides methods for zeroing, duplicating, appending, copying data to, printing formatted data to, and determining the lengths of character strings.

#include <rudiments/charstring.h>
#include <rudiments/stdio.h>

int main(int argc, const char **argv) {

	char		buffer[32];


	// zero the buffer
	charstring::zero(buffer,sizeof(buffer));


	// append strings, integers and floats
	charstring::append(buffer,"Hello ");
	charstring::append(buffer,"there!",6);
	charstring::append(buffer," ");
	charstring::append(buffer,(uint64_t)1);
	charstring::append(buffer,(uint64_t)2);
	charstring::append(buffer,(uint64_t)3);
	charstring::append(buffer," ");
	charstring::append(buffer,1.234,4,3);
	stdoutput.printf("buffer: %s\n",buffer);
	stdoutput.write('\n');


	// get length
	stdoutput.printf("length(buffer)=%d\n",charstring::getLength(buffer));
	stdoutput.write('\n');


	// zero the buffer again
	charstring::zero(buffer,sizeof(buffer));


	// copy to the beginning of the buffer
	charstring::copy(buffer,"Hello!");
	stdoutput.printf("buffer: %s\n",buffer);


	// copy the specified number of bytes to the beginning of the buffer
	charstring::copy(buffer,"Hello again!",6);
	stdoutput.printf("buffer: %s\n",buffer);


	// copy to the specified offset
	charstring::copy(buffer,6,"again!");
	stdoutput.printf("buffer: %s\n",buffer);


	// copy the specified number of bytes to the specified offset
	charstring::copy(buffer,12," Hi!  blah blah blah",4);
	stdoutput.printf("buffer: %s\n",buffer);
	stdoutput.write('\n');


	// get length
	stdoutput.printf("length(buffer)=%d\n",charstring::getLength(buffer));
	stdoutput.write('\n');


	// zero the buffer again
	charstring::zero(buffer,sizeof(buffer));


	// safely copy a long string to a smaller buffer
	charstring::safeCopy(buffer,sizeof(buffer),
				"This string is longer than the buffer");
	stdoutput.printf("buffer: %.*s\n",sizeof(buffer),buffer);


	// safely copy the specified number of bytes of a
	// long string to a smaller buffer
	charstring::safeCopy(buffer,sizeof(buffer),
				"This string is longer than the buffer",36);
	stdoutput.printf("buffer: %.*s\n",sizeof(buffer),buffer);
	stdoutput.write('\n');


	// get length
	stdoutput.printf("length(buffer)=%d\n",charstring::getLength(buffer));
	stdoutput.write('\n');


	// zero the buffer again
	charstring::zero(buffer,sizeof(buffer));


	// print formatted data to the buffer
	charstring::printf(buffer,sizeof(buffer),"%s, %05d, %7.4f",
						"hello",100,123.4567);
	stdoutput.printf("buffer: %s\n",buffer);
	stdoutput.write('\n');


	// get length
	stdoutput.printf("length(buffer)=%d\n",charstring::getLength(buffer));
	stdoutput.write('\n');


	// duplicate a string
	char	*completedup=charstring::duplicate("Hello there!");
	char	*partialdup=charstring::duplicate("Hello there!",5);
	stdoutput.printf("complete duplicate of \"Hello there!\": \"%s\"\n",
								completedup);
	stdoutput.printf(" partial duplicate of \"Hello there!\": \"%s\"\n",
								partialdup);
	delete[] completedup;
	delete[] partialdup;
}

Comparing Character Strings

The charstring class also provides methods for performing various character string comparisons.

#include <rudiments/charstring.h>
#include <rudiments/stdio.h>

int main(int argc, const char **argv) {

	// comparing string...
	const char * const strings[]={
		"hello","HELLO","hello there","HELLO THERE",NULL
	};

	stdoutput.write("direct comparison...\n");
	for (const char * const *s=strings; *s; s++) {
		stdoutput.printf("  does \"hello\"=\"%s\"  %s?\n",*s,
			(!charstring::compare("hello",*s))?"yes":"no");
		
	}
	stdoutput.write('\n');

	stdoutput.write("only first 5 bytes...\n");
	for (const char * const *s=strings; *s; s++) {
		stdoutput.printf("  does \"hello\"=\"%s\"?  %s\n",*s,
			(!charstring::compare("hello",*s,5))?"yes":"no");
	}
	stdoutput.write('\n');

	stdoutput.write("ignoring case...\n");
	for (const char * const *s=strings; *s; s++) {
		stdoutput.printf("  does \"hello\"=\"%s\"?  %s\n",*s,
			(!charstring::compareIgnoringCase("hello",*s,5))?
								"yes":"no");
	}
	stdoutput.write('\n');

	stdoutput.write("ignoring case, only first 5 bytes...\n");
	for (const char * const *s=strings; *s; s++) {
		stdoutput.printf("  does \"hello\"=\"%s\"?  %s\n",*s,
			(!charstring::compareIgnoringCase("hello",*s,5))?
								"yes":"no");
	}
	stdoutput.write('\n');



	// member of a set...
	const char * const greetings[]={
		"hello","hi","good morning",NULL
	};
	const char * const lowercaseexpressions[]={
		"hello","hi","bye","goodbye",NULL
	};
	const char * const uppercaseexpressions[]={
		"HELLO","HI","BYE","GOODBYE",NULL
	};

	stdoutput.write("considering case...\n");
	for (const char * const *le=lowercaseexpressions; *le; le++) {
		stdoutput.printf("  is \"%s\" a greeting?  %s\n",*le,
			(charstring::isInSet(*le,greetings))?"yes":"no");
	}
	stdoutput.write('\n');

	stdoutput.write("ignoring case...\n");
	for (const char * const *ue=uppercaseexpressions; *ue; ue++) {
		stdoutput.printf("  is \"%s\" a greeting?  %s\n",*ue,
			(charstring::isInSetIgnoringCase(*ue,greetings))?
								"yes":"no");
	}
	stdoutput.write('\n');


	// does one string contain another?
	const char	phrase[]="the quick brown fox jumped over the lazy dog";
	const char * const lowercasewords[]={
		"quick","brown","fox","lazy","dog","hello","goodbye",NULL
	};
	const char * const uppercasewords[]={
		"QUICK","BROWN","FOX","LAZY","DOG","HELLO","GOODBYE",NULL
	};
	
	stdoutput.write("considering case...\n");
	for (const char * const *lw=lowercasewords; *lw; lw++) {
		stdoutput.printf("  does \"%s\" contain \"%s\"?  %s\n",
			phrase,*lw,
			(charstring::contains(phrase,*lw))?"yes":"no");
	}
	stdoutput.write('\n');
	
	stdoutput.write("ignoring case...\n");
	for (const char * const *uw=uppercasewords; *uw; uw++) {
		stdoutput.printf("  does \"%s\" contain \"%s\"?  %s\n",
			phrase,*uw,
			(charstring::contains(phrase,*uw))?"yes":"no");
	}
	stdoutput.write('\n');
}

Finding Data in Character Strings

The charstring class also provides methods for finding characters or other character strings within character strings.

The findFirst()/findFirstOfSet() and findLast() methods return the first/last instance of a character/string/set within a string, or NULL if no match is found.

#include <rudiments/charstring.h>
#include <rudiments/stdio.h>

int main(int argc, const char **argv) {

	// first/last instances of a character or string...
	const char	phrase[]="1 and 2 and 3 and 4";
	const char	numbers[]="1234";

	const char	*firsta=charstring::findFirst(phrase,'a');
	const char	*firstand=charstring::findFirst(phrase,"and");

	const char	*lasta=charstring::findLast(phrase,'a');
	const char	*lastand=charstring::findLast(phrase,"and");

	const char	*firstnum=charstring::findFirstOfSet(phrase,numbers);

	stdoutput.printf("in the phrase: \"%s\"...\n",phrase);
	stdoutput.printf("  the first 'a' is	: \"%s\"\n",firsta);
	stdoutput.printf("  the first \"and\" is	: \"%s\"\n",firstand);
	stdoutput.printf("  the last 'a' is	: \"%s\"\n",lasta);
	stdoutput.printf("  the last \"and\" is	: \"%s\"\n",lastand);
	stdoutput.printf("  the first number is	: \"%s\"\n",firstnum);
	stdoutput.write('\n');
}

Transforming Character Strings

The charstring class also provides methods for transforming character strings.

#include <rudiments/charstring.h>
#include <rudiments/stdio.h>

int main(int argc, const char **argv) {

	char	hellothere[]="   hello there!   ";

	// upper-case...
	charstring::upper(hellothere);
	stdoutput.printf("upper cased:   \"%s\"\n",hellothere);

	// lower-case...
	charstring::lower(hellothere);
	stdoutput.printf("lower cased:   \"%s\"\n",hellothere);

	// capitalized...
	charstring::capitalize(hellothere);
	stdoutput.printf("capitalized:   \"%s\"\n",hellothere);

	// right trimmed...
	charstring::rightTrim(hellothere);
	stdoutput.printf("right trimmed: \"%s\"\n",hellothere);

	// left trimmed...
	charstring::leftTrim(hellothere);
	stdoutput.printf("left trimmed:  \"%s\"\n",hellothere);
	stdoutput.write('\n');



	char	paragraph[]="Hello there.\n This is a paragraph\n "
				"with random\n carriage returns\n "
				"scattered throughout.";

	// original...
	stdoutput.printf("original text:\n%s\n\n",paragraph);

	// stripped of carraige returns...
	charstring::strip(paragraph,'\n');
	stdoutput.printf("text without carriage returns:\n%s\n\n",paragraph);

	// stripped of "Hello there."...
	charstring::strip(paragraph,"Hello there. ");
	stdoutput.printf("text without \"Hello There. \":\n%s\n\n",paragraph);

	// with replacements...
	charstring::replace(paragraph,' ','_');
	stdoutput.printf("text with spaces replaced by underscores:\n%s\n\n",
								paragraph);



	char	paddedtext[]="   hello   ";

	// original...
	stdoutput.printf("original text:   \"%s\"\n",paddedtext);

	// left-justified...
	charstring::leftJustify(paddedtext,charstring::getLength(paddedtext));
	stdoutput.printf("left-justified:  \"%s\"\n",paddedtext);

	// right-justified...
	charstring::rightJustify(paddedtext,charstring::getLength(paddedtext));
	stdoutput.printf("right-justified: \"%s\"\n",paddedtext);

	// centered...
	charstring::center(paddedtext,charstring::getLength(paddedtext));
	stdoutput.printf("centered:        \"%s\"\n",paddedtext);
	stdoutput.write('\n');



	const char	unpaddedtext[]="hellothere";

	// original...
	stdoutput.printf("original text:      \"%s\"\n",unpaddedtext);

	// left-padded
	char	*leftpadded=charstring::pad(unpaddedtext,' ',-1,15);
	stdoutput.printf("left padded text:   \"%s\"\n",leftpadded);
	delete[] leftpadded;

	// right-padded
	char	*rightpadded=charstring::pad(unpaddedtext,' ',1,15);
	stdoutput.printf("right padded text:  \"%s\"\n",rightpadded);
	delete[] rightpadded;

	// center-padded
	char	*centerpadded=charstring::pad(unpaddedtext,' ',0,15);
	stdoutput.printf("center padded text: \"%s\"\n",centerpadded);
	delete[] centerpadded;
}

Parsing Character Strings

The charstring class also provides methods for splitting character strings, finding substrings and inserting text into a character string.

#include <rudiments/charstring.h>
#include <rudiments/stdio.h>

int main(int argc, const char **argv) {

	const char	str[]="All along the untrodden paths of the future...";

	// split...
	char		**parts;
	uint64_t	partcount;
	charstring::split(str," ",true,&parts,&partcount);

	stdoutput.printf("original string:\n  %s\n",str);
	stdoutput.printf("split on space:\n");
	for (uint64_t i=0; i<partcount; i++) {
		stdoutput.printf("  %s\n",parts[i]);
	}
	stdoutput.write('\n');

	for (uint64_t i=0; i<partcount; i++) {
		delete[] parts[i];
	}
	delete[] parts;



	// substring...
	char	*substring1=charstring::getSubString(str,14);
	char	*substring2=charstring::getSubString(str,14,28);

	stdoutput.printf("string starting at index 14: %s\n",substring1);
	stdoutput.printf("string from index 14 to 21 : %s\n",substring2);
	stdoutput.write('\n');

	delete[] substring1;
	delete[] substring2;



	// insert string...
	char	*newstr=charstring::insertString(str,
			", I can see the footprints of an unseen hand",43);

	stdoutput.printf("string after insert:\n  %s\n",newstr);
	stdoutput.write('\n');

	delete[] newstr;
}

Converting Numbers and Amounts

The charstring class also provides methods for converting numbers and dollar amounts to and from character strings.

#include <rudiments/charstring.h>
#include <rudiments/stdio.h>

int main(int argc, const char **argv) {

	// conversion of numbers to strings...
	char	*intstr=charstring::parseNumber((uint64_t)12345);
	char	*floatstr=charstring::parseNumber((float)12.345,5,3);

	stdoutput.printf("numbers as strings: %s, %s\n",intstr,floatstr);
	stdoutput.write('\n');

	delete[] intstr;
	delete[] floatstr;



	// conversion of strings to numbers...
	int64_t		intnum=charstring::convertToInteger("12345");
	uint64_t	uintnum=charstring::convertToUnsignedInteger("12345");
	long double	floatnum=charstring::convertToFloat("12.345");

	stdoutput.printf("strings as numbers: %lld, %lld, %5.3Lf\n",
						intnum,uintnum,floatnum);
	stdoutput.write('\n');



	// identification of numeric strings...
	const char * const numbers[]={
		"1","-1","1.1","-1.1","one","hello",NULL
	};
	
	for (const char * const *n=numbers; *n; n++) {
		stdoutput.printf("%s %s a number\n",*n,
				(charstring::isNumber(*n))?"is":"is not");
		stdoutput.printf("%s %s an integer\n",*n,
				(charstring::isInteger(*n))?"is":"is not");
	}
	stdoutput.write('\n');



	// integer lengths
	uint64_t	integers[]={
		1,23,456,7890,12345,678901,0
	};

	for (uint64_t *i=integers; *i; i++) {
		stdoutput.printf("it would take %d bytes to store "
					"%lld as a string\n",
					charstring::getIntegerLength(*i),*i);
	}
	stdoutput.write('\n');



	// dollar amounts
	const char	dollarstr[]="$123.45";
	int64_t	pennies=charstring::convertAmount(dollarstr);
	char	*dollars=charstring::convertAmount(pennies);
	stdoutput.printf("%s as pennies: %lld\n",dollarstr,pennies);
	stdoutput.printf("%lld pennies as dollars: %s\n",pennies,dollars);
}

Encoding Character Strings

The charstring class also provides methods for escaping, encoding and obfuscating character strings.

#include <rudiments/charstring.h>
#include <rudiments/stdio.h>

int main(int argc, const char **argv) {


	// backslash-escaping of quote, backslash and space characters...
	const char	path[]="\"C:\\Program Files\\Firstworks\"";

	stdoutput.printf("original path:\n  %s\n",path);

	char	*escapedpath=charstring::escape(path,"\"\\ ");
	stdoutput.printf("escaped path:\n  %s\n",escapedpath);

	char	*unescapedpath=charstring::unescape(escapedpath);
	stdoutput.printf("unescaped path:\n  %s\n",unescapedpath);
	stdoutput.write('\n');

	delete[] escapedpath;
	delete[] unescapedpath;



	// url encoding...
	const char	urlstr[]="string with spaces and symbols: \\{}\"\'";

	stdoutput.printf("original string:\n  %s\n",urlstr);

	char	*encodedstr=charstring::urlEncode(urlstr);
	stdoutput.printf("url encoded string:\n  %s\n",encodedstr);

	char	*unencodedstr=charstring::urlDecode(encodedstr);
	stdoutput.printf("url unencoded string:\n  %s\n",unencodedstr);
	stdoutput.write('\n');

	delete[] encodedstr;
	delete[] unencodedstr;



	// base-64 encoding...
	const byte_t	text[]="All along the untrodden "
					"paths of the future...";

	stdoutput.printf("original text:\n  %s\n",text);

	char	*encodedtext=charstring::base64Encode(text);
	stdoutput.printf("encoded text:\n  %s\n",encodedtext);

	byte_t	*decodedtext=charstring::base64Decode(encodedtext);
	stdoutput.printf("decoded text:\n  %s\n",decodedtext);
	stdoutput.write('\n');

	delete[] encodedtext;
	delete[] decodedtext;



	// obfuscation...
	char	data[]="sensitive data";

	stdoutput.printf("original data:\n  %s\n",data);

	charstring::obfuscate(data);
	stdoutput.write("obfuscated data:\n  ");
	stdoutput.safePrint(data);
	stdoutput.write("\n");

	charstring::deobfuscate(data);
	stdoutput.printf("deobfuscated data:\n  %s\n",data);
}
Copyright 2017 - David Muse - Contact