]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/nowide/src/filebuf.cpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / libs / nowide / src / filebuf.cpp
1 //
2 // Copyright (c) 2020 Alexander Grund
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8
9 #define BOOST_NOWIDE_SOURCE
10
11 #ifdef BOOST_NOWIDE_NO_LFS
12 #define BOOST_NOWIDE_FTELL ::ftell
13 #define BOOST_NOWIDE_FSEEK ::fseek
14 #define BOOST_NOWIDE_OFF_T long
15 #elif defined(_WIN32) && !defined(__CYGWIN__)
16 #define BOOST_NOWIDE_FTELL _ftelli64
17 #define BOOST_NOWIDE_FSEEK _fseeki64
18 #define BOOST_NOWIDE_OFF_T int64_t
19 #else
20 // IMPORTANT: Have these defines BEFORE any #includes
21 // and make sure changes by those macros don't leak into the public interface
22 // Make LFS functions available
23 #define _LARGEFILE_SOURCE
24 // Make off_t 64 bits if the macro isn't set
25 #ifndef _FILE_OFFSET_BITS
26 #define _FILE_OFFSET_BITS 64
27 #endif
28
29 #define BOOST_NOWIDE_FTELL ftello
30 #define BOOST_NOWIDE_FSEEK fseeko
31 #define BOOST_NOWIDE_OFF_T off_t
32 #endif
33
34 #include <boost/nowide/filebuf.hpp>
35 #include <cassert>
36 #include <cstdint>
37 #include <limits>
38 #include <stdio.h>
39 #include <type_traits>
40
41 namespace boost {
42 namespace nowide {
43 namespace detail {
44
45 template<typename T, typename U>
46 constexpr bool is_in_range(U value)
47 {
48 static_assert(std::is_signed<T>::value == std::is_signed<U>::value,
49 "Mixed sign comparison can lead to problems below");
50 // coverity[result_independent_of_operands]
51 return value >= std::numeric_limits<T>::min() && value <= std::numeric_limits<T>::max();
52 }
53
54 template<typename T, typename U>
55 T cast_if_valid_or_minus_one(U value)
56 {
57 return is_in_range<T>(value) ? static_cast<T>(value) : T(-1);
58 }
59
60 std::streampos ftell(FILE* file)
61 {
62 const auto pos = BOOST_NOWIDE_FTELL(file);
63 // Note that this is used in seekoff for which the standard states:
64 // On success, it returns the new absolute position the internal position pointer points to after the call,
65 // if representable [...] [or] the function returns pos_type(off_type(-1)). Hence we do a range check first,
66 // then cast or return failure instead of silently truncating
67 return cast_if_valid_or_minus_one<std::streamoff>(pos);
68 }
69
70 int fseek(FILE* file, std::streamoff offset, int origin)
71 {
72 // Similar to above: If the value of offset can't fit inside target type
73 // don't silently truncate but fail right away
74 if(!is_in_range<BOOST_NOWIDE_OFF_T>(offset))
75 return -1;
76 return BOOST_NOWIDE_FSEEK(file, static_cast<BOOST_NOWIDE_OFF_T>(offset), origin);
77 }
78 } // namespace detail
79 } // namespace nowide
80 } // namespace boost