Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
            }
        }
Beispiel #3
0
        private void PackBigEndianCompressedDictionary(ZtrFileEntry[] entries)
        {
            if (entries.Length > 0)
                throw new NotImplementedException();

            _bw.Write((int)ZtrFileType.BigEndianCompressedDictionary);
        }
Beispiel #4
0
 public ZtrFileTextPacker(Stream output, ZtrFileEntry[] input, ZtrFileHeader header, FFXIIITextEncoding encoding)
 {
     _output = output;
     _input = input;
     _header = header;
     _encoding = encoding;
 }
Beispiel #5
0
 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;
 }
Beispiel #7
0
 public void Pack(ZtrFileEntry[] entries)
 {
     if (entries.Length == 0)
         PackBigEndianCompressedDictionary(entries);
     else if (entries.Length == 1)
         PackLittleEndianUncompressedPair(entries[0]);
     else
         PackLittleEndianUncompressedDictionary(entries);
 }
Beispiel #8
0
        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 });
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        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);
        }
Beispiel #11
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;
        }
Beispiel #12
0
        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());
            }
        }
Beispiel #13
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);
        }
Beispiel #14
0
        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);
            }
        }
Beispiel #15
0
        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;
        }
Beispiel #16
0
        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);
            }
        }
Beispiel #17
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)
        }
Beispiel #18
0
        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;
        }
Beispiel #19
0
        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;
        }
Beispiel #20
0
        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();
            }
        }
Beispiel #22
0
 public ZtrFileKeysUnpacker(Stream input, ZtrFileEntry[] output)
 {
     _input = input;
     _output = output;
 }
Beispiel #23
0
 public ZtrFileKeysPacker(Stream output, ZtrFileEntry[] input)
 {
     _output = output;
     _input = input;
 }
Beispiel #24
0
 public void Write(StreamWriter sw, ZtrFileEntry entry, int index)
 {
     sw.WriteLine("{0}║{1}║{2}", index.ToString("D4", CultureInfo.InvariantCulture), entry.Key, entry.Value);
 }
Beispiel #25
0
 public void Write(StreamWriter sw, ZtrFileEntry entry, int index)
 {
     sw.WriteLine("{0}║{1}║{2}", index.ToString("D4", CultureInfo.InvariantCulture), entry.Key, entry.Value);
 }
Beispiel #26
0
        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};
        }
Beispiel #27
0
 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("\"", "\\\""));
 }
Beispiel #28
0
        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;
                    }
                }
            }
        }