1 module hunt.time.format.PadPrinterParserDecorator; 2 3 import hunt.time.Exceptions; 4 5 import hunt.time.format.DateTimeParseContext; 6 import hunt.time.format.DateTimePrinterParser; 7 import hunt.time.format.DateTimePrintContext; 8 import hunt.time.temporal.TemporalField; 9 import hunt.util.StringBuilder; 10 11 import hunt.Exceptions; 12 13 import std.conv; 14 15 //----------------------------------------------------------------------- 16 /** 17 * Pads the output to a fixed width. 18 */ 19 static final class PadPrinterParserDecorator : DateTimePrinterParser 20 { 21 private DateTimePrinterParser printerParser; 22 private int padWidth; 23 private char padChar; 24 25 /** 26 * Constructor. 27 * 28 * @param printerParser the printer, not null 29 * @param padWidth the width to pad to, 1 or greater 30 * @param padChar the pad character 31 */ 32 this(DateTimePrinterParser printerParser, int padWidth, char padChar) 33 { 34 // input checked by DateTimeFormatterBuilder 35 this.printerParser = printerParser; 36 this.padWidth = padWidth; 37 this.padChar = padChar; 38 } 39 40 override public bool format(DateTimePrintContext context, StringBuilder buf) 41 { 42 int preLen = buf.length(); 43 if (printerParser.format(context, buf) == false) 44 { 45 return false; 46 } 47 int len = buf.length() - preLen; 48 if (len > padWidth) 49 { 50 throw new DateTimeException("Cannot print as output of " ~ len.to!string 51 ~ " characters exceeds pad width of " ~ padWidth.to!string); 52 } 53 for (int i = 0; i < padWidth - len; i++) 54 { 55 buf.insert(preLen, padChar); 56 } 57 return true; 58 } 59 60 override public int parse(DateTimeParseContext context, string text, int position) 61 { 62 // cache context before changed by decorated parser 63 bool strict = context.isStrict(); 64 // parse 65 if (position > text.length) 66 { 67 throw new IndexOutOfBoundsException(); 68 } 69 if (position == text.length) 70 { 71 return ~position; // no more characters _in the string 72 } 73 int endPos = position + padWidth; 74 if (endPos > text.length) 75 { 76 if (strict) 77 { 78 return ~position; // not enough characters _in the string to meet the parse width 79 } 80 endPos = cast(int)(text.length); 81 } 82 int pos = position; 83 while (pos < endPos && context.charEquals(text[pos], padChar)) 84 { 85 pos++; 86 } 87 text = text[0 .. endPos]; 88 int resultPos = printerParser.parse(context, text, pos); 89 if (resultPos != endPos && strict) 90 { 91 return ~(position + pos); // parse of decorated field didn't parse to the end 92 } 93 return resultPos; 94 } 95 96 override public string toString() 97 { 98 return "Pad(" ~ printerParser.toString ~ "," ~ padWidth.to!string ~ (padChar == ' ' 99 ? ")" : ",'" ~ padChar ~ "')"); 100 } 101 }