using System; using System.Collections.Generic; using System.IO; using System.Text; namespace Oni { internal sealed class SubtitleImporter : Importer { #region Private data private List subtitles; private List offsets; #endregion public override void Import(string filePath, string outputDirPath) { ReadTextFile(filePath); string name = Path.GetFileNameWithoutExtension(filePath); BeginImport(); WriteSUBT(name, subtitles.ToArray()); Write(outputDirPath); } private void ReadTextFile(string filePath) { subtitles = new List(); offsets = new List(); var data = File.ReadAllBytes(filePath); int i = SkipPreamble(data); while (i < data.Length) { int nameStart = i; while (!IsNewLine(data, i) && data[i] != '=') i++; int nameEnd = i; if (IsNewLine(data, i)) { // // This was an empty line or a line that does not contain a =. Skip it. // continue; } i++; int textStart = i; while (!IsNewLine(data, i)) i++; int textEnd = i; if (nameEnd > nameStart) { offsets.Add(subtitles.Count); for (int j = nameStart; j < nameEnd; j++) subtitles.Add(data[j]); subtitles.Add(0); for (int j = textStart; j < textEnd; j++) subtitles.Add(data[j]); subtitles.Add(0); } i = SkipNewLine(data, i); } } private static int SkipPreamble(byte[] data) { int offset = CheckPreamble(data, Encoding.UTF8.GetPreamble()); if (offset > 0) return offset; if (CheckPreamble(data, Encoding.Unicode.GetPreamble()) != 0 || CheckPreamble(data, Encoding.BigEndianUnicode.GetPreamble()) != 0 || CheckPreamble(data, Encoding.UTF32.GetPreamble()) != 0) { throw new InvalidDataException("UTF16/32 input text files are not supported."); } if (data.Length >= 4) { if ((data[1] == 0 && data[3] == 0) || (data[0] == 0 && data[2] == 0)) { throw new InvalidDataException("UTF16/32 input text files are not supported."); } } return 0; } private static int CheckPreamble(byte[] data, byte[] preamble) { if (data.Length < preamble.Length) return 0; for (int i = 0; i < preamble.Length; i++) { if (data[i] != preamble[i]) return 0; } return preamble.Length; } private static bool IsNewLine(byte[] data, int offset) { if (offset >= data.Length) return true; return (SkipNewLine(data, offset) > offset); } private static int SkipNewLine(byte[] data, int offset) { if (offset < data.Length) { if (data[offset] == '\n') { offset++; } else if (data[offset] == '\r') { offset++; if (offset < data.Length && data[offset] == '\n') offset++; } } return offset; } private void WriteSUBT(string name, byte[] subtitles) { var subt = CreateInstance(TemplateTag.SUBT, name); using (var writer = subt.OpenWrite(16)) { writer.Write(WriteRawPart(subtitles)); writer.Write(offsets.Count); writer.Write(offsets.ToArray()); } } } }