namespace Invercargill.Operators { /** * Default stringify function for a generic type. * * Marshalling, same as hash()/equality()/comparison(): * - inline types (bool, char/uchar, int/uint, long/ulong, enums) * arrive as a pointer-sized integer carrying the value itself. * - always-boxed types (int64, uint64, float, double and nullable * forms) arrive as pointers to the boxed payloads and are * dereferenced (a null box stringifies as "null"). * * char stringifies as the character, not its numeric code (typeof * (char) == typeof(int8), so this branch must come first and serves * both). uchar stringifies numerically, matching uint8. Enums * stringify as their value nick when registered, falling back to * the numeric value. * * Note: typeof(T) cannot distinguish T=int from T=int? (same GType); * inline branches serve the non-nullable forms. */ public static StringifyDelegate stringify() { var type = typeof(T); if(type == typeof(string)) { return i => (string)i; } else if(type == typeof(char)) { return i => ((char)i).to_string(); } else if(type == typeof(int)) { return i => ((int)i).to_string(); } else if(type == typeof(uint8)) { return i => ((uint8)i).to_string(); } else if(type == typeof(int16)) { return i => ((int16)i).to_string(); } else if(type == typeof(uint16)) { return i => ((uint16)i).to_string(); } else if(type == typeof(uint)) { return i => ((uint)i).to_string(); } else if(type == typeof(int64)) { return i => ((int64?)i) == null ? "null" : ((int64)((int64?)i)).to_string(); } else if(type == typeof(uint64)) { return i => ((uint64?)i) == null ? "null" : ((uint64)((uint64?)i)).to_string(); } else if(type == typeof(double)) { return i => ((double?)i) == null ? "null" : ((double)((double?)i)).to_string(); } else if(type == typeof(float)) { return i => ((float?)i) == null ? "null" : ((float)((float?)i)).to_string(); } else if(type == typeof(long)) { return i => ((long)i).to_string(); } else if(type == typeof(ulong)) { return i => ((ulong)i).to_string(); } else if(type == typeof(bool)) { return i => ((bool)i).to_string(); } else if(type.is_enum()) { var enum_class = (EnumClass)type.class_ref(); return i => { var v = enum_class.get_value((int)i); return v == null ? ((int)i).to_string() : v.value_nick; }; } else if(type.is_a(typeof(Stringifyable))) { return i => ((Stringifyable)i).to_string(); } else if(type.is_a(typeof(BinaryData))) { return i => "0x" + ((BinaryData)i).to_hex(); } return i => @"[$(type.name()) at 0x$(((int)i).to_string("%x"))]"; } }