static ProgramOption _findProgramOption(ProgramOptions self, const char* name) { ProgramOption potentialMatchOption, optionMatch; CharString optionStringWithoutDashes; unsigned int i; if(_isStringShortOption(name)) { for(i = 0; i < self->numOptions; i++) { potentialMatchOption = self->options[i]; if(potentialMatchOption->hasShortForm && potentialMatchOption->name->data[0] == name[1]) { return potentialMatchOption; } } } if(_isStringLongOption(name)) { optionMatch = NULL; optionStringWithoutDashes = newCharStringWithCapacity(kCharStringLengthShort); strncpy(optionStringWithoutDashes->data, name + 2, strlen(name) - 2); for(i = 0; i < self->numOptions; i++) { potentialMatchOption = self->options[i]; if(charStringIsEqualTo(potentialMatchOption->name, optionStringWithoutDashes, false)) { optionMatch = potentialMatchOption; break; } } freeCharString(optionStringWithoutDashes); return optionMatch; } // If no option was found, then return null return NULL; }
CharString taskTimerHumanReadbleString(TaskTimer self) { int hours, minutes, seconds; CharString outString = newCharStringWithCapacity(kCharStringLengthShort); if (self->totalTaskTime < 1000) { snprintf(outString->data, outString->capacity, "%dms", (int)self->totalTaskTime); } else if (self->totalTaskTime < 60 * 1000) { seconds = (int)(self->totalTaskTime / 1000.0); snprintf(outString->data, outString->capacity, "%dsec", seconds); } else { seconds = (int)(self->totalTaskTime / 1000.0) % 60; minutes = (int)(self->totalTaskTime / (1000.0 * 60.0)); if (minutes > 60) { hours = minutes / 60; minutes = (minutes % 60); snprintf(outString->data, outString->capacity, "%d:%d:%dsec", hours, minutes, seconds); } else { snprintf(outString->data, outString->capacity, "%d:%dsec", minutes, seconds); } } return outString; }
boolByte copyFileToDirectory(const CharString fileAbsolutePath, const CharString directoryAbsolutePath) { boolByte result = false; CharString fileOutPath = newCharStringWithCapacity(kCharStringLengthLong); CharString fileBasename = NULL; FILE *input = NULL; FILE *output = NULL; char ch; fileBasename = newCharStringWithCString(getFileBasename(fileAbsolutePath->data)); buildAbsolutePath(directoryAbsolutePath, fileBasename, NULL, fileOutPath); input = fopen(fileAbsolutePath->data, "rb"); if(input != NULL) { output = fopen(fileOutPath->data, "wb"); if(output != NULL) { while(fread(&ch, 1, 1, input) == 1) { fwrite(&ch, 1, 1, output); } result = true; } } if(input != NULL) { fclose(input); } if(output != NULL) { fclose(output); } freeCharString(fileOutPath); freeCharString(fileBasename); return result; }
static void _logMessage(const LogLevel logLevel, const char *message, va_list arguments) { long elapsedTimeInMs; EventLogger eventLogger = _getEventLoggerInstance(); #if WINDOWS ULONGLONG currentTime; #else struct timeval currentTime; #endif if (eventLogger != NULL && logLevel >= eventLogger->logLevel) { CharString formattedMessage = newCharStringWithCapacity(kCharStringLengthDefault * 2); vsnprintf(formattedMessage->data, formattedMessage->capacity, message, arguments); #if WINDOWS currentTime = GetTickCount(); elapsedTimeInMs = (unsigned long)(currentTime - eventLogger->startTimeInMs); #else gettimeofday(¤tTime, NULL); elapsedTimeInMs = ((currentTime.tv_sec - (eventLogger->startTimeInSec + 1)) * 1000) + (currentTime.tv_usec / 1000) + (1000 - eventLogger->startTimeInMs); #endif _printMessage(logLevel, elapsedTimeInMs, getAudioClock()->currentFrame, formattedMessage->data, eventLogger); freeCharString(formattedMessage); } }
CharString buildTestArgumentString(const char *arguments, ...) { CharString formattedArguments; va_list argumentList; va_start(argumentList, arguments); formattedArguments = newCharStringWithCapacity(kCharStringLengthLong); vsnprintf(formattedArguments->data, formattedArguments->capacity, arguments, argumentList); va_end(argumentList); return formattedArguments; }
unsigned long buildInfoGetYear(void) { unsigned long result = 0; CharString buildDate = newCharStringWithCapacity(kCharStringLengthShort); const char* compilerDate = __DATE__; size_t startingIndex = strlen(compilerDate) - 4; strncpy(buildDate->data, compilerDate + startingIndex, 4); result = strtol(buildDate->data, NULL, 10); freeCharString(buildDate); return result; }
void errorReporterRemapPath(ErrorReporter self, CharString path) { CharString basename = newCharString(); CharString outString = newCharStringWithCapacity(path->capacity); charStringCopyCString(basename, getFileBasename(path->data)); buildAbsolutePath(self->reportDirPath, basename, NULL, outString); charStringCopy(path, outString); freeCharString(basename); freeCharString(outString); }
unsigned long buildInfoGetDatestamp(void) { unsigned long result = buildInfoGetYear() * 10000; CharString buffer = newCharStringWithCapacity(kCharStringLengthShort); strncpy(buffer->data, __DATE__, 3); result += _getMonthNumber(buffer->data) * 100; charStringClear(buffer); strncpy(buffer->data, __DATE__ + 4, 2); result += strtol(buffer->data, NULL, 10); freeCharString(buffer); return result; }
CharString charStringWrap(const CharString srcString, unsigned int indentSize) { CharString destString; if (srcString == NULL) { return NULL; } // Allocate 2x as many characters as needed to avoid buffer overflows. // Since this method is only used in "user-friendly" cases, it's ok to be // a bit wasteful in the name of avoiding memory corruption. Therefore this // function should *not* used for regular logging or text output. destString = newCharStringWithCapacity(srcString->capacity * 2); _charStringWrap(srcString->data, destString->data, destString->capacity, indentSize, TERMINAL_LINE_LENGTH); return destString; }
CharString newCharStringWithCString(const char *string) { size_t length; CharString result = NULL; length = string != NULL ? strlen(string) : 0; if (length > kCharStringLengthLong) { logError("Can't create string with length %d", length); } else if (length == 0) { result = newCharString(); } else { // Add 1 to compensate for trailing null character result = newCharStringWithCapacity(length + 1); strncpy(result->data, string, length); } return result; }
static CharString _getDefaultArguments(const char *testName, const CharString resourcesPath, const CharString outputFilename) { CharString outString = newCharStringWithCapacity(kCharStringLengthLong); CharString logfileName = getTestOutputFilename(testName, kTestOutputText); CharString pluginRootPath = _getTestPluginResourcesPath(resourcesPath); snprintf(outString->data, outString->capacity, "--log-file \"%s\" --verbose --plugin-root \"%s\"", logfileName->data, pluginRootPath->data); if (outputFilename != NULL) { charStringAppendCString(outString, " --output \""); charStringAppend(outString, outputFilename); charStringAppendCString(outString, "\""); } freeCharString(logfileName); freeCharString(pluginRootPath); return outString; }
LinkedList charStringSplit(const CharString self, const char delimiter) { LinkedList result = NULL; char *delimiterPtr = NULL; char *selfIndex = self->data; CharString item = NULL; size_t charsToCopy = 0; boolByte done = false; if (delimiter == '\0') { logError("Cannot split string with NULL delimiter"); return NULL; } result = newLinkedList(); while (!done) { delimiterPtr = strchr(selfIndex, delimiter); if (delimiterPtr == NULL) { done = true; charsToCopy = self->data + strlen(self->data) - selfIndex; } else { charsToCopy = delimiterPtr - selfIndex; } if (charsToCopy > 0) { item = newCharStringWithCapacity(charsToCopy + 1); strncpy(item->data, selfIndex, charsToCopy); linkedListAppend(result, item); } selfIndex = delimiterPtr + 1; } return result; }
int runIntegrationTest(const char *testName, CharString testArguments, ReturnCode expectedResultCode, const TestOutputType testOutputType, const CharString mrsWatsonExePath, const CharString resourcesPath) { int result = 0; int returnCode; ReturnCode resultCode; ChannelCount failedAnalysisChannel; SampleCount failedAnalysisFrame; #if WINDOWS STARTUPINFOA startupInfo; PROCESS_INFORMATION processInfo; #endif // Remove files from a previous test run File outputFolder = newFileWithPathCString(kApplicationRunnerOutputFolder); if (fileExists(outputFolder)) { _removeOutputFiles(testName); } else { fileCreate(outputFolder, kFileTypeDirectory); } freeFile(outputFolder); if (mrsWatsonExePath == NULL) { return -1; } else { File mrsWatsonExe = newFileWithPath(mrsWatsonExePath); boolByte mrsWatsonExeExists = fileExists(mrsWatsonExe); freeFile(mrsWatsonExe); if (!mrsWatsonExeExists) { freeCharString(testArguments); return -1; } } if (resourcesPath == NULL) { freeCharString(testArguments); return -1; } else { File resourcesFile = newFileWithPath(resourcesPath); boolByte resourcesExists = fileExists(resourcesFile); freeFile(resourcesFile); if (!resourcesExists) { freeCharString(testArguments); return -1; } } // Create the command line argument CharString arguments = newCharStringWithCapacity(kCharStringLengthLong); charStringAppendCString(arguments, "\""); charStringAppend(arguments, mrsWatsonExePath); charStringAppendCString(arguments, "\""); charStringAppendCString(arguments, " "); CharString defaultArguments; CharString outputFilename = getTestOutputFilename(testName, testOutputType); defaultArguments = _getDefaultArguments(testName, resourcesPath, outputFilename); charStringAppend(arguments, defaultArguments); freeCharString(defaultArguments); charStringAppendCString(arguments, " "); charStringAppend(arguments, testArguments); // Although testArguments is passed into this function (and hence, it would // generally not take ownership of it), in this case we free the arguments // here to make writing the test cases simpler and reduce the amount of // boilerplate code. freeCharString(testArguments); #if WINDOWS memset(&startupInfo, 0, sizeof(startupInfo)); memset(&processInfo, 0, sizeof(processInfo)); startupInfo.cb = sizeof(startupInfo); returnCode = CreateProcessA( (LPCSTR)(mrsWatsonExePath->data), (LPSTR)(arguments->data), 0, 0, false, CREATE_DEFAULT_ERROR_MODE, 0, 0, &startupInfo, &processInfo); if (returnCode) { // TODO: Check return codes for these calls WaitForSingleObject(processInfo.hProcess, kApplicationRunnerWaitTimeoutInMs); GetExitCodeProcess(processInfo.hProcess, (LPDWORD)&resultCode); CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); } else { logCritical("Could not launch process, got error %s", stringForLastError(GetLastError())); return 1; } #else returnCode = system(arguments->data); resultCode = (ReturnCode)WEXITSTATUS(returnCode); #endif freeCharString(arguments); if (resultCode == RETURN_CODE_FORK_FAILED || resultCode == RETURN_CODE_SHELL_FAILED || resultCode == RETURN_CODE_LAUNCH_FAILED_OTHER) { logCritical("Could not launch shell, got return code %d\n\ Please check the executable path specified in the --mrswatson-path argument.", resultCode); return 1; } else if (resultCode == expectedResultCode) { CharString failedAnalysisFunctionName = newCharString(); if (testOutputType != kTestOutputNone) { if (analyzeFile(outputFilename->data, failedAnalysisFunctionName, &failedAnalysisChannel, &failedAnalysisFrame)) { // TODO: // if (!testEnvironment->results->keepFiles) { // _removeOutputFiles(testName); // } result = 0; } else { fprintf(stderr, "Audio analysis check for %s failed at frame %lu, channel %d. ", failedAnalysisFunctionName->data, failedAnalysisFrame, failedAnalysisChannel); result = 1; } } else { result = 0; // TODO: // if (!testEnvironment->results->keepFiles) { // _removeOutputFiles(testName); // } } freeCharString(failedAnalysisFunctionName); } else { fprintf(stderr, "Expected result code %d (%s), got %d (%s). ", expectedResultCode, _getResultCodeString(expectedResultCode), resultCode, _getResultCodeString(resultCode)); result = 1; } freeCharString(outputFilename); return result; }
CharString newCharString(void) { return newCharStringWithCapacity(kCharStringLengthDefault); }
CharString buildInfoGetVersionString(void) { CharString result = newCharStringWithCapacity(kCharStringLengthShort); snprintf(result->data, result->capacity, "%s version %d.%d.%d", PROGRAM_NAME, VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); return result; }