/// <summary> /// Selects the correct string and interpolates the specified arguments.</summary> /// <param name="ns"> /// Number system to use to interpolate the translation.</param> /// <param name="args"> /// Arguments to be interpolated into the translation.</param> public string Fmt(NumberSystem ns, params object[] args) { try { int n = 0; int m = 1; for (int i = 0; i < IsNumber.Length; i++) { if (IsNumber[i]) { double numD = 0; int numI; bool isInteger; if (args[i] is double || args[i] is float || args[i] is decimal) { numD = ExactConvert.ToDouble(args[i]); numI = unchecked ((int)numD); isInteger = numD == (double)numI; } else if (args[i] is int || args[i] is uint || args[i] is long || args[i] is ulong || args[i] is short || args[i] is ushort || args[i] is byte || args[i] is sbyte) { numI = ExactConvert.ToInt(args[i]); isInteger = true; } else { throw new ArgumentException("Argument #{0} was expected to be a number, but a {1} was given.".Fmt(i, args[i].GetType().FullName), "args"); } if (isInteger) { n += ns.GetString(numI) * m; } else { n += ns.GetString(numD) * m; } m *= ns.NumStrings; } } return(Translations[n].Fmt(args)); } catch { if (Translations != null && Translations.Length > 0) { return(Translations[0]); } else { return("(NO STRING)"); } } }
public void BeforeDeserialize(XElement element) { var el = element.Element("ImplicitlyMirror"); if (el == null) { return; } if (!ExactConvert.Try(typeof(MirrorType), el.Value, out var m)) { el.Remove(); } }
byte[] IClassifyFormat <node> .GetRawData(node element) { if (element.DataType == DataType.List) { // Support a list of integers as this was how Classify encoded byte arrays before GetRawData was introduced return(((listNode)element).List.Select(nd => ExactConvert.ToByte(((valueNode)nd).Value)).ToArray()); } if (element.DataType == DataType.RawData) { return((byte[])((valueNode)element).Value); } return(null); }
/// <summary> /// Returns the value of this element, converted to type T. If the element does not exist returns the default /// value. If the element's value cannot be converted, throws an exception.</summary> public static T ValueOrDefault <T>(this XElement element, XName name, T defaultValue) { XElement el = element.Element(name); if (el == null) { return(defaultValue); } else { try { return(ExactConvert.To <T>(el.Value)); } catch (ExactConvertException E) { throw new InvalidOperationException(("Element \"{0}/{1}\", when present, must contain a value convertible to a certain type: " + E.Message).Fmt(element.Path(), name)); } } }
valueNode tryFormatSimpleValue <T>(object value, DataType dt) { object result, retour; if (!ExactConvert.Try(typeof(T), value, out result)) { return(null); } if (!ExactConvert.Try(value.GetType(), result, out retour) || !retour.Equals(value)) { return(null); } return(new valueNode { DataType = dt, Value = result }); }
public static T GetValidated <T>(this HttpRequest request, string varName, T varDefault, Func <T, bool> validator, string mustBe) { var valueStr = request.Url[varName]; if (valueStr == null) { return(varDefault); } T value; try { value = ExactConvert.To <T>(valueStr); } catch (ExactConvertException) { throw new ValidationException(varName, valueStr, "convertible to {0}".Fmt(typeof(T))); } if (!validator(value)) { throw new ValidationException(varName, valueStr, mustBe); } return(value); }
private string describe(object item) { byte[] b; List <object> list; Function fnc; if ((b = item as byte[]) != null) { return("Byte array: “{0}” ({1})".Fmt(b.FromUtf8().CLiteralEscape(), ScliptingUtil.ToInt(b))); } else if (item is BigInteger) { return("Integer: {0}".Fmt(item)); } else if (item is string) { return("String: “{0}”".Fmt(((string)item).CLiteralEscape())); } else if (item is double) { return("Float: {0}".Fmt(ExactConvert.ToString((double)item))); } else if (item is Mark) { return("Mark"); } else if ((list = item as List <object>) != null) { return("List ({0} items)".Fmt(list.Count) + list.Select((itm, idx) => Environment.NewLine + describe(itm, idx)).JoinString().Indent(4, false)); } else if ((fnc = item as Function) != null) { return("Function" + (fnc.CapturedItem != null ? "; capture: " + describe(fnc.CapturedItem) : "; no capture")); } // unknown type of object? return("{0} ({1})".Fmt(item, item.GetType().FullName)); }
private void Assert_StoresCorrectValueOfCorrectType(RVariant mvalue, object expected, TypeCode code) { Assert.AreEqual(RVariantKind.Value, mvalue.Kind); Assert.AreEqual(code, ExactConvert.GetTypeCode(mvalue.Value)); Assert.AreEqual(expected, mvalue.Value); }
node IClassifyFormat <node> .FormatSimpleValue(object value) { if (value == null) { return new valueNode { Value = null, DataType = DataType.Null } } ; if (value is float) { return new valueNode { DataType = DataType.Single, Value = value } } ; if (value is double) { return new valueNode { DataType = DataType.Double, Value = value } } ; if (value is decimal) { return new valueNode { DataType = DataType.Decimal, Value = value } } ; if (value is DateTime) { return new valueNode { DataType = DataType.DateTime, Value = value } } ; // Use the smallest possible representation of the input. // Note that if the input is, say, the Int64 value 1, it will be stored compactly as the boolean “true”. // In fact, even the string "true" will be stored that way and correctly converted back. // Strings that roundtrip-convert to DateTime are also stored compactly as DateTime. var node = tryFormatSimpleValue <bool>(value, DataType.False) ?? tryFormatSimpleValue <byte>(value, DataType.Byte) ?? tryFormatSimpleValue <sbyte>(value, DataType.SByte) ?? tryFormatSimpleValue <short>(value, DataType.Int16) ?? tryFormatSimpleValue <ushort>(value, DataType.UInt16) ?? tryFormatSimpleValue <int>(value, DataType.Int32) ?? tryFormatSimpleValue <uint>(value, DataType.UInt32) ?? tryFormatSimpleValue <long>(value, DataType.Int64) ?? tryFormatSimpleValue <ulong>(value, DataType.UInt64) ?? tryFormatSimpleValue <DateTime>(value, DataType.DateTime); if (node != null) { if (node.Value.Equals(true)) { node.DataType = DataType.True; } return(node); } var str = ExactConvert.ToString(value); var strAsUtf16 = str.ToUtf16(); return(str.Utf8Length() < strAsUtf16.Length ? new valueNode { Value = str, DataType = DataType.String } : new valueNode { Value = strAsUtf16, DataType = DataType.RawData }); } node IClassifyFormat <node> .FormatSelfValue(node value) { throw new InvalidOperationException("This should never happen."); } node IClassifyFormat <node> .FormatList(bool isTuple, IEnumerable <node> values) { var list = values.ToList(); if (list.Count == 2) { return new kvpNode { Key = list[0], Value = list[1], DataType = DataType.KeyValuePair } } ; return(new listNode { List = values.ToList(), DataType = DataType.List }); } node IClassifyFormat <node> .FormatKeyValuePair(node key, node value) { return(new kvpNode { Key = key, Value = value, DataType = DataType.KeyValuePair }); } node IClassifyFormat <node> .FormatDictionary(IEnumerable <KeyValuePair <object, node> > values) { var dic = values.ToDictionary(); if (dic.Count == 0) { return new dictNode { Dictionary = dic, DataType = DataType.DictionaryString } } ; var firstKey = dic.Keys.First(); var keyType = firstKey.GetType(); Type underlyingType = null; if (firstKey is Enum) { underlyingType = keyType.GetEnumUnderlyingType(); } DataType dt; DataType kt; if (keyType == typeof(ulong) || underlyingType == typeof(ulong)) { dt = DataType.DictionaryOther; kt = DataType.UInt64; } else if (ExactConvert.IsTrueIntegerType(keyType) || ExactConvert.IsTrueIntegerType(underlyingType)) { dt = DataType.DictionaryInt64; kt = 0; } else if (keyType == typeof(string)) { var utf8len = dic.Keys.Take(32).Sum(k => ((string)k).Utf8Length()); var utf16len = dic.Keys.Take(32).Sum(k => ((string)k).Utf16Length()); if (utf8len > utf16len) { dt = DataType.DictionaryOther; kt = DataType.RawData; } else { dt = DataType.DictionaryString; kt = 0; } } else if (keyType == typeof(float)) { dt = DataType.DictionaryOther; kt = DataType.Single; } else if (keyType == typeof(double)) { dt = DataType.DictionaryOther; kt = DataType.Double; } else if (keyType == typeof(decimal)) { dt = DataType.DictionaryOther; kt = DataType.Decimal; } else if (keyType == typeof(DateTime)) { dt = DataType.DictionaryOther; kt = DataType.DateTime; } else { dt = DataType.DictionaryString; kt = 0; } return(new dictNode { Dictionary = dic, DataType = dt, KeyType = kt }); } node IClassifyFormat <node> .FormatObject(IEnumerable <ObjectFieldInfo <node> > fields) { var dic = fields.ToDictionary(f => f.DeclaringType == null ? f.FieldName : (object)new FieldNameWithType(f.FieldName, f.DeclaringType), f => f.Value); return(new dictNode { DataType = dic.Keys.Any(k => k is FieldNameWithType) ? DataType.DictionaryTwoStrings : DataType.DictionaryString, Dictionary = dic }); } node IClassifyFormat <node> .FormatRawData(byte[] value) { return(new valueNode { DataType = DataType.RawData, Value = value }); } node IClassifyFormat <node> .FormatReference(int refId) { return(new valueNode { Value = refId, DataType = DataType.Ref }); } node IClassifyFormat <node> .FormatReferable(node element, int refId) { element.RefId = refId; return(element); } node IClassifyFormat <node> .FormatWithType(node element, string type, bool isFullType) { element.TypeSpec = type; element.TypeSpecIsFull = isFullType; return(element); } void IClassifyFormat <node> .ThrowMissingReferable(int refID) { throw new InvalidOperationException(@"An object reference was encountered, but no matching object was encountered during deserialization. If such an object is present somewhere in the binary data, the relevant object was not deserialized (most likely because a field corresponding to a parent object was removed from its class declaration)."); } } } }
protected override void writeToStreamImpl(Stream stream) { if (DataType == DataType.DictionaryOther) { stream.WriteByte((byte)KeyType); } foreach (var kvp in Dictionary) { // Store value first kvp.Value.WriteToStream(stream); // Then store key switch (DataType) { case DataType.DictionaryInt64: stream.WriteInt32Optim(ExactConvert.ToInt(kvp.Key)); break; case DataType.DictionaryString: WriteBuffer(stream, ExactConvert.ToString(kvp.Key).ToUtf8(), true); break; case DataType.DictionaryTwoStrings: if (kvp.Key is string) { WriteBuffer(stream, ((string)kvp.Key).ToUtf8(), true); WriteBuffer(stream, new byte[0], true); } else { var fn = (FieldNameWithType)kvp.Key; WriteBuffer(stream, fn.FieldName.ToUtf8(), true); WriteBuffer(stream, fn.DeclaringType == null ? new byte[0] : fn.DeclaringType.ToUtf8(), true); } break; case DataType.DictionaryOther: switch (KeyType) { case DataType.UInt64: stream.WriteUInt64Optim(ExactConvert.ToULong(kvp.Key)); break; case DataType.Single: stream.Write(BitConverter.GetBytes(ExactConvert.ToFloat(kvp.Key))); break; case DataType.Double: stream.Write(BitConverter.GetBytes(ExactConvert.ToDouble(kvp.Key))); break; case DataType.DateTime: stream.Write(BitConverter.GetBytes(((DateTime)kvp.Key).ToBinary())); break; case DataType.Decimal: stream.WriteDecimalOptim(ExactConvert.ToDecimal(kvp.Key)); break; case DataType.RawData: WriteBuffer(stream, ExactConvert.ToString(kvp.Key).ToUtf16(), false); break; default: throw new InvalidOperationException("Invalid dictionary key type."); } break; default: throw new InvalidOperationException("Invalid dictionary type."); } } stream.WriteByte((byte)DataType.End); }
byte[] IClassifyFormat <XElement> .GetRawData(XElement element) => element.HasElements // Support a list of integers as this was how Classify encoded byte arrays before GetRawData was introduced ? element.Elements().Select(el => ExactConvert.ToByte(el.Value)).ToArray() : Convert.FromBase64String(element.Value);
JsonValue IClassifyFormat <JsonValue> .FormatDictionary(IEnumerable <KeyValuePair <object, JsonValue> > values) { return(values.ToJsonDict(kvp => ExactConvert.ToString(kvp.Key).Apply(key => key.StartsWith(":") ? ":" + key : key), kvp => kvp.Value)); }
JsonValue IClassifyFormat <JsonValue> .FormatSimpleValue(object value) { if (value == null) { return(null); } // JSON can’t represent NaN and infinities, so use ExactConvert.ToString() for those. if (value is double && !double.IsNaN((double)value) && !double.IsInfinity((double)value)) { return((double)value); } if (value is float && !float.IsNaN((float)value) && !float.IsInfinity((float)value)) { return((float)value); } if (value is byte) { return((long)(byte)value); } if (value is sbyte) { return((sbyte)value); } if (value is short) { return((short)value); } if (value is ushort) { return((ulong)(ushort)value); } if (value is int) { return((int)value); } if (value is uint) { return((ulong)(uint)value); } if (value is long) { return((long)value); } if (value is ulong) { return((ulong)value); } if (value is decimal) { return((decimal)value); } if (value is bool) { return((bool)value); } if (value is string) { return((string)value); } // This takes care of enum types, DateTime and doubles/floats that are NaN or infinities return(ExactConvert.ToString(value)); }
/// <summary> /// Handles an HTTP request by delegating it to the appropriate handler according to the request’s URL.</summary> /// <param name="req"> /// Incoming HTTP request.</param> /// <returns> /// The HTTP response that was returned by the first applicable mapping.</returns> /// <remarks> /// Assign this method to <see cref="HttpServer.Handler"/>.</remarks> public HttpResponse Handle(HttpRequest req) { if (req.Url.Path.StartsWith("/$debug")) { UrlMapping[] candidates = null; if (req.Url["https"] != null && req.Url["host"] != null && req.Url["location"] != null) { candidates = getApplicableMappings(new HttpUrl(ExactConvert.ToBool(req.Url["https"]), req.Url["host"], req.Url["location"])); } return(HttpResponse.Html(new HTML( new HEAD( new TITLE("URL resolver debugging"), new STYLELiteral(@" div.mapping { border: 3px solid black; margin: 1em auto; padding: 1em 2em 1em 5em; } div.mapping.skippable { border: 1px solid black; } div.mapping.applicable { background: #fee; } div.hook { margin-bottom: .5em; }")), new BODY( _mappings.Select(m => new DIV { class_ = "mapping" + (m.Skippable ? " skippable" : "") + (candidates != null && candidates.Contains(m) ? " applicable" : "") /*+ (m.Hook.SpecificDomain ? " specific-domain" : "") + (m.Hook.SpecificPath ? " specific-path" : "")*/ }._( //new DIV { class_ = "domain" }._((object) m.Hook.Domain ?? new EM("<null>")), //new DIV { class_ = "path" }._((object) m.Hook.Path ?? new EM("<null>")), //new DIV { class_ = "port" }._((object) m.Hook.Port ?? new EM("<null>")), //new DIV { class_ = "protocols" }._(ExactConvert.ToString(m.Hook.Protocols)), new DIV { class_ = "hook" }._(m.Hook.ToString()), new DIV { class_ = "module" }._(m.Handler.Target.GetType().FullName))))))); } var originalUrl = req.Url; var applicableMappings = getApplicableMappings(originalUrl); foreach (var mapping in applicableMappings) { var url = req.Url.ToUrl(); if (mapping.Hook.Domain != null) { var parents = url.ParentDomains; url.ParentDomains = new string[parents.Length + 1]; Array.Copy(parents, url.ParentDomains, parents.Length); url.ParentDomains[parents.Length] = mapping.Hook.Domain; url.Domain = url.Domain.Substring(0, url.Domain.Length - mapping.Hook.Domain.Length); } if (mapping.Hook.Path != null) { var parents = url.ParentPaths; url.ParentPaths = new string[parents.Length + 1]; Array.Copy(parents, url.ParentPaths, parents.Length); url.ParentPaths[parents.Length] = mapping.Hook.Path; url.Path = url.Path.Substring(mapping.Hook.Path.Length); } req.Url = url; var response = mapping.Handler(req); if (response == null && !mapping.Skippable) { throw new InvalidOperationException("The handler of a non-skippable handler returned null. Mapping: {0}".Fmt(mapping)); } if (response != null) { return(response); } req.Url = originalUrl; } throw new HttpNotFoundException(originalUrl.ToFull()); }