static string getGearString(SavedVariablesDictionary item) { string sItemString = item["Item"] as string; char[] acSplitCharacters = { ':' }; string[] asItemElements = sItemString.Split(acSplitCharacters); if (item.ContainsKey("Gem")) { SavedVariablesDictionary gems = item["Gem"] as SavedVariablesDictionary; string sItemSlotString = asItemElements[0]; for (long lGemSlot = 1; lGemSlot <= 3; lGemSlot++) { sItemSlotString += "."; if (gems.ContainsKey(lGemSlot)) { string sGemItemString = (gems[lGemSlot] as SavedVariablesDictionary)["Item"] as string; sItemSlotString += sGemItemString.Split(acSplitCharacters)[0]; } else { sItemSlotString += "0"; } } return(sItemSlotString); } else { return(asItemElements[0] + ".0.0.0"); } }
void setTalentsFromTree(SavedVariablesDictionary characterInfo) { if (!characterInfo.ContainsKey("Talents")) { #if RAWR3 || RAWR4 || SILVERLIGHT //new ErrorWindow() { Message = "Not yet implemented." }.Show(); #else MessageBox.Show("Talent data was not found, and must be manually added.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); #endif return; } SavedVariablesDictionary talent_tree = characterInfo["Talents"] as SavedVariablesDictionary; TalentsBase Talents = m_character.CurrentTalents; if (Talents != null) { List <string> treeNames = new List <string>((string[])Talents.GetType().GetField("TreeNames").GetValue(Talents)); //TalentTree currentTree; foreach (PropertyInfo pi in Talents.GetType().GetProperties()) { TalentDataAttribute[] talentDatas = pi.GetCustomAttributes(typeof(TalentDataAttribute), true) as TalentDataAttribute[]; if (talentDatas.Length > 0) { TalentDataAttribute talentData = talentDatas[0]; int points = getTalentPointsFromTree(talent_tree, treeNames[talentData.Tree], talentData); m_character.CurrentTalents.Data[talentData.Index] = points; } } } }
/* * This function is used to help populate the optimizer list. * Rather than add every item in every bag slot, this filter is used * to try to limit the items only to equippable ones. * Note however that the current implentation is a bit of a hack * that involves searching item Tooltips. * Returns true if the item is equippable. */ /*static bool isEquippable(int itemID) * { * if (itemID > 0 && ItemCache.ContainsItemId(itemID)) * { * ItemCache.Items[itemID].Slot * string sTooltip = itemInfo["Tooltip"] as string; * } * * return false; * }*/ static int getEnchant(SavedVariablesDictionary item) { string sItemString = item["Item"] as string; char[] acSplitCharacters = { ':' }; return(Int32.Parse(sItemString.Split(acSplitCharacters)[1])); }
public CharacterProfilerData(string sFileName) { SavedVariablesDictionary savedVariables = SavedVariablesParser.parse(sFileName); if (!savedVariables.ContainsKey("myProfile")) { throw new InvalidDataException("Expected myProfile variable in file."); } SavedVariablesDictionary realms = (SavedVariablesDictionary)savedVariables["myProfile"]; foreach (string sRealm in realms.Keys) { bool bHaveCharacters = false; CharacterProfilerRealm realm = new CharacterProfilerRealm(sRealm); SavedVariablesDictionary characterContainer = (SavedVariablesDictionary)realms[sRealm]; SavedVariablesDictionary characters = (SavedVariablesDictionary)characterContainer["Character"]; foreach (string sCharacter in characters.Keys) { SavedVariablesDictionary characterInfo = (SavedVariablesDictionary)characters[sCharacter]; CharacterProfilerCharacter character = new CharacterProfilerCharacter(sCharacter, sRealm, characterInfo); realm.Characters.Add(character); bHaveCharacters = true; } if (bHaveCharacters) { m_realms.Add(realm); } } }
static void addPossessionsForOptimization(List <string> asOptimizableItems, SavedVariablesDictionary characterInfo) { string [] asSources = { "Inventory", "Bank" }; foreach (string sSource in asSources) { if (characterInfo.ContainsKey(sSource)) { SavedVariablesDictionary bags = characterInfo[sSource] as SavedVariablesDictionary; foreach (object oBag in bags.Values) { SavedVariablesDictionary bag = oBag as SavedVariablesDictionary; SavedVariablesDictionary contents = bag["Contents"] as SavedVariablesDictionary; foreach (object oItem in contents.Values) { SavedVariablesDictionary item = oItem as SavedVariablesDictionary; if (isEquippable(item)) { asOptimizableItems.Add(getGearString(item) + "." + getEnchant(item)); } } } } } }
void setTalentsFromTree(SavedVariablesDictionary characterInfo) { if (!characterInfo.ContainsKey("Talents")) { return; } SavedVariablesDictionary talent_tree = characterInfo["Talents"] as SavedVariablesDictionary; TalentsBase Talents = Character.CurrentTalents; if (Talents != null) { List <string> treeNames = new List <string>((string[])Talents.GetType().GetField("TreeNames").GetValue(Talents)); //TalentTree currentTree; foreach (PropertyInfo pi in Talents.GetType().GetProperties()) { TalentDataAttribute[] talentDatas = pi.GetCustomAttributes(typeof(TalentDataAttribute), true) as TalentDataAttribute[]; if (talentDatas.Length > 0) { TalentDataAttribute talentData = talentDatas[0]; int points = getTalentPointsFromTree(talent_tree, treeNames[talentData.Tree], talentData); Character.CurrentTalents.Data[talentData.Index] = points; } } } }
static int getTalentPointsFromTree(SavedVariablesDictionary talent_tree, string spec, TalentDataAttribute talent) { int points = 0; if (talent_tree.ContainsKey(spec)) { SavedVariablesDictionary spec_tree = talent_tree[spec] as SavedVariablesDictionary; if (spec_tree.ContainsKey(talent.Name)) { SavedVariablesDictionary talent_info = spec_tree[talent.Name] as SavedVariablesDictionary; string rank_info = talent_info["Rank"] as string; int split_pos = rank_info.IndexOf(':'); string points_str = rank_info.Remove(split_pos); points = (int)Int32.Parse(points_str); } else { Debug.WriteLine("Talent Not Found: " + talent); } } else { // we're most likely dealing with non-English data, try to determine by position in tree foreach (SavedVariablesDictionary tree in talent_tree.Values) { if ((long)tree["Order"] == talent.Tree + 1) { string loc = talent.Row + ":" + talent.Column; foreach (object t in tree.Values) { SavedVariablesDictionary td = t as SavedVariablesDictionary; if (td != null) { if ((string)td["Location"] == loc) { string rank_info = td["Rank"] as string; int split_pos = rank_info.IndexOf(':'); string points_str = rank_info.Remove(split_pos); points = (int)Int32.Parse(points_str); return(points); } } } } } Debug.WriteLine("Talent Tree Not Found: " + spec); } return(points); }
/* * public Character(string name, string realm, CharacterRegion region, CharacterRace race, * string head, string neck, string shoulders, string back, string chest, string shirt, string tabard, * string wrist, string hands, string waist, string legs, string feet, string finger1, string finger2, string trinket1, string trinket2, * string mainHand, string offHand, string ranged, string projectile, string projectileBag, * int enchantHead, int enchantShoulders, int enchantBack, int enchantChest, int enchantWrist, * int enchantHands, int enchantLegs, int enchantFeet, int enchantFinger1, int enchantFinger2, int enchantMainHand, int enchantOffHand, int enchantRanged) * */ public CharacterProfilerCharacter(string sName, string sRealm, SavedVariablesDictionary characterInfo) { m_characterInfo = characterInfo; m_sName = sName; m_sRealm = sRealm; m_iLevel = (int)(characterInfo["Level"] as long?); m_sRace = (string)characterInfo["Race"]; m_sClass = (string)characterInfo["Class"]; }
public AltoholicImporter(SavedVariablesDictionary SVCharacters, SavedVariablesDictionary SVSkills, SavedVariablesDictionary SVTalents, SavedVariablesDictionary SVInventory, SavedVariablesDictionary SVStats) { SavedVariables = new AltoholicSavedVariables(SVCharacters, SVSkills, SVTalents, SVInventory, SVStats); }
public AltoholicSavedVariables(SavedVariablesDictionary SVCharacters, SavedVariablesDictionary SVSkills, SavedVariablesDictionary SVTalents, SavedVariablesDictionary SVInventory, SavedVariablesDictionary SVStats) { Characters = SVCharacters; Skills = SVSkills; Talents = SVTalents; Inventory = SVInventory; Stats = SVStats; }
static bool addEquippedItemForOptimization(List <string> asOptimizableItems, SavedVariablesDictionary characterInfo, string sSlot) { string sItem = getGearStringBySlot(characterInfo, sSlot); if (sItem != null) { asOptimizableItems.Add(sItem + "." + getEnchantBySlot(characterInfo, sSlot)); return(true); } return(false); }
/** * This function is actually very slow and used mainly for testing, * to test the equivalence of two dictionaries. */ public bool Equivalent(SavedVariablesDictionary other) { SavedVariablesDictionary leftDictionary, rightDictionary; for (int iPass = 0; iPass < 2; iPass++) { if (iPass == 0) { leftDictionary = this; rightDictionary = other; } else { leftDictionary = other; rightDictionary = this; } // Compare every value in this instance to the other foreach (IComparable key in leftDictionary.Keys) { if (!rightDictionary.ContainsKey(key)) { return(false); } else if (leftDictionary[key] == null || rightDictionary[key] == null) { if (leftDictionary[key] != rightDictionary[key]) { return(false); } } else if (leftDictionary[key].GetType() != rightDictionary[key].GetType()) { return(false); } else if (leftDictionary[key].GetType() == typeof(SavedVariablesDictionary)) { if (!(leftDictionary[key] as SavedVariablesDictionary).Equivalent(rightDictionary[key] as SavedVariablesDictionary)) { return(false); } } else if (!leftDictionary[key].Equals(rightDictionary[key])) { return(false); } } } return(true); }
public List <String> GetCaracterList() { List <string> result = new List <string>(); if (SavedVariables != null) { SavedVariablesDictionary Chars = (SavedVariablesDictionary)((SavedVariablesDictionary)SavedVariables.Characters["global"])["Characters"]; foreach (string Char in Chars.Values) { result.Add(Char); } } return(result); }
static string getGearStringBySlot(SavedVariablesDictionary characterInfo, string sSlot) { SavedVariablesDictionary equipment = (SavedVariablesDictionary)characterInfo["Equipment"]; if (equipment.ContainsKey(sSlot)) { SavedVariablesDictionary item = equipment[sSlot] as SavedVariablesDictionary; return(getGearString(item)); } else { return(null); } }
static int getEnchantBySlot(SavedVariablesDictionary characterInfo, string sSlot) { SavedVariablesDictionary equipment = (SavedVariablesDictionary)characterInfo["Equipment"]; if (equipment.ContainsKey(sSlot)) { SavedVariablesDictionary item = equipment[sSlot] as SavedVariablesDictionary; return(getEnchant(item)); } else { return(0); } }
public static SavedVariablesDictionary parse(string sFileName) { SavedVariablesDictionary savedVariables = new SavedVariablesDictionary(); // Note -- file errors are deliberately allowed to bubble to the caller. // Note 2: This function reads in the entire file. There are undoubtedly better ways to do this. SavedVariablesFileStream stream = new SavedVariablesFileStream(sFileName); for (LuaToken variable = getNextToken(stream); variable != null; variable = getNextToken(stream)) { if (stream.getNextCharacter(false) != '=') { throw new InvalidDataException("Expected 'variable_name = value' pairs in saved variables file."); } savedVariables.Add(((LuaKeywordToken)variable).getKeyword(), getNextToken(stream).getInterpretedValue()); } /* * // Sanity check tests * // First, Save -> Reload should yield equivalent databases * // Second, Save File 1 -> Load File 1 -> Save File 2 should yield identical files * * string sExportTest = "c:\\sv\\original\\" + sFileName.Substring(sFileName.LastIndexOf('\\')); * string sReexportTest = "c:\\sv\\reexport\\" + sFileName.Substring(sFileName.LastIndexOf('\\')); * * if (sFileName != sExportTest) * { * // Test export functionality * export(sExportTest, savedVariables); * // And reimport test file * SavedVariablesDictionary reimport = parse(sExportTest); * * if (!savedVariables.Equivalent(reimport)) * { * throw new InvalidDataException("Export file does not match import file."); * } * * // And test export the reimport * export(sReexportTest, reimport); * } */ stream = null; return(savedVariables); }
/* * This function is used to help populate the optimizer list. * Rather than add every item in every bag slot, this filter is used * to try to limit the items only to equippable ones. * Note however that the current implentation is a bit of a hack * that involves searching item Tooltips. * Returns true if the item is equippable. */ static bool isEquippable(SavedVariablesDictionary itemInfo) { if (itemInfo != null && itemInfo.ContainsKey("Tooltip")) { string sTooltip = itemInfo["Tooltip"] as string; foreach (string sNeedle in s_asEquippableTooltipKeywords) { if (sTooltip.IndexOf(sNeedle) != -1) { return(true); } } } return(false); }
static bool addEquippedItemForOptimization(List <string> asOptimizableItems, SavedVariablesDictionary characterInfo, string sSlot) { string sItem = getGearStringBySlot(characterInfo, sSlot, true); if (sItem != null) { char[] acSplitCharacters = { '.' }; string[] asItemElements = sItem.Split(acSplitCharacters); if (sItem.Substring(asItemElements[0].Length) == ".*.*.*.*") { sItem = asItemElements[0]; } asOptimizableItems.Add(sItem); return(true); } return(false); }
static string getGearStringBySlot(SavedVariablesDictionary characterInfo, string sSlot, bool replaceAsterisks) { SavedVariablesDictionary equipment = (SavedVariablesDictionary)characterInfo["Equipment"]; if (equipment.ContainsKey(sSlot)) { SavedVariablesDictionary item = equipment[sSlot] as SavedVariablesDictionary; string enchant = getEnchant(item).ToString(); if (enchant == "0" && replaceAsterisks) { enchant = "*"; } return(getGearString(item, replaceAsterisks) + "." + enchant); } else { return(null); } }
/** * Saves out a SavedVariablesDictionary * Comparison against (my set of) SavedVariable files showed them * to be identical with one insignificant difference. For lua tables, * if an entry is not assigned a key, it is given one implicitly. * SavedVariable files use these implicit keys and have a comment that * follow the variables indicating which key they should have. * This class just outputs the key explicitly. * * WoW export: * { * ["a"] = 1, * ["b"] = 0.5, * ["g"] = 0.9, * ["r"] = 1, * }, -- [2] * nil, -- [3] * * SavedVariablesParser export: * [2] = { * ["a"] = 1, * ["b"] = 0.5, * ["g"] = 0.9, * ["r"] = 1, * }, * [3] = nil, * * Note the data is identical. */ public static void export(string sFileName, SavedVariablesDictionary exportData) { StreamWriter writer = new StreamWriter(sFileName); // Not sure why, but SavedVariables files seem to start // with a newline character. writer.WriteLine(); foreach (string sKey in exportData.Keys) { writer.Write(sKey + " = "); exportObject(writer, exportData[sKey], ""); writer.WriteLine(); } writer.Flush(); writer.Close(); writer = null; }
static void addPossessionsForOptimization(List <string> asOptimizableItems, SavedVariablesDictionary characterInfo) { string[] asSources = { "Inventory", "Bank" }; foreach (string sSource in asSources) { if (characterInfo.ContainsKey(sSource)) { SavedVariablesDictionary bags = characterInfo[sSource] as SavedVariablesDictionary; foreach (object oBag in bags.Values) { SavedVariablesDictionary bag = oBag as SavedVariablesDictionary; SavedVariablesDictionary contents = bag["Contents"] as SavedVariablesDictionary; foreach (object oItem in contents.Values) { SavedVariablesDictionary item = oItem as SavedVariablesDictionary; if (isEquippable(item)) { string enchant = getEnchant(item).ToString(); if (enchant == "0") { enchant = "*"; } string item2 = getGearString(item, true) + "." + enchant; char[] acSplitCharacters = { '.' }; string[] asItemElements = item2.Split(acSplitCharacters); if (item2.Substring(asItemElements[0].Length) == ".*.*.*.*") { item2 = asItemElements[0]; } asOptimizableItems.Add(item2); } } } } } }
public Character GetCharacter(string cCharacterString) { Character result = new Character() { IsLoading = false }; char[] acSplitCharacters = { '.' }; string[] asCharInfo = cCharacterString.Split(acSplitCharacters); result.Realm = asCharInfo[asCharInfo.Length - 2]; //Pull base stats Gender, Class, Level ets out of Character File SavedVariablesDictionary CharBase = (SavedVariablesDictionary)( (SavedVariablesDictionary)( (SavedVariablesDictionary)SavedVariables.Characters["global"]) ["Characters"]) [cCharacterString]; //result.Level = (int)CharBase["level"]; // Level not setable result.Name = CharBase["name"] as string; result.Class = (CharacterClass)Enum.Parse(typeof(CharacterClass), CharBase["englishClass"] as string, true); result.Race = (CharacterRace)Enum.Parse(typeof(CharacterRace), CharBase["englishRace"] as string, true); //This sets faction //Pull Equipped Invenotry out of Character File SavedVariablesDictionary Equiped = (SavedVariablesDictionary)( (SavedVariablesDictionary)( (SavedVariablesDictionary)( (SavedVariablesDictionary)SavedVariables.Inventory["global"]) ["Characters"]) [cCharacterString]) ["Inventory"]; foreach (KeyValuePair <IComparable, object> item in Equiped) { addItemToCharacter(item, result); } return(result); }
static void exportObject(StreamWriter writer, object exportData, string sIndentation) { if (exportData == null) { writer.Write("nil"); } else if (exportData.GetType() == typeof(long)) { writer.Write(exportData as long?); } else if (exportData.GetType() == typeof(int)) { writer.Write(exportData as int?); } else if (exportData.GetType() == typeof(double)) { writer.Write(string.Format("{0:G16}", exportData as double?)); } else if (exportData.GetType() == typeof(bool)) { writer.Write(((bool)exportData) ? "true" : "false"); } else if (exportData.GetType() == typeof(string)) { // Todo: // Write this more efficiently string sExportString = exportData as string; sExportString = sExportString.Replace("\0", "\\0"); sExportString = sExportString.Replace("\a", "\\a"); sExportString = sExportString.Replace("\b", "\\b"); sExportString = sExportString.Replace("\f", "\\f"); sExportString = sExportString.Replace("\n", "\\n"); sExportString = sExportString.Replace("\r", "\\r"); // For whatever reason SavedVariable files don't escape tabs. //sExportString = sExportString.Replace("\t", "\\t"); sExportString = sExportString.Replace("\v", "\\v"); sExportString = sExportString.Replace("\"", "\\\""); writer.Write('"' + sExportString + '"'); } else if (exportData.GetType() == typeof(SavedVariablesDictionary)) { SavedVariablesDictionary dict = exportData as SavedVariablesDictionary; string sInnerIndentation = sIndentation + "\t"; writer.WriteLine("{"); foreach (IComparable key in dict.Keys) { writer.Write(sInnerIndentation + "["); exportObject(writer, key, sInnerIndentation); writer.Write("] = "); exportObject(writer, dict[key], sInnerIndentation); writer.WriteLine(","); } writer.Write(sIndentation + "}"); } else { throw new InvalidDataException("Don't know how to export type: " + exportData.GetType()); } }
/* * public Character(string name, string realm, Character.CharacterRegion region, CharacterRace race, * string head, string neck, string shoulders, string back, string chest, string shirt, string tabard, * string wrist, string hands, string waist, string legs, string feet, string finger1, string finger2, string trinket1, string trinket2, * string mainHand, string offHand, string ranged, string projectile, string projectileBag, * int enchantHead, int enchantShoulders, int enchantBack, int enchantChest, int enchantWrist, * int enchantHands, int enchantLegs, int enchantFeet, int enchantFinger1, int enchantFinger2, int enchantMainHand, int enchantOffHand, int enchantRanged) * */ public CharacterProfilerCharacter(string sName, string sRealm, SavedVariablesDictionary characterInfo) { m_characterInfo = characterInfo; m_sName = sName; m_iLevel = (int)(characterInfo["Level"] as long?); m_sRace = (string)characterInfo["Race"]; m_sClass = (string)characterInfo["Class"]; m_character = new Character(sName, sRealm, Character.CharacterRegion.US, // Have to figure out if I know the region s_stringToRace[characterInfo["Race"] as string], getGearStringBySlot(characterInfo, "Head"), getGearStringBySlot(characterInfo, "Neck"), getGearStringBySlot(characterInfo, "Shoulder"), getGearStringBySlot(characterInfo, "Back"), getGearStringBySlot(characterInfo, "Chest"), getGearStringBySlot(characterInfo, "Shirt"), getGearStringBySlot(characterInfo, "Tabard"), getGearStringBySlot(characterInfo, "Wrist"), getGearStringBySlot(characterInfo, "Hands"), getGearStringBySlot(characterInfo, "Waist"), getGearStringBySlot(characterInfo, "Legs"), getGearStringBySlot(characterInfo, "Feet"), getGearStringBySlot(characterInfo, "Finger0"), getGearStringBySlot(characterInfo, "Finger1"), getGearStringBySlot(characterInfo, "Trinket0"), getGearStringBySlot(characterInfo, "Trinket1"), getGearStringBySlot(characterInfo, "MainHand"), getGearStringBySlot(characterInfo, "SecondaryHand"), getGearStringBySlot(characterInfo, "Ranged"), getGearStringBySlot(characterInfo, "Ammo"), null, // Not sure what projectile bag is called getEnchantBySlot(characterInfo, "Head"), getEnchantBySlot(characterInfo, "Shoulder"), getEnchantBySlot(characterInfo, "Back"), getEnchantBySlot(characterInfo, "Chest"), getEnchantBySlot(characterInfo, "Wrist"), getEnchantBySlot(characterInfo, "Hands"), getEnchantBySlot(characterInfo, "Legs"), getEnchantBySlot(characterInfo, "Feet"), getEnchantBySlot(characterInfo, "Finger0"), getEnchantBySlot(characterInfo, "Finger1"), getEnchantBySlot(characterInfo, "MainHand"), getEnchantBySlot(characterInfo, "SecondaryHand"), getEnchantBySlot(characterInfo, "Ranged")); // Populate available items // Note that some of these items cannot be enchanted // But they should correctly return ".0" for their enchants. List <string> asOptimizableItems = new List <string>(); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Head"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Neck"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Shoulder"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Back"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Chest"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Shirt"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Tabard"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Wrist"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Hands"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Waist"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Legs"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Feet"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Finger0"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Finger1"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Trinket0"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Trinket1"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "MainHand"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "SecondaryHand"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Ranged"); addEquippedItemForOptimization(asOptimizableItems, characterInfo, "Ammo"); addPossessionsForOptimization(asOptimizableItems, characterInfo); m_character.AvailableItems = asOptimizableItems; }
public LuaTableToken(SavedVariablesDictionary values) : base(LuaTokenTypes.LUA_TABLE) { m_values = values; }
private static LuaToken getNextToken(SavedVariablesFileStream stream) { // Note: // The general rule on the true/false parameter of getNextCharacter/peekNextCharacter. // That boolean indicates whether the function should parse out comments & white-spaces // from the next possible character. While it's useful to ignore those characters // when talking about separators between keywords, those characters should not // be ignored when the next keyword is being processed. Imagine the following // example: // var1 = 0xc0 // ffee = 72 // In this case, if we were processing the numer '0xc0' and asked for the next // character ignoring white spaces, 'ffee' would be appended letting var1 = 0xc0ffee // when in actuality ffee is the name of the next keyword / variable. char?cCharacter = stream.getNextCharacter(false); if (cCharacter == null) { return(null); } if ((cCharacter >= '0' && cCharacter <= '9') || (cCharacter == '-' || cCharacter == '+')) { char?cNextCharacter = stream.peekNextCharacter(true); // Numeric token if (cCharacter == '0' && cNextCharacter != null && Char.ToUpper((char)cNextCharacter) == 'X') { // Hexadecimal character long lValue = 0; // Consume 'X' stream.getNextCharacter(true); while (true) { cNextCharacter = stream.peekNextCharacter(true); if (cNextCharacter != null && Char.ToUpper((char)cNextCharacter) >= 'A' && Char.ToUpper((char)cNextCharacter) <= 'F') { lValue = lValue * 16 + (10 + (char)cNextCharacter - 'A'); } else if (cNextCharacter >= '0' && (char)cNextCharacter <= '9') { lValue = lValue * 16 + (char)cNextCharacter - '0'; } else { break; } // Consume the character we just read in stream.getNextCharacter(true); } return(new LuaIntegerToken(lValue)); } else { // Numeric token -- scan for the whole string then choose the number format String sValue = null; bool bIsInteger = true; sValue += cCharacter; while (true) { cNextCharacter = stream.peekNextCharacter(true); if (cNextCharacter == 'e' || cNextCharacter == 'E' || cNextCharacter == '.' || cNextCharacter == '-') { bIsInteger = false; } else if (!(cNextCharacter >= '0' && cNextCharacter <= '9')) { break; } sValue += cNextCharacter; // Consume the character we just read in stream.getNextCharacter(true); } if (bIsInteger) { return(new LuaIntegerToken(Int64.Parse(sValue))); } else { return(new LuaDoubleToken(Double.Parse(sValue, System.Globalization.CultureInfo.InvariantCulture))); } } } else if (cCharacter == '"' || cCharacter == '\'') { string sValue = ""; while (true) { char?cNextCharacter = stream.getNextCharacter(true); // String terminates when it ends with the same character // it began with (i.e. ' is needed to close ', and " for ") if (cNextCharacter == cCharacter) { break; } else if (cNextCharacter == null) { throw new InvalidDataException("Unterminated lua string."); } else if (cNextCharacter == '\\') { // Escape the next character... Read it in whatever it is. cNextCharacter = stream.getNextCharacter(true); switch (cNextCharacter) { case '0': cNextCharacter = '\0'; break; case 'a': cNextCharacter = '\a'; break; case 'b': cNextCharacter = '\b'; break; case 'f': cNextCharacter = '\f'; break; case 'n': cNextCharacter = '\n'; break; case 'r': cNextCharacter = '\r'; break; case 't': cNextCharacter = '\t'; break; case 'v': cNextCharacter = '\v'; break; case '\'': case '\"': // These types pass through break; default: // If it's an escape sequence we don't understand // just reproduce it. Sometimes it's not properly formatted // strings (e.g. !Swatter had some paths that used the '\' from // the path separator without escape codes) sValue += '\\'; break; } } sValue += cNextCharacter; } return(new LuaStringToken(sValue)); } else if (cCharacter == '[') { LuaToken key = getNextToken(stream); if (key == null) { throw new InvalidDataException("Expected a field identifier after ["); } else if (stream.getNextCharacter(false) != ']') { throw new InvalidDataException("Expected a ] after field key"); } else if (stream.getNextCharacter(false) != '=') { throw new InvalidDataException("Expected a value after field key"); } else { LuaToken value = getNextToken(stream); if (value == null) { throw new InvalidDataException("Expected value after [" + key + "] = "); } return(new LuaFieldToken(key, value.getInterpretedValue())); } } else if (cCharacter == '{') { SavedVariablesDictionary items = new SavedVariablesDictionary(); long lAnonymousKey = 1; while (true) { char?cNextCharacter = stream.peekNextCharacter(false); if (cNextCharacter == null) { throw new InvalidDataException("Unterminated lua table (no '}' after '{' in file)."); } else if (cNextCharacter == '}') { // Consume the close brackets stream.getNextCharacter(false); break; } else if (cNextCharacter == ',' || cNextCharacter == ';') { stream.getNextCharacter(false); } else { LuaToken nextToken = getNextToken(stream); if (nextToken == null) { throw new InvalidDataException("Unterminated lua table (no '}' after '{' in file)."); } // Case 1: [key] = value pair if (nextToken.getTokenType() == LuaTokenTypes.LUA_FIELD) { items.Add(((LuaFieldToken)nextToken).getKeyValueKey(), ((LuaFieldToken)nextToken).getKeyValueValue()); } else if (stream.peekNextCharacter(false) == '=') // Case 2: key = value pair { // Consume the '=' stream.getNextCharacter(false); switch (nextToken.getTokenType()) { case LuaTokenTypes.LUA_INTEGER: case LuaTokenTypes.LUA_KEYWORD: case LuaTokenTypes.LUA_STRING: items.Add((IComparable)nextToken.getValue(), getNextToken(stream).getInterpretedValue()); break; default: throw new InvalidDataException("Don't know how to hash by " + nextToken.getTokenType() + " token type."); } } else // Case 3: value { items.Add(lAnonymousKey++, nextToken.getInterpretedValue()); } } } return(new LuaTableToken(items)); } else if ((cCharacter >= 'a' && cCharacter <= 'z') || (cCharacter >= 'A' && cCharacter <= 'Z') || cCharacter == '_') { string sKeyword = null; sKeyword += cCharacter; while (true) { char?cNextCharacter = stream.peekNextCharacter(true); if ((cNextCharacter >= 'a' && cNextCharacter <= 'z') || (cNextCharacter >= 'A' && cNextCharacter <= 'Z') || (cNextCharacter >= '0' && cNextCharacter <= '9') || cNextCharacter == '_') { sKeyword += stream.getNextCharacter(true); } else { return(new LuaKeywordToken(sKeyword)); } } } throw new InvalidDataException("Can't parse string " + stream.getErrorContext()); }