stream_utils.cc revision 1b79239785bf964fd5f1a607a6ed9c9bbb57a4b1
11e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko// Copyright 2015 The Chromium OS Authors. All rights reserved. 21e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko// Use of this source code is governed by a BSD-style license that can be 31e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko// found in the LICENSE file. 41e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko 51e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko#include <chromeos/streams/stream_utils.h> 61e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko 71e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko#include <limits> 81e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko 91e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko#include <chromeos/streams/stream_errors.h> 101e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko 111e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenkonamespace chromeos { 121e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenkonamespace stream_utils { 131e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko 141e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenkobool ErrorStreamClosed(const tracked_objects::Location& location, 151e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko ErrorPtr* error) { 161e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko Error::AddTo(error, 171e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko location, 181e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko errors::stream::kDomain, 191e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko errors::stream::kStreamClosed, 201e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko "Stream is closed"); 211e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko return false; 221e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko} 231e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko 241e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenkobool ErrorOperationNotSupported(const tracked_objects::Location& location, 251e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko ErrorPtr* error) { 261e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko Error::AddTo(error, 271e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko location, 281e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko errors::stream::kDomain, 291e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko errors::stream::kOperationNotSupported, 301e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko "Stream operation not supported"); 311e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko return false; 321e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko} 331e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko 341e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenkobool ErrorReadPastEndOfStream(const tracked_objects::Location& location, 351e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko ErrorPtr* error) { 361e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko Error::AddTo(error, 371e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko location, 381e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko errors::stream::kDomain, 391e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko errors::stream::kPartialData, 401e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko "Reading past the end of stream"); 411e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko return false; 421e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko} 431e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko 441b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenkobool ErrorOperationTimeout(const tracked_objects::Location& location, 451b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko ErrorPtr* error) { 461b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko Error::AddTo(error, 471b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko location, 481b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko errors::stream::kDomain, 491b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko errors::stream::kTimeout, 501b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko "Operation timed out"); 511b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko return false; 521b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko} 531b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko 541b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko 551e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenkobool CheckInt64Overflow(const tracked_objects::Location& location, 561e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko uint64_t position, 571e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko int64_t offset, 581e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko ErrorPtr* error) { 591e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko if (offset < 0) { 601e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko // Subtracting the offset. Make sure we do not underflow. 611e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko uint64_t unsigned_offset = static_cast<uint64_t>(-offset); 621e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko if (position >= unsigned_offset) 631e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko return true; 641e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko } else { 651e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko // Adding the offset. Make sure we do not overflow unsigned 64 bits first. 661e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko if (position <= std::numeric_limits<uint64_t>::max() - offset) { 671e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko // We definitely will not overflow the unsigned 64 bit integer. 681e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko // Now check that we end up within the limits of signed 64 bit integer. 691e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko uint64_t new_position = position + offset; 701e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko uint64_t max = std::numeric_limits<int64_t>::max(); 711e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko if (new_position <= max) 721e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko return true; 731e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko } 741e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko } 751e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko Error::AddTo(error, 761e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko location, 771e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko errors::stream::kDomain, 781e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko errors::stream::kInvalidParameter, 791e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko "The stream offset value is out of range"); 801e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko return false; 811e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko} 821e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko 831e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenkobool CalculateStreamPosition(const tracked_objects::Location& location, 841e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko int64_t offset, 851e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko Stream::Whence whence, 861e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko uint64_t current_position, 871e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko uint64_t stream_size, 881e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko uint64_t* new_position, 891e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko ErrorPtr* error) { 901e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko uint64_t pos = 0; 911e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko switch (whence) { 921e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko case Stream::Whence::FROM_BEGIN: 931e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko pos = 0; 941e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko break; 951e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko 961e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko case Stream::Whence::FROM_CURRENT: 971e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko pos = current_position; 981e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko break; 991e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko 1001e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko case Stream::Whence::FROM_END: 1011e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko pos = stream_size; 1021e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko break; 1031e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko 1041e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko default: 1051e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko Error::AddTo(error, 1061e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko location, 1071e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko errors::stream::kDomain, 1081e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko errors::stream::kInvalidParameter, 1091e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko "Invalid stream position whence"); 1101e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko return false; 1111e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko } 1121e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko 1131e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko if (!CheckInt64Overflow(location, pos, offset, error)) 1141e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko return false; 1151e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko 1161e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko *new_position = static_cast<uint64_t>(pos + offset); 1171e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko return true; 1181e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko} 1191e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko 1201e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko} // namespace stream_utils 1211e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko} // namespace chromeos 122