Commit a2fa6413 authored by Kenton Varda's avatar Kenton Varda

Apply some capnproto -> capnp renames that didn't happen before, update docs,…

Apply some capnproto -> capnp renames that didn't happen before, update docs, put samples in a place where they are easy to compile.
parent 8747ca9c
......@@ -95,9 +95,9 @@ nodist_includecapnp_HEADERS = \
# No dynamic library for now since C++ binary compatibility is hard.
# It may make more sense to have every module statically link Cap'n Proto
# and pass around messages via memory pointers.
lib_LIBRARIES = libcapnproto.a
lib_LIBRARIES = libcapnp.a
libcapnproto_a_SOURCES= \
libcapnp_a_SOURCES= \
src/kj/common.c++ \
src/kj/units.c++ \
src/kj/memory.c++ \
......@@ -118,7 +118,7 @@ libcapnproto_a_SOURCES= \
src/capnp/stringify.c++ \
src/capnp/serialize.c++ \
src/capnp/serialize-packed.c++
nodist_libcapnproto_a_SOURCES = \
nodist_libcapnp_a_SOURCES = \
src/capnp/schema.capnp.c++
# Source files intentionally not included in the dist at this time:
......@@ -150,9 +150,9 @@ $(test_capnpc_outputs): test_capnpc_middleman
BUILT_SOURCES = $(test_capnpc_outputs) $(capnpc_outputs)
check_PROGRAMS = capnproto-test
capnproto_test_LDADD = -lgtest -lgtest_main libcapnproto.a
capnproto_test_SOURCES = \
check_PROGRAMS = capnp-test
capnp_test_LDADD = -lgtest -lgtest_main libcapnp.a
capnp_test_SOURCES = \
src/kj/common-test.c++ \
src/kj/memory-test.c++ \
src/kj/array-test.c++ \
......@@ -177,6 +177,6 @@ capnproto_test_SOURCES = \
src/capnp/serialize-packed-test.c++ \
src/capnp/test-util.c++ \
src/capnp/test-util.h
nodist_capnproto_test_SOURCES = $(test_capnpc_outputs)
nodist_capnp_test_SOURCES = $(test_capnpc_outputs)
TESTS = capnproto-test
TESTS = capnp-test
// This sample code appears in the documentation for the C++ implementation.
//
// Compile with:
// capnpc -oc++ addressbook.capnp
// c++ -std=c++11 -Wall addressbook.c++ addressbook.capnp.c++ -lcapnp -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>
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;
}
}
}
#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::DynamicUnion;
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<DynamicUnion>()
.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<DynamicUnion>()
.set("unemployed", Void::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 member:
structValue.getSchema().getMembers()) {
if (first) {
first = false;
} else {
std::cout << ", ";
}
std::cout << member.getProto().getName().cStr()
<< " = ";
dynamicPrintValue(structValue.get(member));
}
std::cout << ")";
break;
}
case DynamicValue::UNION: {
auto unionValue = value.as<DynamicUnion>();
KJ_IF_MAYBE(tag, unionValue.which()) {
std::cout << tag->getProto().getName().cStr() << "(";
dynamicPrintValue(unionValue.get());
std::cout << ")";
} else {
// Unknown union member; must have come from newer
// version of the protocol.
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;
}
int main(int argc, char* argv[]) {
StructSchema schema = Schema::from<AddressBook>();
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);
} else if (strcmp(argv[1], "dwrite") == 0) {
dynamicWriteAddressBook(1, schema);
} else if (strcmp(argv[1], "dread") == 0) {
dynamicPrintMessage(0, schema);
} else {
std::cerr << "Invalid arg: " << argv[1] << std::endl;
return 1;
}
return 0;
}
@0x9eb32e19f86ee174;
struct Person {
id @0 :UInt32;
name @1 :Text;
email @2 :Text;
phones @3 :List(PhoneNumber);
struct PhoneNumber {
number @0 :Text;
type @1 :Type;
enum Type {
mobile @0;
home @1;
work @2;
}
}
employment @4 union {
unemployed @5 :Void;
employer @6 :Text;
school @7 :Text;
selfEmployed @8 :Void;
# We assume that a person is only one of these.
}
}
struct AddressBook {
people @0 :List(Person);
}
#! /bin/bash
#
# Quick script that compiles and runs the samples, then cleans up.
# Used for release testing.
set -exuo pipefail
capnpc -oc++ addressbook.capnp
c++ -std=c++11 -Wall addressbook.c++ addressbook.capnp.c++ -lcapnp -o addressbook
./addressbook write | ./addressbook read
./addressbook dwrite | ./addressbook dread
rm addressbook addressbook.capnp.c++ addressbook.capnp.h
......@@ -62,7 +62,7 @@ void writeAddressBook(int fd) {
alice.setName("Alice");
alice.setEmail("alice@example.com");
// Type shown for explanation purposes; normally you'd use auto.
capnp::List<Person::PhoneNumber>::Builder alicePhones =
::capnp::List<Person::PhoneNumber>::Builder alicePhones =
alice.initPhones(1);
alicePhones[0].setNumber("555-1212");
alicePhones[0].setType(Person::PhoneNumber::Type::MOBILE);
......@@ -88,7 +88,8 @@ void printAddressBook(int fd) {
AddressBook::Reader addressBook = message.getRoot<AddressBook>();
for (Person::Reader person : addressBook.getPeople()) {
std::cout << person.getName() << ": " << person.getEmail() << std::endl;
std::cout << person.getName().cStr() << ": "
<< person.getEmail().cStr() << std::endl;
for (Person::PhoneNumber::Reader phone: person.getPhones()) {
const char* typeName = "UNKNOWN";
switch (phone.getType()) {
......@@ -97,7 +98,7 @@ void printAddressBook(int fd) {
case Person::PhoneNumber::Type::WORK: typeName = "work"; break;
}
std::cout << " " << typeName << " phone: "
<< phone.getNumber() << std::endl;
<< phone.getNumber().cStr() << std::endl;
}
Person::Employment::Reader employment = person.getEmployment();
switch (employment.which()) {
......@@ -106,11 +107,11 @@ void printAddressBook(int fd) {
break;
case Person::Employment::EMPLOYER:
std::cout << " employer: "
<< employment.getEmployer() << std::endl;
<< employment.getEmployer().cStr() << std::endl;
break;
case Person::Employment::SCHOOL:
std::cout << " student at: "
<< employment.getSchool() << std::endl;
<< employment.getSchool().cStr() << std::endl;
break;
case Person::Employment::SELF_EMPLOYED:
std::cout << " self-employed" << std::endl;
......@@ -387,20 +388,20 @@ of the dynamic API:
#include <capnp/schema.h>
#include <capnp/dynamic.h>
using capnp::DynamicValue;
using capnp::DynamicStruct;
using capnp::DynamicEnum;
using capnp::DynamicList;
using capnp::DynamicUnion;
using capnp::List;
using capnp::Schema;
using capnp::StructSchema;
using capnp::EnumSchema;
using capnp::Void;
using capnp::Text;
using capnp::MallocMessageBuilder;
using capnp::PackedFdMessageReader;
using ::capnp::DynamicValue;
using ::capnp::DynamicStruct;
using ::capnp::DynamicEnum;
using ::capnp::DynamicList;
using ::capnp::DynamicUnion;
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
......@@ -470,7 +471,7 @@ void dynamicPrintValue(DynamicValue::Reader value) {
std::cout << value.as<double>();
break;
case DynamicValue::TEXT:
std::cout << '\"' << value.as<Text>().c_str() << '\"';
std::cout << '\"' << value.as<Text>().cStr() << '\"';
break;
case DynamicValue::LIST: {
std::cout << "[";
......@@ -490,7 +491,7 @@ void dynamicPrintValue(DynamicValue::Reader value) {
auto enumValue = value.as<DynamicEnum>();
KJ_IF_MAYBE(enumerant, enumValue.getEnumerant()) {
std::cout <<
enumerant->getProto().getName().c_str();
enumerant->getProto().getName().cStr();
} else {
// Unknown enum value; output raw number.
std::cout << enumValue.getRaw();
......@@ -508,7 +509,7 @@ void dynamicPrintValue(DynamicValue::Reader value) {
} else {
std::cout << ", ";
}
std::cout << member.getProto().getName().c_str()
std::cout << member.getProto().getName().cStr()
<< " = ";
dynamicPrintValue(structValue.get(member));
}
......@@ -518,7 +519,7 @@ void dynamicPrintValue(DynamicValue::Reader value) {
case DynamicValue::UNION: {
auto unionValue = value.as<DynamicUnion>();
KJ_IF_MAYBE(tag, unionValue.which()) {
std::cout << tag->getProto().getName() << "(";
std::cout << tag->getProto().getName().cStr() << "(";
dynamicPrintValue(unionValue.get());
std::cout << ")";
} else {
......
......@@ -88,9 +88,9 @@ Once Ekam is installed, you can do:
This will build everything it can and run tests.
Note that Ekam will fail to build some things and output a bunch of error messages. You should
be able to ignore any errors that originate outside of the `capnproto` directory -- these are just
parts of other packages like Google Test that Ekam doesn't fully know how to build, but aren't
needed by Cap'n Proto anyway.
be able to ignore any errors that originate outside of the `capnp` and `kj` directories -- these
are just parts of other packages like Google Test that Ekam doesn't fully know how to build, but
aren't needed by Cap'n Proto anyway.
### Running the Benchmarks
......@@ -102,9 +102,9 @@ technologies. Don't assume anything. If you find Cap'n Proto performs sub-opti
That said, Cap'n Proto does have a small suite of silly benchmarks used to validate changes.
The Ekam build will put the benchmark binaries in `tmp/capnproto/benchmark`.
The Ekam build will put the benchmark binaries in `tmp/capnp/benchmark`.
tmp/capnproto/benchmark
tmp/capnp/benchmark
This runs the default test case, CatRank. CatRank simulates a search engine scoring algorithm
which promotes pages that discuss cats (and demotes ones discussing dogs). A list of up to 1000
......@@ -115,7 +115,7 @@ result list sorted by score.
This test case is very string-heavy. Cap'n Proto performs well due to its zero-copy strings, but
packing the message doesn't help much.
tmp/capnproto/benchmark eval
tmp/capnp/benchmark eval
In this test case, the client generates a random, deeply-nested arithmetic expression for the
server to evaluate. This case is a pathologically bad case for Cap'n Proto as it involves lots of
......@@ -123,7 +123,7 @@ pointers with relatively little actual data. When packing is enabled it actuall
Protobufs by a little bit on CPU time (as of this writing, at least; it'll probably get better with
optimization).
tmp/capnproto/benchmark carsales
tmp/capnp/benchmark carsales
This test case involves sending to the server a description of a bunch of cars, and asks the server
to decide how much the lot is worth. This case is very number-heavy, and because of this
......@@ -181,5 +181,5 @@ If setting up Ekam is too much work for you, you can also build with Automake.
make -j4 check
sudo make install
This will install `libcapnproto.a` in `/usr/local/lib` and headers in
`/usr/local/include/capnp` and `/usr/local/include/kj`.
This will install `libcapnp.a` in `/usr/local/lib` and headers in `/usr/local/include/capnp` and
`/usr/local/include/kj`.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment