Google Cloud Spanner C++ Client  1.33.0
A C++ Client Library for Google Cloud Spanner
bytes.cc
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 #include "google/cloud/spanner/bytes.h"
16 #include "google/cloud/internal/base64_transforms.h"
17 #include "google/cloud/status.h"
18 #include <array>
19 #include <cctype>
20 #include <climits>
21 #include <cstdio>
22 
23 namespace google {
24 namespace cloud {
25 namespace spanner {
27 
28 using ::google::cloud::internal::Base64Decoder;
29 
30 // Prints the bytes in the form B"...", where printable bytes are output
31 // normally, double quotes are backslash escaped, and non-printable characters
32 // are printed as a 3-digit octal escape sequence.
33 std::ostream& operator<<(std::ostream& os, Bytes const& bytes) {
34  os << R"(B")";
35  for (auto const byte : Base64Decoder(bytes.base64_rep_)) {
36  if (byte == '"') {
37  os << R"(\")";
38  } else if (std::isprint(byte)) {
39  os << byte;
40  } else {
41  // This uses snprintf rather than iomanip so we don't mess up the
42  // formatting on `os` for other streaming operations.
43  std::array<char, sizeof(R"(\000)")> buf;
44  auto n = std::snprintf(buf.data(), buf.size(), R"(\%03o)", byte);
45  if (n == static_cast<int>(buf.size() - 1)) {
46  os << buf.data();
47  } else {
48  os << R"(\?)";
49  }
50  }
51  }
52  // Can't use raw string literal here because of a doxygen bug.
53  return os << "\"";
54 }
55 
57 } // namespace spanner
58 
59 namespace spanner_internal {
61 struct BytesInternals {
62  static spanner::Bytes Create(std::string rep) {
63  spanner::Bytes bytes;
64  bytes.base64_rep_ = std::move(rep);
65  return bytes;
66  }
67 
68  static std::string GetRep(spanner::Bytes&& bytes) {
69  return std::move(bytes.base64_rep_);
70  }
71 };
72 
73 // Construction from a base64-encoded US-ASCII `std::string`.
74 StatusOr<spanner::Bytes> BytesFromBase64(std::string input) {
75  auto status = google::cloud::internal::ValidateBase64String(input);
76  if (!status.ok()) return status;
77  return BytesInternals::Create(std::move(input));
78 }
79 
80 // Conversion to a base64-encoded US-ASCII `std::string`.
81 std::string BytesToBase64(spanner::Bytes b) {
82  return BytesInternals::GetRep(std::move(b));
83 }
84 
86 } // namespace spanner_internal
87 } // namespace cloud
88 } // namespace google