| 270 | } |
| 271 | |
| 272 | void Compute(OpKernelContext* ctx) override { |
| 273 | const Tensor* input_tensor; |
| 274 | OP_REQUIRES_OK(ctx, ctx->input("input", &input_tensor)); |
| 275 | |
| 276 | static thread_local std::unique_ptr<WrappedConverter> input_encoder; |
| 277 | if (!input_encoder) { |
| 278 | input_encoder.reset(new WrappedConverter()); |
| 279 | } |
| 280 | input_encoder->init(input_encoding_); |
| 281 | OP_REQUIRES(ctx, input_encoder->converter_, |
| 282 | errors::InvalidArgument( |
| 283 | "Could not create converter for input encoding: " + |
| 284 | input_encoding_)); |
| 285 | |
| 286 | // Output may be forwardable from input, in which case work in-place. |
| 287 | Tensor* output_tensor; |
| 288 | std::unique_ptr<Tensor> maybe_forwarded = |
| 289 | ctx->forward_input(0 /*input_index*/, 0 /*output_index*/, |
| 290 | tensorflow::DT_STRING, input_tensor->shape(), |
| 291 | ctx->input_memory_type(0), ctx->input_alloc_attr(0)); |
| 292 | if (maybe_forwarded) { |
| 293 | output_tensor = maybe_forwarded.get(); |
| 294 | OP_REQUIRES_OK(ctx, ctx->set_output("output", *output_tensor)); |
| 295 | } else { |
| 296 | OP_REQUIRES_OK(ctx, ctx->allocate_output("output", input_tensor->shape(), |
| 297 | &output_tensor)); |
| 298 | output_tensor->flat<tstring>() = input_tensor->flat<tstring>(); |
| 299 | } |
| 300 | |
| 301 | auto output_flat = output_tensor->flat<tstring>(); |
| 302 | bool found_any_format_error = false; |
| 303 | for (size_t i = 0; i < output_flat.size(); ++i) { |
| 304 | Transcode(&(output_flat(i)), input_encoder->converter_, |
| 305 | &found_any_format_error); |
| 306 | } |
| 307 | if (error_options_.error_on_malformatting && found_any_format_error) { |
| 308 | ctx->CtxFailure( |
| 309 | errors::InvalidArgument("Invalid formatting on input string")); |
| 310 | } |
| 311 | } |
| 312 | |
| 313 | private: |
| 314 | // Consume a codepoint from the input string and add it to the buffer. |
nothing calls this directly
no test coverage detected