xref: /aosp_15_r20/external/image_io/src/xml/xml_reader.cc (revision ca0779eb572efbbfda2e47f806647c3c7eeea8c3)
1*ca0779ebSJerome Gaillard #include "image_io/xml/xml_reader.h"
2*ca0779ebSJerome Gaillard 
3*ca0779ebSJerome Gaillard #include <iomanip>
4*ca0779ebSJerome Gaillard #include <sstream>
5*ca0779ebSJerome Gaillard #include <string>
6*ca0779ebSJerome Gaillard #include <utility>
7*ca0779ebSJerome Gaillard 
8*ca0779ebSJerome Gaillard #include "image_io/base/message.h"
9*ca0779ebSJerome Gaillard #include "image_io/base/message_handler.h"
10*ca0779ebSJerome Gaillard 
11*ca0779ebSJerome Gaillard namespace photos_editing_formats {
12*ca0779ebSJerome Gaillard namespace image_io {
13*ca0779ebSJerome Gaillard 
14*ca0779ebSJerome Gaillard namespace {
15*ca0779ebSJerome Gaillard 
16*ca0779ebSJerome Gaillard /// The reader name used for error messages.
17*ca0779ebSJerome Gaillard const char kReaderName[] = "XmlReader";
18*ca0779ebSJerome Gaillard 
19*ca0779ebSJerome Gaillard }  // namespace
20*ca0779ebSJerome Gaillard 
StartParse(std::unique_ptr<XmlRule> rule)21*ca0779ebSJerome Gaillard bool XmlReader::StartParse(std::unique_ptr<XmlRule> rule) {
22*ca0779ebSJerome Gaillard   bytes_parsed_ = 0;
23*ca0779ebSJerome Gaillard   rule_stack_.clear();
24*ca0779ebSJerome Gaillard   if (!rule) {
25*ca0779ebSJerome Gaillard     std::string text = std::string(kReaderName) + ":StartParse:NoTopLevelRule";
26*ca0779ebSJerome Gaillard     Message message(Message::kInternalError, 0, text);
27*ca0779ebSJerome Gaillard     ReportError(message);
28*ca0779ebSJerome Gaillard     return false;
29*ca0779ebSJerome Gaillard   }
30*ca0779ebSJerome Gaillard   rule_stack_.push_back(std::move(rule));
31*ca0779ebSJerome Gaillard   has_internal_or_syntax_error_ = false;
32*ca0779ebSJerome Gaillard   has_errors_ = false;
33*ca0779ebSJerome Gaillard   return true;
34*ca0779ebSJerome Gaillard }
35*ca0779ebSJerome Gaillard 
FinishParse()36*ca0779ebSJerome Gaillard bool XmlReader::FinishParse() {
37*ca0779ebSJerome Gaillard   if (has_internal_or_syntax_error_) {
38*ca0779ebSJerome Gaillard     return false;
39*ca0779ebSJerome Gaillard   }
40*ca0779ebSJerome Gaillard   std::string error_text;
41*ca0779ebSJerome Gaillard   if (rule_stack_.empty() ||
42*ca0779ebSJerome Gaillard       (rule_stack_.size() == 1 &&
43*ca0779ebSJerome Gaillard        rule_stack_.back()->IsPermissibleToFinish(&error_text))) {
44*ca0779ebSJerome Gaillard     return true;
45*ca0779ebSJerome Gaillard   }
46*ca0779ebSJerome Gaillard   std::stringstream ss;
47*ca0779ebSJerome Gaillard   ss << kReaderName << ":";
48*ca0779ebSJerome Gaillard   if (error_text.empty()) {
49*ca0779ebSJerome Gaillard     ss << "While parsing text with rule:";
50*ca0779ebSJerome Gaillard     ss << rule_stack_.back()->GetName();
51*ca0779ebSJerome Gaillard     XmlTerminal* terminal = rule_stack_.back()->GetCurrentTerminal();
52*ca0779ebSJerome Gaillard     if (terminal) {
53*ca0779ebSJerome Gaillard       if (!terminal->GetName().empty()) {
54*ca0779ebSJerome Gaillard         ss << ":" << terminal->GetName();
55*ca0779ebSJerome Gaillard       }
56*ca0779ebSJerome Gaillard       ss << ":" << terminal->GetScanner()->GetDescription();
57*ca0779ebSJerome Gaillard     }
58*ca0779ebSJerome Gaillard   } else {
59*ca0779ebSJerome Gaillard     ss << error_text;
60*ca0779ebSJerome Gaillard   }
61*ca0779ebSJerome Gaillard   Message message(Message::kPrematureEndOfDataError, 0, ss.str());
62*ca0779ebSJerome Gaillard   has_internal_or_syntax_error_ = true;
63*ca0779ebSJerome Gaillard   ReportError(message);
64*ca0779ebSJerome Gaillard   return false;
65*ca0779ebSJerome Gaillard }
66*ca0779ebSJerome Gaillard 
Parse(const std::string & value)67*ca0779ebSJerome Gaillard bool XmlReader::Parse(const std::string& value) {
68*ca0779ebSJerome Gaillard   size_t location = GetBytesParsed();
69*ca0779ebSJerome Gaillard   DataRange range(location, location + value.length());
70*ca0779ebSJerome Gaillard   const Byte* bytes = reinterpret_cast<const Byte*>(value.c_str());
71*ca0779ebSJerome Gaillard   auto segment = DataSegment::Create(range, bytes, DataSegment::kDontDelete);
72*ca0779ebSJerome Gaillard   return Parse(location, range, *segment);
73*ca0779ebSJerome Gaillard }
74*ca0779ebSJerome Gaillard 
Parse(size_t start_location,const DataRange & range,const DataSegment & segment)75*ca0779ebSJerome Gaillard bool XmlReader::Parse(size_t start_location, const DataRange& range,
76*ca0779ebSJerome Gaillard                       const DataSegment& segment) {
77*ca0779ebSJerome Gaillard   if (has_internal_or_syntax_error_) {
78*ca0779ebSJerome Gaillard     return false;
79*ca0779ebSJerome Gaillard   }
80*ca0779ebSJerome Gaillard   XmlHandlerContext context(start_location, range, segment, *data_line_map_,
81*ca0779ebSJerome Gaillard                             handler_);
82*ca0779ebSJerome Gaillard   InitializeContextNameList(&context);
83*ca0779ebSJerome Gaillard   if (!context.IsValidLocationAndRange()) {
84*ca0779ebSJerome Gaillard     DataMatchResult result;
85*ca0779ebSJerome Gaillard     result.SetMessage(Message::kInternalError,
86*ca0779ebSJerome Gaillard                       context.GetInvalidLocationAndRangeErrorText());
87*ca0779ebSJerome Gaillard     ReportError(result, context);
88*ca0779ebSJerome Gaillard     return false;
89*ca0779ebSJerome Gaillard   }
90*ca0779ebSJerome Gaillard   if (rule_stack_.empty()) {
91*ca0779ebSJerome Gaillard     DataMatchResult result;
92*ca0779ebSJerome Gaillard     result.SetMessage(Message::kInternalError, "NoActiveRule");
93*ca0779ebSJerome Gaillard     ReportError(result, context);
94*ca0779ebSJerome Gaillard     return false;
95*ca0779ebSJerome Gaillard   }
96*ca0779ebSJerome Gaillard   if (data_line_map_ == &internal_data_line_map_) {
97*ca0779ebSJerome Gaillard     internal_data_line_map_.FindDataLines(range, segment);
98*ca0779ebSJerome Gaillard   }
99*ca0779ebSJerome Gaillard   size_t bytes_remaining = range.GetEnd() - start_location;
100*ca0779ebSJerome Gaillard   while (bytes_remaining > 0 && !rule_stack_.empty() &&
101*ca0779ebSJerome Gaillard          !has_internal_or_syntax_error_) {
102*ca0779ebSJerome Gaillard     auto& rule = rule_stack_.back();
103*ca0779ebSJerome Gaillard     InitializeContextNameList(&context);
104*ca0779ebSJerome Gaillard     DataMatchResult result = rule->Parse(context);
105*ca0779ebSJerome Gaillard     switch (result.GetType()) {
106*ca0779ebSJerome Gaillard       case DataMatchResult::kError:
107*ca0779ebSJerome Gaillard       case DataMatchResult::kNone:
108*ca0779ebSJerome Gaillard         ReportError(result, context);
109*ca0779ebSJerome Gaillard         break;
110*ca0779ebSJerome Gaillard       case DataMatchResult::kPartial:
111*ca0779ebSJerome Gaillard         ReportMessageIfNeeded(result);
112*ca0779ebSJerome Gaillard         bytes_parsed_ += result.GetBytesConsumed();
113*ca0779ebSJerome Gaillard         bytes_remaining -= result.GetBytesConsumed();
114*ca0779ebSJerome Gaillard         context.IncrementLocation(result.GetBytesConsumed());
115*ca0779ebSJerome Gaillard         if (rule->HasNextRule()) {
116*ca0779ebSJerome Gaillard           // Delegation by child rule: push the next.
117*ca0779ebSJerome Gaillard           rule_stack_.push_back(rule->ReleaseNextRule());
118*ca0779ebSJerome Gaillard         }
119*ca0779ebSJerome Gaillard         break;
120*ca0779ebSJerome Gaillard       case DataMatchResult::kPartialOutOfData:
121*ca0779ebSJerome Gaillard         ReportMessageIfNeeded(result);
122*ca0779ebSJerome Gaillard         bytes_parsed_ += result.GetBytesConsumed();
123*ca0779ebSJerome Gaillard         return true;
124*ca0779ebSJerome Gaillard       case DataMatchResult::kFull:
125*ca0779ebSJerome Gaillard         ReportMessageIfNeeded(result);
126*ca0779ebSJerome Gaillard         bytes_parsed_ += result.GetBytesConsumed();
127*ca0779ebSJerome Gaillard         bytes_remaining -= result.GetBytesConsumed();
128*ca0779ebSJerome Gaillard         context.IncrementLocation(result.GetBytesConsumed());
129*ca0779ebSJerome Gaillard         if (rule->HasNextRule()) {
130*ca0779ebSJerome Gaillard           // Delegation by chaining: pop the current rule and push the next.
131*ca0779ebSJerome Gaillard           auto next_rule = rule->ReleaseNextRule();
132*ca0779ebSJerome Gaillard           rule_stack_.pop_back();
133*ca0779ebSJerome Gaillard           rule_stack_.push_back(std::move(next_rule));
134*ca0779ebSJerome Gaillard         } else {
135*ca0779ebSJerome Gaillard           rule_stack_.pop_back();
136*ca0779ebSJerome Gaillard         }
137*ca0779ebSJerome Gaillard         break;
138*ca0779ebSJerome Gaillard     }
139*ca0779ebSJerome Gaillard   }
140*ca0779ebSJerome Gaillard   if (bytes_remaining > 0 && rule_stack_.empty()) {
141*ca0779ebSJerome Gaillard     InitializeContextNameList(&context);
142*ca0779ebSJerome Gaillard     std::string text = context.GetErrorText("NoActiveRule", "");
143*ca0779ebSJerome Gaillard     Message message(Message::kSyntaxError, 0, text);
144*ca0779ebSJerome Gaillard     ReportError(message);
145*ca0779ebSJerome Gaillard     return false;
146*ca0779ebSJerome Gaillard   }
147*ca0779ebSJerome Gaillard   return !has_internal_or_syntax_error_;
148*ca0779ebSJerome Gaillard }
149*ca0779ebSJerome Gaillard 
InitializeContextNameList(XmlHandlerContext * context)150*ca0779ebSJerome Gaillard void XmlReader::InitializeContextNameList(XmlHandlerContext* context) {
151*ca0779ebSJerome Gaillard   auto name_list = context->GetNameList();
152*ca0779ebSJerome Gaillard   name_list.clear();
153*ca0779ebSJerome Gaillard   name_list.push_back(kReaderName);
154*ca0779ebSJerome Gaillard   if (!rule_stack_.empty()) {
155*ca0779ebSJerome Gaillard     name_list.push_back(rule_stack_.back()->GetName());
156*ca0779ebSJerome Gaillard   }
157*ca0779ebSJerome Gaillard }
158*ca0779ebSJerome Gaillard 
ReportMessageIfNeeded(const DataMatchResult & result)159*ca0779ebSJerome Gaillard void XmlReader::ReportMessageIfNeeded(const DataMatchResult& result) {
160*ca0779ebSJerome Gaillard   if (result.HasMessage()) {
161*ca0779ebSJerome Gaillard     ReportError(result.GetMessage());
162*ca0779ebSJerome Gaillard   }
163*ca0779ebSJerome Gaillard }
164*ca0779ebSJerome Gaillard 
ReportError(const DataMatchResult & result,const DataContext & context)165*ca0779ebSJerome Gaillard void XmlReader::ReportError(const DataMatchResult& result,
166*ca0779ebSJerome Gaillard                             const DataContext& context) {
167*ca0779ebSJerome Gaillard   if (!result.HasMessage()) {
168*ca0779ebSJerome Gaillard     Message message(Message::kInternalError, 0,
169*ca0779ebSJerome Gaillard                     context.GetErrorText("Rule had error but no message", ""));
170*ca0779ebSJerome Gaillard     ReportError(message);
171*ca0779ebSJerome Gaillard   }
172*ca0779ebSJerome Gaillard   ReportError(result.GetMessage());
173*ca0779ebSJerome Gaillard }
174*ca0779ebSJerome Gaillard 
ReportError(const Message & message)175*ca0779ebSJerome Gaillard void XmlReader::ReportError(const Message& message) {
176*ca0779ebSJerome Gaillard   if (message_handler_) {
177*ca0779ebSJerome Gaillard     message_handler_->ReportMessage(message);
178*ca0779ebSJerome Gaillard   }
179*ca0779ebSJerome Gaillard   if (message.GetType() == Message::kInternalError ||
180*ca0779ebSJerome Gaillard       message.GetType() == Message::kSyntaxError) {
181*ca0779ebSJerome Gaillard     has_internal_or_syntax_error_ = true;
182*ca0779ebSJerome Gaillard   }
183*ca0779ebSJerome Gaillard   if (message.IsError()) {
184*ca0779ebSJerome Gaillard     has_errors_ = true;
185*ca0779ebSJerome Gaillard   }
186*ca0779ebSJerome Gaillard }
187*ca0779ebSJerome Gaillard 
188*ca0779ebSJerome Gaillard }  // namespace image_io
189*ca0779ebSJerome Gaillard }  // namespace photos_editing_formats
190