String View APIs
C++-Stringfeld-APIs, die std::string stark nutzen, schränken die interne Implementierung und Weiterentwicklung von Protobuf erheblich ein. Zum Beispiel gibt mutable_string_field() einen std::string* zurück, der uns zwingt, std::string zur Speicherung des Feldes zu verwenden. Dies erschwert die Interaktion mit Arenen und wir müssen Arena-Spendenstatus verwalten, um zu verfolgen, ob die String-Payload-Allokation von der Arena oder dem Heap stammt.
Langfristig möchten wir alle unsere Laufzeit- und generierten APIs so umstellen, dass sie string_view als Eingaben akzeptieren und von Accessors zurückgeben. Dieses Dokument beschreibt den Stand der Migration zum Release 30.x.
String Feld-Zugriffsmethoden
Als Teil der Edition 2023 wurde das Feature string_type mit der Option VIEW veröffentlicht, um eine inkrementelle Migration zu generierten string_view-APIs zu ermöglichen. Die Verwendung dieses Features wirkt sich auf den C++-generierten Code von string- und bytes-Feldern aus.
Interaktion mit ctype
In Edition 2023 können Sie ctype immer noch auf Feld-Ebene angeben, während Sie string_type entweder auf Datei- oder Feld-Ebene angeben können. Die gleichzeitige Angabe auf demselben Feld ist nicht zulässig. Wenn string_type auf Datei-Ebene gesetzt ist, haben die auf Feldern angegebenen ctype Vorrang.
Mit Ausnahme der Option VIEW haben alle möglichen Werte von string_type einen entsprechenden ctype-Wert, der gleich geschrieben ist und das gleiche Verhalten aufweist. Beide Enums haben zum Beispiel einen CORD-Wert.
In Edition 2024 und darüber hinaus wird es nicht mehr möglich sein, ctype anzugeben.
Generierte singuläre Felder
Für eine dieser Felddefinitionen in Edition 2023
bytes foo = 1 [features.(pb.cpp).string_type=VIEW];
string foo = 1 [features.(pb.cpp).string_type=VIEW];
Der Compiler generiert die folgenden Accessor-Methoden:
::absl::string_view foo() const: Gibt den aktuellen Wert des Feldes zurück. Wenn das Feld nicht gesetzt ist, wird der Standardwert zurückgegeben.void clear_foo(): Löscht den Wert des Feldes. Nach dem Aufruf dieser Methode gibtfoo()den Standardwert zurück.bool has_foo(): Gibttruezurück, wenn das Feld gesetzt ist.void set_foo(::absl::string_view value): Setzt den Wert des Feldes. Nach dem Aufruf dieser Methode gibthas_foo()truezurück undfoo()gibt eine Kopie vonvaluezurück.void set_foo(const string& value): Setzt den Wert des Feldes. Nach dem Aufruf dieser Methode gibthas_foo()truezurück undfoo()gibt eine Kopie vonvaluezurück.void set_foo(string&& value): Setzt den Wert des Feldes, indem der übergebene String verschoben wird. Nach dem Aufruf dieser Methode gibthas_foo()truezurück undfoo()gibtvaluezurück.void set_foo(const char* value): Setzt den Wert des Feldes mit einem C-Style-String mit Nullterminierung. Nach dem Aufruf dieser Methode gibthas_foo()truezurück undfoo()gibt eine Kopie vonvaluezurück.
Generierte wiederholte Felder
Für eine dieser Felddefinitionen
repeated string foo = 1 [features.(pb.cpp).string_type=VIEW];
repeated bytes foo = 1 [features.(pb.cpp).string_type=VIEW];
Der Compiler generiert die folgenden Accessor-Methoden:
int foo_size() const: Gibt die aktuelle Anzahl der Elemente im Feld zurück.::absl::string_view foo(int index) const: Gibt das Element am angegebenen nullbasierten Index zurück. Der Aufruf dieser Methode mit einem Index außerhalb von[0, foo_size()-1]führt zu undefiniertem Verhalten.void set_foo(int index, ::absl::string_view value): Setzt den Wert des Elements am angegebenen nullbasierten Index.void set_foo(int index, const string& value): Setzt den Wert des Elements am angegebenen nullbasierten Index.void set_foo(int index, string&& value): Setzt den Wert des Elements am angegebenen nullbasierten Index, indem der übergebene String verschoben wird.void set_foo(int index, const char* value): Setzt den Wert des Elements am angegebenen nullbasierten Index mit einem C-Style-String mit Nullterminierung.void add_foo(::absl::string_view value): Fügt am Ende des Feldes ein neues Element mit dem angegebenen Wert hinzu.void add_foo(const string& value): Fügt am Ende des Feldes ein neues Element mit dem angegebenen Wert hinzu.void add_foo(string&& value): Fügt am Ende des Feldes ein neues Element hinzu, indem der übergebene String verschoben wird.void add_foo(const char* value): Fügt am Ende des Feldes ein neues Element mit einem C-Style-String mit Nullterminierung hinzu.void clear_foo(): Entfernt alle Elemente aus dem Feld. Nach dem Aufruf dieser Methode gibtfoo_size()Null zurück.const RepeatedPtrField<string>& foo() const: Gibt das zugrundeliegendeRepeatedPtrFieldzurück, das die Elemente des Feldes speichert. Diese Containerklasse bietet STL-ähnliche Iteratoren und weitere Methoden.RepeatedPtrField<string>* mutable_foo(): Gibt einen Zeiger auf das zugrundeliegende veränderbareRepeatedPtrFieldzurück, das die Elemente des Feldes speichert. Diese Containerklasse bietet STL-ähnliche Iteratoren und weitere Methoden.
Generierte Oneof-Felder
Für eine dieser oneof-Felddefinitionen
oneof example_name {
string foo = 1 [features.(pb.cpp).string_type=VIEW];
...
}
oneof example_name {
bytes foo = 1 [features.(pb.cpp).string_type=VIEW];
...
}
Der Compiler generiert die folgenden Accessor-Methoden:
bool has_foo() const: Gibttruezurück, wenn der Oneof-FallkFooist.::absl::string_view foo() const: Gibt den aktuellen Wert des Feldes zurück, wenn der Oneof-FallkFooist. Andernfalls wird der Standardwert zurückgegeben.void set_foo(::absl::string_view value):- Wenn ein anderes Oneof-Feld im selben Oneof gesetzt ist, wird
clear_example_name()aufgerufen. - Setzt den Wert dieses Feldes und den Oneof-Fall auf
kFoo. has_foo()gibttruezurück,foo()gibt eine Kopie vonvaluezurück undexample_name_case()gibtkFoozurück.
- Wenn ein anderes Oneof-Feld im selben Oneof gesetzt ist, wird
void set_foo(const string& value): Wie das ersteset_foo(), aber kopiert von einerconst stringReferenz.void set_foo(string&& value): Wie das ersteset_foo(), aber verschiebt vom übergebenen String.void set_foo(const char* value): Wie das ersteset_foo(), aber kopiert von einem C-Style-String mit Nullterminierung.void clear_foo():- Wenn der Oneof-Fall nicht
kFooist, wird nichts geändert. - Wenn der Oneof-Fall
kFooist, wird das Feld freigegeben und der Oneof-Fall gelöscht.has_foo()gibtfalsezurück,foo()gibt den Standardwert zurück undexample_name_case()gibtEXAMPLE_NAME_NOT_SETzurück.
- Wenn der Oneof-Fall nicht
Enumerationsnamen-Hilfsfunktion
Ab der Edition 2024 wird ein neues Feature enum_name_uses_string_view eingeführt und ist standardmäßig auf true gesetzt. Sofern nicht deaktiviert, wird für eine Enum wie diese
enum Foo {
VALUE_A = 0;
VALUE_B = 5;
VALUE_C = 1234;
}
Der Protocol Buffer Compiler generiert zusätzlich zur Foo-Enum die folgende neue Funktion zusätzlich zum Standard generierten Code
::absl::string_view Foo_Name(int value): Gibt den Namen für den gegebenen numerischen Wert zurück. Gibt einen leeren String zurück, wenn kein solcher Wert existiert. Wenn mehrere Werte diese Nummer haben, wird der erste definierte zurückgegeben. Im obigen Beispiel würdeFoo_Name(5)VALUE_Bzurückgeben.
Dies kann durch Hinzufügen eines Feature-Overrides wie folgt zum alten Verhalten zurückgesetzt werden:
enum Foo {
option features.(pb.cpp).enum_name_uses_string_view = false;
VALUE_A = 0;
VALUE_B = 5;
VALUE_C = 1234;
}
In diesem Fall wechselt die Namens-Hilfsfunktion zurück zu const string& Foo_Name(int value).