SectionTemplate.h
Go to the documentation of this file.
1 /****
2  * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
3  * Created 2015 by Skurydin Alexey
4  * http://github.com/SmingHub/Sming
5  * All files of the Sming Core are provided under the LGPL v3 license.
6  *
7  * SectionTemplate.h
8  *
9  * @author mikee47 <mike@sillyhouse.net> Nov 2020
10  *
11  ****/
12 
13 #pragma once
14 
15 #include "SectionStream.h"
16 #include "TemplateStream.h"
17 #include <Data/BitSet.h>
18 #include "../Format.h"
19 
34 #define SECTION_TEMPLATE_COMMAND_MAP(XX) \
35  XX(Qas_int, "{!int:A} Output A as integer") \
36  XX(Qas_float, "{!float:A} Output A as float") \
37  XX(Qas_string, "{!string:A} Output A as quoted string") \
38  XX(Qmime_type, "{!mime_type:A} Get MIME type string for a filename") \
39  XX(Qreplace, "{!replace:A:B:C} Copy of A with all occurrences of B replaced with C") \
40  XX(Qlength, "{!length:A} Number of characters in A") \
41  XX(Qpad, \
42  "{!pad:A:B:C} Copy of A padded to at least B characters with C (default is space). Use -ve B to left-pad. C") \
43  XX(Qrepeat, "{!repeat:A:B} Repeat A, number of iterations is B") \
44  XX(Qkb, "{!kb:A} Convert A to KB") \
45  XX(Qifdef, "{!ifdef:A}block{/if} emit block if A is not zero-length") \
46  XX(Qifndef, "{!ifdef:A}block{/if} emit block if A is zero-length") \
47  XX(Qifeq, "{!ifeq:A:B} emit block if A == B") \
48  XX(Qifneq, "{!ifneq:A:B} emit block if A != B") \
49  XX(Qifgt, "{!ifgt:A:B} emit block if A > B") \
50  XX(Qiflt, "{!iflt:A:B} emit block if A < B") \
51  XX(Qifge, "{!ifge:A:B} emit block if A >= B") \
52  XX(Qifle, "{!ifle:A:B} emit block if A <= B") \
53  XX(Qifbtw, "{!ifbtw:A:B:C} emit block if B <= A <= C") \
54  XX(Qifin, "{!ifin:A:B} emit block if A contains B") \
55  XX(Qifnin, "{!ifin:A:B} emit block if A does not contain B") \
56  XX(Qelse, "{!else}") \
57  XX(Qendif, "{!endif}") \
58  XX(Qadd, "{!add:A:B} A - B") \
59  XX(Qsub, "{!sub:A:B} A - B") \
60  XX(Qgoto, "{!goto:A} move to section A") \
61  XX(Qcount, "{!count:A} emit number of records in section A") \
62  XX(Qindex, "{!index:A} emit current record index for section A")
63 
64 #define SECTION_TEMPLATE_FIELD_MAP(XX) \
65  XX(section, "{$section} Current section index") \
66  XX(record, "{$record} Current record index")
67 
72 {
73 public:
74  enum class Command {
75  Qunknown = 0,
76 #define XX(name, comment) name,
78 #undef XX
79  };
80 
81  enum class Field {
82  unknown = 0,
83 #define XX(name, comment) name,
85 #undef XX
86  };
87 
89 
99 
101 
102  void onGetValue(GetValue callback)
103  {
104  getValueCallback = callback;
105  }
106 
108  {
109  activeFormatter = &formatter;
110  }
111 
113  {
114  return *activeFormatter;
115  }
116 
117  MimeType getMimeType() const override
118  {
119  return activeFormatter->mimeType();
120  }
121 
122  const SectionStream& stream() const
123  {
124  return sectionStream;
125  }
126 
127  int sectionIndex() const
128  {
129  return sectionStream.sectionIndex();
130  }
131 
132  uint8_t sectionCount() const
133  {
134  return sectionStream.count();
135  }
136 
137  int recordIndex() const
138  {
139  return sectionStream.recordIndex();
140  }
141 
142  bool gotoSection(uint8_t index);
143 
144  void onNextRecord(NextRecord callback)
145  {
146  nextRecordCallback = callback;
147  }
148 
149  String evaluate(char*& expr) override;
150  String getValue(const char* name) override;
151 
152 protected:
157  virtual bool nextRecord()
158  {
159  if(nextRecordCallback) {
160  return nextRecordCallback();
161  }
162 
163  // By default, emit section once
164  return recordIndex() < 0;
165  }
166 
167 private:
168  String openTag(bool enable);
169  String closeTag();
170  String elseTag();
171 
172  SectionStream sectionStream;
173  Formatter* activeFormatter;
174  GetValue getValueCallback;
175  NextRecord nextRecordCallback;
176  BitSet32 conditionalFlags; // Enable state for each level
177  uint8_t conditionalLevel{0};
178  int8_t newSection{-1};
179 };
void onNextRecord(NextRecord callback)
Definition: SectionTemplate.h:144
int recordIndex() const
Definition: SectionTemplate.h:137
String getValue(const char *name) override
Fetch a templated value.
Command
Definition: SectionTemplate.h:74
bool gotoSection(uint8_t index)
Base class for read-only stream.
Definition: DataSourceStream.h:40
#define SECTION_TEMPLATE_FIELD_MAP(XX)
Definition: SectionTemplate.h:64
void onGetValue(GetValue callback)
Definition: SectionTemplate.h:102
void setFormatter(Formatter &formatter)
Definition: SectionTemplate.h:107
Delegate< bool()> NextRecord
Application callback to move to next record.
Definition: SectionStream.h:52
The String class.
Definition: WString.h:136
#define SECTION_TEMPLATE_COMMAND_MAP(XX)
Command map.
Definition: SectionTemplate.h:34
SectionTemplate(IDataSourceStream *source)
Field
Definition: SectionTemplate.h:81
virtual bool nextRecord()
Move to next record.
Definition: SectionTemplate.h:157
Stream which performs variable-value substitution on-the-fly.
Definition: TemplateStream.h:32
uint8_t sectionCount() const
Definition: SectionTemplate.h:132
MimeType getMimeType() const override
Get MIME type for stream content.
Definition: SectionTemplate.h:117
Virtual class to perform format-specific String adjustments.
Definition: Formatter.h:23
Provides enhanced template tag processing for use with a SectionStream.
Definition: SectionTemplate.h:71
Presents each section within a source stream as a separate stream.
Definition: SectionStream.h:26
int sectionIndex() const
Definition: SectionTemplate.h:127
MimeType
Definition: WebConstants.h:53
const SectionStream & stream() const
Definition: SectionTemplate.h:122
Formatter & formatter() const
Definition: SectionTemplate.h:112
String evaluate(char *&expr) override