| 1342 | } |
| 1343 | |
| 1344 | void TF_OperationGetAttrStringList(TF_Operation* oper, const char* attr_name, |
| 1345 | void** values, size_t* lengths, |
| 1346 | int max_values, void* storage, |
| 1347 | size_t storage_size, TF_Status* status) { |
| 1348 | const auto* attr = GetAttrValue(oper, attr_name, status); |
| 1349 | if (TF_GetCode(status) != TF_OK) return; |
| 1350 | if (attr->value_case() != tensorflow::AttrValue::kList) { |
| 1351 | status->status = |
| 1352 | InvalidArgument("Value for '", attr_name, "' is not a list"); |
| 1353 | return; |
| 1354 | } |
| 1355 | const auto len = std::min(max_values, attr->list().s_size()); |
| 1356 | char* p = static_cast<char*>(storage); |
| 1357 | for (int i = 0; i < len; ++i) { |
| 1358 | const string& s = attr->list().s(i); |
| 1359 | values[i] = p; |
| 1360 | lengths[i] = s.size(); |
| 1361 | if ((p + s.size()) > (static_cast<char*>(storage) + storage_size)) { |
| 1362 | status->status = InvalidArgument( |
| 1363 | "Not enough storage to hold the requested list of strings"); |
| 1364 | return; |
| 1365 | } |
| 1366 | memcpy(values[i], s.data(), s.size()); |
| 1367 | p += s.size(); |
| 1368 | } |
| 1369 | } |
| 1370 | |
| 1371 | #define DEFINE_GETATTR(func, c_type, cpp_type, list_field) \ |
| 1372 | void func(TF_Operation* oper, const char* attr_name, c_type* value, \ |