//----------------------------------------------
// NGUI: Next-Gen UI kit
// Copyright © 2011-2016 Tasharen Entertainment
//----------------------------------------------
using UnityEngine;
using System.Text;
using System.Collections.Generic;
using System.IO;
///
/// MemoryStream.ReadLine has an interesting oddity: it doesn't always advance the stream's position by the correct amount:
/// http://social.msdn.microsoft.com/Forums/en-AU/Vsexpressvcs/thread/b8f7837b-e396-494e-88e1-30547fcf385f
/// Solution? Custom line reader with the added benefit of not having to use streams at all.
///
public class ByteReader
{
byte[] mBuffer;
int mOffset = 0;
public ByteReader (byte[] bytes) { mBuffer = bytes; }
public ByteReader (TextAsset asset) { mBuffer = asset.bytes; }
///
/// Read the contents of the specified file and return a Byte Reader to work with.
///
static public ByteReader Open (string path)
{
#if UNITY_EDITOR || (!UNITY_FLASH && !NETFX_CORE && !UNITY_WP8 && !UNITY_WP_8_1)
FileStream fs = File.OpenRead(path);
if (fs != null)
{
fs.Seek(0, SeekOrigin.End);
byte[] buffer = new byte[fs.Position];
fs.Seek(0, SeekOrigin.Begin);
fs.Read(buffer, 0, buffer.Length);
fs.Close();
return new ByteReader(buffer);
}
#endif
return null;
}
///
/// Whether the buffer is readable.
///
public bool canRead { get { return (mBuffer != null && mOffset < mBuffer.Length); } }
///
/// Read a single line from the buffer.
///
static string ReadLine (byte[] buffer, int start, int count)
{
#if UNITY_FLASH
// Encoding.UTF8 is not supported in Flash :(
StringBuilder sb = new StringBuilder();
int max = start + count;
for (int i = start; i < max; ++i)
{
byte byte0 = buffer[i];
if ((byte0 & 128) == 0)
{
// If an UCS fits 7 bits, its coded as 0xxxxxxx. This makes ASCII character represented by themselves
sb.Append((char)byte0);
}
else if ((byte0 & 224) == 192)
{
// If an UCS fits 11 bits, it is coded as 110xxxxx 10xxxxxx
if (++i == count) break;
byte byte1 = buffer[i];
int ch = (byte0 & 31) << 6;
ch |= (byte1 & 63);
sb.Append((char)ch);
}
else if ((byte0 & 240) == 224)
{
// If an UCS fits 16 bits, it is coded as 1110xxxx 10xxxxxx 10xxxxxx
if (++i == count) break;
byte byte1 = buffer[i];
if (++i == count) break;
byte byte2 = buffer[i];
if (byte0 == 0xEF && byte1 == 0xBB && byte2 == 0xBF)
{
// Byte Order Mark -- generally the first 3 bytes in a Windows-saved UTF-8 file. Skip it.
}
else
{
int ch = (byte0 & 15) << 12;
ch |= (byte1 & 63) << 6;
ch |= (byte2 & 63);
sb.Append((char)ch);
}
}
else if ((byte0 & 248) == 240)
{
// If an UCS fits 21 bits, it is coded as 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
if (++i == count) break;
byte byte1 = buffer[i];
if (++i == count) break;
byte byte2 = buffer[i];
if (++i == count) break;
byte byte3 = buffer[i];
int ch = (byte0 & 7) << 18;
ch |= (byte1 & 63) << 12;
ch |= (byte2 & 63) << 6;
ch |= (byte3 & 63);
sb.Append((char)ch);
}
}
return sb.ToString();
#else
return Encoding.UTF8.GetString(buffer, start, count);
#endif
}
///
/// Read a single line from the buffer.
///
public string ReadLine () { return ReadLine(true); }
///
/// Read a single line from the buffer.
///
public string ReadLine (bool skipEmptyLines)
{
int max = mBuffer.Length;
// Skip empty characters
if (skipEmptyLines)
{
while (mOffset < max && mBuffer[mOffset] < 32) ++mOffset;
}
int end = mOffset;
if (end < max)
{
for (; ; )
{
if (end < max)
{
int ch = mBuffer[end++];
if (ch != '\n' && ch != '\r') continue;
}
else ++end;
string line = ReadLine(mBuffer, mOffset, end - mOffset - 1);
mOffset = end;
return line;
}
}
mOffset = max;
return null;
}
///
/// Assume that the entire file is a collection of key/value pairs.
///
public Dictionary ReadDictionary ()
{
Dictionary dict = new Dictionary();
char[] separator = new char[] { '=' };
while (canRead)
{
string line = ReadLine();
if (line == null) break;
if (line.StartsWith("//")) continue;
#if UNITY_FLASH
string[] split = line.Split(separator, System.StringSplitOptions.RemoveEmptyEntries);
#else
string[] split = line.Split(separator, 2, System.StringSplitOptions.RemoveEmptyEntries);
#endif
if (split.Length == 2)
{
string key = split[0].Trim();
string val = split[1].Trim().Replace("\\n", "\n");
dict[key] = val;
}
}
return dict;
}
static BetterList mTemp = new BetterList();
///
/// Read a single line of Comma-Separated Values from the file.
///
public BetterList ReadCSV ()
{
mTemp.Clear();
string line = "";
bool insideQuotes = false;
int wordStart = 0;
while (canRead)
{
if (insideQuotes)
{
string s = ReadLine(false);
if (s == null) return null;
s = s.Replace("\\n", "\n");
line += "\n" + s;
}
else
{
line = ReadLine(true);
if (line == null) return null;
line = line.Replace("\\n", "\n");
wordStart = 0;
}
for (int i = wordStart, imax = line.Length; i < imax; ++i)
{
char ch = line[i];
if (ch == ',')
{
if (!insideQuotes)
{
mTemp.Add(line.Substring(wordStart, i - wordStart));
wordStart = i + 1;
}
}
else if (ch == '"')
{
if (insideQuotes)
{
if (i + 1 >= imax)
{
mTemp.Add(line.Substring(wordStart, i - wordStart).Replace("\"\"", "\""));
return mTemp;
}
if (line[i + 1] != '"')
{
mTemp.Add(line.Substring(wordStart, i - wordStart).Replace("\"\"", "\""));
insideQuotes = false;
if (line[i + 1] == ',')
{
++i;
wordStart = i + 1;
}
}
else ++i;
}
else
{
wordStart = i + 1;
insideQuotes = true;
}
}
}
if (wordStart < line.Length)
{
if (insideQuotes) continue;
mTemp.Add(line.Substring(wordStart, line.Length - wordStart));
}
return mTemp;
}
return null;
}
}