annotate src/capnproto-git-20161025/c++/samples/addressbook.c++ @ 169:223a55898ab9 tip default

Add null config files
author Chris Cannam <cannam@all-day-breakfast.com>
date Mon, 02 Mar 2020 14:03:47 +0000
parents 1ac99bfc383d
children
rev   line source
cannam@133 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
cannam@133 2 // Licensed under the MIT License:
cannam@133 3 //
cannam@133 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
cannam@133 5 // of this software and associated documentation files (the "Software"), to deal
cannam@133 6 // in the Software without restriction, including without limitation the rights
cannam@133 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
cannam@133 8 // copies of the Software, and to permit persons to whom the Software is
cannam@133 9 // furnished to do so, subject to the following conditions:
cannam@133 10 //
cannam@133 11 // The above copyright notice and this permission notice shall be included in
cannam@133 12 // all copies or substantial portions of the Software.
cannam@133 13 //
cannam@133 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
cannam@133 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
cannam@133 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
cannam@133 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
cannam@133 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
cannam@133 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
cannam@133 20 // THE SOFTWARE.
cannam@133 21
cannam@133 22 // This sample code appears in the documentation for the C++ implementation.
cannam@133 23 //
cannam@133 24 // If Cap'n Proto is installed, build the sample like:
cannam@133 25 // capnp compile -oc++ addressbook.capnp
cannam@133 26 // c++ -std=c++11 -Wall addressbook.c++ addressbook.capnp.c++ `pkg-config --cflags --libs capnp` -o addressbook
cannam@133 27 //
cannam@133 28 // If Cap'n Proto is not installed, but the source is located at $SRC and has been
cannam@133 29 // compiled in $BUILD (often both are simply ".." from here), you can do:
cannam@133 30 // $BUILD/capnp compile -I$SRC/src -o$BUILD/capnpc-c++ addressbook.capnp
cannam@133 31 // c++ -std=c++11 -Wall addressbook.c++ addressbook.capnp.c++ -I$SRC/src -L$BUILD/.libs -lcapnp -lkj -o addressbook
cannam@133 32 //
cannam@133 33 // Run like:
cannam@133 34 // ./addressbook write | ./addressbook read
cannam@133 35 // Use "dwrite" and "dread" to use dynamic code instead.
cannam@133 36
cannam@133 37 // TODO(test): Needs cleanup.
cannam@133 38
cannam@133 39 #include "addressbook.capnp.h"
cannam@133 40 #include <capnp/message.h>
cannam@133 41 #include <capnp/serialize-packed.h>
cannam@133 42 #include <iostream>
cannam@133 43
cannam@133 44 using addressbook::Person;
cannam@133 45 using addressbook::AddressBook;
cannam@133 46
cannam@133 47 void writeAddressBook(int fd) {
cannam@133 48 ::capnp::MallocMessageBuilder message;
cannam@133 49
cannam@133 50 AddressBook::Builder addressBook = message.initRoot<AddressBook>();
cannam@133 51 ::capnp::List<Person>::Builder people = addressBook.initPeople(2);
cannam@133 52
cannam@133 53 Person::Builder alice = people[0];
cannam@133 54 alice.setId(123);
cannam@133 55 alice.setName("Alice");
cannam@133 56 alice.setEmail("alice@example.com");
cannam@133 57 // Type shown for explanation purposes; normally you'd use auto.
cannam@133 58 ::capnp::List<Person::PhoneNumber>::Builder alicePhones =
cannam@133 59 alice.initPhones(1);
cannam@133 60 alicePhones[0].setNumber("555-1212");
cannam@133 61 alicePhones[0].setType(Person::PhoneNumber::Type::MOBILE);
cannam@133 62 alice.getEmployment().setSchool("MIT");
cannam@133 63
cannam@133 64 Person::Builder bob = people[1];
cannam@133 65 bob.setId(456);
cannam@133 66 bob.setName("Bob");
cannam@133 67 bob.setEmail("bob@example.com");
cannam@133 68 auto bobPhones = bob.initPhones(2);
cannam@133 69 bobPhones[0].setNumber("555-4567");
cannam@133 70 bobPhones[0].setType(Person::PhoneNumber::Type::HOME);
cannam@133 71 bobPhones[1].setNumber("555-7654");
cannam@133 72 bobPhones[1].setType(Person::PhoneNumber::Type::WORK);
cannam@133 73 bob.getEmployment().setUnemployed();
cannam@133 74
cannam@133 75 writePackedMessageToFd(fd, message);
cannam@133 76 }
cannam@133 77
cannam@133 78 void printAddressBook(int fd) {
cannam@133 79 ::capnp::PackedFdMessageReader message(fd);
cannam@133 80
cannam@133 81 AddressBook::Reader addressBook = message.getRoot<AddressBook>();
cannam@133 82
cannam@133 83 for (Person::Reader person : addressBook.getPeople()) {
cannam@133 84 std::cout << person.getName().cStr() << ": "
cannam@133 85 << person.getEmail().cStr() << std::endl;
cannam@133 86 for (Person::PhoneNumber::Reader phone: person.getPhones()) {
cannam@133 87 const char* typeName = "UNKNOWN";
cannam@133 88 switch (phone.getType()) {
cannam@133 89 case Person::PhoneNumber::Type::MOBILE: typeName = "mobile"; break;
cannam@133 90 case Person::PhoneNumber::Type::HOME: typeName = "home"; break;
cannam@133 91 case Person::PhoneNumber::Type::WORK: typeName = "work"; break;
cannam@133 92 }
cannam@133 93 std::cout << " " << typeName << " phone: "
cannam@133 94 << phone.getNumber().cStr() << std::endl;
cannam@133 95 }
cannam@133 96 Person::Employment::Reader employment = person.getEmployment();
cannam@133 97 switch (employment.which()) {
cannam@133 98 case Person::Employment::UNEMPLOYED:
cannam@133 99 std::cout << " unemployed" << std::endl;
cannam@133 100 break;
cannam@133 101 case Person::Employment::EMPLOYER:
cannam@133 102 std::cout << " employer: "
cannam@133 103 << employment.getEmployer().cStr() << std::endl;
cannam@133 104 break;
cannam@133 105 case Person::Employment::SCHOOL:
cannam@133 106 std::cout << " student at: "
cannam@133 107 << employment.getSchool().cStr() << std::endl;
cannam@133 108 break;
cannam@133 109 case Person::Employment::SELF_EMPLOYED:
cannam@133 110 std::cout << " self-employed" << std::endl;
cannam@133 111 break;
cannam@133 112 }
cannam@133 113 }
cannam@133 114 }
cannam@133 115
cannam@133 116 #include "addressbook.capnp.h"
cannam@133 117 #include <capnp/message.h>
cannam@133 118 #include <capnp/serialize-packed.h>
cannam@133 119 #include <iostream>
cannam@133 120 #include <capnp/schema.h>
cannam@133 121 #include <capnp/dynamic.h>
cannam@133 122
cannam@133 123 using ::capnp::DynamicValue;
cannam@133 124 using ::capnp::DynamicStruct;
cannam@133 125 using ::capnp::DynamicEnum;
cannam@133 126 using ::capnp::DynamicList;
cannam@133 127 using ::capnp::List;
cannam@133 128 using ::capnp::Schema;
cannam@133 129 using ::capnp::StructSchema;
cannam@133 130 using ::capnp::EnumSchema;
cannam@133 131
cannam@133 132 using ::capnp::Void;
cannam@133 133 using ::capnp::Text;
cannam@133 134 using ::capnp::MallocMessageBuilder;
cannam@133 135 using ::capnp::PackedFdMessageReader;
cannam@133 136
cannam@133 137 void dynamicWriteAddressBook(int fd, StructSchema schema) {
cannam@133 138 // Write a message using the dynamic API to set each
cannam@133 139 // field by text name. This isn't something you'd
cannam@133 140 // normally want to do; it's just for illustration.
cannam@133 141
cannam@133 142 MallocMessageBuilder message;
cannam@133 143
cannam@133 144 // Types shown for explanation purposes; normally you'd
cannam@133 145 // use auto.
cannam@133 146 DynamicStruct::Builder addressBook =
cannam@133 147 message.initRoot<DynamicStruct>(schema);
cannam@133 148
cannam@133 149 DynamicList::Builder people =
cannam@133 150 addressBook.init("people", 2).as<DynamicList>();
cannam@133 151
cannam@133 152 DynamicStruct::Builder alice =
cannam@133 153 people[0].as<DynamicStruct>();
cannam@133 154 alice.set("id", 123);
cannam@133 155 alice.set("name", "Alice");
cannam@133 156 alice.set("email", "alice@example.com");
cannam@133 157 auto alicePhones = alice.init("phones", 1).as<DynamicList>();
cannam@133 158 auto phone0 = alicePhones[0].as<DynamicStruct>();
cannam@133 159 phone0.set("number", "555-1212");
cannam@133 160 phone0.set("type", "mobile");
cannam@133 161 alice.get("employment").as<DynamicStruct>()
cannam@133 162 .set("school", "MIT");
cannam@133 163
cannam@133 164 auto bob = people[1].as<DynamicStruct>();
cannam@133 165 bob.set("id", 456);
cannam@133 166 bob.set("name", "Bob");
cannam@133 167 bob.set("email", "bob@example.com");
cannam@133 168
cannam@133 169 // Some magic: We can convert a dynamic sub-value back to
cannam@133 170 // the native type with as<T>()!
cannam@133 171 List<Person::PhoneNumber>::Builder bobPhones =
cannam@133 172 bob.init("phones", 2).as<List<Person::PhoneNumber>>();
cannam@133 173 bobPhones[0].setNumber("555-4567");
cannam@133 174 bobPhones[0].setType(Person::PhoneNumber::Type::HOME);
cannam@133 175 bobPhones[1].setNumber("555-7654");
cannam@133 176 bobPhones[1].setType(Person::PhoneNumber::Type::WORK);
cannam@133 177 bob.get("employment").as<DynamicStruct>()
cannam@133 178 .set("unemployed", ::capnp::VOID);
cannam@133 179
cannam@133 180 writePackedMessageToFd(fd, message);
cannam@133 181 }
cannam@133 182
cannam@133 183 void dynamicPrintValue(DynamicValue::Reader value) {
cannam@133 184 // Print an arbitrary message via the dynamic API by
cannam@133 185 // iterating over the schema. Look at the handling
cannam@133 186 // of STRUCT in particular.
cannam@133 187
cannam@133 188 switch (value.getType()) {
cannam@133 189 case DynamicValue::VOID:
cannam@133 190 std::cout << "";
cannam@133 191 break;
cannam@133 192 case DynamicValue::BOOL:
cannam@133 193 std::cout << (value.as<bool>() ? "true" : "false");
cannam@133 194 break;
cannam@133 195 case DynamicValue::INT:
cannam@133 196 std::cout << value.as<int64_t>();
cannam@133 197 break;
cannam@133 198 case DynamicValue::UINT:
cannam@133 199 std::cout << value.as<uint64_t>();
cannam@133 200 break;
cannam@133 201 case DynamicValue::FLOAT:
cannam@133 202 std::cout << value.as<double>();
cannam@133 203 break;
cannam@133 204 case DynamicValue::TEXT:
cannam@133 205 std::cout << '\"' << value.as<Text>().cStr() << '\"';
cannam@133 206 break;
cannam@133 207 case DynamicValue::LIST: {
cannam@133 208 std::cout << "[";
cannam@133 209 bool first = true;
cannam@133 210 for (auto element: value.as<DynamicList>()) {
cannam@133 211 if (first) {
cannam@133 212 first = false;
cannam@133 213 } else {
cannam@133 214 std::cout << ", ";
cannam@133 215 }
cannam@133 216 dynamicPrintValue(element);
cannam@133 217 }
cannam@133 218 std::cout << "]";
cannam@133 219 break;
cannam@133 220 }
cannam@133 221 case DynamicValue::ENUM: {
cannam@133 222 auto enumValue = value.as<DynamicEnum>();
cannam@133 223 KJ_IF_MAYBE(enumerant, enumValue.getEnumerant()) {
cannam@133 224 std::cout <<
cannam@133 225 enumerant->getProto().getName().cStr();
cannam@133 226 } else {
cannam@133 227 // Unknown enum value; output raw number.
cannam@133 228 std::cout << enumValue.getRaw();
cannam@133 229 }
cannam@133 230 break;
cannam@133 231 }
cannam@133 232 case DynamicValue::STRUCT: {
cannam@133 233 std::cout << "(";
cannam@133 234 auto structValue = value.as<DynamicStruct>();
cannam@133 235 bool first = true;
cannam@133 236 for (auto field: structValue.getSchema().getFields()) {
cannam@133 237 if (!structValue.has(field)) continue;
cannam@133 238 if (first) {
cannam@133 239 first = false;
cannam@133 240 } else {
cannam@133 241 std::cout << ", ";
cannam@133 242 }
cannam@133 243 std::cout << field.getProto().getName().cStr()
cannam@133 244 << " = ";
cannam@133 245 dynamicPrintValue(structValue.get(field));
cannam@133 246 }
cannam@133 247 std::cout << ")";
cannam@133 248 break;
cannam@133 249 }
cannam@133 250 default:
cannam@133 251 // There are other types, we aren't handling them.
cannam@133 252 std::cout << "?";
cannam@133 253 break;
cannam@133 254 }
cannam@133 255 }
cannam@133 256
cannam@133 257 void dynamicPrintMessage(int fd, StructSchema schema) {
cannam@133 258 PackedFdMessageReader message(fd);
cannam@133 259 dynamicPrintValue(message.getRoot<DynamicStruct>(schema));
cannam@133 260 std::cout << std::endl;
cannam@133 261 }
cannam@133 262
cannam@133 263 int main(int argc, char* argv[]) {
cannam@133 264 StructSchema schema = Schema::from<AddressBook>();
cannam@133 265 if (argc != 2) {
cannam@133 266 std::cerr << "Missing arg." << std::endl;
cannam@133 267 return 1;
cannam@133 268 } else if (strcmp(argv[1], "write") == 0) {
cannam@133 269 writeAddressBook(1);
cannam@133 270 } else if (strcmp(argv[1], "read") == 0) {
cannam@133 271 printAddressBook(0);
cannam@133 272 } else if (strcmp(argv[1], "dwrite") == 0) {
cannam@133 273 dynamicWriteAddressBook(1, schema);
cannam@133 274 } else if (strcmp(argv[1], "dread") == 0) {
cannam@133 275 dynamicPrintMessage(0, schema);
cannam@133 276 } else {
cannam@133 277 std::cerr << "Invalid arg: " << argv[1] << std::endl;
cannam@133 278 return 1;
cannam@133 279 }
cannam@133 280 return 0;
cannam@133 281 }
cannam@133 282