Пример #1
0
void processClangFlags(String& clangFlags, const String& absProjDirOld, const String& absProjDirNew) {
    // Tokenize the flags
    StringVec clangFlagTokens;
    tokenize(clangFlags, clangFlagTokens, " \t", "", "\"'", "", "", true, false);
    reduceClangTokens(clangFlagTokens);

    auto tokensIt = clangFlagTokens.begin();
    while (tokensIt != clangFlagTokens.end()) {
        if (strBeginsWith(*tokensIt, "-iquote")) {
            String newPath = makeRelativePath(tokensIt->substr(7), absProjDirOld, absProjDirNew);
            *tokensIt = "-iquote" + quoteIfNeeded(newPath);
        } else if (strBeginsWith(*tokensIt, "-I")) {
            String newPath = makeRelativePath(tokensIt->substr(2), absProjDirOld, absProjDirNew);
            *tokensIt = "-I" + quoteIfNeeded(newPath);
        } else if (strBeginsWith(*tokensIt, "-F")) {
            tokensIt = clangFlagTokens.erase(tokensIt);
            continue; // don't increment iterator
        } else {
            *tokensIt = quoteIfNeeded(*tokensIt);
        }

        tokensIt++;
    }

    clangFlags = joinStrings(clangFlagTokens, " ");
}
bool isAbsolutePath(const String &path, PathStyle style)
{
  if (style == WindowsPath)
    return ((path.length() >= 2 && isalpha(path[0]) && path[1] == ':') ||
            strBeginsWith(path, "/") || strBeginsWith(path, "\\"));
  else if (style == PosixPath)
    return strBeginsWith(path, "/");
  else
    return false;
}
Пример #3
0
void processLDFlags(const String& ldFlags, StringVec& libs) {
    // Tokenize flags
    StringVec ldFlagTokens;
    tokenize(ldFlags, ldFlagTokens, " \t", "", "\"'", "", "", true, false);

    // Expand -Wl, and -Xlinker tokens to make parsing easier
    StringVec ldFlagsFixed;
    replaceWlArgs(ldFlagTokens, ldFlagsFixed);

    String savedToken;
    for (auto opt : ldFlagsFixed) {
        if (savedToken.empty()) {
            opt = reduceLinkerToken(opt);
            if (opt == "-library" || opt == "-framework") {
                savedToken = opt;
            } else if (strBeginsWith(opt, "-l")) {
                String libName = strEndsWith(opt, ".o") ? opt.substr(2) : "lib" + opt.substr(2) + ".?";
                libs.push_back(libName);
            } else if (strEndsWith(opt, ".a") || strEndsWith(opt, ".dylib") || strEndsWith(opt, ".o")) {
                libs.push_back(opt);
            }
        } else {
            if (savedToken == "-library") {
                libs.push_back(opt);
            } else if (savedToken == "-framework") {
                std::string frameworkName = opt.substr(0, opt.find(',')) + ".framework";
                libs.push_back(frameworkName);
            }
            savedToken.clear();
        }
    }
}
Пример #4
0
// "Expand" -Wl and -Xlinker tokens
// This is OK to do since we're interested in a small subset of flags.
// Preserving correctness is not important.
static void replaceWlArgs(const StringVec& inArgs, StringVec& outArgs) {
    for (auto arg : inArgs) {
        if (strBeginsWith(arg, "-Wl,")) {
            StringVec tokens;
            tokenize(arg, tokens, ",", "", "", "", "");
            outArgs.insert(outArgs.end(), tokens.begin() + 1, tokens.end());
        } else if (arg != "-Xlinker") {
            outArgs.push_back(arg);
        }
    }
}
Пример #5
0
static String reduceLinkerToken(const String& token) {
    static const char* const _prefixes[] = { "-weak", "-reexport", "-lazy", "-upward" };
    static StringVec prefixes(_prefixes, _prefixes + sizeof(_prefixes) / sizeof(char*));

    StringVec::const_iterator pIt = prefixes.begin();
    for (; pIt != prefixes.end(); ++pIt) {
        size_t prefixLen = pIt->length();
        if (token.length() > prefixLen && strBeginsWith(token, *pIt) && (token[prefixLen] == '_' || token[prefixLen] == '-'))
            return "-" + token.substr(prefixLen + 1);
    }

    return token;
}
Пример #6
0
void SBTarget::validateSDK()
{
  // Check if this is an iphoneos target
  // Could take the form of "iphone" or a full path to the SDK
  for (auto bs : m_buildSettings) {
    const VariableCollectionHierarchy& vch = bs.second->getHierarchy();
    String sdkRoot = vch.getValue("SDKROOT", vch.size() - 2);
    sdkRoot = strToLower(sb_basename(sdkRoot));
    if (!strBeginsWith(sdkRoot, "iphoneos")) {
      SBLog::warning() << "The \"" << bs.first << "\" configuration of the \"" << getName() << "\" target does not target an iOS SDK." << std::endl;
    }
  }
}
Пример #7
0
//IMPLEMENT HEADER
MultiVCFreader::MultiVCFreader(string file,string indexForFile,string chrName,int start,int end,int indelsAhead) {
    readAhead=indelsAhead;
    rt = new ReadTabix (file,indexForFile,chrName,start,end);


    //reading header
    istringstream f (rt->getHeader());
    string line;
    numPop=0;
    while (getline(f, line)) {
        //std::cout << line << std::endl;
        if(strBeginsWith(line,"#CHROM")) {
            vector<string> tok = allTokens(line,'\t');
            if(tok.size() < 10 ) {
                cerr<<"The header line"<<line<<" does not contain enough fields"<<endl;
                exit(1);
            }

            for(unsigned int i=9; i<tok.size(); i++) {
                //cerr<<tok[i]<<endl;
                numPop++;
                populationNames.push_back(tok[i]);
            }

        }
    }


    if( numPop == 0 ) {
        cerr<<"No populations have been found for file "<<file<<endl;
        exit(1);
    }

    needToPopulateQueue           = true;
    fullQueue                     = false;
    endQueue                      = false;
    numberOfTimesHasDataWasCalled = 0;

    svcfToReturn                  = 0;

    repoCalledHasData             = false;

    indexInQueueOfIndels          = -1;
    indexOfLastIndel              = 0;
    previouslyFoundIndel          = false;

    tabixMode                     = true;
    textMode                      = false;
}
Пример #8
0
void extractAcctounts(FILE *fp)
{
	char buff[256], *ptr;
	int x;
	while ( !feof(fp) )
	{
		fgets(buff, 255, fp);
		if ( strBeginsWith("name=", buff) )
		{
			buff[strlen(buff)-1] = 0;
			pAccounts[nAccounts] = (struct account*)malloc(sizeof(struct account));
			if ( pAccounts[nAccounts] == NULL )
			{
				perror("Failed to malloc()");
				exit(errno);
			}
			ptr = pAccounts[nAccounts]->username;
			for ( x = 5 ; x < strlen(buff) ; x++ )
			{
				ptr[x-5] = buff[x];
			}
			ptr[x-5] = 0;
			nAccounts++;
		}
		if ( strBeginsWith("password=", buff) )
		{
			buff[strlen(buff)-1] = 0;
			ptr = pAccounts[nAccounts-1]->cyphertext;
			for ( x = 9 ; x < strlen(buff) ; x++ )
			{
				ptr[x-9] = buff[x];
			}
			ptr[x-9] = 0;
		}
	}
}
Пример #9
0
void MistarParser::parseHeader(istream & in){
    bool firstLine=true;
    string line;

    while(getline ( in,line)){
	//cout<<"line "<<line<<endl;
	if(line[0] == '#'){
	    // cout<<line;
	    if(firstLine){
		if(line != "#MISTAR"){
		    cerr << "Error: MistarParser first line must be #MISTAR found: " << line <<endl;
		    exit(1);	    
		}		
		firstLine=false;
		continue;
	    }

	    
	    if(strBeginsWith(line, "#chr")){
		defline=line;
		vector<string> fields=allTokens(line,'\t');

		if(fields[0] != "#chr")   { cerr<<"Field #1 ("<<fields[0]<<") of header must be #chr in line #"<<line<<"#"<<endl;    exit(1); }
		if(fields[1] != "coord")  { cerr<<"Field #2 of header must be coord ";   exit(1); }
		if(fields[2] != "REF,ALT"){ cerr<<"Field #3 of header must be REF,ALT "; exit(1); }
		if(fields[3] != "root")   { cerr<<"Field #4 of header must be root ";    exit(1); }
		if(fields[4] != "anc")    { cerr<<"Field #5 of header must be anc ";     exit(1); }

		for(unsigned int i=3;i<fields.size();i++){
		    populationNames->push_back(fields[i]);
		    numberPopulations++;
		}
		header+=line+"\n";

		break;
	    }else{
		header+=line+"\n";
		headerNoDefline+=line+"\n";
	    }
	    
	}else{
	    cerr << "Error: MistarParser cannot get header"  <<endl;
	    exit(1);
	}
    }
}
String sanitizePath(const String &path)
{
  // Standardize slashes to POSIX style
  String fixedPath = posixPath(path);

  // Check if path is absolute
  bool isAbsolute = isAbsolutePath(fixedPath);

  // Tokenize path
  StringList pathComponents;
  std::size_t start = 0;
  do {
    std::size_t separator = (std::min)(fixedPath.find('/', start), fixedPath.length());
    String token = fixedPath.substr(start, separator - start);
    if (token.empty() || token == ".") {
      // a/./b -> a/b and a//b -> a/b
    } else if (token == "..") {
      if (pathComponents.empty()) {
        // ../a -> ../a
        // /../a -> /a
        if (!isAbsolute)
          pathComponents.push_back(token);
      } else {
        // ../../a -> ../../a
        // a/../c -> c
        if (pathComponents.back() == "..")
          pathComponents.push_back(token);
        else
          pathComponents.pop_back();
      }
    } else {
      pathComponents.push_back(token);
    }

    start = separator + 1;
  } while (start < path.length());

  // Figure out if we need to add a leading slash
  String prefix;
  if (strBeginsWith(fixedPath, "/"))
    prefix = "/";

  // Return reassembled path
  return prefix + joinStrings(pathComponents, "/");
}
Пример #11
0
int getFilePointer(char* params, char** pointerParam){

	int i;
	*pointerParam = KFS;
	unsigned char** pointer = (unsigned char**) pointerParam;
	char* KFS_sig = "KFS Begin";
	for(i=0; i<strLen(KFS_sig)-1; i++){
		if((*pointer)[i] != KFS_sig[i]){
			ttprint("Error! KFS does not start with:");
			ttprint(KFS_sig);
			return -1;
		}
	}

	*pointer += 25;
	// 25 is filesystem header, 94 is max # files
	for(i=0; i < 94; i++){
		//ttprintln(*pointer);
		if(strEquals(params,*pointer) || strLen(params) == 11 && strBeginsWith(*pointer,params)) break;
		*pointer += 16;
	}
	if(i == 94){
		ttprint("File not found:");
		ttprint(params);
		return -2;
	}
	i = 0;
	*pointer += 10;
	int sec,off,len;
	sec = (*pointer)[i++];

	off = (*pointer)[i++] << 8 ;
	off |= (*pointer)[i++];
	
	len = (*pointer)[i++] << 16;
	len |= ((*pointer)[i++] << 8);
	len |= (*pointer)[i++];

	*pointer = KFS + (sec+3)*512 + off;
	return len;
}
Пример #12
0
 void print(const String& varName, const String& varValue) const {
   if (!strBeginsWith(varName, "VSIMPORTER")) {
     m_ofs << varName << " = " << trim(varValue) << std::endl;
   }
 }
Пример #13
0
MultiVCFreader::MultiVCFreader(string file,int indelsAhead) {
    readAhead=indelsAhead;
    numberOfTimesHasDataWasCalled=0;
    svcfToReturn=0;

    vcfFile.open(file.c_str(), ios::in);    // open the streams
    if (vcfFile.good()) {
        //fine
    } else {
        cerr<<"Unable to open the file "<<file<<endl;
        exit(1);
    }

    bool firstLine=true;
    bool haveCaptureCHROM=false;
    numPop=0;

    while(1) {
        bool flag=getline(vcfFile,currentline);
        if(!flag) {
            cerr<<"ERROR file : "+file+" is probably empty"<<endl;
            exit(1);
        }

        if(firstLine) {

            if(currentline.length() > 0 && currentline[0] != '#') {
                cerr<<"ERROR first line in "<<file<<"does not begin with #"<<endl;
                exit(1);
            }

            firstLine = false;
        }

        if(!firstLine) {

            if(currentline.length() > 0) {
                if(currentline[0] == '#') {

                    if(strBeginsWith(currentline,"#CHROM")) {
                        haveCaptureCHROM=true;
                        vector<string> tok = allTokens(currentline,'\t');
                        if(tok.size() < 10 ) {
                            cerr<<"The header line"<<currentline<<" does not contain enough fields for file "<<file<<endl;
                            exit(1);
                        }

                        for(unsigned int i=9; i<tok.size(); i++) {
                            //cerr<<tok[i]<<endl;
                            numPop++;
                            populationNames.push_back(tok[i]);
                        }
                        break;
                    }

                    // cerr<<"ERROR first line in "<<file<<"does not begin with #"<<endl;
                    // return 1;
                } else {
                    break;
                }
            }

        }

    }//end while(1)
    // vcfFile.close();
    // //vcfFile.seekg(0, std::ios::beg);

    // vcfFile.open(file.c_str(), ios::in);    // open the streams
    // if (vcfFile.good()) {
    // 	//fine
    // }else{
    // 	cerr<<"Unable to open the file for second pass "<<file<<endl;
    // 	exit(1);
    // }

    if( numPop == 0 ) {
        cerr<<"No populations have been found for file "<<file<<endl;
        exit(1);
    }

    if(!haveCaptureCHROM) {
        cerr<<"The header with #CHROM has not been found in file:"<<file<<endl;
        exit(1);
    }


    needToPopulateQueue = true;
    fullQueue           = false;
    endQueue            = false;
    repoCalledHasData   = false;


    indexInQueueOfIndels=-1;
    indexOfLastIndel=0;
    previouslyFoundIndel=false;

    tabixMode = false;
    textMode  = true;
}
Пример #14
0
/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
void
testRun(void)
{
    FUNCTION_HARNESS_VOID();

    // *****************************************************************************************************************************
    if (testBegin("strNew(), strNewBuf(), strNewN(), strEmpty(), strPtr(), strSize(), and strFree()"))
    {
        // We don't want this struct to grow since there are generally a lot of strings, so make sure it doesn't grow without us
        // knowing about it
        TEST_RESULT_UINT(sizeof(StringConst), TEST_64BIT() ? 16 : 12, "check StringConst struct size");

        // Test the size macro
        TEST_RESULT_VOID(CHECK_SIZE(555), "valid size");
        TEST_ERROR(CHECK_SIZE(STRING_SIZE_MAX + 1), AssertError, "string size must be <= 1073741824 bytes");

        String *string = strNew("static string");
        TEST_RESULT_STR(strPtr(string), "static string", "new with static string");
        TEST_RESULT_INT(strSize(string), 13, "check size");
        TEST_RESULT_BOOL(strEmpty(string), false, "is not empty");
        TEST_RESULT_INT(strlen(strPtr(string)), 13, "check size with strlen()");
        TEST_RESULT_CHAR(strPtr(string)[2], 'a', "check character");

        TEST_RESULT_VOID(strFree(string), "free string");

        // -------------------------------------------------------------------------------------------------------------------------
        TEST_RESULT_STR(strPtr(strNewN("testmorestring", 4)), "test", "new string with size limit");

        // -------------------------------------------------------------------------------------------------------------------------
        Buffer *buffer = bufNew(8);
        memcpy(bufPtr(buffer), "12345678", 8);
        bufUsedSet(buffer, 8);

        TEST_RESULT_STR(strPtr(strNewBuf(buffer)), "12345678", "new string from buffer");

        // -------------------------------------------------------------------------------------------------------------------------
        string = strNewFmt("formatted %s %04d", "string", 1);
        TEST_RESULT_STR(strPtr(string), "formatted string 0001", "new with formatted string");
        TEST_RESULT_PTR(strPtr(NULL), NULL, "null string pointer");

        TEST_RESULT_VOID(strFree(string), "free string");
        TEST_RESULT_VOID(strFree(NULL), "free null string");
    }

    // *****************************************************************************************************************************
    if (testBegin("STRING_STATIC()"))
    {
        TEST_RESULT_STR(strPtr(TEST_STRING), "a very interesting string!", "check static string");
        TEST_RESULT_STR(strPtr(strSubN(TEST_STRING, 0, 6)), "a very", "read-only strSub() works");
    }

    // *****************************************************************************************************************************
    if (testBegin("strBase() and strPath()"))
    {
        TEST_RESULT_STR(strPtr(strBase(STRDEF(""))), "", "empty string");
        TEST_RESULT_STR(strPtr(strBase(STRDEF("/"))), "", "/ only");
        TEST_RESULT_STR(strPtr(strBase(STRDEF("/file"))), "file", "root file");
        TEST_RESULT_STR(strPtr(strBase(STRDEF("/dir1/dir2/file"))), "file", "subdirectory file");

        TEST_RESULT_STR(strPtr(strPath(STRDEF(""))), "", "empty string");
        TEST_RESULT_STR(strPtr(strPath(STRDEF("/"))), "/", "/ only");
        TEST_RESULT_STR(strPtr(strPath(STRDEF("/file"))), "/", "root path");
        TEST_RESULT_STR(strPtr(strPath(STRDEF("/dir1/dir2/file"))), "/dir1/dir2", "subdirectory file");
    }

    // *****************************************************************************************************************************
    if (testBegin("strCat(), strCatChr(), and strCatFmt()"))
    {
        String *string = strNew("XXXX");
        String *string2 = strNew("ZZZZ");

        TEST_RESULT_STR(strPtr(strCat(string, "YYYY")), "XXXXYYYY", "cat string");
        TEST_RESULT_SIZE(string->extra, 4, "check extra");
        TEST_RESULT_STR(strPtr(strCatFmt(string, "%05d", 777)), "XXXXYYYY00777", "cat formatted string");
        TEST_RESULT_SIZE(string->extra, 6, "check extra");
        TEST_RESULT_STR(strPtr(strCatChr(string, '!')), "XXXXYYYY00777!", "cat chr");
        TEST_RESULT_SIZE(string->extra, 5, "check extra");

        TEST_RESULT_STR(strPtr(string2), "ZZZZ", "check unaltered string");
    }

    // *****************************************************************************************************************************
    if (testBegin("strDup()"))
    {
        const String *string = STRDEF("duplicated string");
        String *stringDup = strDup(string);
        TEST_RESULT_STR(strPtr(stringDup), strPtr(string), "duplicated strings match");

        TEST_RESULT_PTR(strDup(NULL), NULL, "duplicate null string");
    }

    // *****************************************************************************************************************************
    if (testBegin("strBeginsWith() and strBeginsWithZ()"))
    {
        TEST_RESULT_BOOL(strBeginsWith(STRDEF(""), STRDEF("aaa")), false, "empty string");
        TEST_RESULT_BOOL(strBeginsWith(STRDEF("astring"), STRDEF("")), true, "empty begins with");
        TEST_RESULT_BOOL(strBeginsWithZ(STRDEF("astring"), "astr"), true, "partial begins with");
        TEST_RESULT_BOOL(strBeginsWithZ(STRDEF("astring"), "astring"), true, "equal strings");
    }

    // *****************************************************************************************************************************
    if (testBegin("strEndsWith() and strEndsWithZ()"))
    {
        TEST_RESULT_BOOL(strEndsWith(STRDEF(""), STRDEF(".doc")), false, "empty string");
        TEST_RESULT_BOOL(strEndsWith(STRDEF("astring"), STRDEF("")), true, "empty ends with");
        TEST_RESULT_BOOL(strEndsWithZ(STRDEF("astring"), "ing"), true, "partial ends with");
        TEST_RESULT_BOOL(strEndsWithZ(STRDEF("astring"), "astring"), true, "equal strings");
    }

    // *****************************************************************************************************************************
    if (testBegin("strEq(), strEqZ(), strCmp(), strCmpZ()"))
    {
        TEST_RESULT_BOOL(strEq(STRDEF("equalstring"), STRDEF("equalstring")), true, "strings equal");
        TEST_RESULT_BOOL(strEq(STRDEF("astring"), STRDEF("anotherstring")), false, "strings not equal");
        TEST_RESULT_BOOL(strEq(STRDEF("astring"), STRDEF("bstring")), false, "equal length strings not equal");

        TEST_RESULT_INT(strCmp(STRDEF("equalstring"), STRDEF("equalstring")), 0, "strings equal");
        TEST_RESULT_INT(strCmp(STRDEF("a"), STRDEF("b")), -1, "a < b");
        TEST_RESULT_INT(strCmp(STRDEF("b"), STRDEF("a")), 1, "b > a");

        TEST_RESULT_BOOL(strEqZ(STRDEF("equalstring"), "equalstring"), true, "strings equal");
        TEST_RESULT_BOOL(strEqZ(STRDEF("astring"), "anotherstring"), false, "strings not equal");
        TEST_RESULT_BOOL(strEqZ(STRDEF("astring"), "bstring"), false, "equal length strings not equal");

        TEST_RESULT_INT(strCmpZ(STRDEF("equalstring"), "equalstring"), 0, "strings equal");
        TEST_RESULT_INT(strCmpZ(STRDEF("a"), "b"), -1, "a < b");
        TEST_RESULT_INT(strCmpZ(STRDEF("b"), "a"), 1, "b > a");
    }

    // *****************************************************************************************************************************
    if (testBegin("strFirstUpper(), strFirstLower(), strUpper(), strLower()"))
    {
        TEST_RESULT_STR(strPtr(strFirstUpper(strNew(""))), "", "empty first upper");
        TEST_RESULT_STR(strPtr(strFirstUpper(strNew("aaa"))), "Aaa", "first upper");
        TEST_RESULT_STR(strPtr(strFirstUpper(strNew("Aaa"))), "Aaa", "first already upper");

        TEST_RESULT_STR(strPtr(strFirstLower(strNew(""))), "", "empty first lower");
        TEST_RESULT_STR(strPtr(strFirstLower(strNew("AAA"))), "aAA", "first lower");
        TEST_RESULT_STR(strPtr(strFirstLower(strNew("aAA"))), "aAA", "first already lower");

        TEST_RESULT_STR(strPtr(strLower(strNew("K123aBc"))), "k123abc", "all lower");
        TEST_RESULT_STR(strPtr(strLower(strNew("k123abc"))), "k123abc", "already lower");
        TEST_RESULT_STR(strPtr(strLower(strNew("C"))), "c", "char lower");
        TEST_RESULT_STR(strPtr(strLower(strNew(""))), "", "empty lower");

        TEST_RESULT_STR(strPtr(strUpper(strNew("K123aBc"))), "K123ABC", "all upper");
        TEST_RESULT_STR(strPtr(strUpper(strNew("K123ABC"))), "K123ABC", "already upper");
        TEST_RESULT_STR(strPtr(strUpper(strNew("c"))), "C", "char upper");
        TEST_RESULT_STR(strPtr(strUpper(strNew(""))), "", "empty upper");
    }

    // *****************************************************************************************************************************
    if (testBegin("strQuote()"))
    {
        TEST_RESULT_STR(strPtr(strQuote(STRDEF("abcd"), STRDEF("'"))), "'abcd'", "quote string");
    }

    // *****************************************************************************************************************************
    if (testBegin("strReplaceChr()"))
    {
        TEST_RESULT_STR(strPtr(strReplaceChr(strNew("ABCD"), 'B', 'R')), "ARCD", "replace chr");
    }

    // *****************************************************************************************************************************
    if (testBegin("strSub() and strSubN()"))
    {
        TEST_RESULT_STR(strPtr(strSub(STRDEF("ABCD"), 2)), "CD", "sub string");
        TEST_RESULT_STR(strPtr(strSubN(STRDEF("ABCD"), 1, 2)), "BC", "sub string with length");
    }

    // *****************************************************************************************************************************
    if (testBegin("strTrim()"))
    {
        TEST_RESULT_STR(strPtr(strTrim(strNew(""))), "", "trim empty");
        TEST_RESULT_STR(strPtr(strTrim(strNew("X"))), "X", "no trim (one char)");
        TEST_RESULT_STR(strPtr(strTrim(strNew("no-trim"))), "no-trim", "no trim (string)");
        TEST_RESULT_STR(strPtr(strTrim(strNew(" \t\r\n"))), "", "all whitespace");
        TEST_RESULT_STR(strPtr(strTrim(strNew(" \tbegin-only"))), "begin-only", "trim begin");
        TEST_RESULT_STR(strPtr(strTrim(strNew("end-only\t "))), "end-only", "trim end");
        TEST_RESULT_STR(strPtr(strTrim(strNew("\n\rboth\r\n"))), "both", "trim both");
        TEST_RESULT_STR(strPtr(strTrim(strNew("begin \r\n\tend"))), "begin \r\n\tend", "ignore whitespace in middle");
    }

    // *****************************************************************************************************************************
    if (testBegin("strChr() and strTrunc()"))
    {
        TEST_RESULT_INT(strChr(STRDEF("abcd"), 'c'), 2, "c found");
        TEST_RESULT_INT(strChr(STRDEF("abcd"), 'C'), -1, "capital C not found");
        TEST_RESULT_INT(strChr(STRDEF("abcd"), 'i'), -1, "i not found");
        TEST_RESULT_INT(strChr(STRDEF(""), 'x'), -1, "empty string - x not found");

        String *val = strNew("abcdef");
        TEST_ERROR(
            strTrunc(val, (int)(strSize(val) + 1)), AssertError,
            "assertion 'idx >= 0 && (size_t)idx <= this->size' failed");
        TEST_ERROR(strTrunc(val, -1), AssertError, "assertion 'idx >= 0 && (size_t)idx <= this->size' failed");

        TEST_RESULT_STR(strPtr(strTrunc(val, strChr(val, 'd'))), "abc", "simple string truncated");
        strCat(val, "\r\n to end");
        TEST_RESULT_STR(strPtr(strTrunc(val, strChr(val, 'n'))), "abc\r\n to e", "complex string truncated");
        TEST_RESULT_STR(strPtr(strTrunc(val, strChr(val, 'a'))), "", "complete string truncated - empty string");

        TEST_RESULT_INT(strSize(val), 0, "0 size");
        TEST_RESULT_STR(strPtr(strTrunc(val, 0)), "", "test coverage of empty string - no error thrown for index 0");
    }

    // *****************************************************************************************************************************
    if (testBegin("strToLog() and strObjToLog()"))
    {
        TEST_RESULT_STR(strPtr(strToLog(STRDEF("test"))), "{\"test\"}", "format string");
        TEST_RESULT_STR(strPtr(strToLog(NULL)), "null", "format null string");

        char buffer[256];
        TEST_RESULT_UINT(strObjToLog(NULL, (StrObjToLogFormat)strToLog, buffer, sizeof(buffer)), 4, "format null string");
        TEST_RESULT_STR(buffer, "null", "check null string");

        TEST_RESULT_UINT(strObjToLog(STRDEF("teststr"), (StrObjToLogFormat)strToLog, buffer, sizeof(buffer)), 11, "format string");
        TEST_RESULT_STR(buffer, "{\"teststr\"}", "check string");
    }

    // *****************************************************************************************************************************
    if (testBegin("strSizeFormat()"))
    {
        TEST_RESULT_STR(strPtr(strSizeFormat(0)), "0B", "zero bytes");
        TEST_RESULT_STR(strPtr(strSizeFormat(1023)), "1023B", "1023 bytes");
        TEST_RESULT_STR(strPtr(strSizeFormat(1024)), "1KB", "1 KB");
        TEST_RESULT_STR(strPtr(strSizeFormat(2200)), "2.1KB", "2.1 KB");
        TEST_RESULT_STR(strPtr(strSizeFormat(1048576)), "1MB", "1 MB");
        TEST_RESULT_STR(strPtr(strSizeFormat(20162900)), "19.2MB", "19.2 MB");
        TEST_RESULT_STR(strPtr(strSizeFormat(1073741824)), "1GB", "1 GB");
        TEST_RESULT_STR(strPtr(strSizeFormat(1073741824 + 107374183)), "1.1GB", "1.1 GB");
        TEST_RESULT_STR(strPtr(strSizeFormat(UINT64_MAX)), "17179869183GB", "uint64 max");
    }

    // *****************************************************************************************************************************
    if (testBegin("strLstNew(), strLstAdd*(), strLstGet(), strLstMove(), strLstSize(), and strLstFree()"))
    {
        // Add strings to the list
        // -------------------------------------------------------------------------------------------------------------------------
        StringList *list = NULL;

        MEM_CONTEXT_TEMP_BEGIN()
        {
            list = strLstNew();

            for (int listIdx = 0; listIdx <= LIST_INITIAL_SIZE; listIdx++)
            {
                if (listIdx == 0)
                {
                    TEST_RESULT_PTR(strLstAdd(list, NULL), list, "add null item");
                }
                else
                    TEST_RESULT_PTR(strLstAdd(list, strNewFmt("STR%02d", listIdx)), list, "add item %d", listIdx);
            }

            strLstMove(list, MEM_CONTEXT_OLD());
        }
        MEM_CONTEXT_TEMP_END();

        TEST_RESULT_INT(strLstSize(list), 9, "list size");

        // Read them back and check values
        // -------------------------------------------------------------------------------------------------------------------------
        for (unsigned int listIdx = 0; listIdx < strLstSize(list); listIdx++)
        {
            if (listIdx == 0)
            {
                TEST_RESULT_PTR(strLstGet(list, listIdx), NULL, "check null item");
            }
            else
                TEST_RESULT_STR(strPtr(strLstGet(list, listIdx)), strPtr(strNewFmt("STR%02u", listIdx)), "check item %u", listIdx);
        }

        TEST_RESULT_VOID(strLstFree(list), "free string list");
        TEST_RESULT_VOID(strLstFree(NULL), "free null string list");
    }