/** * Appends C# code to write a string to the byte buffer. */ public static void AppendWriteString(ref string code, string varName) { string sizeFieldName = PB.CreateRandomFieldName("stringLength"); code += " uint " + sizeFieldName + ";\r\n"; PBUV.AppendGetUnsignedVariantSize(ref code, varName + ".Length", sizeFieldName, "uint", 2); AppendWriteString(ref code, varName, sizeFieldName); }
/** * Append C# code to read a UTF-8 string from the byte buffer. */ public static void AppendReadString(ref string code, string varName) { string stringLengthFieldName = PB.CreateRandomFieldName("stringLength"); AppendReadVariant(ref code, stringLengthFieldName, "ushort", "ushort", 2); code += " " + varName + " = Encoding.UTF8.GetString(bytes, index, " + stringLengthFieldName + ");\r\n"; code += " index += " + stringLengthFieldName + ";\r\n"; }
/** * Append C# code to write a double to the byte buffer. */ public static void AppendWriteDouble(ref string code, string varName) { string doubleFieldName = PB.CreateRandomFieldName("double"); string doubleAsULongFieldName = PB.CreateRandomFieldName("doubleAsULong"); code += " double " + doubleFieldName + " = " + varName + ";\r\n"; code += " ulong " + doubleAsULongFieldName + ";\r\n"; code += " unsafe {\r\n"; code += " " + doubleAsULongFieldName + " = *((ulong*)&(" + doubleFieldName + "));\r\n"; code += " }\r\n"; AppendWriteWhole(ref code, doubleAsULongFieldName, 8); }
/** * Append C# code to read a double from the byte buffer. */ public static void AppendReadDouble(ref string code, string varName) { string doubleFieldName = PB.CreateRandomFieldName("double"); string doubleAsUintFieldName = PB.CreateRandomFieldName("doubleAsUInt"); AppendReadWhole(ref code, "ulong " + doubleAsUintFieldName, 8, "ulong"); code += " double " + doubleFieldName + ";\r\n"; code += " unsafe {\r\n"; code += " " + doubleFieldName + " = *((double*)&(" + doubleAsUintFieldName + "));\r\n"; code += " }\r\n"; code += " " + varName + " = " + doubleFieldName + ";\r\n"; }
/** * Append C# code to read a float from the byte buffer. */ public static void AppendReadFloat(ref string code, string varName) { string floatFieldName = PB.CreateRandomFieldName("float"); string floatAsUintFieldName = PB.CreateRandomFieldName("floatAsUInt"); AppendReadWhole(ref code, "uint " + floatAsUintFieldName, 4, "uint"); code += " float " + floatFieldName + ";\r\n"; code += " unsafe {\r\n"; code += " " + floatFieldName + " = *((float*)&(" + floatAsUintFieldName + "));\r\n"; code += " }\r\n"; code += " " + varName + " = " + floatFieldName + ";\r\n"; }
/** * Appends C# code to compute a signed variant's byte size. */ private static string AppendGetSignVariantSize(ref string code, string varName) { string resultFieldName = PB.CreateRandomFieldName("vr"); string v = PB.CreateRandomFieldName("v"); code += " byte " + resultFieldName + " = 1;\r\n"; code += " for (int " + v + " = 56; " + v + " >= 0; " + v + " -= 8) {\r\n"; code += " if (((255UL << " + v + ") & " + varName + ") > 0) {\r\n"; code += " " + resultFieldName + " = (byte)(" + v + " / 8 + 2);\r\n"; code += " break;\r\n"; code += " }\r\n"; code += " }\r\n"; return(resultFieldName); }
/** * Appends C# code to write a variable-length whole value to the byte buffer. Shared across multiple types. */ public static void AppendWriteVariantInner(ref string code, string byteCountVarName) { string i = PB.CreateRandomFieldName("i"); code += " for (int " + i + " = 0; " + i + " < " + byteCountVarName + "; " + i + "++) {\r\n"; code += " if (" + i + " < " + byteCountVarName + " - 1) {\r\n"; code += " byte b = (byte)(value & 127);\r\n"; code += " if (" + i + " < " + byteCountVarName + " - 1) {\r\n"; code += " b += 128;\r\n"; code += " }\r\n"; code += " bytes[index++] = b;\r\n"; code += " value = value >> 7;\r\n"; code += " }\r\n"; code += " else {\r\n"; code += " bytes[index++] = (byte)value;\r\n"; code += " value = value >> 8;\r\n"; code += " }\r\n"; code += " }\r\n"; }
/** * Append C# code to write a variable-length signed whole number to the byte buffer. */ public static void AppendReadVInt(ref string code, string varName, string typeName) { // First byte string byteFieldName = PB.CreateRandomFieldName("rv" + typeName + "_b"); code += " byte " + byteFieldName + " = bytes[index++];\r\n"; // Sign string signFieldName = PB.CreateRandomFieldName("rv" + typeName + "_sign"); code += " byte " + signFieldName + " = (byte)(" + byteFieldName + " & 1);\r\n"; // Size string sizeFieldName = PB.CreateRandomFieldName("rv" + typeName + "_size"); code += " byte " + sizeFieldName + " = (byte)(" + byteFieldName + " >> 1);\r\n"; // Remaining bytes string remainingFieldName = PB.CreateRandomFieldName("rv" + typeName + "_remaining"); code += " ulong " + remainingFieldName + " = 0;\r\n"; string i = PB.CreateRandomFieldName("i"); code += " for (int " + i + " = 0; " + i + " < " + sizeFieldName + " - 1; " + i + "++) {\r\n"; code += " " + remainingFieldName + " = " + remainingFieldName + " | (((ulong)bytes[index++] << (8 * " + i + ")));\r\n"; code += " }\r\n"; // Make long string resultFieldName = PB.CreateRandomFieldName("rv" + typeName + "_result"); code += " " + typeName + " " + resultFieldName + " = (" + typeName + ")" + remainingFieldName + ";\r\n"; // Invert code += " " + resultFieldName + " = ~" + resultFieldName + ";\r\n"; // Swap in MIN for MAX code += " if (" + resultFieldName + " == " + typeName + ".MaxValue) {\r\n"; code += " " + resultFieldName + " = " + typeName + ".MinValue;\r\n"; code += " }\r\n"; code += " else {\r\n"; code += " // Add offset\r\n"; code += " " + resultFieldName + " += 1;\r\n"; // If positive, negate code += " if (" + signFieldName + " == 0) {\r\n"; code += " " + resultFieldName + " = -" + resultFieldName + ";\r\n"; code += " }\r\n"; code += " }\r\n"; code += " " + varName + " = " + resultFieldName + ";\r\n"; }
/** * Append C# code to write a variable-length signed long to the byte buffer. */ public static void AppendWriteVInt64(ref string code, string varName) { // Make ulong code += " //// AppendSignedToULong(" + varName + ")\r\n"; string signedToULongFieldName = AppendSignedToULong(ref code, varName); // Get size code += " //// AppendGetSignVariantSize(" + signedToULongFieldName + ")\r\n"; string signedVariantSizeFieldName = AppendGetSignVariantSize(ref code, signedToULongFieldName); // First byte code += " bytes[index++] = (byte)((byte)(" + signedVariantSizeFieldName + " << 1) | (byte)(" + varName + " > 0 ? 0 : 1));\r\n"; // Remaining bytes string i = PB.CreateRandomFieldName("vi"); code += " for (int " + i + " = 0; " + i + " < " + signedVariantSizeFieldName + " - 1; " + i + "++) {\r\n"; code += " bytes[index++] = (byte)(" + signedToULongFieldName + " & 255);\r\n"; code += " " + signedToULongFieldName + " = " + signedToULongFieldName + " >> 8;\r\n"; code += " }\r\n"; }
/** * Reads an unsugned variant of type "type" and max byte size "maxBytes" into a variable named "varName". */ public static void AppendReadVariant(ref string code, string varName, string type, string castTo, int maxBytes) { string readVariantTemp = PB.CreateRandomFieldName("vuread"); code += " ulong " + readVariantTemp + " = 0;\r\n"; string i = PB.CreateRandomFieldName("i"); code += " for (int " + i + " = 0; " + i + " < 9; " + i + "++) {\r\n"; code += " byte b = bytes[index++];\r\n"; code += " if (" + i + " < 8) {\r\n"; code += " " + readVariantTemp + " += (((ulong)b & (ulong)127) << (7 * " + i + "));\r\n"; code += " if ((int)(b & 128) == 0) {\r\n"; code += " break;\r\n"; code += " }\r\n"; code += " }\r\n"; code += " else {\r\n"; code += " " + readVariantTemp + " += (ulong)b << (7 * " + i + ");\r\n"; code += " break;\r\n"; code += " }\r\n"; code += " }\r\n"; code += " " + (type != null ? type + " " : "") + varName + " = " + (castTo != null ? "(" + castTo + ")" : "") + readVariantTemp + ";\r\n"; }
/** * Appends C# code to convert a signed integer or long to variant ulong form. */ private static string AppendSignedToULong(ref string code, string varName) { //internal static ulong SignedToULong(long value) { string tempFieldName = PB.CreateRandomFieldName("s2ultemp"); string resultFieldName = PB.CreateRandomFieldName("s2ulresult"); code += " long " + tempFieldName + " = " + varName + ";\r\n"; // Swap MAX in for MIN code += " if (" + tempFieldName + " == long.MinValue) {\r\n"; code += " " + tempFieldName + " = long.MaxValue;\r\n"; code += " }\r\n"; code += " else {\r\n"; // If positive, negate code += " if (" + tempFieldName + " > 0) {\r\n"; code += " " + tempFieldName + " = -" + tempFieldName + ";\r\n"; code += " }\r\n"; // Add offset code += " " + tempFieldName + " -= 1;\r\n"; code += " }\r\n"; // Invert code += " " + tempFieldName + " = ~" + tempFieldName + ";\r\n"; code += " ulong " + resultFieldName + " = (ulong)" + tempFieldName + ";\r\n"; return(resultFieldName); }