| 238 | |
| 239 | template<typename Scalar> |
| 240 | void LoadArrayFromNumpy( |
| 241 | const std::string& filename, std::vector<int>& shape, |
| 242 | std::vector<Scalar>& data) |
| 243 | { |
| 244 | std::ifstream stream(filename.c_str(), std::ios::in|std::ios::binary); |
| 245 | if(!stream) { |
| 246 | throw std::runtime_error("io error: failed to open a file."); |
| 247 | } |
| 248 | // check if this file is the valid .npy file |
| 249 | std::string valid_preamble = "\x93NUMPY"; |
| 250 | valid_preamble.push_back(char(1)); |
| 251 | valid_preamble.push_back(char(0)); |
| 252 | std::string preamble(8, ' '); |
| 253 | stream.read(&preamble[0], 8); |
| 254 | if(valid_preamble != preamble) { |
| 255 | throw std::runtime_error( |
| 256 | "io error: this file do not have a valid npy format."); |
| 257 | } |
| 258 | // load header |
| 259 | uint16_t header_length; |
| 260 | stream.read(reinterpret_cast<char*>(&header_length), sizeof(uint16_t)); |
| 261 | header_length = detail::ReorderInteger(header_length); |
| 262 | if((header_length + preamble.size() + sizeof(uint16_t)) % 16 != 0) { |
| 263 | throw std::runtime_error( |
| 264 | "formatting error: metadata length is not divisible by 16."); |
| 265 | } |
| 266 | std::string header(header_length, ' '); |
| 267 | stream.read(reinterpret_cast<char*>(&header[0]), header_length); |
| 268 | |
| 269 | // load fortran order |
| 270 | typedef std::string::size_type size_type; |
| 271 | const size_type header_loc = header.find("fortran_order") + 16; |
| 272 | const bool fortran_order = (header.substr(header_loc, 4) == "True"); |
| 273 | |
| 274 | // load shape |
| 275 | const size_type shape_loc1 = header.find("("); |
| 276 | const size_type shape_loc2 = header.find(")"); |
| 277 | std::string shape_str = header.substr( |
| 278 | shape_loc1 + 1, shape_loc2 - shape_loc1 - 1); |
| 279 | if(shape_str[shape_str.size() - 1] == ',') shape.resize(1); |
| 280 | else shape.resize(std::count(shape_str.begin(), shape_str.end(), ',') + 1); |
| 281 | for(size_t i=0; i<shape.size(); ++i) { |
| 282 | std::stringstream ss; |
| 283 | const size_type loc = shape_str.find(","); |
| 284 | ss << shape_str.substr(0, loc); |
| 285 | ss >> shape[i]; |
| 286 | shape_str = shape_str.substr(loc + 1); |
| 287 | } |
| 288 | if(fortran_order) { |
| 289 | std::reverse(shape.begin(), shape.end()); |
| 290 | } |
| 291 | |
| 292 | // load descriptor |
| 293 | const size_type descr_loc = header.find("descr") + 9; |
| 294 | const char endian_str = header[descr_loc]; |
| 295 | const bool little_endian = (endian_str == '<' || endian_str == '|'); |
| 296 | #ifdef AOBA_NUMPY_BIG_ENDIAN |
| 297 | const bool is_same_endian = !little_endian; |
no test coverage detected