Extended MaximInterface
Dependents: mbed_DS28EC20_GPIO
Diff: Utilities/Segment.hpp
- Revision:
- 0:f77ad7f72d04
- Child:
- 6:a8c83a2e6fa4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Utilities/Segment.hpp Mon Nov 06 14:39:18 2017 -0600 @@ -0,0 +1,131 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterface_Segment +#define MaximInterface_Segment + +#include <iterator> +#include <utility> +#include "type_traits.hpp" + +namespace MaximInterface { + +/// Advances a given iterator by a given number of elements with bounds checking. +/// InputIt must meet the requirements of InputIterator. +/// @param[in,out] it Iterator to advance. +/// @param bound +/// Past-the-end boundary iterator. If distance is positive, bound must be +/// reachable by incrementing the given iterator. If distance is negative, bound +/// must be reachable by decrementing the given iterator. +/// @param distance +/// Number of elements to advance the given iterator. If distance is positive, +/// the given iterator is incremented. If distance is negative, the given +/// iterator is decremented, and InputIt must meet the requirements of +/// BidirectionalIterator. +/// @returns The number of elements that the given iterator was advanced. +template <typename InputIt> +typename std::iterator_traits<InputIt>::difference_type checkedAdvance( + InputIt & it, const InputIt bound, + typename std::iterator_traits<InputIt>::difference_type distance) { + typedef + typename std::iterator_traits<InputIt>::difference_type difference_type; + + // Use constant-time operations if InputIt is a random access iterator. + if (is_same<typename std::iterator_traits<InputIt>::iterator_category, + std::random_access_iterator_tag>::value) { + const difference_type boundDistance = std::distance(it, bound); + if (boundDistance >= 0) { + if (distance > boundDistance) { + distance = boundDistance; + } else if (distance < 0) { + distance = 0; + } + } else { + if (distance < boundDistance) { + distance = boundDistance; + } else if (distance > 0) { + distance = 0; + } + } + std::advance(it, distance); + } else { + const difference_type startingDistance = distance; + while (distance != 0 && it != bound) { + if (distance > 0) { + ++it; + --distance; + } else { + --it; + ++distance; + } + } + if (startingDistance > 0) { + distance = startingDistance - distance; + } else { + distance = startingDistance + distance; + } + } + return distance; +} + +/// Locates an iterator sub-range using segment number addressing. Useful for +/// devices that divide the memory space into uniform chunks such as pages and +/// segments. ForwardIt must meet the requirements of ForwardIterator. +/// @param begin Beginning of the input data range. +/// @param end End of the input data range. +/// @param segmentSize Number of elements contained in a segment. +/// @param segmentNum Zero-indexed number of the desired segment. +/// @returns Pair of iterators representing the sub-range of the segment within +/// the input range. If the segment does not exist within the input range, both +/// iterators in the pair are set to the end interator of the input range. +template <typename ForwardIt, typename Index> +std::pair<ForwardIt, ForwardIt> createSegment( + ForwardIt begin, const ForwardIt end, + const typename std::iterator_traits<ForwardIt>::difference_type segmentSize, + Index segmentNum) { + ForwardIt segmentEnd = begin; + typename std::iterator_traits<ForwardIt>::difference_type lastSegmentSize = + checkedAdvance(segmentEnd, end, segmentSize); + while (segmentNum > 0 && segmentEnd != end) { + begin = segmentEnd; + lastSegmentSize = checkedAdvance(segmentEnd, end, segmentSize); + --segmentNum; + } + if (segmentNum > 0 || lastSegmentSize != segmentSize) { + begin = segmentEnd; + } + return std::make_pair(begin, segmentEnd); +} + +} // namespace MaximInterface + +#endif \ No newline at end of file