1 /*
2  * Hunt - A high-level D Programming Language Web framework that encourages rapid development and clean, pragmatic design.
3  *
4  * Copyright (C) 2015-2019, HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.framework.util.Formatter;
13 
14 private
15 {
16     import std.regex;
17     import std.json;
18     import std.array;
19     import std.string;
20     import std.format;
21 }
22 
23 private
24 {
25     const string formatSpecifier = "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])";
26 
27     string[] parseFormat(string message)
28     {
29         string[] frams;
30         int offset = 0;
31         auto matchers = matchAll(message, regex(formatSpecifier, "im"));
32         foreach (matcher; matchers)
33         {
34             string text = matcher.captures[0];
35             int pos = cast(int)(message[offset .. $].indexOf(text)) + offset;
36             frams ~= message[offset .. pos + text.length];
37             offset = pos + cast(int)(text.length);
38         }
39         if (offset != message.length)
40             frams ~= message[offset .. $];
41         return frams;
42     }
43 }
44 
45 string StrFormat(string message, JSONValue data)
46 {
47     void singleFormat(ref Appender!string buffer, string text, JSONValue item)
48     {
49         switch (item.type) with (JSONType)
50         {
51         case integer:
52             formattedWrite(buffer, text, item.integer);
53             break;
54         case uinteger:
55             formattedWrite(buffer, text, item.uinteger);
56             break;
57         case float_:
58             formattedWrite(buffer, text, item.floating);
59             break;
60         case string:
61             formattedWrite(buffer, text, item.str);
62             break;
63         case true_:
64             formattedWrite(buffer, text, true);
65             break;
66         case false_:
67             formattedWrite(buffer, text, false);
68             break;
69         default:
70             throw new Exception("error param : " ~ item.toString);
71         }
72     }
73 
74     auto frams = parseFormat(message);
75     if (data.type == JSONType.array)
76     {
77         assert(frams.length >= data.array.length);
78         Appender!string buffer;
79         for (int i = 0; i < data.array.length; i++)
80         {
81             JSONValue item = data.array[i];
82             singleFormat(buffer, frams[i], item);
83         }
84         for (size_t i = data.array.length; i < frams.length; i++)
85             buffer.put(frams[i]);
86         return buffer.data;
87     }
88     else
89     {
90         Appender!string buffer;
91         singleFormat(buffer, frams[0], data);
92         for (size_t i = 1; i < frams.length; i++)
93             buffer.put(frams[i]);
94         return buffer.data;
95     }
96 }
97 
98 string StrFormat(A...)(string message , lazy A args)
99 {
100     Appender!string buffer;
101     formattedWrite(buffer, message, args);
102     return buffer.data;
103 }
104 
105 unittest
106 {
107     import std.json;
108     import std.stdio;
109 
110     string message = "hello %s, your id is %2d, 
111                                         your score is %.2f, bye!";
112 	JSONValue data = [JSONValue("gaoxincheng"),JSONValue(100),JSONValue(89.345)];
113 
114 	writeln("format message : ",StrFormat(message,data));
115 
116 	string msg1 = "hello %s ! ";
117 	writeln("format msg1 : ",StrFormat(msg1,JSONValue(" world")));
118 
119 	string msg2 = "hello world! ";
120 	writeln("format msg2 : ",StrFormat(msg2,JSONValue(1)));
121 
122 	writeln("format varags : ",StrFormat(message,"gaoxincheng",99,45.2223));
123 
124 	// UniNode nodes = [UniNode("world"),UniNode(100),UniNode(89.345)];
125 
126 	// writeln("format message by UniNode : ",StrFormat(message,uniNodeToJSON(nodes)));
127 }