1 module hunt.time.format.CompositePrinterParser;
2 
3 import hunt.time.format.DateTimeParseContext;
4 import hunt.time.format.DateTimePrinterParser;
5 import hunt.time.format.DateTimePrintContext;
6 import hunt.time.temporal.TemporalField;
7 import hunt.util.StringBuilder;
8 
9 import hunt.collection.List;
10 
11 //-----------------------------------------------------------------------
12 /**
13  * Composite printer and parser.
14  */
15 static final class CompositePrinterParser : DateTimePrinterParser
16 {
17     private DateTimePrinterParser[] printerParsers;
18     private bool optional;
19 
20     this(List!(DateTimePrinterParser) printerParsers, bool optional)
21     {
22         auto a = printerParsers.toArray()/* new DateTimePrinterParser[printerParsers.size()] */;
23         // foreach (l; printerParsers)
24         // {
25         //     if(l is null)
26         //     {
27         //         version(HUNT_DEBUG) trace("is null");
28         //     }
29         //     version(HUNT_DEBUG) trace("----> :",(cast(Object)(l)).toString);
30         //     a ~= l;
31         // }
32         // foreach(p ; a)
33         // {
34         //     if(p is null)
35         //     {
36         //         import hunt.logging;
37         //         version(HUNT_DEBUG) trace("is null");
38         //     }
39         // }
40         this(a, optional);
41     }
42 
43     this(DateTimePrinterParser[] printerParsers, bool optional)
44     {
45         this.printerParsers = printerParsers;
46         // foreach(p ; this.printerParsers)
47         // {
48         //     if(p is null)
49         //     {
50         //         import hunt.logging;
51         //         version(HUNT_DEBUG) trace("is null");
52         //     }
53         // }
54         this.optional = optional;
55     }
56 
57     /**
58      * Returns a copy of this printer-parser with the optional flag changed.
59      *
60      * @param optional  the optional flag to set _in the copy
61      * @return the new printer-parser, not null
62      */
63     public CompositePrinterParser withOptional(bool optional)
64     {
65         if (optional == this.optional)
66         {
67             return this;
68         }
69         return new CompositePrinterParser(printerParsers, optional);
70     }
71 
72     override public bool format(DateTimePrintContext context, StringBuilder buf)
73     {
74         int length = buf.length();
75         if (optional)
76         {
77             context.startOptional();
78         }
79         try
80         {
81             foreach (DateTimePrinterParser pp; printerParsers)
82             {
83                 if (pp.format(context, buf) == false)
84                 {
85                     buf.setLength(length); // reset buffer
86                     return true;
87                 }
88             }
89         }
90         finally
91         {
92             if (optional)
93             {
94                 context.endOptional();
95             }
96         }
97         return true;
98     }
99 
100     override public int parse(DateTimeParseContext context, string text, int position)
101     {
102         if (optional)
103         {
104             context.startOptional();
105             int pos = position;
106             foreach (DateTimePrinterParser pp; printerParsers)
107             {
108                 pos = pp.parse(context, text, pos);
109                 if (pos < 0)
110                 {
111                     context.endOptional(false);
112                     return position; // return original position
113                 }
114             }
115             context.endOptional(true);
116             return pos;
117         }
118         else
119         {
120             foreach (DateTimePrinterParser pp; printerParsers)
121             {
122                 position = pp.parse(context, text, position);
123                 if (position < 0)
124                 {
125                     break;
126                 }
127             }
128             return position;
129         }
130     }
131 
132     override public string toString()
133     {
134         StringBuilder buf = new StringBuilder();
135         if (printerParsers !is null)
136         {
137             buf.append(optional ? "[" : "(");
138             foreach (DateTimePrinterParser pp; printerParsers)
139             {
140                 buf.append(pp.toString);
141             }
142             buf.append(optional ? "]" : ")");
143         }
144         return buf.toString();
145     }
146 }