예제 #1
0
/// <summary>
/// Replace all instances of a character in a string with a replacement character.
/// </summary>
/// <param name="str">The string to search through (if NULL, an empty string is returned).</param>
/// <param name="pattern">The pattern to search for.</param>
/// <param name="replacement">A replacement character for each instance of the pattern.</param>
/// <returns>A new string where all instances of the pattern character have been replaced by the given replacement character.</returns>
String String_ReplaceChar(const String str, Byte pattern, Byte replacement)
{
	const struct StringInt *s;
	struct StringInt *newString;
	Byte *text, *newText, *dest;
	const Byte *src;
	Int length;
	Byte ch;
	Int i;

	if (String_IsNullOrEmpty(str)) return String_Empty;

	s = (const struct StringInt *)str;
	text = s->text;
	length = s->length;

	newString = GC_MALLOC_STRUCT(struct StringInt);
	if (newString == NULL) Smile_Abort_OutOfMemory();
	newText = GC_MALLOC_TEXT(length);
	if (newText == NULL) Smile_Abort_OutOfMemory();

	newString->length = length;
	newString->text = newText;

	src = text;
	dest = newText;

	for (i = 0; i < length; i++)
	{
		*dest++ = ((ch = *src++) == pattern ? replacement : ch);
	}
	*dest = '\0';

	return (String)newString;
}
예제 #2
0
/// <summary>
/// Construct a new String instance by concatenating a byte onto the end of a string.
/// </summary>
/// <param name="str">The string to concatenate.</param>
/// <param name="ch">The byte to append to it.</param>
/// <returns>The new String instance.</returns>
String String_ConcatByte(const String str, Byte ch)
{
	struct StringInt *result, *s1;
	Byte *newText;
	Int length;

	s1 = (struct StringInt *)str;

	if (s1 == NULL || s1->length == 0)
		return String_CreateRepeat(ch, 1);

	length = s1->length + 1;

	result = GC_MALLOC_STRUCT(struct StringInt);
	if (result == NULL) Smile_Abort_OutOfMemory();
	newText = GC_MALLOC_TEXT(length);
	if (newText == NULL) Smile_Abort_OutOfMemory();

	result->length = length;
	result->text = newText;

	MemCpy(newText, s1->text, s1->length);
	newText[length-1] = ch;
	newText[length] = '\0';

	return (String)result;
}
예제 #3
0
/// <summary>
/// Construct a new String instance by concatenating exactly two strings together.
/// </summary>
/// <param name="str">The first string to concatenate.</param>
/// <param name="other">The second string to concatenate.</param>
/// <returns>The new String instance.</returns>
String String_Concat(const String str, const String other)
{
	struct StringInt *result, *s1, *s2;
	Byte *newText;
	Int length;

	s1 = (struct StringInt *)str;
	s2 = (struct StringInt *)other;

	if (s1 == NULL || s1->length == 0) return s2 != NULL ? (String)s2 : String_Empty;
	if (s2 == NULL || s2->length == 0) return (String)s1;

	length = s1->length + s2->length;

	result = GC_MALLOC_STRUCT(struct StringInt);
	if (result == NULL) Smile_Abort_OutOfMemory();
	newText = GC_MALLOC_TEXT(length);
	if (newText == NULL) Smile_Abort_OutOfMemory();

	result->length = length;
	result->text = newText;

	MemCpy(newText, s1->text, s1->length);
	MemCpy(newText + s1->length, s2->text, s2->length);
	newText[length] = '\0';

	return (String)result;
}
예제 #4
0
파일: testlib.c 프로젝트: seanofw/smile
/// <summary>
/// Run all the tests in the given test suite, and return a new collection of results for it.
/// </summary>
/// <param name="name">The name of the test suite.</param>
/// <param name="funcs">An array of the functions in the test suite to be run.</param>
/// <param name="numFuncs">The number of functions to run.</param>
/// <returns>A new collection of results that describes the overall state of this test suite.</returns>
TestSuiteResults *RunTestSuiteInternal(const char *name, TestFunc *funcs, int numFuncs)
{
	int numSuccesses, numFailures, succeeded, i;
	TestSuiteResults *results;

	if (!IsTestSuiteRequested(name)) {
		results = GC_MALLOC_STRUCT(TestSuiteResults);
		if (results == NULL) Smile_Abort_OutOfMemory();
		results->numFailures = 0;
		results->numSuccesses = 0;
		return results;
	}

	if (!QuietMode) {
		printf("\x1B[0;1;37m Test suite %s: \x1B[0m\n", name);
		fflush(stdout);
	}

	numSuccesses = 0, numFailures = 0;
	for (i = 0; i < numFuncs; i++, funcs++) {
		succeeded = (*funcs)();
		if (succeeded) numSuccesses++;
		else numFailures++;
	}

	if (!QuietMode)
		printf("\n");

	results = GC_MALLOC_STRUCT(TestSuiteResults);
	if (results == NULL) Smile_Abort_OutOfMemory();
	results->numFailures = numFailures;
	results->numSuccesses = numSuccesses;
	return results;
}
예제 #5
0
/// <summary>
/// Construct a new String instance by concatenating many other strings together, with a glue string between them.
/// </summary>
/// <param name="glue">The glue string to insert between successive string instances.  This will not be
/// added to the start and end of the resulting string:  Only between strings.</param>
/// <param name="strs">The array of string instances to join to create the new string.</param>
/// <param name="numStrs">The number of string instances in the array.</param>
/// <returns>The new String instance.</returns>
String String_Join(const String glue, const String *strs, Int numStrs)
{
	Int length, dest, i;
	struct StringInt *str;
	Byte *newText;
	const Byte *glueText;
	Int glueLength;

	if (numStrs <= 0) return String_Empty;

	length = 0;
	for (i = 0; i < numStrs; i++)
	{
		length += ((const struct StringInt *)(strs[i]))->length;
	}
	length += (numStrs - 1) * ((const struct StringInt *)glue)->length;

	if (length <= 0) return String_Empty;

	str = GC_MALLOC_STRUCT(struct StringInt);
	if (str == NULL) Smile_Abort_OutOfMemory();
	newText = GC_MALLOC_TEXT(length);
	if (newText == NULL) Smile_Abort_OutOfMemory();

	str->length = length;
	str->text = newText;

	glueText = ((const struct StringInt *)glue)->text;
	glueLength = ((const struct StringInt *)glue)->length;

	MemCpy(newText, ((const struct StringInt *)(strs[0]))->text, ((const struct StringInt *)(strs[0]))->length);
	dest = ((const struct StringInt *)(strs[0]))->length;

	for (i = 1; i < numStrs; i++)
	{
		MemCpy(newText + dest, glueText, glueLength);
		dest += glueLength;
		MemCpy(newText + dest, ((const struct StringInt *)(strs[i]))->text, ((const struct StringInt *)(strs[i]))->length);
		dest += ((const struct StringInt *)(strs[i]))->length;
	}

	newText[length] = '\0';

	return (String)str;
}
예제 #6
0
/// <summary>
/// Construct a new String instance of the given length, but whose bytes are as yet uninitialized (garbage).
/// </summary>
/// <param name="length">The length of bytes for the new string (not including the terminating nul character).</param>
/// <returns>The new String instance.</returns>
String String_CreateInternal(Int length)
{
	struct StringInt *str;
	Byte *newText;

	if (length <= 0) return String_Empty;

	str = GC_MALLOC_STRUCT(struct StringInt);
	if (str == NULL) Smile_Abort_OutOfMemory();
	newText = GC_MALLOC_TEXT(length);
	if (newText == NULL) Smile_Abort_OutOfMemory();

	str->length = length;
	str->text = newText;

	newText[length] = '\0';

	return (String)str;
}
예제 #7
0
/// <summary>
/// Construct a new String instance containing the given character repeated for the given count.
/// </summary>
/// <param name="b">The source character to use to construct the new string.</param>
/// <param name="repeatCount">The number of times to repeat that character when constructing the new string.</param>
/// <returns>The new String instance.</returns>
String String_CreateRepeat(Byte b, Int repeatCount)
{
	struct StringInt *str;
	Byte *newText;

	if (repeatCount <= 0) return String_Empty;

	str = GC_MALLOC_STRUCT(struct StringInt);
	if (str == NULL) Smile_Abort_OutOfMemory();
	newText = GC_MALLOC_TEXT(repeatCount);
	if (newText == NULL) Smile_Abort_OutOfMemory();

	str->length = repeatCount;
	str->text = newText;

	MemSet(newText, b, repeatCount);
	newText[repeatCount] = '\0';

	return (String)str;
}
예제 #8
0
/// <summary>
/// Construct a new String instance by concatenating many other strings together.
/// </summary>
/// <param name="strs">The array of string instances to join to create the new string.</param>
/// <param name="numStrs">The number of string instances in the array.</param>
/// <returns>The new String instance.</returns>
String String_ConcatMany(const String *strs, Int numStrs)
{
	Int length, dest, i;
	struct StringInt *str;
	const struct StringInt *temp;
	Byte *newText;

	if (numStrs <= 0) return String_Empty;

	length = 0;
	for (i = 0; i < numStrs; i++)
	{
		length += ((const struct StringInt *)(strs[i]))->length;
	}

	if (length <= 0) return String_Empty;

	str = GC_MALLOC_STRUCT(struct StringInt);
	if (str == NULL) Smile_Abort_OutOfMemory();
	newText = GC_MALLOC_TEXT(length);
	if (newText == NULL) Smile_Abort_OutOfMemory();

	str->length = length;
	str->text = newText;

	dest = 0;
	for (i = 0; i < numStrs; i++)
	{
		temp = ((const struct StringInt *)(strs[i]));
		MemCpy(newText + dest, temp->text, temp->length);
		dest += temp->length;
	}

	newText[length] = '\0';

	return (String)str;
}
예제 #9
0
파일: testlib.c 프로젝트: seanofw/smile
/// <summary>
/// Cause the current test to fail, aborting all successive execution.
/// </summary>
/// <param name="message">The message to display to the user explaining why this test failed.</param>
/// <param name="file">The file in which the failure occurred.</param>
/// <param name="line">The line at which the failure occurred.</param>
/// <returns>Never returns.</returns>
int FailTestWithLineInternal(const char *message, const char *file, int line)
{
	char *safeMessage;

	// Save the message so the test runner can find it (and save it in case it gets stomped on).
	safeMessage = GC_MALLOC_ATOMIC(strlen(message) + 1);
	if (safeMessage == NULL)
		Smile_Abort_OutOfMemory();
	strcpy(safeMessage, message);
	TestFailureMessage = safeMessage;
	TestFailureFile = file;
	TestFailureLine = line;

	// Long-jump back to abort the test.  We pass '1', which is what will be returned by the
	// original setjmp() call.
	longjmp(TestJmpBuf, 1);

	return 0;	// Never reached.
}