public void TrimEndSubstring(string input, char trimChar, string expected) { var substring = new Substring(input); substring = Substring.TrimEnd(substring, trimChar); Assert.Equal(expected, substring.ToString()); }
public void SubstringConstructor() { AString astr = new AString(); AString res = new AString(); constructorTest("a", res, false); UT_EQ("a", res); constructorTest(" a", res, false); UT_EQ(" a", res); constructorTest("a ", res, false); UT_EQ("a ", res); constructorTest("a b", res, false); UT_EQ("a b", res); constructorTest(" a b", res, false); UT_EQ(" a b", res); constructorTest("a b ", res, false); UT_EQ("a b ", res); constructorTest("a", res, true); UT_EQ("a", res); constructorTest(" a", res, true); UT_EQ("a", res); constructorTest("a ", res, true); UT_EQ("a", res); constructorTest("a b", res, true); UT_EQ("a b", res); constructorTest(" a b", res, true); UT_EQ("a b", res); constructorTest("a b ", res, true); UT_EQ("a b", res); // changing whitespaces { { astr.Clear()._("xy xz abc xy"); Substring subs = new Substring(); subs.Set(astr).Trim("xy ".ToCharArray()); subs.CopyTo(res); UT_EQ("z abc", res); } { Substring subs = new Substring("xy xz abc xy"); subs.TrimStart("xy ".ToCharArray()); subs.TrimEnd("xy ".ToCharArray()); subs.CopyTo(res); UT_EQ("z abc", res); } } // test other constructors { astr.Clear()._(" astring "); UT_TRUE((new Substring()).IsEmpty()); UT_TRUE((new Substring()).IsNull()); UT_EQ("astring", (new Substring(astr)).Trim().ToString()); UT_EQ("str", (new Substring(astr, 2, 3)).ToString()); UT_EQ("", (new Substring(astr, 20, 3)).ToString()); UT_TRUE((new Substring(astr, 20, 3)).IsEmpty()); UT_FALSE((new Substring(astr, 20, 3)).IsNull()); Substring s2 = new Substring(astr); s2.Trim(); UT_EQ("astring", new Substring(s2.ToString()).ToString()); UT_EQ("str", (new Substring((new Substring(astr, 2, 3)))).ToString()); } }
bool Get(Object category, Object name, AString target) { // assemble option name as CATEGORY_NAME target.Clear()._(category); if (target.IsNotEmpty()) { target._('_'); } target._(name); int optionLength = target.Length(); Substring actVar = new Substring(); for (int i = 0; i < args.Length; i++) { // remove whitespaces (if somebody would work with quotation marks...) actVar.Set(args[i]).Trim(); // request '-' and allow a second '-' if (!actVar.Consume('-')) { continue; } actVar.Consume('-'); if (target.CompareTo(args[i], Case.Ignore, actVar.Start, optionLength, 0, optionLength) == 0) { //again, lets trim before searching the = sign (really almost unnecessary) actVar.Start += optionLength; if (actVar.Consume('=', Whitespaces.Trim)) { actVar.TrimStart(); actVar.TrimEnd(); target.Clear(); target._NC(args[i], actVar.Start, actVar.Length()); return(true); } } } return(false); }
/** **************************************************************************************** * Returns the next token, which is afterwards also available through field #Actual. * If no further token was available, the returned * \ref cs::aworx::lib::strings::Substring "Substring" will be 'nulled' * (see \ref cs::aworx::lib::strings::Substring::IsNull "Substring.IsNull"). * To prevent this, the availability of a next token should be * checked using method #HasNext(). * * For clarification, see the explanation and sample code in this classes documentation. * * @param trimming Determines if the token is trimmed in respect to the white space * characters defined in field #Whitespaces. * Defaults to \c Whitespaces.Trim. * @param newDelim The delimiter separates the tokens. Defaults to 0, which keeps the * current delimiter intact. * However, it a new delimiter can be provided for every next token. * @return true if a next token was available, false if not. ******************************************************************************************/ public Substring Next(Whitespaces trimming = enums.Whitespaces.Trim, char newDelim = '\0') { if (Rest.IsNull()) { Actual.SetNull(); return(Actual); } // change of delim? if (newDelim != '\0') { delim = newDelim; } // set buf, start and find end Actual.Buf = Rest.Buf; Actual.Start = Rest.Start; int nextDelimiter = Rest.IndexOf(delim); if (nextDelimiter >= 0) { Rest.Start += nextDelimiter + 1; Actual.End = Rest.Start - 2; } else { Actual.End = Rest.End; Rest.SetNull(); } // trim if (trimming == enums.Whitespaces.Trim) { Actual.TrimStart(Whitespaces); Actual.TrimEnd(Whitespaces); } return(Actual); }
// ############################################################################################# // file IO // ############################################################################################# /** **************************************************************************************** * Clears all configuration data and reads the file. It might happen that lines are * ignored or otherwise marked as faulty. All numbers of such lines get collected in * field LinesWithReadErrors. * @return Returns the #Status of the operation. ******************************************************************************************/ public IniFile.Status ReadFile() { Clear(); LastStatus = Status.OK; // read all variables StreamReader file; try { file = new StreamReader(FileName.ToString()); } catch (Exception) { return(LastStatus = Status.ERROR_OPENING_FILE); } String lineS; AString name = new AString(); AString value = new AString(); AString comments = new AString(); Section actSection = Sections[0]; Substring line = new Substring(); Tokenizer tn = new Tokenizer(); int lineNo = 0; bool fileHeaderRead = false; LinesWithReadErrors.Clear(); while ((lineS = file.ReadLine()) != null) { lineNo = 0; // place in AString line.Set(lineS).Trim(); // empty line? if (line.IsEmpty()) { // already collecting a comment? if (comments.IsNotEmpty()) { // first empty line in file found? if (!fileHeaderRead) { //store comments belonging to file fileHeaderRead = true; FileComments = comments; comments = new AString(); continue; } comments.NewLine(); } continue; } // comments line: find comment character '#', ';' or // if (startsWithCommentSymbol(line)) { //gather in comments string if (comments.IsNotEmpty()) { comments.NewLine(); } line.CopyTo(comments, true); continue; } // section line if (line.Consume('[')) { fileHeaderRead = true; // we do not care if there is no closing bracket. But if there is one, we remove it. if (!line.ConsumeFromEnd(']')) { LinesWithReadErrors.Add(lineNo); } // search the section in our section list (if section existed already, new comments // are dropped) actSection = SearchOrCreateSection(line, comments); comments.Clear(); continue; } // variable line? If not, we just drop the line! tn.Set(line, '='); tn.Next(); if (!tn.HasNext()) { LinesWithReadErrors.Add(lineNo); continue; } tn.Actual.CopyTo(name); if (tn.GetRest().IsEmpty()) { LinesWithReadErrors.Add(lineNo); continue; } value.Clear(); Substring valueRead = tn.Actual; // read continues as long as lines end with '\' (must not be '\\') char delim = '\0'; while (valueRead.CharAtEnd() == '\\' && valueRead.CharAtEnd(1) != '\\') { // search end before '\'. The first of all broken lines determines the delimiter valueRead.End--; valueRead.TrimEnd(); if (delim == 0) { delim = valueRead.CharAtEnd(); if (delim == '\"' || char.IsLetterOrDigit(delim)) { delim = '\0'; } } removeEscapeSequences(valueRead, value); if ((lineS = file.ReadLine()) == null) { // last line of the file ended with '\' ! valueRead.Clear(); break; } valueRead.Set(lineS).Trim(); } removeEscapeSequences(valueRead, value); actSection.Insert(name, value, comments).Delim = delim; comments.Clear(); } file.Close(); return(LastStatus); }