void ThrowFormatException(string expected, string found) { _state = LineInfoState.Invalid; string msg = string.Format("Expected: '{0}'. '{1}' found instead.", expected, found); LineFormatException e = new LineFormatException(msg); e.Position = _content.Size; }
void CheckMaxLineLength(int newChunkLength) { int curLength = (null == _content)?0:_content.Size; if (newChunkLength + curLength >= _maxLineLength) { _state = LineInfoState.Invalid; throw new LineLengthExceededException(); } }
internal void PutChunk(byte[] data, DataChunk chunk) { if (LineInfoState.Invalid == State) { throw new InvalidOperationException("Invalid line cannot be modified."); } CheckMaxLineLength(chunk.Length); if (false == _seekLF) { if (DataChunkType.CR == chunk.Type) { _seekLF = true; } else { if (DataChunkType.LF == chunk.Type) { if (_requiredCR) { ThrowFormatException("<CR> or <Data>", chunk.ToString()); } else { _state = LineInfoState.Completed; } } } AppendToContent(data, chunk); } else { //Missing LF, let's handle it... if (DataChunkType.LF != chunk.Type) { ThrowFormatException("<LF>", chunk.ToString()); } AppendToContent(data, chunk); _state = LineInfoState.Completed; } }
/// <summary> /// Parse the PO formatted file into a dictionary of entries. /// </summary> Dictionary <string /*MsgInfo.UniqueID*/, MsgInfo> BuildMsgInfoDictionary(IEnumerable <LineInfo> lines) { Dictionary <string /*MsgInfo.UniqueID*/, MsgInfo> result = new Dictionary <string, MsgInfo>(); // Add a whitespace entry to the end of the list, so our state machine can rely on // whitespace as an end-of-entry marker. IEnumerable <LineInfo> linesPlusWhitespace = lines.Concat(new LineInfo[] { new LineInfo(LineType.Whitespace, -1, "") }); LineInfoState state = LineInfoState.FinishedEntry; MsgInfo newEntry = new MsgInfo(); foreach (LineInfo line in linesPlusWhitespace) { // The state machine is small enough to do with a switch. // // The .PO formats is roughly like this: // // Whitespace, followed by // [Optional]# Comments, followed by // [Optional]msgctxt, optionally followed by multi-line context string, followed by // msgid, optionally followed by multi-line id string, followed by // [Optional]msgid_plural - I'm not supporting plural forms, followed by // msgstr, optionally followed by multi-line msg string, followed by // [Optional]msgstr[x] - I'm not supporting plural forms, followed by // EOF or Whitespace switch (state) { case LineInfoState.FinishedEntry: // We're looking for the start of the next entry if (line.Type == LineType.Msgid) { state = LineInfoState.AddingMsgid; newEntry.Msgid_Value = ExtractString(line); } else if (line.Type == LineType.Msgctxt) { // msgctxt is optional, but if present it appears before the msgid state = LineInfoState.AddingMsgctxt; newEntry.Msgctxt_Value = ExtractString(line); } else if (line.Type == LineType.Msgstr || line.Type == LineType.StrContinuation) { // An entry can't start with a msgstr or string-continuation ErrorEncountered(line, "Unexpected string or msgstr"); } break; case LineInfoState.AddingMsgctxt: if (line.Type == LineType.StrContinuation) { newEntry.Msgctxt_Value += ExtractString(line); } else if (line.Type == LineType.Msgid) { state = LineInfoState.AddingMsgid; newEntry.Msgid_Value = ExtractString(line); } else { // msgctxt is optional, but if present it appears before the msgid ErrorEncountered(line, "msgid not found after msgctxt"); } break; case LineInfoState.AddingMsgid: if (line.Type == LineType.StrContinuation) { newEntry.Msgid_Value += ExtractString(line); } else if (line.Type == LineType.Msgstr) { state = LineInfoState.AddingMsgstr; newEntry.Msgstr_Value = ExtractString(line); newEntry.Msgstr_Info = line; } else if (line.Type == LineType.Msgid) { // We can't have two msgids in a row! if (line.Line.StartsWith("msgid_plural", true, CultureInfo.InvariantCulture)) { ErrorEncountered(line, "Multiple msgids encountered, PO plural-forms are not currently supported :("); } else { ErrorEncountered(line, "Unexpected msgid"); } } break; case LineInfoState.AddingMsgstr: if (line.Type == LineType.StrContinuation) { newEntry.Msgstr_Value += ExtractString(line); newEntry.Msgstr_LineCount++; } else if (line.Type == LineType.Whitespace) { // We've found the end of the entry state = LineInfoState.FinishedEntry; if (newEntry.IsValid()) { string uniqueID = newEntry.UniqueID(_options.CaseSensitiveIDs); if (result.ContainsKey(uniqueID)) { // Duplicate msgids encountered - Abort if the msgstr contains a reference, as duplicate msgids are now supported yet and will result in the reference not expanding TestDuplicateEntry(newEntry); } else { result.Add(newEntry.UniqueID(_options.CaseSensitiveIDs), newEntry); } } else { ErrorEncountered(line, "[End found of] invalid entry"); } newEntry = new MsgInfo(); } else if (line.Type == LineType.Msgstr) { // Multiple msgstrs encountered, PO plural-forms are not currently supported :( TestPluralForm(line); } else { ErrorEncountered(line, "Unexpected line encountered at end of entry \"" + newEntry.Msgid_Value + "\" (was expecting whitespace)"); } break; } } return(result); }