1 /++
2 String manipulation utilities needed by Godot-D
3 +/
4 module godot.d..string;
5 
6 import std.string, std.uni, std.utf;
7 import std.range, std.traits;
8 
9 /++
10 Convert snake_case or CONSTANT_CASE to D-style camelCase.
11 
12 Preserves leading underscore.
13 +/
14 T snakeToCamel(T)(in T inputStr) if(isSomeString!T)
15 {
16 	Unqual!T str = inputStr;
17 	alias Char = Unqual!(ElementEncodingType!T);
18 	Char[] ret = [];
19 
20 	bool newWord = false;
21 	while(!str.empty)
22 	{
23 		dchar c = str.decodeFront;
24 		if(c == '_')
25 		{
26 			if(ret.empty) ret.encode('_');
27 			else newWord = true;
28 		}
29 		else
30 		{
31 			if(newWord)
32 			{
33 				ret.encode(c.toUpper);
34 				newWord = false;
35 			}
36 			else ret.encode(c.toLower);
37 		}
38 	}
39 	return ret;
40 }
41 
42 static assert("snake_case".snakeToCamel == "snakeCase");
43 static assert("_physics_process".snakeToCamel == "_physicsProcess", "_physics_process".snakeToCamel);
44 static assert("CONSTANT_CASE".snakeToCamel == "constantCase");
45 
46 /++
47 Convert camelCase to Godot-style snake_case.
48 
49 Preserves leading underscore.
50 +/
51 T camelToSnake(T)(in T inputStr) if(isSomeString!T)
52 {
53 	Unqual!T str = inputStr;
54 	alias Char = Unqual!(ElementEncodingType!T);
55 	Char[] ret = [];
56 
57 	bool inUppercaseWord = false;
58 	while(!str.empty)
59 	{
60 		dchar c = str.decodeFront;
61 		if(c.isUpper)
62 		{
63 			if(!ret.empty && !inUppercaseWord) ret.encode('_');
64 			ret.encode(c.toLower);
65 			inUppercaseWord = true;
66 		}
67 		else
68 		{
69 			ret.encode(c);
70 			inUppercaseWord = false;
71 		}
72 	}
73 	return ret;
74 }
75 
76 static assert("camelCase".camelToSnake == "camel_case");
77 static assert("_physicsProcess".camelToSnake == "_physics_process");
78 static assert("toUTF32".camelToSnake == "to_utf32");
79