Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-17 09:37:10

0001 // Copyright 2017 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //      https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 
0015 #ifndef ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_
0016 #define ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_
0017 
0018 #include <algorithm>
0019 #include <cstdint>
0020 #include <iterator>
0021 #include <type_traits>
0022 #include <utility>
0023 #include <vector>
0024 
0025 #include "absl/base/macros.h"
0026 #include "absl/container/inlined_vector.h"
0027 #include "absl/meta/type_traits.h"
0028 #include "absl/random/internal/pool_urbg.h"
0029 #include "absl/random/internal/salted_seed_seq.h"
0030 #include "absl/random/internal/seed_material.h"
0031 #include "absl/types/span.h"
0032 
0033 namespace absl {
0034 ABSL_NAMESPACE_BEGIN
0035 namespace random_internal {
0036 
0037 // RandenPoolSeedSeq is a custom seed sequence type where generate() fills the
0038 // provided buffer via the RandenPool entropy source.
0039 class RandenPoolSeedSeq {
0040  private:
0041   struct ContiguousTag {};
0042   struct BufferTag {};
0043 
0044   // Generate random unsigned values directly into the buffer.
0045   template <typename Contiguous>
0046   void generate_impl(ContiguousTag, Contiguous begin, Contiguous end) {
0047     const size_t n = static_cast<size_t>(std::distance(begin, end));
0048     auto* a = &(*begin);
0049     RandenPool<uint8_t>::Fill(
0050         absl::MakeSpan(reinterpret_cast<uint8_t*>(a), sizeof(*a) * n));
0051   }
0052 
0053   // Construct a buffer of size n and fill it with values, then copy
0054   // those values into the seed iterators.
0055   template <typename RandomAccessIterator>
0056   void generate_impl(BufferTag, RandomAccessIterator begin,
0057                      RandomAccessIterator end) {
0058     const size_t n = std::distance(begin, end);
0059     absl::InlinedVector<uint32_t, 8> data(n, 0);
0060     RandenPool<uint32_t>::Fill(absl::MakeSpan(data.begin(), data.end()));
0061     std::copy(std::begin(data), std::end(data), begin);
0062   }
0063 
0064  public:
0065   using result_type = uint32_t;
0066 
0067   size_t size() { return 0; }
0068 
0069   template <typename OutIterator>
0070   void param(OutIterator) const {}
0071 
0072   template <typename RandomAccessIterator>
0073   void generate(RandomAccessIterator begin, RandomAccessIterator end) {
0074     // RandomAccessIterator must be assignable from uint32_t
0075     if (begin != end) {
0076       using U = typename std::iterator_traits<RandomAccessIterator>::value_type;
0077       // ContiguousTag indicates the common case of a known contiguous buffer,
0078       // which allows directly filling the buffer. In C++20,
0079       // std::contiguous_iterator_tag provides a mechanism for testing this
0080       // capability, however until Abseil's support requirements allow us to
0081       // assume C++20, limit checks to a few common cases.
0082       using TagType = absl::conditional_t<
0083           (std::is_pointer<RandomAccessIterator>::value ||
0084            std::is_same<RandomAccessIterator,
0085                         typename std::vector<U>::iterator>::value),
0086           ContiguousTag, BufferTag>;
0087 
0088       generate_impl(TagType{}, begin, end);
0089     }
0090   }
0091 };
0092 
0093 // Each instance of NonsecureURBGBase<URBG> will be seeded by variates produced
0094 // by a thread-unique URBG-instance.
0095 template <typename URBG, typename Seeder = RandenPoolSeedSeq>
0096 class NonsecureURBGBase {
0097  public:
0098   using result_type = typename URBG::result_type;
0099 
0100   // Default constructor
0101   NonsecureURBGBase() : urbg_(ConstructURBG()) {}
0102 
0103   // Copy disallowed, move allowed.
0104   NonsecureURBGBase(const NonsecureURBGBase&) = delete;
0105   NonsecureURBGBase& operator=(const NonsecureURBGBase&) = delete;
0106   NonsecureURBGBase(NonsecureURBGBase&&) = default;
0107   NonsecureURBGBase& operator=(NonsecureURBGBase&&) = default;
0108 
0109   // Constructor using a seed
0110   template <class SSeq, typename = typename absl::enable_if_t<
0111                             !std::is_same<SSeq, NonsecureURBGBase>::value>>
0112   explicit NonsecureURBGBase(SSeq&& seq)
0113       : urbg_(ConstructURBG(std::forward<SSeq>(seq))) {}
0114 
0115   // Note: on MSVC, min() or max() can be interpreted as MIN() or MAX(), so we
0116   // enclose min() or max() in parens as (min)() and (max)().
0117   // Additionally, clang-format requires no space before this construction.
0118 
0119   // NonsecureURBGBase::min()
0120   static constexpr result_type(min)() { return (URBG::min)(); }
0121 
0122   // NonsecureURBGBase::max()
0123   static constexpr result_type(max)() { return (URBG::max)(); }
0124 
0125   // NonsecureURBGBase::operator()()
0126   result_type operator()() { return urbg_(); }
0127 
0128   // NonsecureURBGBase::discard()
0129   void discard(unsigned long long values) {  // NOLINT(runtime/int)
0130     urbg_.discard(values);
0131   }
0132 
0133   bool operator==(const NonsecureURBGBase& other) const {
0134     return urbg_ == other.urbg_;
0135   }
0136 
0137   bool operator!=(const NonsecureURBGBase& other) const {
0138     return !(urbg_ == other.urbg_);
0139   }
0140 
0141  private:
0142   static URBG ConstructURBG() {
0143     Seeder seeder;
0144     return URBG(seeder);
0145   }
0146 
0147   template <typename SSeq>
0148   static URBG ConstructURBG(SSeq&& seq) {  // NOLINT(runtime/references)
0149     auto salted_seq =
0150         random_internal::MakeSaltedSeedSeq(std::forward<SSeq>(seq));
0151     return URBG(salted_seq);
0152   }
0153 
0154   URBG urbg_;
0155 };
0156 
0157 }  // namespace random_internal
0158 ABSL_NAMESPACE_END
0159 }  // namespace absl
0160 
0161 #endif  // ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_