18#include "absl/container/inlined_vector.h"
19#include "absl/status/status.h"
20#include "absl/status/statusor.h"
21#include "absl/strings/ascii.h"
22#include "absl/strings/match.h"
23#include "absl/strings/string_view.h"
30static constexpr int kFieldStartPos[kNumMpsFields] = {1, 4, 14, 24, 39, 49};
33static constexpr int kFieldLength[kNumMpsFields] = {2, 8, 8, 12, 8, 12};
36static constexpr int kSpacePos[12] = {12, 13, 22, 23, 36, 37,
37 38, 47, 48, 61, 62, 63};
42absl::StatusOr<MPSLineInfo> MPSLineInfo::Create(int64_t line_num,
44 absl::string_view
line) {
46 line = absl::StripTrailingAsciiWhitespace(
line);
47 if (!free_form && absl::StrContains(
line,
'\t')) {
48 return absl::InvalidArgumentError(
"File contains tabs.");
51 MPSLineInfo line_info = MPSLineInfo(line_num, free_form,
line);
52 if (!free_form && !line_info.IsFixedFormat()) {
53 return line_info.InvalidArgumentError(
"Line is not in fixed format.");
55 if (!line_info.IsCommentOrBlank()) {
61bool MPSLineInfo::IsFixedFormat()
const {
62 if (IsCommentOrBlank()) {
66 absl::string_view first_word = GetFirstWord();
73 return first_word == line_ || first_word ==
"NAME";
75 constexpr int kMaxLineSize =
76 kFieldStartPos[kNumMpsFields - 1] + kFieldLength[kNumMpsFields - 1];
78 const int line_size = line_.size();
79 if (line_size > kMaxLineSize)
return false;
80 for (
const int i : kSpacePos) {
81 if (i >= line_size)
break;
82 if (line_[i] !=
' ')
return false;
87absl::Status MPSLineInfo::SplitLineIntoFields() {
89 absl::string_view remaining_line = absl::StripLeadingAsciiWhitespace(line_);
93 while (!remaining_line.empty()) {
94 if (fields_.size() == kNumMpsFields) {
95 return InvalidArgumentError(
"Found too many fields.");
99 const int pos = remaining_line.find_first_of(
" \t");
100 fields_.push_back(remaining_line.substr(0, pos));
101 if (pos == absl::string_view::npos) {
106 absl::StripLeadingAsciiWhitespace(remaining_line.substr(pos));
109 const int line_size = line_.size();
110 for (
int i = 0;
i < kNumMpsFields; ++
i) {
111 if (kFieldStartPos[i] >= line_size)
break;
112 fields_.push_back(absl::StripTrailingAsciiWhitespace(
113 line_.substr(kFieldStartPos[i], kFieldLength[i])));
116 return absl::OkStatus();
119absl::string_view MPSLineInfo::GetFirstWord()
const {
120 return line_.substr(0, line_.find(
' '));
123bool MPSLineInfo::IsCommentOrBlank()
const {
126 return (line_.empty() || line_[0] ==
'*');
129absl::Status MPSLineInfo::InvalidArgumentError(
130 absl::string_view error_message)
const {
131 return AppendLineToError(absl::InvalidArgumentError(error_message));
134absl::Status MPSLineInfo::AppendLineToError(
const absl::Status&
status)
const {
136 <<
" Line " << line_num_ <<
": \"" << line_ <<
"\".";
#define RETURN_IF_ERROR(expr)
StatusBuilder & SetAppend()
End of the interface. Below is the implementation.