xref: /aosp_15_r20/external/image_io/src/xml/xml_token_context.cc (revision ca0779eb572efbbfda2e47f806647c3c7eeea8c3)
1 #include "image_io/xml/xml_token_context.h"
2 
3 #include <string>
4 
5 #include "image_io/xml/xml_action.h"
6 #include "image_io/xml/xml_terminal.h"
7 
8 namespace photos_editing_formats {
9 namespace image_io {
10 
11 using std::vector;
12 
13 namespace {
14 
15 const XmlPortion kAllPortions =
16     XmlPortion::kBegin | XmlPortion::kMiddle | XmlPortion::kEnd;
17 
GetPortion(const XmlActionContext & context)18 XmlPortion GetPortion(const XmlActionContext& context) {
19   return XmlTokenContext::ComputeTokenPortion(
20       context.GetTerminal()->GetScanner()->GetScanCallCount(),
21       context.GetResult().GetType());
22 }
23 
24 }  // namespace
25 
XmlTokenContext(const XmlActionContext & context)26 XmlTokenContext::XmlTokenContext(const XmlActionContext& context)
27     : DataContext(context),
28       result_(context.GetResult()),
29       token_range_(context.GetTerminal()->GetScanner()->GetTokenRange()),
30       token_portion_(GetPortion(context)) {}
31 
XmlTokenContext(size_t location,const DataRange & range,const DataSegment & segment,const DataLineMap & data_line_map,const DataMatchResult & result,const DataRange & token_range,const XmlPortion & token_portion)32 XmlTokenContext::XmlTokenContext(size_t location, const DataRange& range,
33                                  const DataSegment& segment,
34                                  const DataLineMap& data_line_map,
35                                  const DataMatchResult& result,
36                                  const DataRange& token_range,
37                                  const XmlPortion& token_portion)
38     : DataContext(location, range, segment, data_line_map),
39       result_(result),
40       token_range_(token_range),
41       token_portion_(token_portion) {}
42 
BuildTokenValue(std::string * value,bool trim_first_and_last_chars) const43 bool XmlTokenContext::BuildTokenValue(std::string* value,
44                                       bool trim_first_and_last_chars) const {
45   bool contains_end = ContainsAny(token_portion_, XmlPortion::kEnd);
46   size_t end_delta = trim_first_and_last_chars && contains_end ? 1 : 0;
47   size_t begin_delta = 0;
48   if (ContainsAny(token_portion_, XmlPortion::kBegin)) {
49     begin_delta = trim_first_and_last_chars ? 1 : 0;
50     value->clear();
51   }
52   if (ContainsAny(token_portion_, kAllPortions)) {
53     const auto& segment = GetSegment();
54     DataRange range_with_deltas(token_range_.GetBegin() + begin_delta,
55                                 token_range_.GetEnd() - end_delta);
56     auto clipped_range = GetRange().GetIntersection(range_with_deltas);
57     if (clipped_range.IsValid()) {
58       const char* cbytes = reinterpret_cast<const char*>(
59           segment.GetBuffer(clipped_range.GetBegin()));
60       value->append(cbytes, clipped_range.GetLength());
61     }
62   }
63   return contains_end;
64 }
65 
BuildTokenValueRanges(vector<DataRange> * value_ranges,bool trim_first_and_last_chars) const66 bool XmlTokenContext::BuildTokenValueRanges(
67     vector<DataRange>* value_ranges, bool trim_first_and_last_chars) const {
68   size_t delta = trim_first_and_last_chars ? 1 : 0;
69   auto clipped_range = GetRange().GetIntersection(token_range_);
70   if (ContainsAny(token_portion_, XmlPortion::kBegin)) {
71     value_ranges->clear();
72     if (clipped_range.IsValid()) {
73       value_ranges->push_back(
74           DataRange(clipped_range.GetBegin() + delta, clipped_range.GetEnd()));
75     }
76 
77   } else if (ContainsAny(token_portion_, kAllPortions)) {
78     if (clipped_range.IsValid()) {
79       if (!value_ranges->empty() &&
80           value_ranges->back().GetEnd() == clipped_range.GetBegin()) {
81         value_ranges->back() =
82             DataRange(value_ranges->back().GetBegin(), clipped_range.GetEnd());
83       } else {
84         value_ranges->push_back(clipped_range);
85       }
86     }
87   }
88   bool has_end = ContainsAny(token_portion_, XmlPortion::kEnd);
89   if (has_end && !value_ranges->empty() && clipped_range.IsValid() &&
90       trim_first_and_last_chars) {
91     auto& back_range = value_ranges->back();
92     back_range = DataRange(back_range.GetBegin(), back_range.GetEnd() - delta);
93   }
94   return has_end;
95 }
96 
ComputeTokenPortion(size_t token_scan_count,DataMatchResult::Type result_type)97 XmlPortion XmlTokenContext::ComputeTokenPortion(
98     size_t token_scan_count, DataMatchResult::Type result_type) {
99   const bool first_scan = token_scan_count == 1;
100   const bool subsequent_scan = token_scan_count > 1;
101   const bool full_match = result_type == DataMatchResult::kFull;
102   const bool partial_match =
103       result_type == DataMatchResult::kPartialOutOfData ||
104       result_type == DataMatchResult::kPartial;
105   XmlPortion portion = XmlPortion::kNone;
106   if (first_scan && full_match) {
107     portion = kAllPortions;
108   } else if (first_scan && partial_match) {
109     portion = XmlPortion::kBegin | XmlPortion::kMiddle;
110   } else if (subsequent_scan && full_match) {
111     portion = XmlPortion::kMiddle | XmlPortion::kEnd;
112   } else if (subsequent_scan && partial_match) {
113     portion = XmlPortion::kMiddle;
114   }
115   return portion;
116 }
117 
118 }  // namespace image_io
119 }  // namespace photos_editing_formats
120