using System; using System.Collections.Generic; using System.Linq; using Clang.Ast; namespace SharpieBinder { public static class StringUtil { public static string DropPrefix (this string w) { var j = w.IndexOf ("_", StringComparison.Ordinal); if (j < 0 || j == w.Length - 1) return w; return w.Substring(j + 1); } public static string SafeParamName(string paramName) { //some C#'s keywords which can be potentially used as arguments string[] csharpKeywords = { "object", "event", "string", "operator", "fixed", "ref", "case", "default", "lock", "unchecked" }; if (csharpKeywords.Contains(paramName)) return "@" + paramName; return paramName; } /// /// Removes the "const" and "&" from a typename string definition /// public static string DropConstAndReference(this string tname) { tname = DropConst(tname); // strip the & if (tname.EndsWith("&")) tname = tname.Substring(0, tname.Length - 1); return tname.Trim(); } public static string DropConst(this string str) { return str.Replace("const ", ""); } public static string ExtractGenericParameter(this string str) { var open = str.IndexOf("<"); var close = str.LastIndexOf(">"); if (open < 0 || close < 0 || close <= open) return str; return str.Substring(open + 1, close - open - 1); } public static string DropClassOrStructPrefix(this string str) { if (str.StartsWith("class ")) return str.Substring("class ".Length); if (str.StartsWith("enum ")) return str.Substring("enum ".Length); if (str.StartsWith("struct ")) return str.Substring("struct ".Length); return str; } public static string DropUrhoNamespace(this string str) { if (str.StartsWith("Urho3D::")) return str.Substring("Urho3D::".Length); return str; } public static string Remap (string source) { switch (source) { case "TraversingLink": return "TraversingLink"; case "Conetwist": return "ConeTwist"; case "Waitingforqueue": return "WaitingForQueue"; case "Waitingforpath": return "WaitingForPath"; case "Lookat": return "LookAt"; case "Readwrite": return "ReadWrite"; case "Notfocusable": return "NotFocusable"; case "Resetfocus": return "ResetFocus"; case "Premulalpha": return "PremultipliedAlpha"; case "Subtractalpha": return "SubtractAlpha"; case "Invdestalpha": return "InvDestAlpha"; case "Notequal": return "NotEqual"; case "Lessequal": return "LessEqual"; case "Greaterequal": return "GreaterEqual"; case "Bottomleft": return "BottomLeft"; case "Topleft": return "TopLeft"; case "Topright": return "Topright"; case "Bottomright": return "BottomRight"; case "Horizontalnvidia": return "HorizontalNvidia"; case "Horizontalcross": return "HorizontalCross"; case "Verticalcross": return "VerticalCross"; } return source; } public static string RemapEnumName(string type, string value) { if (value.StartsWith("MAX_")) return value.PascalCase(); switch (type) { case "InterpolationMode": return value.PascalCase(); case "PrimitiveType": return value.Replace("Prim_", "").PascalCase(); //there are more than one enum with this name case "Orientation2D": case "Orientation": return value.Replace("O_", "").PascalCase(); //there are more than one enum with this name case "EmitterTypeGravity": case "EmitterType2D": case "CrowdAgentTargetState": case "NavmeshPartitionType": return value.DropPrefix().DropPrefix().PascalCase(); case "ShaderType": if (value.Length < 3) return value.ToUpper(); goto default; default: return value.DropPrefix().PascalCase(); } } public static string RemapAcronyms(this string source) { if (string.IsNullOrEmpty(source)) return source; var map = new Dictionary { {"XML", "Xml"}, {"JSON", "Json"} }; return map.Aggregate(source, (current, mapItem) => current.Replace(mapItem.Key, mapItem.Value)); } public static string PascalCase (this string w) { return string.Join ("", w.Split ('_').Select (x => Remap (Capitalize (x)))); } public static string Capitalize (this string word, bool restLower = true) { if (string.IsNullOrEmpty(word)) return string.Empty; if (word.Length > 1) { if (char.IsDigit(word[0])) { string digits = ""; foreach (char symbol in word) { if (char.IsDigit(symbol)) digits += symbol; else break; } string result = "N" + digits; if (result.Length < word.Length) { result += Capitalize(word.Substring(digits.Length)); } return result; } else { var r = word.Substring(1); return char.ToUpper(word[0]) + (restLower ? r.ToLower() : r); } } return char.ToUpper (word[0]).ToString (); } public static IEnumerable GetMethodComments(CXXMethodDecl decl) { return ExtractTextComments(decl.DumpToString()); } public static IEnumerable GetTypeComments(EnumDecl decl) { return ExtractTextComments(decl.DumpToString()).Take(1); } public static IEnumerable GetTypeComments(CXXRecordDecl decl) { return ExtractTextComments(decl.DumpToString()).Take(1); } static IEnumerable ExtractTextComments(string dump) { //workaround since TextComment type is not surfaced in Clang.dll yet var dumpLines = dump.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries).Where(l => l.Contains("-TextComment ")); foreach (var dumpLine in dumpLines) { int start = dumpLine.IndexOf("\""); int end = dumpLine.LastIndexOf("\""); if (start > 0 && end > 0) yield return dumpLine.Substring(start + 1, end - start - 1); } } } }