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