1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "mojo/common/data_pipe_utils.h" 6 7#include <utility> 8 9#include "base/bind.h" 10 11namespace mojo { 12namespace common { 13namespace { 14 15bool BlockingCopyHelper(ScopedDataPipeConsumerHandle source, 16 const base::Callback<size_t(const void*, uint32_t)>& write_bytes) { 17 for (;;) { 18 const void* buffer; 19 uint32_t num_bytes; 20 MojoResult result = BeginReadDataRaw( 21 source.get(), &buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE); 22 if (result == MOJO_RESULT_OK) { 23 size_t bytes_written = write_bytes.Run(buffer, num_bytes); 24 result = EndReadDataRaw(source.get(), num_bytes); 25 if (bytes_written < num_bytes || result != MOJO_RESULT_OK) 26 return false; 27 } else if (result == MOJO_RESULT_SHOULD_WAIT) { 28 result = Wait(source.get(), 29 MOJO_HANDLE_SIGNAL_READABLE, 30 MOJO_DEADLINE_INDEFINITE, 31 nullptr); 32 if (result != MOJO_RESULT_OK) { 33 // If the producer handle was closed, then treat as EOF. 34 return result == MOJO_RESULT_FAILED_PRECONDITION; 35 } 36 } else if (result == MOJO_RESULT_FAILED_PRECONDITION) { 37 // If the producer handle was closed, then treat as EOF. 38 return true; 39 } else { 40 // Some other error occurred. 41 break; 42 } 43 } 44 45 return false; 46} 47 48size_t CopyToStringHelper( 49 std::string* result, const void* buffer, uint32_t num_bytes) { 50 result->append(static_cast<const char*>(buffer), num_bytes); 51 return num_bytes; 52} 53 54} // namespace 55 56// TODO(hansmuller): Add a max_size parameter. 57bool BlockingCopyToString(ScopedDataPipeConsumerHandle source, 58 std::string* result) { 59 CHECK(result); 60 result->clear(); 61 return BlockingCopyHelper(std::move(source), 62 base::Bind(&CopyToStringHelper, result)); 63} 64 65bool MOJO_COMMON_EXPORT BlockingCopyFromString( 66 const std::string& source, 67 const ScopedDataPipeProducerHandle& destination) { 68 auto it = source.begin(); 69 for (;;) { 70 void* buffer = nullptr; 71 uint32_t buffer_num_bytes = 0; 72 MojoResult result = 73 BeginWriteDataRaw(destination.get(), &buffer, &buffer_num_bytes, 74 MOJO_WRITE_DATA_FLAG_NONE); 75 if (result == MOJO_RESULT_OK) { 76 char* char_buffer = static_cast<char*>(buffer); 77 uint32_t byte_index = 0; 78 while (it != source.end() && byte_index < buffer_num_bytes) { 79 char_buffer[byte_index++] = *it++; 80 } 81 EndWriteDataRaw(destination.get(), byte_index); 82 if (it == source.end()) 83 return true; 84 } else if (result == MOJO_RESULT_SHOULD_WAIT) { 85 result = Wait(destination.get(), MOJO_HANDLE_SIGNAL_WRITABLE, 86 MOJO_DEADLINE_INDEFINITE, nullptr); 87 if (result != MOJO_RESULT_OK) { 88 // If the consumer handle was closed, then treat as EOF. 89 return result == MOJO_RESULT_FAILED_PRECONDITION; 90 } 91 } else { 92 // If the consumer handle was closed, then treat as EOF. 93 return result == MOJO_RESULT_FAILED_PRECONDITION; 94 } 95 } 96} 97 98} // namespace common 99} // namespace mojo 100