Skip to content

Commit c2fd8d1

Browse files
authored
Add a nanopb string (#1839)
* Add Equatable and Comparable * Add nanopb String
1 parent 407f5d6 commit c2fd8d1

File tree

8 files changed

+384
-1
lines changed

8 files changed

+384
-1
lines changed

Firestore/Example/Firestore.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@
179179
7346E61D20325C6900FD6CEF /* FSTDispatchQueueTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7346E61C20325C6900FD6CEF /* FSTDispatchQueueTests.mm */; };
180180
73866AA12082B0A5009BB4FF /* FIRArrayTransformTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 73866A9F2082B069009BB4FF /* FIRArrayTransformTests.mm */; };
181181
73FE5066020EF9B2892C86BF /* hard_assert_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 444B7AB3F5A2929070CB1363 /* hard_assert_test.cc */; };
182+
84DBE646DCB49305879D3500 /* nanopb_string_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 353EEE078EF3F39A9B7279F6 /* nanopb_string_test.cc */; };
182183
873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */; };
183184
8C82D4D3F9AB63E79CC52DC8 /* Pods_Firestore_IntegrationTests_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECEBABC7E7B693BE808A1052 /* Pods_Firestore_IntegrationTests_iOS.framework */; };
184185
AB356EF7200EA5EB0089B766 /* field_value_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB356EF6200EA5EB0089B766 /* field_value_test.cc */; };
@@ -308,6 +309,7 @@
308309
2A0CF41BA5AED6049B0BEB2C /* type_traits_apple_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = type_traits_apple_test.mm; sourceTree = "<group>"; };
309310
2B50B3A0DF77100EEE887891 /* Pods_Firestore_Tests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
310311
332485C4DCC6BA0DBB5E31B7 /* leveldb_util_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_util_test.cc; sourceTree = "<group>"; };
312+
353EEE078EF3F39A9B7279F6 /* nanopb_string_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = nanopb_string_test.cc; path = nanopb/nanopb_string_test.cc; sourceTree = "<group>"; };
311313
358C3B5FE573B1D60A4F7592 /* strerror_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = strerror_test.cc; sourceTree = "<group>"; };
312314
3B843E4A1F3930A400548890 /* remote_store_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = remote_store_spec_test.json; sourceTree = "<group>"; };
313315
3C81DE3772628FE297055662 /* Pods-Firestore_Example_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_Example_iOS/Pods-Firestore_Example_iOS.debug.xcconfig"; sourceTree = "<group>"; };
@@ -729,6 +731,7 @@
729731
54EB764B202277970088B8F3 /* immutable */,
730732
54995F70205B6E1A004EFFA0 /* local */,
731733
AB356EF5200E9D1A0089B766 /* model */,
734+
5C332D7293E6114E491D3662 /* nanopb */,
732735
546854A720A3681B004BDBD5 /* remote */,
733736
5467FB05203E652F009C9584 /* testutil */,
734737
54740A561FC913EB00713A1A /* util */,
@@ -781,6 +784,14 @@
781784
path = immutable;
782785
sourceTree = "<group>";
783786
};
787+
5C332D7293E6114E491D3662 /* nanopb */ = {
788+
isa = PBXGroup;
789+
children = (
790+
353EEE078EF3F39A9B7279F6 /* nanopb_string_test.cc */,
791+
);
792+
name = nanopb;
793+
sourceTree = "<group>";
794+
};
784795
5CAE131A20FFFED600BE9A4A /* Benchmarks */ = {
785796
isa = PBXGroup;
786797
children = (
@@ -1939,6 +1950,7 @@
19391950
AB6B908620322E6D00CC290A /* maybe_document_test.cc in Sources */,
19401951
618BBEA820B89AAC00B5BCE7 /* mutation.pb.cc in Sources */,
19411952
32F022CB75AEE48CDDAF2982 /* mutation_test.cc in Sources */,
1953+
84DBE646DCB49305879D3500 /* nanopb_string_test.cc in Sources */,
19421954
AB6B908820322E8800CC290A /* no_document_test.cc in Sources */,
19431955
AB380D04201BC6E400D97691 /* ordered_code_test.cc in Sources */,
19441956
5A080105CCBFDB6BF3F3772D /* path_test.cc in Sources */,

Firestore/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,6 @@ add_subdirectory(test/firebase/firestore/core)
3131
add_subdirectory(test/firebase/firestore/immutable)
3232
add_subdirectory(test/firebase/firestore/local)
3333
add_subdirectory(test/firebase/firestore/model)
34+
add_subdirectory(test/firebase/firestore/nanopb)
3435
add_subdirectory(test/firebase/firestore/remote)
3536
add_subdirectory(test/firebase/firestore/util)

Firestore/core/src/firebase/firestore/nanopb/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
cc_library(
1616
firebase_firestore_nanopb
1717
SOURCES
18-
tag.h
18+
nanopb_string.cc
19+
nanopb_string.h
1920
reader.h
2021
reader.cc
22+
tag.h
2123
writer.h
2224
writer.cc
2325
DEPENDS
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2018 Google
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "Firestore/core/src/firebase/firestore/nanopb/nanopb_string.h"
18+
19+
#include <cstdlib>
20+
#include <utility>
21+
22+
namespace firebase {
23+
namespace firestore {
24+
namespace nanopb {
25+
26+
/* static */ pb_bytes_array_t* String::MakeBytesArray(absl::string_view value) {
27+
auto size = static_cast<pb_size_t>(value.size());
28+
29+
// Allocate one extra byte for the null terminator that's not necessarily
30+
// there in a string_view. As long as we're making a copy, might as well
31+
// make a copy that won't overrun when used as a regular C string. This is
32+
// essentially just to make debugging easier--actual user data can have
33+
// embedded nulls so we shouldn't be using this as a C string under normal
34+
// circumstances.
35+
auto result = static_cast<pb_bytes_array_t*>(
36+
malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(size) + 1));
37+
result->size = size;
38+
memcpy(result->bytes, value.data(), size);
39+
result->bytes[size] = '\0';
40+
41+
return result;
42+
}
43+
44+
pb_bytes_array_t* String::release() {
45+
pb_bytes_array_t* result = bytes_;
46+
bytes_ = nullptr;
47+
return result;
48+
}
49+
50+
void swap(String& lhs, String& rhs) noexcept {
51+
using std::swap;
52+
swap(lhs.bytes_, rhs.bytes_);
53+
}
54+
55+
/* static */ String String::Wrap(pb_bytes_array_t* bytes) {
56+
return String{bytes};
57+
}
58+
59+
/* static */ absl::string_view String::ToStringView(pb_bytes_array_t* bytes) {
60+
const char* str = reinterpret_cast<const char*>(bytes->bytes);
61+
return absl::string_view{str, bytes->size};
62+
}
63+
64+
} // namespace nanopb
65+
} // namespace firestore
66+
} // namespace firebase
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* Copyright 2018 Google
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_NANOPB_NANOPB_STRING_H_
18+
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_NANOPB_NANOPB_STRING_H_
19+
20+
#include <pb.h>
21+
22+
#include <string>
23+
#include <utility>
24+
25+
#include "Firestore/core/src/firebase/firestore/util/comparison.h"
26+
#include "absl/strings/string_view.h"
27+
28+
namespace firebase {
29+
namespace firestore {
30+
namespace nanopb {
31+
32+
/**
33+
* A string-like object backed by a nanopb byte array.
34+
*/
35+
class String : public util::Comparable<String> {
36+
public:
37+
/**
38+
* Creates a new, null-terminated byte array that's a copy of the given string
39+
* value.
40+
*/
41+
static pb_bytes_array_t* MakeBytesArray(absl::string_view value);
42+
43+
String() {
44+
}
45+
46+
/**
47+
* Creates a new String whose backing byte array is a copy of the of the
48+
* given C string.
49+
*/
50+
explicit String(const char* value) : bytes_{MakeBytesArray(value)} {
51+
}
52+
53+
/**
54+
* Creates a new String whose backing byte array is a copy of the of the
55+
* given string.
56+
*/
57+
explicit String(const std::string& value) : bytes_{MakeBytesArray(value)} {
58+
}
59+
60+
/**
61+
* Creates a new String whose backing byte array is a copy of the of the
62+
* given string_view.
63+
*/
64+
explicit String(absl::string_view value) : bytes_{MakeBytesArray(value)} {
65+
}
66+
67+
String(const String& other)
68+
: bytes_{MakeBytesArray(absl::string_view{other})} {
69+
}
70+
71+
String(String&& other) noexcept : String{} {
72+
swap(*this, other);
73+
}
74+
75+
~String() {
76+
delete bytes_;
77+
}
78+
79+
String& operator=(String other) {
80+
swap(*this, other);
81+
return *this;
82+
}
83+
84+
/**
85+
* Creates a new String that takes ownership of the given byte array.
86+
*/
87+
static String Wrap(pb_bytes_array_t* bytes);
88+
89+
bool empty() const {
90+
return !bytes_ || bytes_->size == 0;
91+
}
92+
93+
/**
94+
* Returns a pointer to the character data backing this String. The return
95+
* value is `nullptr` if the backing bytes are themselves null.
96+
*/
97+
const char* data() const {
98+
return bytes_ ? reinterpret_cast<const char*>(bytes_->bytes) : nullptr;
99+
}
100+
101+
/** Returns a const view of the underlying byte array. */
102+
const pb_bytes_array_t* get() const {
103+
return bytes_;
104+
}
105+
106+
/**
107+
* Returns the current byte array and assigns the backing byte array to
108+
* nullptr, releasing the ownership of the array contents to the caller.
109+
*/
110+
pb_bytes_array_t* release();
111+
112+
/**
113+
* Converts this String to an absl::string_view (without changing ownership).
114+
*/
115+
explicit operator absl::string_view() const {
116+
return ToStringView(bytes_);
117+
}
118+
119+
/**
120+
* Swaps the contents of the given Strings.
121+
*/
122+
friend void swap(String& lhs, String& rhs) noexcept;
123+
124+
friend bool operator==(const String& lhs, const String& rhs) {
125+
return absl::string_view{lhs} == absl::string_view{rhs};
126+
}
127+
friend bool operator<(const String& lhs, const String& rhs) {
128+
return absl::string_view{lhs} < absl::string_view{rhs};
129+
}
130+
131+
friend bool operator==(const String& lhs, absl::string_view rhs) {
132+
absl::string_view lhs_view{lhs};
133+
return lhs_view == rhs;
134+
}
135+
136+
friend bool operator!=(const String& lhs, absl::string_view rhs) {
137+
return !(lhs == rhs);
138+
}
139+
140+
private:
141+
explicit String(pb_bytes_array_t* bytes) : bytes_{bytes} {
142+
}
143+
144+
static absl::string_view ToStringView(pb_bytes_array_t* bytes);
145+
146+
pb_bytes_array_t* bytes_ = nullptr;
147+
};
148+
149+
} // namespace nanopb
150+
} // namespace firestore
151+
} // namespace firebase
152+
153+
#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_NANOPB_NANOPB_STRING_H_

Firestore/core/src/firebase/firestore/util/comparison.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,28 @@ bool DoubleBitwiseEquals(double left, double right);
179179
*/
180180
size_t DoubleBitwiseHash(double d);
181181

182+
template <typename T>
183+
class Equatable {
184+
public:
185+
friend bool operator!=(const T& lhs, const T& rhs) {
186+
return !(lhs == rhs);
187+
}
188+
};
189+
190+
template <typename T>
191+
class Comparable : public Equatable<T> {
192+
public:
193+
friend bool operator>(const T& lhs, const T& rhs) {
194+
return rhs < lhs;
195+
}
196+
friend bool operator<=(const T& lhs, const T& rhs) {
197+
return !(rhs < lhs);
198+
}
199+
friend bool operator>=(const T& lhs, const T& rhs) {
200+
return !(lhs < rhs);
201+
}
202+
};
203+
182204
} // namespace util
183205
} // namespace firestore
184206
} // namespace firebase
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Copyright 2018 Google
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+
cc_test(
16+
firebase_firestore_nanopb_test
17+
SOURCES
18+
nanopb_string_test.cc
19+
DEPENDS
20+
firebase_firestore_nanopb
21+
)

0 commit comments

Comments
 (0)