Serializes string tensor "val". "bytes_written" is treated in the same fashion as WriteTensor(). Checksums all bytes written and stores it into "crc32c". REQUIRES: val.dtype() == DT_STRING
| 238 | // Checksums all bytes written and stores it into "crc32c". |
| 239 | // REQUIRES: val.dtype() == DT_STRING |
| 240 | Status WriteStringTensor(const Tensor& val, FileOutputBuffer* out, |
| 241 | size_t* bytes_written, uint32* crc32c) { |
| 242 | // On-disk format: |
| 243 | // [varint64 len0]..[varint64 lenL][4 byte cksum on lengths][string bytes] |
| 244 | // Var "crc32c" checksums the string lengths (as uint64, not varint64 bytes), |
| 245 | // the length-checksum, and all the string bytes. |
| 246 | DCHECK_EQ(val.dtype(), DT_STRING); |
| 247 | const tstring* strings = GetStringBackingBuffer(val); |
| 248 | |
| 249 | // Writes the varint lengths. |
| 250 | string lengths; |
| 251 | lengths.reserve(val.NumElements()); // At least 1 byte per element. |
| 252 | *crc32c = 0; |
| 253 | for (int64 i = 0; i < val.NumElements(); ++i) { |
| 254 | const tstring* elem = &strings[i]; |
| 255 | DCHECK_EQ(elem->size(), static_cast<uint64>(elem->size())); |
| 256 | const uint64 elem_size = static_cast<uint64>(elem->size()); |
| 257 | |
| 258 | core::PutVarint64(&lengths, elem_size); |
| 259 | if (elem_size <= UINT32_MAX) { |
| 260 | // We need to do this because older checkpoints only used uint32s and we |
| 261 | // should still support them. |
| 262 | const uint32 elem_size_uint32 = static_cast<uint32>(elem_size); |
| 263 | *crc32c = crc32c::Extend(*crc32c, |
| 264 | reinterpret_cast<const char*>(&elem_size_uint32), |
| 265 | sizeof(uint32)); |
| 266 | } else { |
| 267 | *crc32c = crc32c::Extend( |
| 268 | *crc32c, reinterpret_cast<const char*>(&elem_size), sizeof(uint64)); |
| 269 | } |
| 270 | } |
| 271 | TF_RETURN_IF_ERROR(out->Append(lengths)); |
| 272 | *bytes_written = lengths.size(); |
| 273 | |
| 274 | // Writes the length checksum. |
| 275 | const uint32 length_checksum = crc32c::Mask(*crc32c); |
| 276 | TF_RETURN_IF_ERROR(out->Append(StringPiece( |
| 277 | reinterpret_cast<const char*>(&length_checksum), sizeof(uint32)))); |
| 278 | *crc32c = crc32c::Extend( |
| 279 | *crc32c, reinterpret_cast<const char*>(&length_checksum), sizeof(uint32)); |
| 280 | *bytes_written += sizeof(uint32); |
| 281 | |
| 282 | // Writes all the string bytes out. |
| 283 | for (int64 i = 0; i < val.NumElements(); ++i) { |
| 284 | const tstring* string = &strings[i]; |
| 285 | TF_RETURN_IF_ERROR(out->Append(*string)); |
| 286 | *bytes_written += string->size(); |
| 287 | *crc32c = crc32c::Extend(*crc32c, string->data(), string->size()); |
| 288 | } |
| 289 | return Status::OK(); |
| 290 | } |
| 291 | |
| 292 | Status WriteVariantTensor(const Tensor& val, FileOutputBuffer* out, |
| 293 | size_t* bytes_written, uint32* crc32c) { |
no test coverage detected