/** **************************************************************************************** * Converts variable value data. Replaces certain characters by escape sequences. * @param os The output stream to write to. * @param value The value to write * @param temp A temporary AString needed internally. * @return The difference of length written and given value length. ******************************************************************************************/ protected int addEscapeSequences(TextWriter os, Substring value, AString temp) { int sizeDiff = 0; temp.Clear(); if (char.IsWhiteSpace(value.CharAtStart()) || char.IsWhiteSpace(value.CharAtEnd())) { temp._('\"')._(value)._('\"'); sizeDiff = 2; } else { temp._(value); } for (int i = 0; i < EscapeSequences.Count;) { String replacement = EscapeSequences[i++]; String needle = EscapeSequences[i++]; sizeDiff += temp.SearchAndReplace(needle, replacement, 0) * (replacement.Length - needle.Length); } os.Write(temp.Buffer(), 0, temp.Length()); return(sizeDiff); }
/** **************************************************************************************** * Converts variable value data provided in the token and appends it to the target * variable. * Respects (and removes) quotation marks. * Replaces certain characters by escape sequences. * @param value The input string. * @param target The AString that gets the converted result appended. ******************************************************************************************/ protected void removeEscapeSequences(Substring value, AString target) { // remove quotation markes if (value.CharAtStart() == '\"' && value.CharAtEnd() == '\"') { value.Start++; value.End--; } int regionStart = target.Length(); value.CopyTo(target, true); for (int i = 0; i < EscapeSequences.Count;) { String needle = EscapeSequences[i++]; String replacement = EscapeSequences[i++]; target.SearchAndReplace(needle, replacement, regionStart); } }
public void FrontEnd() { // empty substring { Substring subs = new Substring(); UT_EQ('\0', subs.CharAtStart( )); UT_EQ('\0', subs.CharAt(0)); UT_EQ('\0', subs.CharAt(1)); UT_EQ('\0', subs.CharAt(-1)); UT_EQ('\0', subs.CharAt(2)); UT_EQ('\0', subs.CharAt(-2)); UT_EQ('\0', subs.CharAtEnd( )); UT_EQ('\0', subs.CharAtEnd(0)); UT_EQ('\0', subs.CharAtEnd(1)); UT_EQ('\0', subs.CharAtEnd(-1)); UT_EQ('\0', subs.CharAtEnd(2)); UT_EQ('\0', subs.CharAtEnd(-2)); } // empty substring { Substring subs = new Substring("aaaaaaaaaaaa"); subs.Start = 5; subs.End = 4; UT_EQ('\0', subs.CharAtStart( )); UT_EQ('\0', subs.CharAt(0)); UT_EQ('\0', subs.CharAt(1)); UT_EQ('\0', subs.CharAt(-1)); UT_EQ('\0', subs.CharAt(2)); UT_EQ('\0', subs.CharAt(-2)); UT_EQ('\0', subs.CharAtEnd( )); UT_EQ('\0', subs.CharAtEnd(0)); UT_EQ('\0', subs.CharAtEnd(1)); UT_EQ('\0', subs.CharAtEnd(-1)); UT_EQ('\0', subs.CharAtEnd(2)); UT_EQ('\0', subs.CharAtEnd(-2)); } // substring of length 1 { Substring subs = new Substring("aaaaaaaaaaaa"); subs.Start = subs.End = 5; UT_EQ('a', subs.CharAtStart( )); UT_EQ('a', subs.CharAt(0)); UT_EQ('\0', subs.CharAt(1)); UT_EQ('\0', subs.CharAt(-1)); UT_EQ('\0', subs.CharAt(2)); UT_EQ('\0', subs.CharAt(-2)); UT_EQ('a', subs.CharAtEnd( )); UT_EQ('a', subs.CharAtEnd(0)); UT_EQ('\0', subs.CharAtEnd(1)); UT_EQ('\0', subs.CharAtEnd(-1)); UT_EQ('\0', subs.CharAtEnd(2)); UT_EQ('\0', subs.CharAtEnd(-2)); } // substring of length 2 { Substring subs = new Substring("aaaaabbbbbb"); subs.End = subs.IndexOf('b'); subs.Start = subs.End - 1; UT_EQ('a', subs.CharAtStart( )); UT_EQ('a', subs.CharAt(0)); UT_EQ('b', subs.CharAt(1)); UT_EQ('\0', subs.CharAt(-1)); UT_EQ('\0', subs.CharAt(2)); UT_EQ('\0', subs.CharAt(-2)); UT_EQ('b', subs.CharAtEnd( )); UT_EQ('b', subs.CharAtEnd(0)); UT_EQ('a', subs.CharAtEnd(1)); UT_EQ('\0', subs.CharAtEnd(-1)); UT_EQ('\0', subs.CharAtEnd(2)); UT_EQ('\0', subs.CharAtEnd(-2)); } }
// ############################################################################################# // 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); }