xref: /aosp_15_r20/external/image_io/src/base/data_context.cc (revision ca0779eb572efbbfda2e47f806647c3c7eeea8c3)
1*ca0779ebSJerome Gaillard #include "image_io/base/data_context.h"
2*ca0779ebSJerome Gaillard 
3*ca0779ebSJerome Gaillard #include <algorithm>
4*ca0779ebSJerome Gaillard #include <cctype>
5*ca0779ebSJerome Gaillard #include <iomanip>
6*ca0779ebSJerome Gaillard #include <sstream>
7*ca0779ebSJerome Gaillard #include <string>
8*ca0779ebSJerome Gaillard 
9*ca0779ebSJerome Gaillard #include "image_io/base/byte_data.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 
AddNames(const std::list<std::string> & name_list,std::stringstream * ss)16*ca0779ebSJerome Gaillard void AddNames(const std::list<std::string>& name_list, std::stringstream* ss) {
17*ca0779ebSJerome Gaillard   for (const auto& name : name_list) {
18*ca0779ebSJerome Gaillard     *ss << name << ":";
19*ca0779ebSJerome Gaillard   }
20*ca0779ebSJerome Gaillard }
21*ca0779ebSJerome Gaillard 
22*ca0779ebSJerome Gaillard }  // namespace
23*ca0779ebSJerome Gaillard 
GetInvalidLocationAndRangeErrorText() const24*ca0779ebSJerome Gaillard std::string DataContext::GetInvalidLocationAndRangeErrorText() const {
25*ca0779ebSJerome Gaillard   std::stringstream ss;
26*ca0779ebSJerome Gaillard   ss << "Invalid location:" << location_ << " range:[" << range_.GetBegin()
27*ca0779ebSJerome Gaillard      << "," << range_.GetEnd() << ") segment_range:["
28*ca0779ebSJerome Gaillard      << segment_.GetDataRange().GetBegin() << ","
29*ca0779ebSJerome Gaillard      << segment_.GetDataRange().GetEnd() << ")";
30*ca0779ebSJerome Gaillard   return GetErrorText(ss.str(), "");
31*ca0779ebSJerome Gaillard }
32*ca0779ebSJerome Gaillard 
GetErrorText(const std::string & error_description,const std::string & expectation_description) const33*ca0779ebSJerome Gaillard std::string DataContext::GetErrorText(
34*ca0779ebSJerome Gaillard     const std::string& error_description,
35*ca0779ebSJerome Gaillard     const std::string& expectation_description) const {
36*ca0779ebSJerome Gaillard   std::list<std::string> none;
37*ca0779ebSJerome Gaillard   return GetErrorText(none, none, error_description, expectation_description);
38*ca0779ebSJerome Gaillard }
39*ca0779ebSJerome Gaillard 
GetErrorText(const std::list<std::string> & prefix_name_list,const std::list<std::string> & postfix_name_list,const std::string & error_description,const std::string & expectation_description) const40*ca0779ebSJerome Gaillard std::string DataContext::GetErrorText(
41*ca0779ebSJerome Gaillard     const std::list<std::string>& prefix_name_list,
42*ca0779ebSJerome Gaillard     const std::list<std::string>& postfix_name_list,
43*ca0779ebSJerome Gaillard     const std::string& error_description,
44*ca0779ebSJerome Gaillard     const std::string& expectation_description) const {
45*ca0779ebSJerome Gaillard   const std::string kContinue("- ");
46*ca0779ebSJerome Gaillard   std::stringstream ss;
47*ca0779ebSJerome Gaillard 
48*ca0779ebSJerome Gaillard   // Write error description if present.
49*ca0779ebSJerome Gaillard   if (!error_description.empty()) {
50*ca0779ebSJerome Gaillard     ss << error_description << std::endl;
51*ca0779ebSJerome Gaillard   }
52*ca0779ebSJerome Gaillard 
53*ca0779ebSJerome Gaillard   // Write name:name:... if present.
54*ca0779ebSJerome Gaillard   std::string names_string =
55*ca0779ebSJerome Gaillard       GetNamesString(prefix_name_list, postfix_name_list);
56*ca0779ebSJerome Gaillard   if (!names_string.empty()) {
57*ca0779ebSJerome Gaillard     ss << kContinue << names_string << std::endl;
58*ca0779ebSJerome Gaillard   }
59*ca0779ebSJerome Gaillard 
60*ca0779ebSJerome Gaillard   // Get the line:XX part of the line string.
61*ca0779ebSJerome Gaillard   DataLine data_line;
62*ca0779ebSJerome Gaillard   std::string line_number_string;
63*ca0779ebSJerome Gaillard   if (IsValidLocationAndRange()) {
64*ca0779ebSJerome Gaillard     data_line = line_info_map_.GetDataLine(location_);
65*ca0779ebSJerome Gaillard     line_number_string = GetLineNumberString(data_line);
66*ca0779ebSJerome Gaillard   }
67*ca0779ebSJerome Gaillard 
68*ca0779ebSJerome Gaillard   // Get the line_string related ranges and the line string.
69*ca0779ebSJerome Gaillard   DataRange clipped_range, line_range;
70*ca0779ebSJerome Gaillard   size_t spaces_before_caret = line_number_string.length();
71*ca0779ebSJerome Gaillard   GetClippedAndLineRange(data_line, &clipped_range, &line_range);
72*ca0779ebSJerome Gaillard   std::string line_string =
73*ca0779ebSJerome Gaillard       GetLineString(clipped_range, line_range, &spaces_before_caret);
74*ca0779ebSJerome Gaillard 
75*ca0779ebSJerome Gaillard   // Write the line string
76*ca0779ebSJerome Gaillard   ss << kContinue << line_number_string << line_string << std::endl;
77*ca0779ebSJerome Gaillard 
78*ca0779ebSJerome Gaillard   // Write the caret and expectation description
79*ca0779ebSJerome Gaillard   size_t spaces_count = location_ + spaces_before_caret - line_range.GetBegin();
80*ca0779ebSJerome Gaillard   std::string spaces(spaces_count, ' ');
81*ca0779ebSJerome Gaillard   ss << kContinue << spaces << '^';
82*ca0779ebSJerome Gaillard   if (!expectation_description.empty()) {
83*ca0779ebSJerome Gaillard     ss << "expected:" << expectation_description;
84*ca0779ebSJerome Gaillard   }
85*ca0779ebSJerome Gaillard   return ss.str();
86*ca0779ebSJerome Gaillard }
87*ca0779ebSJerome Gaillard 
GetNamesString(const std::list<std::string> & prefix_name_list,const std::list<std::string> & postfix_name_list) const88*ca0779ebSJerome Gaillard std::string DataContext::GetNamesString(
89*ca0779ebSJerome Gaillard     const std::list<std::string>& prefix_name_list,
90*ca0779ebSJerome Gaillard     const std::list<std::string>& postfix_name_list) const {
91*ca0779ebSJerome Gaillard   std::stringstream ss;
92*ca0779ebSJerome Gaillard   if (!prefix_name_list.empty() || !name_list_.empty() ||
93*ca0779ebSJerome Gaillard       !postfix_name_list.empty()) {
94*ca0779ebSJerome Gaillard     AddNames(prefix_name_list, &ss);
95*ca0779ebSJerome Gaillard     AddNames(name_list_, &ss);
96*ca0779ebSJerome Gaillard     AddNames(postfix_name_list, &ss);
97*ca0779ebSJerome Gaillard   }
98*ca0779ebSJerome Gaillard   return ss.str();
99*ca0779ebSJerome Gaillard }
100*ca0779ebSJerome Gaillard 
GetLineNumberString(const DataLine & data_line) const101*ca0779ebSJerome Gaillard std::string DataContext::GetLineNumberString(const DataLine& data_line) const {
102*ca0779ebSJerome Gaillard   std::stringstream liness;
103*ca0779ebSJerome Gaillard   liness << "line:";
104*ca0779ebSJerome Gaillard   if (data_line.number == 0) {
105*ca0779ebSJerome Gaillard     liness << "?:";
106*ca0779ebSJerome Gaillard   } else {
107*ca0779ebSJerome Gaillard     liness << data_line.number << ":";
108*ca0779ebSJerome Gaillard   }
109*ca0779ebSJerome Gaillard   return liness.str();
110*ca0779ebSJerome Gaillard }
111*ca0779ebSJerome Gaillard 
GetClippedAndLineRange(const DataLine & data_line,DataRange * clipped_range,DataRange * line_range) const112*ca0779ebSJerome Gaillard void DataContext::GetClippedAndLineRange(const DataLine& data_line,
113*ca0779ebSJerome Gaillard                                          DataRange* clipped_range,
114*ca0779ebSJerome Gaillard                                          DataRange* line_range) const {
115*ca0779ebSJerome Gaillard   // Lines could be really long, so provide some sane limits: some kLimit chars
116*ca0779ebSJerome Gaillard   // on either side of the current location.
117*ca0779ebSJerome Gaillard   const size_t kLimit = 25;
118*ca0779ebSJerome Gaillard   size_t line_begin, line_end;
119*ca0779ebSJerome Gaillard   *clipped_range = data_line.range.IsValid()
120*ca0779ebSJerome Gaillard                        ? range_.GetIntersection(data_line.range)
121*ca0779ebSJerome Gaillard                        : range_;
122*ca0779ebSJerome Gaillard   if (clipped_range->IsValid() && clipped_range->Contains(location_)) {
123*ca0779ebSJerome Gaillard     line_begin = (clipped_range->GetBegin() + kLimit < location_)
124*ca0779ebSJerome Gaillard                      ? location_ - kLimit
125*ca0779ebSJerome Gaillard                      : clipped_range->GetBegin();
126*ca0779ebSJerome Gaillard     line_end = std::min(line_begin + 2 * kLimit, clipped_range->GetEnd());
127*ca0779ebSJerome Gaillard   } else {
128*ca0779ebSJerome Gaillard     line_begin = location_;
129*ca0779ebSJerome Gaillard     line_end = std::min(location_ + 2 * kLimit, range_.GetEnd());
130*ca0779ebSJerome Gaillard     *clipped_range = DataRange(line_begin, line_end);
131*ca0779ebSJerome Gaillard   }
132*ca0779ebSJerome Gaillard   *line_range = DataRange(line_begin, line_end);
133*ca0779ebSJerome Gaillard }
134*ca0779ebSJerome Gaillard 
GetLineString(const DataRange & clipped_range,const DataRange & line_range,size_t * spaces_before_caret) const135*ca0779ebSJerome Gaillard std::string DataContext::GetLineString(const DataRange& clipped_range,
136*ca0779ebSJerome Gaillard                                        const DataRange& line_range,
137*ca0779ebSJerome Gaillard                                        size_t* spaces_before_caret) const {
138*ca0779ebSJerome Gaillard   std::stringstream ss;
139*ca0779ebSJerome Gaillard   if (!IsValidLocationAndRange()) {
140*ca0779ebSJerome Gaillard     ss << "Invalid location or range";
141*ca0779ebSJerome Gaillard     return ss.str();
142*ca0779ebSJerome Gaillard   }
143*ca0779ebSJerome Gaillard 
144*ca0779ebSJerome Gaillard   const char* cbytes =
145*ca0779ebSJerome Gaillard       reinterpret_cast<const char*>(segment_.GetBuffer(line_range.GetBegin()));
146*ca0779ebSJerome Gaillard   if (cbytes != nullptr) {
147*ca0779ebSJerome Gaillard     if (line_range.GetBegin() != clipped_range.GetBegin()) {
148*ca0779ebSJerome Gaillard       ss << "...";
149*ca0779ebSJerome Gaillard       *spaces_before_caret += 3;
150*ca0779ebSJerome Gaillard     }
151*ca0779ebSJerome Gaillard     for (size_t index = 0; index < line_range.GetLength(); ++index) {
152*ca0779ebSJerome Gaillard       char cbyte = cbytes[index];
153*ca0779ebSJerome Gaillard       if (isprint(cbyte)) {
154*ca0779ebSJerome Gaillard         ss << cbyte;
155*ca0779ebSJerome Gaillard       } else {
156*ca0779ebSJerome Gaillard         ss << "\\x" << ByteData::Byte2Hex(cbyte);
157*ca0779ebSJerome Gaillard         if (index + line_range.GetBegin() < location_) {
158*ca0779ebSJerome Gaillard           *spaces_before_caret += 4;
159*ca0779ebSJerome Gaillard         }
160*ca0779ebSJerome Gaillard       }
161*ca0779ebSJerome Gaillard     }
162*ca0779ebSJerome Gaillard     if (line_range.GetEnd() != clipped_range.GetEnd()) {
163*ca0779ebSJerome Gaillard       ss << "...";
164*ca0779ebSJerome Gaillard     }
165*ca0779ebSJerome Gaillard   }
166*ca0779ebSJerome Gaillard   return ss.str();
167*ca0779ebSJerome Gaillard }
168*ca0779ebSJerome Gaillard 
169*ca0779ebSJerome Gaillard }  // namespace image_io
170*ca0779ebSJerome Gaillard }  // namespace photos_editing_formats
171