private int NextStringLoc(int stringLoc) { UInt16 sz = BinUtils.Get2ByteNumberAtLocation(stringLoc + 4, mData); int retVal = sz + stringLoc; return(retVal); }
/// <summary> /// String size seem to be always be a multiple of 4. With 4-6 'zero bytes' at the end /// </summary> /// <param name="stringId">the id of the string to modify</param> /// <param name="newValue">the new value</param> /// <returns>The string location, -1 if not found</returns> public int SetString(string stringId, string newValue) { uint hashId = GetHashId(stringId); StringBuilder sb = new StringBuilder(20); int stringLoc = GetString(hashId, sb); string prevValue = sb.ToString(); if (stringLoc > 0 && prevValue != newValue) { UInt32 oldSz = BinUtils.Get2ByteNumberAtLocation(stringLoc + 4, mData); UInt16 sz = (UInt16)((newValue.Length * 2) + 2 + 4 + 4); // 2:size info 4:hashId 4 min zero bytes if (sz % 4 != 0) { sz += (UInt16)2; } bool sixZeros = false; int diff = (int)(sz - oldSz); //2 * (newValue.Length - prevValue.Length); if (diff % 4 != 0) { diff = diff + 2; sixZeros = true; } int dataEnd = mData.Count + diff; if (diff > 0) { AddBytes(diff); ShiftDataDown(stringLoc, diff, dataEnd); } else if (diff < 0) { ShiftDataUp(stringLoc, -1 * diff, dataEnd); } //write hashId BinUtils.WriteNumberAtLocation(stringLoc, hashId, mData); // write the size BinUtils.Write2ByteNumberAtLocation(stringLoc + 4, sz, mData); // lay down string stringLoc += 6; /** MODIFYING 'stringLoc' NOW!! **/ for (int i = 0; i < newValue.Length; i++) { BinUtils.Write2ByteNumberAtLocation(stringLoc, newValue[i], mData); stringLoc += 2; } BinUtils.WriteNumberAtLocation(stringLoc, 0, mData); if (sixZeros) { BinUtils.Write2ByteNumberAtLocation(stringLoc + 4, 0, mData); } AddBodySize(diff); } return(stringLoc); }
/// <summary> /// Places the string with the given hashid into the stringbuilder passed in. /// String ids can be present multiple times. This will return the last occurance /// of the string. /// </summary> /// <param name="hashId"></param> /// <param name="sb">string will be added to the builder</param> /// <returns>The location of the string id, -1 if not found </returns> public int GetString(UInt32 hashId, StringBuilder sb) { int stringLoc = (int)BodyStart; int occurance = 0; int target_occurance = 1; if (mStringSet2 != null && mStringSet2.ContainsKey(hashId)) { target_occurance++; } UInt32 currentHash = 0; while (true) { currentHash = BinUtils.GetNumberAtLocation(stringLoc, mData); if (currentHash == hashId) { occurance++; if (occurance == target_occurance) { break; } } stringLoc = NextStringLoc(stringLoc); if (stringLoc + 10 > mData.Count) { return(-1); } } UInt16 sz = BinUtils.Get2ByteNumberAtLocation(stringLoc + 4, mData); int byteStart = stringLoc + 6; int byteEnd = stringLoc + sz - 1; char current = '\0'; for (int i = byteStart; i < byteEnd; i += 2) { current = (char)BinUtils.Get2ByteNumberAtLocation(i, mData); if (current != '\0') { sb.Append(current); } } return(stringLoc); }
public string GetAllStrings() { /*bool debug = true; * UInt16 prevSz = 0; * int prevLoc = 0; debug stuff*/ mStringSet = new Dictionary <uint, string>(2000); mStringSet2 = new Dictionary <uint, string>(200); StringBuilder cur = new StringBuilder(80); StringBuilder sb = new StringBuilder(50 * 3200); int stringLoc = (int)BodyStart; UInt32 currentHash = 0; UInt16 sz = 0; int byteStart = 0; int byteEnd = 0; char current = '\0'; string stringId = ""; while ((currentHash = BinUtils.GetNumberAtLocation(stringLoc, mData)) > 0) { stringId = HashHelper.GetStringFromHash(currentHash); if (stringId == null) { stringId = String.Format("0x{0:x6}", currentHash); } sb.Append(stringId); sb.Append("=\""); sz = BinUtils.Get2ByteNumberAtLocation(stringLoc + 4, mData); //Console.WriteLine("GetAllStrings: Size={0}", sz); byteStart = stringLoc + 6; byteEnd = stringLoc + sz - 1; current = '\0'; for (int i = byteStart; i < byteEnd; i += 2) { current = (char)BinUtils.Get2ByteNumberAtLocation(i, mData); if (current == '"') { sb.Append("\\\""); // escape the quote cur.Append("\\\""); } else if (current == '\\') { sb.Append("\\\\"); // escape the escape! cur.Append("\\\\"); } else if (current != '\0') { sb.Append(current); cur.Append(current); } } if (currentHash != 0xffffffff) { if (mStringSet.ContainsKey(currentHash)) { if (!mStringSet2.ContainsKey(currentHash)) { mStringSet2.Add(currentHash, cur.ToString()); } else { Console.WriteLine("Sorry, not showing 3+ instances of string 0x{0:x}:'{1}'", currentHash, cur.ToString()); } //Console.WriteLine("Error! key 0x{0:x} ({1}) already exists as: {2}", currentHash, stringId, mStringSet[currentHash]); //Console.WriteLine("Cannot add {0}:{1}",stringId, cur.ToString() ); } else { mStringSet.Add(currentHash, cur.ToString()); } } /*if (debug && cur.Length == 0) * Console.WriteLine("MT, sz:0x{0:x2} pos:0x{1:x6} prevSz:0x{2:x2} prevPos:0x{3:x6}", sz, stringLoc, prevSz, prevLoc); * prevLoc = stringLoc; // TODO remove these 2 after debugging * prevSz = sz; */ cur.Length = 0; // clear sb.Append("\"\n"); stringLoc = NextStringLoc(stringLoc); if (stringLoc + 10 > mData.Count) // for a string you need minimum 4 bytes for the hash, 2 for size and 4 for nulls { break; } } //Console.WriteLine("mStringSet2.Count:{0}",mStringSet2.Count); return(sb.ToString()); }