/// <summary> /// serialize an item (field/global param/...) to an XML format (applicable to be passed to the server). /// </summary> /// <param name = "itemVal">item's value</param> /// <param name = "itemAttr">item's attribute</param> /// <param name = "cellAttr">cell's attribute - relevant only if 'itemAttr' is vector</param> /// <param name = "toBase64">decide Base64 encoding is to be done</param> /// <returns>serialized buffer</returns> public static String serializeItemVal(String itemVal, StorageAttribute itemAttr, StorageAttribute cellAttr, bool toBase64) { Debug.Assert(itemVal != null); int significantNumSize = Manager.Environment.GetSignificantNumSize() * 2; String valueSize; int j; var tmpBuf = new StringBuilder(); // for alpha type add the length of the value as hex number of 4 digits switch (itemAttr) { case StorageAttribute.NUMERIC: case StorageAttribute.DATE: case StorageAttribute.TIME: itemVal = !toBase64 ? itemVal.Substring(0, significantNumSize) : Base64.encode(byteStreamToString(itemVal.Substring(0, significantNumSize)), Manager.Environment.GetEncoding()); break; case StorageAttribute.ALPHA: case StorageAttribute.UNICODE: itemVal = StrUtil.rtrim(itemVal); int pos = 0; int fldValLen = itemVal.Length; do { int nullChrPos = itemVal.IndexOf((Char)0, pos); if (nullChrPos == -1) { valueSize = (Convert.ToString(fldValLen - pos, 16)).ToUpper(); // add leading zeros (if needed) for (j = 0; j < 4 - valueSize.Length; j++) { tmpBuf.Append('0'); } tmpBuf.Append(valueSize); if (pos > 0) { itemVal = itemVal.Substring(pos, (fldValLen) - (pos)); } pos = fldValLen; } else { // If NULL chars exist in the middle of the value - create a spanned record // Turn on the high most bit in the length (to indicate a segment) valueSize = (Convert.ToString(nullChrPos - pos + 0x8000, 16)).ToUpper(); tmpBuf.Append(valueSize); tmpBuf.Append(itemVal.Substring(pos, (nullChrPos) - (pos))); // Count number of consecutive NULL chars, and add their count to XML for (j = 1; j < fldValLen - nullChrPos && itemVal[nullChrPos + j] == 0; j++) { } // add leading zeros (if needed) valueSize = "0000" + (Convert.ToString(j, 16)).ToUpper(); tmpBuf.Append(valueSize.Substring(valueSize.Length - 4)); // Append a hex dump of special chars for (pos = nullChrPos; j > 0; j--, pos++) { string tmpStr = "0" + (Convert.ToString(itemVal[nullChrPos], 16)); tmpBuf.Append(tmpStr.Substring(tmpStr.Length - 2)); } // If special chars were last, add the length of the last segment (zero) if (pos >= fldValLen) { tmpBuf.Append("0000"); itemVal = ""; break; } } } while (pos < fldValLen); break; case StorageAttribute.BLOB: case StorageAttribute.BLOB_VECTOR: case StorageAttribute.DOTNET: pos = 0; // convert dotnet object into magic equivalent and append as data into blob suffix. if (itemAttr == StorageAttribute.DOTNET) { Object itmObj = null; int key = BlobType.getKey(itemVal); String itmMagicVal = ""; if (key != 0) { itmObj = DNManager.getInstance().DNObjectsCollection.GetDNObj(key); } // convert dotnet object into magic type if (itmObj != null) { StorageAttribute magicType = DNConvert.getDefaultMagicTypeForDotNetType(itmObj.GetType()); itmMagicVal = DNConvert.convertDotNetToMagic(itmObj, magicType); // append to dotnet blob as data if (itmMagicVal.Length > 0) { itemVal = BlobType.addDataToDotNetBlob(itemVal, itmMagicVal, magicType); } } } fldValLen = itemVal.Length; if (UtilStrByteMode.isLocaleDefLangDBCS() && itemAttr == StorageAttribute.BLOB_VECTOR) { if (cellAttr == StorageAttribute.ALPHA || cellAttr == StorageAttribute.MEMO) { itemVal = VectorType.adjustAlphaStringsInFlatData(itemVal); // The flat data will be divided by 0x3FFF characters. // Each segment will be size in 0x3FFF ~ 0x7FFF bytes. // The size depends on the number of DBCS characters, not fixed in 0x7FFF. do { if (itemVal.Length < pos + 0x3FFF) //(0x8000 - 1) / 2 = 0x3FFF { if (pos > 0) { itemVal = itemVal.Substring(pos); } valueSize = (Convert.ToString(UtilStrByteMode.lenB(itemVal), 16)).ToUpper(); // add leading zeros (if needed) for (j = 0; j < 4 - valueSize.Length; j++) { tmpBuf.Append('0'); } tmpBuf.Append(valueSize); //hex encoding itemVal = !toBase64 ? StrUtil.stringToHexaDump(itemVal, 4) : Base64.encode(itemVal, true, Manager.Environment.GetEncoding()); pos = fldValLen; } else { String strSub = itemVal.Substring(pos, 0x3FFF); // + 0x8000 ... to indicate not the last segment valueSize = (Convert.ToString(UtilStrByteMode.lenB(strSub) + 0x8000, 16)).ToUpper(); tmpBuf.Append(valueSize); //hex or base64 encoding tmpBuf.Append(!toBase64 ? StrUtil.stringToHexaDump(strSub, 4) : Base64.encode(strSub, true, Manager.Environment.GetEncoding())); tmpBuf.Append("0000"); pos += 0x3FFF; } } while (pos < fldValLen); break; } } do { if (fldValLen < pos + 0x7FFF) //0x8000 -1 = 0x7FFF { valueSize = (Convert.ToString(fldValLen - pos, 16)).ToUpper(); // add leading zeros (if needed) for (j = 0; j < 4 - valueSize.Length; j++) { tmpBuf.Append('0'); } tmpBuf.Append(valueSize); if (pos > 0) { itemVal = itemVal.Substring(pos, (fldValLen) - (pos)); } //hex encoding itemVal = !toBase64 ? StrUtil.stringToHexaDump(itemVal, 4) : Base64.encode(itemVal, Manager.Environment.GetEncoding()); pos = fldValLen; } else { //to indicate the full segment valueSize = "FFFF"; //(Integer.toHexString (0xFFFF)).toUpperCase() tmpBuf.Append(valueSize); //hex or base64 encoding if (!toBase64) { tmpBuf.Append(StrUtil.stringToHexaDump(itemVal.Substring(pos, 0x7FFF), 4)); } else { tmpBuf.Append(Base64.encode(itemVal.Substring(pos, 0x7FFF), Manager.Environment.GetEncoding())); } tmpBuf.Append("0000"); pos += 0x7FFF; } } while (pos < fldValLen); break; } //end of the type case block tmpBuf.Append(itemVal); return(tmpBuf.ToString()); }