Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
string_util.cc
Go to the documentation of this file.
1// Copyright 2010-2024 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#include <algorithm>
15#include <string>
16#include <vector>
17
18#include "absl/strings/str_format.h"
19#include "absl/strings/str_join.h"
20#include "absl/strings/str_split.h"
22
23namespace operations_research {
24
25std::string CropMultiLineString(const std::string& s, int max_line_length,
26 int max_num_lines) {
27 if (s.empty()) return "";
28 std::vector<std::string> lines = absl::StrSplit(s, '\n');
29 DCHECK_GE(lines.size(), 1); // Even an empty string yields one (empty) line.
30 // We ignore the terminating newline for line accounting, but we do output it
31 // back in the end.
32 const bool has_terminating_newline = lines.back().empty();
33 if (has_terminating_newline) lines.pop_back();
34
35 constexpr char kMultiLineCropTemplate[] = "###% 4d LINES SKIPPED ###";
36 constexpr char kSingleLineCropTemplate[] = " ..[% 4d CHARS CROPPED ].. ";
37 const int single_line_crop_template_length =
38 absl::StrFormat(kSingleLineCropTemplate, 0).size();
39 int num_lines_before = -1;
40 int num_lines_after = -1;
41 int num_lines_cropped = -1;
42 if (lines.size() > max_num_lines) {
43 num_lines_after = (max_num_lines - 1) / 2;
44 // There's a corner case for max_num_lines=0. See the unit test.
45 num_lines_before =
46 max_num_lines == 0 ? 0 : max_num_lines - 1 - num_lines_after;
47 num_lines_cropped = lines.size() - num_lines_before - num_lines_after;
48 lines.erase(lines.begin() + num_lines_before + 1,
49 lines.end() - num_lines_after);
50 // We only fill the special line mentioning the skipped lines after we're
51 // done with the horizontal crops, in the loop below.
52 lines[num_lines_before].clear();
53 }
54 for (std::string& line : lines) {
55 if (line.size() <= max_line_length) continue;
56 const int num_chars_after = std::max(
57 0, static_cast<int>(
58 (max_line_length - single_line_crop_template_length) / 2));
59 const int num_chars_before = std::max(
60 0, static_cast<int>(max_line_length - single_line_crop_template_length -
61 num_chars_after));
62 line = absl::StrCat(
63 line.substr(0, num_chars_before),
64 absl::StrFormat(
65 kSingleLineCropTemplate,
66 static_cast<int>(line.size() - num_chars_after - num_chars_before)),
67 line.substr(line.size() - num_chars_after));
68 }
69 if (num_lines_cropped >= 0) {
70 lines[num_lines_before] =
71 absl::StrFormat(kMultiLineCropTemplate, num_lines_cropped);
72 }
73 if (has_terminating_newline) lines.push_back("");
74 return absl::StrJoin(lines, "\n");
75}
76
77} // namespace operations_research
In SWIG mode, we don't want anything besides these top-level includes.
std::string CropMultiLineString(const std::string &s, int max_line_length, int max_num_lines)
int line