private ZtrFileEntry[] ExtractLittleEndianUncompressedDictionary(int count) { if (count < 0 || count > 102400) { throw new ArgumentOutOfRangeException(nameof(count), count.ToString()); } ZtrFileEntry[] entries = new ZtrFileEntry[count]; entries.InitializeElements(); int[] offsets = new int[count * 2]; for (int i = 0; i < count * 2; i++) { offsets[i] = _br.ReadInt32(); } for (int i = 0; i < count; i++) { _input.Position = offsets[i * 2]; entries[i].Key = _input.ReadNullTerminatedString(Encoding.ASCII, 1); _input.Position = offsets[i * 2 + 1]; entries[i].Value = _input.ReadNullTerminatedString(_encoding, 2); } return(entries); }
private void PackLittleEndianUncompressedDictionary(ZtrFileEntry[] entries) { int count = entries.Length; byte[][] keys = new byte[count][]; byte[][] values = new byte[count][]; int[] offsets = new int[count * 2]; int index = 0; offsets[0] = 4 + count * 2 * 4; for (int i = 0; i < count; i++) { ZtrFileEntry entry = entries[i]; keys[i] = Encoding.ASCII.GetBytes(entry.Key); values[i] = (entry.IsAnimatedText ? FFXIIITextEncodingFactory.DefaultEuroEncoding.Value : _encoding).GetBytes(entry.Value); offsets[index + 1] = offsets[index++] + keys[i].Length + 1; if (index + 1 < offsets.Length) offsets[index + 1] = offsets[index++] + values[i].Length + 2; } _bw.Write(count); for (int i = 0; i < count * 2; i++) _bw.Write(offsets[i]); for (int i = 0; i < count; i++) { _bw.Write(keys[i], 0, keys[i].Length); _bw.Write((byte)0); _bw.Write(values[i], 0, values[i].Length); _bw.Write((short)0); } }
private void PackBigEndianCompressedDictionary(ZtrFileEntry[] entries) { if (entries.Length > 0) throw new NotImplementedException(); _bw.Write((int)ZtrFileType.BigEndianCompressedDictionary); }
public ZtrFileTextPacker(Stream output, ZtrFileEntry[] input, ZtrFileHeader header, FFXIIITextEncoding encoding) { _output = output; _input = input; _header = header; _encoding = encoding; }
public void Write(StreamWriter sw, ZtrFileEntry entry, int index) { sw.WriteLine("\"{0}║{1}\" = \"{2}\";", index.ToString("D4", CultureInfo.InvariantCulture), entry.Key, entry.Value.Replace("\\", "\\\\").Replace("\"", "\\\"")); }
public ZtrFileTextUnpacker(Stream input, ZtrFileEntry[] output, ZtrFileHeaderLineInfo[] offsets, FFXIIITextEncoding encoding) { _input = input; _output = output; _offsets = offsets; _encoding = encoding; }
public void Pack(ZtrFileEntry[] entries) { if (entries.Length == 0) PackBigEndianCompressedDictionary(entries); else if (entries.Length == 1) PackLittleEndianUncompressedPair(entries[0]); else PackLittleEndianUncompressedDictionary(entries); }
private ZtrFileEntry[] ExtractLittleEndianUncompressedPair() { ZtrFileEntry result = new ZtrFileEntry(); int keyOffset = _br.ReadInt32(); int textOffset = _br.ReadInt32(); _input.Position = keyOffset; result.Key = _input.ReadNullTerminatedString(Encoding.ASCII, 1); _input.Position = textOffset; result.Value = _input.ReadNullTerminatedString(_encoding, 2); return(new[] { result }); }
private void PackLittleEndianUncompressedPair(ZtrFileEntry entry) { _bw.Write((int)ZtrFileType.LittleEndianUncompressedPair); byte[] key = Encoding.ASCII.GetBytes(entry.Key); byte[] value = (entry.IsAnimatedText ? FFXIIITextEncodingFactory.DefaultEuroEncoding.Value : _encoding).GetBytes(entry.Value); _bw.Write(12); _bw.Write(12 + key.Length + 1); _bw.Write(key); _bw.Write((byte)0); _bw.Write(value); _bw.Write((short)0); }
private ZtrFileEntry[] ExtractBigEndianCompressedDictionary() { ZtrFileHeader header = new ZtrFileHeader(); header.ReadFromStream(_input); ZtrFileEntry[] result = new ZtrFileEntry[header.Count]; result.InitializeElements(); ZtrFileKeysUnpacker keysUnpacker = new ZtrFileKeysUnpacker(_input, result); keysUnpacker.Unpack(header.KeysUnpackedSize); ZtrFileTextUnpacker textUnpacker = new ZtrFileTextUnpacker(_input, result, header.TextLinesTable, _encoding); textUnpacker.Unpack(header.TextBlockTable[header.TextBlockTable.Length - 1]); return result; }
public ZtrFileEntry[] Read(out string name) { using (StreamReader sr = new StreamReader(_input, Encoding.UTF8, true, 4096, true)) { name = sr.ReadLine(); if (_formatter is StringsZtrFormatter) // TEMP { name = name.Substring(2, name.Length - 4); } string countStr = sr.ReadLine(); if (_formatter is StringsZtrFormatter) // TEMP { countStr = countStr.Substring(2, countStr.Length - 4); } int count = int.Parse(countStr, CultureInfo.InvariantCulture); List <ZtrFileEntry> result = new List <ZtrFileEntry>(count); for (int i = 0; i < count && !sr.EndOfStream; i++) { int index; ZtrFileEntry entry = _formatter.Read(sr, out index); if (entry == null) { continue; } if (string.IsNullOrWhiteSpace(entry.Key)) { Log.Warning("Неверная запись [Key: {0}, Value: {1}] в файле: {2}", entry.Key, entry.Value, name); continue; } result.Add(entry); } if (result.Count != count) { Log.Warning("Неверное количество строк в файле: {0} из {1}", result.Count, count); } return(result.ToArray()); } }
private ZtrFileEntry[] ExtractBigEndianCompressedDictionary() { ZtrFileHeader header = new ZtrFileHeader(); header.ReadFromStream(_input); ZtrFileEntry[] result = new ZtrFileEntry[header.Count]; result.InitializeElements(); ZtrFileKeysUnpacker keysUnpacker = new ZtrFileKeysUnpacker(_input, result); keysUnpacker.Unpack(header.KeysUnpackedSize); ZtrFileTextUnpacker textUnpacker = new ZtrFileTextUnpacker(_input, result, header.TextLinesTable, _encoding); textUnpacker.Unpack(header.TextBlockTable[header.TextBlockTable.Length - 1]); return(result); }
public void Write(string name, ZtrFileEntry[] entries) { using (StreamWriter sw = new StreamWriter(_output, Encoding.UTF8, 4096, true)) { if (_formatter is StringsZtrFormatter) // TEMP { sw.WriteLine("/*" + name + "*/"); sw.WriteLine("/*" + entries.Length.ToString("D4", CultureInfo.InvariantCulture) + "*/"); } else { sw.WriteLine(name); sw.WriteLine(entries.Length.ToString("D4", CultureInfo.InvariantCulture)); } for (int i = 0; i < entries.Length; i++) _formatter.Write(sw, entries[i], i); } }
private ZtrFileEntry[] ExtractLittleEndianUncompressedDictionary(int count) { if (count < 0 || count > 102400) throw new ArgumentOutOfRangeException(nameof(count), count.ToString()); ZtrFileEntry[] entries = new ZtrFileEntry[count]; entries.InitializeElements(); int[] offsets = new int[count * 2]; for (int i = 0; i < count * 2; i++) offsets[i] = _br.ReadInt32(); for (int i = 0; i < count; i++) { _input.Position = offsets[i * 2]; entries[i].Key = _input.ReadNullTerminatedString(Encoding.ASCII, 1); _input.Position = offsets[i * 2 + 1]; entries[i].Value = _input.ReadNullTerminatedString(_encoding, 2); } return entries; }
private void PackLittleEndianUncompressedDictionary(ZtrFileEntry[] entries) { int count = entries.Length; byte[][] keys = new byte[count][]; byte[][] values = new byte[count][]; int[] offsets = new int[count * 2]; int index = 0; offsets[0] = 4 + count * 2 * 4; for (int i = 0; i < count; i++) { ZtrFileEntry entry = entries[i]; keys[i] = Encoding.ASCII.GetBytes(entry.Key); values[i] = (entry.IsAnimatedText ? FFXIIITextEncodingFactory.DefaultEuroEncoding.Value : _encoding).GetBytes(entry.Value); offsets[index + 1] = offsets[index++] + keys[i].Length + 1; if (index + 1 < offsets.Length) { offsets[index + 1] = offsets[index++] + values[i].Length + 2; } } _bw.Write(count); for (int i = 0; i < count * 2; i++) { _bw.Write(offsets[i]); } for (int i = 0; i < count; i++) { _bw.Write(keys[i], 0, keys[i].Length); _bw.Write((byte)0); _bw.Write(values[i], 0, values[i].Length); _bw.Write((short)0); } }
private void PackBigEndianCompressedDictionary(ZtrFileEntry[] entries) { if (entries.Length > 0) throw new NotImplementedException(); _bw.Write((int)ZtrFileType.BigEndianCompressedDictionary); ZtrFileHeader header = new ZtrFileHeader(); header.Version = 1; header.Count = entries.Length; using (MemoryStream ms = new MemoryStream(32 * 1024)) { ZtrFileKeysPacker keyPacker = new ZtrFileKeysPacker(ms, entries); keyPacker.Pack(header); ZtrFileTextPacker textPacker = new ZtrFileTextPacker(ms, entries, header, _encoding); textPacker.Pack(); } long headerPosition = _output.Position; //_output.Seek(entries.Length * 8) }
public unsafe void Pack(ZtrFileHeader header) { int uncompressedSize = 0; ushort index = 0; byte[] writeBuff = new byte[4096]; byte[] codeBuff = new byte[256]; fixed(byte *writeBuffPtr = &writeBuff[0]) fixed(byte *codeBuffPtr = &codeBuff[0]) { for (int e = 0; e < _input.Length; e++) { ZtrFileEntry entry = _input[e]; int count = Encoding.ASCII.GetBytes(entry.Key, 0, entry.Key.Length, codeBuff, 0); codeBuff[count++] = 0; for (int b = 0; b < count; b++) { writeBuffPtr[index++] = codeBuffPtr[b]; if (index == writeBuff.Length) { WriteBlock(writeBuff, ref index, ref uncompressedSize); } } } } if (index > 0) { WriteBlock(writeBuff, ref index, ref uncompressedSize); } header.KeysUnpackedSize = uncompressedSize; }
public unsafe void Pack(ZtrFileHeader header) { _blockOffset = 0; _blockNumber = 0; _innerIndex = 0; _innerCount = 0; List <int> blockOffsets = new List <int>(256) { 0 }; ZtrFileHeaderLineInfo[] lines = new ZtrFileHeaderLineInfo[_input.Length]; ushort[,] innerOffsets = new ushort[_input.Length, 2]; ushort writeIndex = 0; byte[] writeBuff = new byte[4096]; byte[] codeBuff = new byte[64 * 1024]; fixed(byte *writeBuffPtr = &writeBuff[0]) fixed(byte *codeBuffPtr = &codeBuff[0]) { for (int e = 0; e < _input.Length; e++) { _innerCount++; innerOffsets[e, 0] = writeIndex; ZtrFileEntry entry = _input[e]; int count = _encoding.GetBytes(entry.Value, 0, entry.Value.Length, codeBuff, 0); codeBuff[count++] = 0; codeBuff[count++] = 0; lines[e] = new ZtrFileHeaderLineInfo { Block = _blockNumber, BlockOffset = 0 // See below: lines[i].BlockOffset = checked ((byte)innerOffsets[i, 1]); }; for (int b = 0; b < count; b++) { writeBuffPtr[writeIndex++] = codeBuffPtr[b]; if (writeIndex == writeBuff.Length) { WriteBlock(writeBuff, ref writeIndex, innerOffsets, blockOffsets); } } } } if (writeIndex > 0) { WriteBlock(writeBuff, ref writeIndex, innerOffsets, blockOffsets); } for (int i = 0; i < innerOffsets.Length / 2; i++) { lines[i].PackedOffset = innerOffsets[i, 0]; lines[i].BlockOffset = checked ((byte)innerOffsets[i, 1]); } if (blockOffsets.Count > _blockNumber) { _blockNumber++; } header.TextBlocksCount = _blockNumber; header.TextBlockTable = blockOffsets.ToArray(); header.TextLinesTable = lines; }
public ZtrFileEntry Read(StreamReader sr, out int index) { index = -1; ZtrFileEntry result = new ZtrFileEntry(); StringBuilder sb = new StringBuilder(512); bool key = false; bool block = false; bool escape = false; int line = 0; while (true) { int value = sr.Read(); if (value < 0) { if (sb.Length == 0) { return(null); } throw Exceptions.CreateException("Неожиданный конец потока."); } char ch = (char)value; switch (ch) { case '║': { if (!block) { continue; } index = int.Parse(sb.ToString(), CultureInfo.InvariantCulture); sb.Clear(); key = true; break; } case '\\': { if (!block) { continue; } if (escape) { sb.Append('\\'); escape = false; } else { escape = true; } break; } case '"': { if (escape) { sb.Append('"'); escape = false; } else { if (block) { if (key) { result.Key = sb.ToString(); key = false; } else { result.Value = sb.ToString(); return(result); } block = false; sb.Clear(); } else { block = true; } } break; } case '\r': case '\n': { if (!block) { continue; } line++; break; } default: { if (!block) { continue; } if (line > 0) { for (int i = 0; i < (line + 1) / 2; i++) { sb.Append(Environment.NewLine); } line = 0; } sb.Append(ch); break; } } } }
private static void MergeEntries(Dictionary<string, string> newEntries, ZtrFileEntry[] targetEntries) { StringBuilder sb = new StringBuilder(1024); foreach (ZtrFileEntry entry in targetEntries) { string oldText = entry.Value; string newText; if (!newEntries.TryGetValue(entry.Key, out newText)) { Log.Warning("[ArchiveEntryInjectorStringsToZtr] Пропущена неизвестная запись {0}={1}.", entry.Key, entry.Value); continue; } entry.IsAnimatedText = TryReplaceAnimatedText(entry.Key, ref newText); GetEndingTags(oldText, sb); string oldEnding = sb.ToString(); sb.Clear(); int endingLength = GetEndingTags(newText, sb); int newLength = newText.Length - endingLength; sb.Clear(); // Восстановление старых хвостов и тегов новой строки bool cr = false; for (int i = 0; i < newLength; i++) { char ch = newText[i]; switch (ch) { case '\n': { cr = false; sb.Append(NewLineTag); break; } case '\r': { cr = true; break; } default: { if (cr) { sb.Append(NewLineTag); cr = false; } sb.Append(ch); break; } } } sb.Append(oldEnding); entry.Value = sb.ToString(); // Many, article //int nameLength = entry.Value.IndexOf('{'); //string name = nameLength < 0 ? entry.Value : entry.Value.Substring(0, nameLength); //if (oldText.Contains("{End}{Many}") && !entry.Value.Contains("{End}{Many}")) // entry.Value += ("{End}{Many}" + name); //if (oldText.Contains("{End}{Article}") && !entry.Value.Contains("{End}{Article}")) // entry.Value += ("{End}{Article}"); sb.Clear(); } }
public ZtrFileKeysUnpacker(Stream input, ZtrFileEntry[] output) { _input = input; _output = output; }
public ZtrFileKeysPacker(Stream output, ZtrFileEntry[] input) { _output = output; _input = input; }
public void Write(StreamWriter sw, ZtrFileEntry entry, int index) { sw.WriteLine("{0}║{1}║{2}", index.ToString("D4", CultureInfo.InvariantCulture), entry.Key, entry.Value); }
private ZtrFileEntry[] ExtractLittleEndianUncompressedPair() { ZtrFileEntry result = new ZtrFileEntry(); int keyOffset = _br.ReadInt32(); int textOffset = _br.ReadInt32(); _input.Position = keyOffset; result.Key = _input.ReadNullTerminatedString(Encoding.ASCII, 1); _input.Position = textOffset; result.Value = _input.ReadNullTerminatedString(_encoding, 2); return new[] {result}; }
public ZtrFileEntry Read(StreamReader sr, out int index) { index = -1; ZtrFileEntry result = new ZtrFileEntry(); StringBuilder sb = new StringBuilder(512); bool key = false; bool block = false; bool escape = false; int line = 0; while (true) { int value = sr.Read(); if (value < 0) { if (sb.Length == 0) return null; throw Exceptions.CreateException("Неожиданный конец потока."); } char ch = (char)value; switch (ch) { case '║': { if (!block) continue; index = int.Parse(sb.ToString(), CultureInfo.InvariantCulture); sb.Clear(); key = true; break; } case '\\': { if (!block) continue; if (escape) { sb.Append('\\'); escape = false; } else { escape = true; } break; } case '"': { if (escape) { sb.Append('"'); escape = false; } else { if (block) { if (key) { result.Key = sb.ToString(); key = false; } else { result.Value = sb.ToString(); return result; } block = false; sb.Clear(); } else { block = true; } } break; } case '\r': case '\n': { if (!block) continue; line++; break; } default: { if (!block) continue; if (line > 0) { for (int i = 0; i < (line + 1) / 2; i++) sb.Append(Environment.NewLine); line = 0; } sb.Append(ch); break; } } } }