| 147 | }; |
| 148 | |
| 149 | Result<std::vector<std::string>> GetOrderedColumnNames( |
| 150 | const csv::ReadOptions& read_options, const csv::ParseOptions& parse_options, |
| 151 | std::string_view first_block, MemoryPool* pool) { |
| 152 | // Skip BOM when reading column names (ARROW-14644, ARROW-17382) |
| 153 | auto size = first_block.length(); |
| 154 | const uint8_t* data = reinterpret_cast<const uint8_t*>(first_block.data()); |
| 155 | ARROW_ASSIGN_OR_RAISE(auto data_no_bom, util::SkipUTF8BOM(data, size)); |
| 156 | size = size - static_cast<uint32_t>(data_no_bom - data); |
| 157 | first_block = std::string_view(reinterpret_cast<const char*>(data_no_bom), size); |
| 158 | if (!read_options.column_names.empty()) { |
| 159 | return read_options.column_names; |
| 160 | } |
| 161 | |
| 162 | uint32_t parsed_size = 0; |
| 163 | int32_t max_num_rows = read_options.skip_rows + 1; |
| 164 | csv::BlockParser parser(pool, parse_options, /*num_cols=*/-1, /*first_row=*/1, |
| 165 | max_num_rows); |
| 166 | |
| 167 | RETURN_NOT_OK(parser.Parse(std::string_view{first_block}, &parsed_size)); |
| 168 | |
| 169 | if (parser.num_rows() != max_num_rows) { |
| 170 | return Status::Invalid("Could not read first ", max_num_rows, |
| 171 | " rows from CSV file, either file is truncated or" |
| 172 | " header is larger than block size"); |
| 173 | } |
| 174 | |
| 175 | if (parser.num_cols() == 0) { |
| 176 | return Status::Invalid("No columns in CSV file"); |
| 177 | } |
| 178 | |
| 179 | std::vector<std::string> column_names; |
| 180 | |
| 181 | if (read_options.autogenerate_column_names) { |
| 182 | column_names.reserve(parser.num_cols()); |
| 183 | for (int32_t i = 0; i < parser.num_cols(); ++i) { |
| 184 | std::stringstream ss; |
| 185 | ss << "f" << i; |
| 186 | column_names.emplace_back(ss.str()); |
| 187 | } |
| 188 | return column_names; |
| 189 | } |
| 190 | |
| 191 | RETURN_NOT_OK( |
| 192 | parser.VisitLastRow([&](const uint8_t* data, uint32_t size, bool quoted) -> Status { |
| 193 | std::string_view view{reinterpret_cast<const char*>(data), size}; |
| 194 | column_names.emplace_back(view); |
| 195 | return Status::OK(); |
| 196 | })); |
| 197 | |
| 198 | return column_names; |
| 199 | } |
| 200 | |
| 201 | Result<std::unordered_set<std::string>> GetColumnNames( |
| 202 | const csv::ReadOptions& read_options, const csv::ParseOptions& parse_options, |