aboutsummaryrefslogtreecommitdiffstats
path: root/examples/capnproto/addressbook_cpp/addressbook.cpp
diff options
context:
space:
mode:
authorThe Qt Project <gerrit-noreply@qt-project.org>2020-07-27 14:47:46 +0000
committerThe Qt Project <gerrit-noreply@qt-project.org>2020-07-27 14:47:46 +0000
commit34349e6574500e087ced56cc9504431b3e3b6469 (patch)
treed1e822daf5382d536d3b2c8940152526fd2a8f04 /examples/capnproto/addressbook_cpp/addressbook.cpp
parent31a841ade7b1a3b10d5a132cc58a476295e2e0b5 (diff)
parenteb6adb2a65902ca507dd1fdcd97fde333f324068 (diff)
Merge "Merge branch 1.17 into master"
Diffstat (limited to 'examples/capnproto/addressbook_cpp/addressbook.cpp')
-rw-r--r--examples/capnproto/addressbook_cpp/addressbook.cpp288
1 files changed, 288 insertions, 0 deletions
diff --git a/examples/capnproto/addressbook_cpp/addressbook.cpp b/examples/capnproto/addressbook_cpp/addressbook.cpp
new file mode 100644
index 000000000..b2bece947
--- /dev/null
+++ b/examples/capnproto/addressbook_cpp/addressbook.cpp
@@ -0,0 +1,288 @@
+// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
+// Licensed under the MIT License:
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+// This sample code appears in the documentation for the C++ implementation.
+//
+// If Cap'n Proto is installed, build the sample like:
+// capnp compile -oc++ addressbook.capnp
+// c++ -std=c++14 -Wall addressbook.c++ addressbook.capnp.c++ `pkg-config --cflags --libs capnp` -o addressbook
+//
+// If Cap'n Proto is not installed, but the source is located at $SRC and has been
+// compiled in $BUILD (often both are simply ".." from here), you can do:
+// $BUILD/capnp compile -I$SRC/src -o$BUILD/capnpc-c++ addressbook.capnp
+// c++ -std=c++14 -Wall addressbook.c++ addressbook.capnp.c++ -I$SRC/src -L$BUILD/.libs -lcapnp -lkj -o addressbook
+//
+// Run like:
+// ./addressbook write | ./addressbook read
+// Use "dwrite" and "dread" to use dynamic code instead.
+
+// TODO(test): Needs cleanup.
+
+#include "addressbook.capnp.h"
+#include <capnp/message.h>
+#include <capnp/serialize-packed.h>
+#include <iostream>
+
+using addressbook::Person;
+using addressbook::AddressBook;
+
+void writeAddressBook(int fd) {
+ ::capnp::MallocMessageBuilder message;
+
+ AddressBook::Builder addressBook = message.initRoot<AddressBook>();
+ ::capnp::List<Person>::Builder people = addressBook.initPeople(2);
+
+ Person::Builder alice = people[0];
+ alice.setId(123);
+ alice.setName("Alice");
+ alice.setEmail("alice@example.com");
+ // Type shown for explanation purposes; normally you'd use auto.
+ ::capnp::List<Person::PhoneNumber>::Builder alicePhones =
+ alice.initPhones(1);
+ alicePhones[0].setNumber("555-1212");
+ alicePhones[0].setType(Person::PhoneNumber::Type::MOBILE);
+ alice.getEmployment().setSchool("MIT");
+
+ Person::Builder bob = people[1];
+ bob.setId(456);
+ bob.setName("Bob");
+ bob.setEmail("bob@example.com");
+ auto bobPhones = bob.initPhones(2);
+ bobPhones[0].setNumber("555-4567");
+ bobPhones[0].setType(Person::PhoneNumber::Type::HOME);
+ bobPhones[1].setNumber("555-7654");
+ bobPhones[1].setType(Person::PhoneNumber::Type::WORK);
+ bob.getEmployment().setUnemployed();
+
+ writePackedMessageToFd(fd, message);
+}
+
+void printAddressBook(int fd) {
+ ::capnp::PackedFdMessageReader message(fd);
+
+ AddressBook::Reader addressBook = message.getRoot<AddressBook>();
+
+ for (Person::Reader person : addressBook.getPeople()) {
+ std::cout << person.getName().cStr() << ": "
+ << person.getEmail().cStr() << std::endl;
+ for (Person::PhoneNumber::Reader phone: person.getPhones()) {
+ const char* typeName = "UNKNOWN";
+ switch (phone.getType()) {
+ case Person::PhoneNumber::Type::MOBILE: typeName = "mobile"; break;
+ case Person::PhoneNumber::Type::HOME: typeName = "home"; break;
+ case Person::PhoneNumber::Type::WORK: typeName = "work"; break;
+ }
+ std::cout << " " << typeName << " phone: "
+ << phone.getNumber().cStr() << std::endl;
+ }
+ Person::Employment::Reader employment = person.getEmployment();
+ switch (employment.which()) {
+ case Person::Employment::UNEMPLOYED:
+ std::cout << " unemployed" << std::endl;
+ break;
+ case Person::Employment::EMPLOYER:
+ std::cout << " employer: "
+ << employment.getEmployer().cStr() << std::endl;
+ break;
+ case Person::Employment::SCHOOL:
+ std::cout << " student at: "
+ << employment.getSchool().cStr() << std::endl;
+ break;
+ case Person::Employment::SELF_EMPLOYED:
+ std::cout << " self-employed" << std::endl;
+ break;
+ }
+ }
+}
+
+#if !CAPNP_LITE
+
+#include "addressbook.capnp.h"
+#include <capnp/message.h>
+#include <capnp/serialize-packed.h>
+#include <iostream>
+#include <capnp/schema.h>
+#include <capnp/dynamic.h>
+
+using ::capnp::DynamicValue;
+using ::capnp::DynamicStruct;
+using ::capnp::DynamicEnum;
+using ::capnp::DynamicList;
+using ::capnp::List;
+using ::capnp::Schema;
+using ::capnp::StructSchema;
+using ::capnp::EnumSchema;
+
+using ::capnp::Void;
+using ::capnp::Text;
+using ::capnp::MallocMessageBuilder;
+using ::capnp::PackedFdMessageReader;
+
+void dynamicWriteAddressBook(int fd, StructSchema schema) {
+ // Write a message using the dynamic API to set each
+ // field by text name. This isn't something you'd
+ // normally want to do; it's just for illustration.
+
+ MallocMessageBuilder message;
+
+ // Types shown for explanation purposes; normally you'd
+ // use auto.
+ DynamicStruct::Builder addressBook =
+ message.initRoot<DynamicStruct>(schema);
+
+ DynamicList::Builder people =
+ addressBook.init("people", 2).as<DynamicList>();
+
+ DynamicStruct::Builder alice =
+ people[0].as<DynamicStruct>();
+ alice.set("id", 123);
+ alice.set("name", "Alice");
+ alice.set("email", "alice@example.com");
+ auto alicePhones = alice.init("phones", 1).as<DynamicList>();
+ auto phone0 = alicePhones[0].as<DynamicStruct>();
+ phone0.set("number", "555-1212");
+ phone0.set("type", "mobile");
+ alice.get("employment").as<DynamicStruct>()
+ .set("school", "MIT");
+
+ auto bob = people[1].as<DynamicStruct>();
+ bob.set("id", 456);
+ bob.set("name", "Bob");
+ bob.set("email", "bob@example.com");
+
+ // Some magic: We can convert a dynamic sub-value back to
+ // the native type with as<T>()!
+ List<Person::PhoneNumber>::Builder bobPhones =
+ bob.init("phones", 2).as<List<Person::PhoneNumber>>();
+ bobPhones[0].setNumber("555-4567");
+ bobPhones[0].setType(Person::PhoneNumber::Type::HOME);
+ bobPhones[1].setNumber("555-7654");
+ bobPhones[1].setType(Person::PhoneNumber::Type::WORK);
+ bob.get("employment").as<DynamicStruct>()
+ .set("unemployed", ::capnp::VOID);
+
+ writePackedMessageToFd(fd, message);
+}
+
+void dynamicPrintValue(DynamicValue::Reader value) {
+ // Print an arbitrary message via the dynamic API by
+ // iterating over the schema. Look at the handling
+ // of STRUCT in particular.
+
+ switch (value.getType()) {
+ case DynamicValue::VOID:
+ std::cout << "";
+ break;
+ case DynamicValue::BOOL:
+ std::cout << (value.as<bool>() ? "true" : "false");
+ break;
+ case DynamicValue::INT:
+ std::cout << value.as<int64_t>();
+ break;
+ case DynamicValue::UINT:
+ std::cout << value.as<uint64_t>();
+ break;
+ case DynamicValue::FLOAT:
+ std::cout << value.as<double>();
+ break;
+ case DynamicValue::TEXT:
+ std::cout << '\"' << value.as<Text>().cStr() << '\"';
+ break;
+ case DynamicValue::LIST: {
+ std::cout << "[";
+ bool first = true;
+ for (auto element: value.as<DynamicList>()) {
+ if (first) {
+ first = false;
+ } else {
+ std::cout << ", ";
+ }
+ dynamicPrintValue(element);
+ }
+ std::cout << "]";
+ break;
+ }
+ case DynamicValue::ENUM: {
+ auto enumValue = value.as<DynamicEnum>();
+ KJ_IF_MAYBE(enumerant, enumValue.getEnumerant()) {
+ std::cout <<
+ enumerant->getProto().getName().cStr();
+ } else {
+ // Unknown enum value; output raw number.
+ std::cout << enumValue.getRaw();
+ }
+ break;
+ }
+ case DynamicValue::STRUCT: {
+ std::cout << "(";
+ auto structValue = value.as<DynamicStruct>();
+ bool first = true;
+ for (auto field: structValue.getSchema().getFields()) {
+ if (!structValue.has(field)) continue;
+ if (first) {
+ first = false;
+ } else {
+ std::cout << ", ";
+ }
+ std::cout << field.getProto().getName().cStr()
+ << " = ";
+ dynamicPrintValue(structValue.get(field));
+ }
+ std::cout << ")";
+ break;
+ }
+ default:
+ // There are other types, we aren't handling them.
+ std::cout << "?";
+ break;
+ }
+}
+
+void dynamicPrintMessage(int fd, StructSchema schema) {
+ PackedFdMessageReader message(fd);
+ dynamicPrintValue(message.getRoot<DynamicStruct>(schema));
+ std::cout << std::endl;
+}
+
+#endif // !CAPNP_LITE
+
+int main(int argc, char* argv[]) {
+ if (argc != 2) {
+ std::cerr << "Missing arg." << std::endl;
+ return 1;
+ } else if (strcmp(argv[1], "write") == 0) {
+ writeAddressBook(1);
+ } else if (strcmp(argv[1], "read") == 0) {
+ printAddressBook(0);
+#if !CAPNP_LITE
+ } else if (strcmp(argv[1], "dwrite") == 0) {
+ StructSchema schema = Schema::from<AddressBook>();
+ dynamicWriteAddressBook(1, schema);
+ } else if (strcmp(argv[1], "dread") == 0) {
+ StructSchema schema = Schema::from<AddressBook>();
+ dynamicPrintMessage(0, schema);
+#endif
+ } else {
+ std::cerr << "Invalid arg: " << argv[1] << std::endl;
+ return 1;
+ }
+ return 0;
+}