Google Cloud Spanner C++ Client
A C++ Client Library for Google Cloud Spanner
bytes.h
Go to the documentation of this file.
1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_BYTES_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_BYTES_H
17 
19 #include "google/cloud/status_or.h"
20 #include <array>
21 #include <cstddef>
22 #include <iterator>
23 #include <ostream>
24 #include <string>
25 
26 namespace google {
27 namespace cloud {
28 namespace spanner {
29 inline namespace SPANNER_CLIENT_NS {
30 
31 class Bytes; // defined below
32 
33 // Internal forward declarations to befriend.
34 namespace internal {
35 StatusOr<Bytes> BytesFromBase64(std::string input);
36 std::string BytesToBase64(Bytes b);
37 } // namespace internal
38 
45 class Bytes {
46  public:
48  Bytes() = default;
49 
52  template <typename InputIt>
53  Bytes(InputIt first, InputIt last) {
54  Encoder encoder(base64_rep_);
55  while (first != last) {
56  encoder.buf_[encoder.len_++] = *first++;
57  if (encoder.len_ == encoder.buf_.size()) encoder.Flush();
58  }
59  if (encoder.len_ != 0) encoder.FlushAndPad();
60  }
61  template <typename Container>
62  explicit Bytes(Container const& c) : Bytes(std::begin(c), std::end(c)) {}
64 
67  template <typename Container>
68  Container get() const {
69  Decoder decoder(base64_rep_);
70  return Container(decoder.begin(), decoder.end());
71  }
72 
75  friend bool operator==(Bytes const& a, Bytes const& b) {
76  return a.base64_rep_ == b.base64_rep_;
77  }
78  friend bool operator!=(Bytes const& a, Bytes const& b) { return !(a == b); }
80 
87  friend std::ostream& operator<<(std::ostream& os, Bytes const& bytes);
88 
89  private:
90  friend StatusOr<Bytes> internal::BytesFromBase64(std::string input);
91  friend std::string internal::BytesToBase64(Bytes b);
92 
93  struct Encoder {
94  explicit Encoder(std::string& rep) : rep_(rep), len_(0) {}
95  void Flush();
96  void FlushAndPad();
97 
98  std::string& rep_; // encoded
99  std::size_t len_; // buf_[0 .. len_-1] pending encode
100  std::array<unsigned char, 3> buf_;
101  };
102 
103  struct Decoder {
104  class Iterator {
105  public:
106  using iterator_category = std::input_iterator_tag;
107  using value_type = unsigned char;
108  using difference_type = std::ptrdiff_t;
109  using pointer = value_type*;
111 
112  Iterator(std::string::const_iterator begin,
113  std::string::const_iterator end)
114  : pos_(begin), end_(end), len_(0) {
115  Fill();
116  }
117 
118  void Fill();
119 
120  reference operator*() { return buf_[len_]; }
121  pointer operator->() { return &buf_[len_]; }
122 
124  if (--len_ == 0) Fill();
125  return *this;
126  }
128  auto const old = *this;
129  operator++();
130  return old;
131  }
132 
133  friend bool operator==(Iterator const& a, Iterator const& b) {
134  return a.pos_ == b.pos_ && a.len_ == b.len_;
135  }
136  friend bool operator!=(Iterator const& a, Iterator const& b) {
137  return !(a == b);
138  }
139 
140  private:
141  std::string::const_iterator pos_; // [pos_ .. end_) pending decode
142  std::string::const_iterator end_;
143  std::size_t len_; // buf_[len_ .. 1] decoded
144  std::array<value_type, 1 + 3> buf_;
145  };
146 
147  explicit Decoder(std::string const& rep) : rep_(rep) {}
148  Iterator begin() { return Iterator(rep_.begin(), rep_.end()); }
149  Iterator end() { return Iterator(rep_.end(), rep_.end()); }
150 
151  std::string const& rep_; // encoded
152  };
153 
154  std::string base64_rep_; // valid base64 representation
155 };
156 
157 } // namespace SPANNER_CLIENT_NS
158 } // namespace spanner
159 } // namespace cloud
160 } // namespace google
161 
162 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_BYTES_H
friend bool operator==(Bytes const &a, Bytes const &b)
Definition: bytes.h:75
Bytes(Container const &c)
Definition: bytes.h:62
Container get() const
Conversion to a sequence of octets.
Definition: bytes.h:68
friend bool operator!=(Iterator const &a, Iterator const &b)
Definition: bytes.h:136
friend bool operator!=(Bytes const &a, Bytes const &b)
Definition: bytes.h:78
Contains all the Cloud Spanner C++ client types and functions.
friend bool operator==(Iterator const &a, Iterator const &b)
Definition: bytes.h:133
A representation of the Spanner BYTES type: variable-length binary data.
Definition: bytes.h:45
#define SPANNER_CLIENT_NS
Definition: version.h:22
Bytes(InputIt first, InputIt last)
Construction from a sequence of octets.
Definition: bytes.h:53
Iterator(std::string::const_iterator begin, std::string::const_iterator end)
Definition: bytes.h:112
std::ostream & operator<<(std::ostream &os, Backup const &bn)
Definition: backup.cc:35