diff --git a/unity_protobuf_sample/README.md b/unity_protobuf_sample/README.md index 2635b1d..80eaff6 100644 --- a/unity_protobuf_sample/README.md +++ b/unity_protobuf_sample/README.md @@ -38,3 +38,9 @@ protobuf_tools build_server_protobuf.bat(自动生成proto服务器代码) + + + +### protobuf_examples + +protobuf_examples目录是从google官方checkout的example https://github.com/google/protobuf/trunk/examples \ No newline at end of file diff --git a/unity_protobuf_sample/protobuf_examples/AddPerson.java b/unity_protobuf_sample/protobuf_examples/AddPerson.java new file mode 100644 index 0000000..c262ab7 --- /dev/null +++ b/unity_protobuf_sample/protobuf_examples/AddPerson.java @@ -0,0 +1,95 @@ +// See README.txt for information and build instructions. + +import com.example.tutorial.AddressBookProtos.AddressBook; +import com.example.tutorial.AddressBookProtos.Person; +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.io.PrintStream; + +class AddPerson { + // This function fills in a Person message based on user input. + static Person PromptForAddress(BufferedReader stdin, + PrintStream stdout) throws IOException { + Person.Builder person = Person.newBuilder(); + + stdout.print("Enter person ID: "); + person.setId(Integer.valueOf(stdin.readLine())); + + stdout.print("Enter name: "); + person.setName(stdin.readLine()); + + stdout.print("Enter email address (blank for none): "); + String email = stdin.readLine(); + if (email.length() > 0) { + person.setEmail(email); + } + + while (true) { + stdout.print("Enter a phone number (or leave blank to finish): "); + String number = stdin.readLine(); + if (number.length() == 0) { + break; + } + + Person.PhoneNumber.Builder phoneNumber = + Person.PhoneNumber.newBuilder().setNumber(number); + + stdout.print("Is this a mobile, home, or work phone? "); + String type = stdin.readLine(); + if (type.equals("mobile")) { + phoneNumber.setType(Person.PhoneType.MOBILE); + } else if (type.equals("home")) { + phoneNumber.setType(Person.PhoneType.HOME); + } else if (type.equals("work")) { + phoneNumber.setType(Person.PhoneType.WORK); + } else { + stdout.println("Unknown phone type. Using default."); + } + + person.addPhones(phoneNumber); + } + + return person.build(); + } + + // Main function: Reads the entire address book from a file, + // adds one person based on user input, then writes it back out to the same + // file. + public static void main(String[] args) throws Exception { + if (args.length != 1) { + System.err.println("Usage: AddPerson ADDRESS_BOOK_FILE"); + System.exit(-1); + } + + AddressBook.Builder addressBook = AddressBook.newBuilder(); + + // Read the existing address book. + try { + FileInputStream input = new FileInputStream(args[0]); + try { + addressBook.mergeFrom(input); + } finally { + try { input.close(); } catch (Throwable ignore) {} + } + } catch (FileNotFoundException e) { + System.out.println(args[0] + ": File not found. Creating a new file."); + } + + // Add an address. + addressBook.addPeople( + PromptForAddress(new BufferedReader(new InputStreamReader(System.in)), + System.out)); + + // Write the new address book back to disk. + FileOutputStream output = new FileOutputStream(args[0]); + try { + addressBook.build().writeTo(output); + } finally { + output.close(); + } + } +} diff --git a/unity_protobuf_sample/protobuf_examples/CMakeLists.txt b/unity_protobuf_sample/protobuf_examples/CMakeLists.txt new file mode 100644 index 0000000..2cd2acc --- /dev/null +++ b/unity_protobuf_sample/protobuf_examples/CMakeLists.txt @@ -0,0 +1,63 @@ +# Minimum CMake required +cmake_minimum_required(VERSION 2.8.12) + +# Project +project(protobuf-examples) + +# Find required protobuf package +find_package(protobuf CONFIG REQUIRED) + +if(protobuf_VERBOSE) + message(STATUS "Using Protocol Buffers ${Protobuf_VERSION}") +endif() + +set(CMAKE_INCLUDE_CURRENT_DIR TRUE) + +# http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F +if(MSVC AND protobuf_MSVC_STATIC_RUNTIME) + foreach(flag_var + CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + if(${flag_var} MATCHES "/MD") + string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + endif(${flag_var} MATCHES "/MD") + endforeach() +endif() + +foreach(example add_person list_people) + set(${example}_SRCS ${example}.cc) + set(${example}_PROTOS addressbook.proto) + + #Code Generation + if(protobuf_MODULE_COMPATIBLE) #Legacy Support + protobuf_generate_cpp(${example}_PROTO_SRCS ${example}_PROTO_HDRS ${${example}_PROTOS}) + list(APPEND ${example}_SRCS ${${example}_PROTO_SRCS} ${${example}_PROTO_HDRS}) + else() + + foreach(proto_file ${${example}_PROTOS}) + get_filename_component(proto_file_abs ${proto_file} ABSOLUTE) + get_filename_component(basename ${proto_file} NAME_WE) + set(generated_files ${basename}.pb.cc ${basename}.pb.h) + list(APPEND ${example}_SRCS ${generated_files}) + + add_custom_command( + OUTPUT ${generated_files} + COMMAND protobuf::protoc + ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} -I ${CMAKE_CURRENT_SOURCE_DIR} ${proto_file_abs} + COMMENT "Generating ${generated_files} from ${proto_file}" + VERBATIM + ) + endforeach() + endif() + + #Executable setup + set(executable_name ${example}_cpp) + add_executable(${executable_name} ${${example}_SRCS} ${${example}_PROTOS}) + if(protobuf_MODULE_COMPATIBLE) #Legacy mode + target_include_directories(${executable_name} PUBLIC ${PROTOBUF_INCLUDE_DIRS}) + target_link_libraries(${executable_name} ${PROTOBUF_LIBRARIES}) + else() + target_link_libraries(${executable_name} protobuf::libprotobuf) + endif() + +endforeach() diff --git a/unity_protobuf_sample/protobuf_examples/ListPeople.java b/unity_protobuf_sample/protobuf_examples/ListPeople.java new file mode 100644 index 0000000..7892430 --- /dev/null +++ b/unity_protobuf_sample/protobuf_examples/ListPeople.java @@ -0,0 +1,50 @@ +// See README.txt for information and build instructions. + +import com.example.tutorial.AddressBookProtos.AddressBook; +import com.example.tutorial.AddressBookProtos.Person; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.PrintStream; + +class ListPeople { + // Iterates though all people in the AddressBook and prints info about them. + static void Print(AddressBook addressBook) { + for (Person person: addressBook.getPeopleList()) { + System.out.println("Person ID: " + person.getId()); + System.out.println(" Name: " + person.getName()); + if (!person.getEmail().isEmpty()) { + System.out.println(" E-mail address: " + person.getEmail()); + } + + for (Person.PhoneNumber phoneNumber : person.getPhonesList()) { + switch (phoneNumber.getType()) { + case MOBILE: + System.out.print(" Mobile phone #: "); + break; + case HOME: + System.out.print(" Home phone #: "); + break; + case WORK: + System.out.print(" Work phone #: "); + break; + } + System.out.println(phoneNumber.getNumber()); + } + } + } + + // Main function: Reads the entire address book from a file and prints all + // the information inside. + public static void main(String[] args) throws Exception { + if (args.length != 1) { + System.err.println("Usage: ListPeople ADDRESS_BOOK_FILE"); + System.exit(-1); + } + + // Read the existing address book. + AddressBook addressBook = + AddressBook.parseFrom(new FileInputStream(args[0])); + + Print(addressBook); + } +} diff --git a/unity_protobuf_sample/protobuf_examples/Makefile b/unity_protobuf_sample/protobuf_examples/Makefile new file mode 100644 index 0000000..51f1342 --- /dev/null +++ b/unity_protobuf_sample/protobuf_examples/Makefile @@ -0,0 +1,79 @@ +# See README.txt. + +.PHONY: all cpp java python clean + +all: cpp java python + +cpp: add_person_cpp list_people_cpp +go: add_person_go list_people_go +gotest: add_person_gotest list_people_gotest +java: add_person_java list_people_java +python: add_person_python list_people_python + +clean: + rm -f add_person_cpp list_people_cpp add_person_java list_people_java add_person_python list_people_python + rm -f javac_middleman AddPerson*.class ListPeople*.class com/example/tutorial/*.class + rm -f protoc_middleman addressbook.pb.cc addressbook.pb.h addressbook_pb2.py com/example/tutorial/AddressBookProtos.java + rm -f *.pyc + rm -f protoc_middleman_go tutorial/*.pb.go add_person_go list_people_go + rmdir tutorial 2>/dev/null || true + rmdir com/example/tutorial 2>/dev/null || true + rmdir com/example 2>/dev/null || true + rmdir com 2>/dev/null || true + +protoc_middleman: addressbook.proto + protoc --cpp_out=. --java_out=. --python_out=. addressbook.proto + @touch protoc_middleman + +protoc_middleman_go: addressbook.proto + mkdir tutorial # make directory for go package + protoc --go_out=tutorial addressbook.proto + @touch protoc_middleman_go + +add_person_cpp: add_person.cc protoc_middleman + pkg-config --cflags protobuf # fails if protobuf is not installed + c++ add_person.cc addressbook.pb.cc -o add_person_cpp `pkg-config --cflags --libs protobuf` + +list_people_cpp: list_people.cc protoc_middleman + pkg-config --cflags protobuf # fails if protobuf is not installed + c++ list_people.cc addressbook.pb.cc -o list_people_cpp `pkg-config --cflags --libs protobuf` + +add_person_go: add_person.go protoc_middleman_go + go build -o add_person_go add_person.go + +add_person_gotest: add_person_test.go add_person_go + go test add_person.go add_person_test.go + +list_people_go: list_people.go protoc_middleman_go + go build -o list_people_go list_people.go + +list_people_gotest: list_people.go list_people_go + go test list_people.go list_people_test.go + +javac_middleman: AddPerson.java ListPeople.java protoc_middleman + javac AddPerson.java ListPeople.java com/example/tutorial/AddressBookProtos.java + @touch javac_middleman + +add_person_java: javac_middleman + @echo "Writing shortcut script add_person_java..." + @echo '#! /bin/sh' > add_person_java + @echo 'java -classpath .:$$CLASSPATH AddPerson "$$@"' >> add_person_java + @chmod +x add_person_java + +list_people_java: javac_middleman + @echo "Writing shortcut script list_people_java..." + @echo '#! /bin/sh' > list_people_java + @echo 'java -classpath .:$$CLASSPATH ListPeople "$$@"' >> list_people_java + @chmod +x list_people_java + +add_person_python: add_person.py protoc_middleman + @echo "Writing shortcut script add_person_python..." + @echo '#! /bin/sh' > add_person_python + @echo './add_person.py "$$@"' >> add_person_python + @chmod +x add_person_python + +list_people_python: list_people.py protoc_middleman + @echo "Writing shortcut script list_people_python..." + @echo '#! /bin/sh' > list_people_python + @echo './list_people.py "$$@"' >> list_people_python + @chmod +x list_people_python diff --git a/unity_protobuf_sample/protobuf_examples/README.txt b/unity_protobuf_sample/protobuf_examples/README.txt new file mode 100644 index 0000000..b33f841 --- /dev/null +++ b/unity_protobuf_sample/protobuf_examples/README.txt @@ -0,0 +1,54 @@ +This directory contains example code that uses Protocol Buffers to manage an +address book. Two programs are provided, each with three different +implementations, one written in each of C++, Java, and Python. The add_person +example adds a new person to an address book, prompting the user to input +the person's information. The list_people example lists people already in the +address book. The examples use the exact same format in all three languages, +so you can, for example, use add_person_java to create an address book and then +use list_people_python to read it. + +You must install the protobuf package before you can build these. + +To build all the examples (on a unix-like system), simply run "make". This +creates the following executable files in the current directory: + add_person_cpp list_people_cpp + add_person_java list_people_java + add_person_python list_people_python + +If you only want to compile examples in one language, use "make cpp"*, +"make java", or "make python". + +All of these programs simply take an address book file as their parameter. +The add_person programs will create the file if it doesn't already exist. + +These examples are part of the Protocol Buffers tutorial, located at: + https://developers.google.com/protocol-buffers/docs/tutorials + +* Note that on some platforms you may have to edit the Makefile and remove +"-lpthread" from the linker commands (perhaps replacing it with something else). +We didn't do this automatically because we wanted to keep the example simple. + +## Go ## + +The Go example requires a plugin to the protocol buffer compiler, so it is not +build with all the other examples. See: + https://github.com/golang/protobuf +for more information about Go protocol buffer support. + +First, install the Protocol Buffers compiler (protoc). +Then, install the Go Protocol Buffers plugin +($GOPATH/bin must be in your $PATH for protoc to find it): + go get github.com/golang/protobuf/protoc-gen-go + +Build the Go samples in this directory with "make go". This creates the +following executable files in the current directory: + add_person_go list_people_go +To run the example: + ./add_person_go addressbook.data +to add a person to the protocol buffer encoded file addressbook.data. The file +is created if it does not exist. To view the data, run: + ./list_people_go addressbook.data + +Observe that the C++, Python, and Java examples in this directory run in a +similar way and can view/modify files created by the Go example and vice +versa. diff --git a/unity_protobuf_sample/protobuf_examples/add_person.cc b/unity_protobuf_sample/protobuf_examples/add_person.cc new file mode 100644 index 0000000..9bec4b3 --- /dev/null +++ b/unity_protobuf_sample/protobuf_examples/add_person.cc @@ -0,0 +1,95 @@ +// See README.txt for information and build instructions. + +#include +#include +#include +#include "addressbook.pb.h" +using namespace std; + +// This function fills in a Person message based on user input. +void PromptForAddress(tutorial::Person* person) { + cout << "Enter person ID number: "; + int id; + cin >> id; + person->set_id(id); + cin.ignore(256, '\n'); + + cout << "Enter name: "; + getline(cin, *person->mutable_name()); + + cout << "Enter email address (blank for none): "; + string email; + getline(cin, email); + if (!email.empty()) { + person->set_email(email); + } + + while (true) { + cout << "Enter a phone number (or leave blank to finish): "; + string number; + getline(cin, number); + if (number.empty()) { + break; + } + + tutorial::Person::PhoneNumber* phone_number = person->add_phones(); + phone_number->set_number(number); + + cout << "Is this a mobile, home, or work phone? "; + string type; + getline(cin, type); + if (type == "mobile") { + phone_number->set_type(tutorial::Person::MOBILE); + } else if (type == "home") { + phone_number->set_type(tutorial::Person::HOME); + } else if (type == "work") { + phone_number->set_type(tutorial::Person::WORK); + } else { + cout << "Unknown phone type. Using default." << endl; + } + } +} + +// Main function: Reads the entire address book from a file, +// adds one person based on user input, then writes it back out to the same +// file. +int main(int argc, char* argv[]) { + // Verify that the version of the library that we linked against is + // compatible with the version of the headers we compiled against. + GOOGLE_PROTOBUF_VERIFY_VERSION; + + if (argc != 2) { + cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl; + return -1; + } + + tutorial::AddressBook address_book; + + { + // Read the existing address book. + fstream input(argv[1], ios::in | ios::binary); + if (!input) { + cout << argv[1] << ": File not found. Creating a new file." << endl; + } else if (!address_book.ParseFromIstream(&input)) { + cerr << "Failed to parse address book." << endl; + return -1; + } + } + + // Add an address. + PromptForAddress(address_book.add_people()); + + { + // Write the new address book back to disk. + fstream output(argv[1], ios::out | ios::trunc | ios::binary); + if (!address_book.SerializeToOstream(&output)) { + cerr << "Failed to write address book." << endl; + return -1; + } + } + + // Optional: Delete all global objects allocated by libprotobuf. + google::protobuf::ShutdownProtobufLibrary(); + + return 0; +} diff --git a/unity_protobuf_sample/protobuf_examples/add_person.go b/unity_protobuf_sample/protobuf_examples/add_person.go new file mode 100644 index 0000000..4f2e7f7 --- /dev/null +++ b/unity_protobuf_sample/protobuf_examples/add_person.go @@ -0,0 +1,133 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "io/ioutil" + "log" + "os" + "strings" + + "github.com/golang/protobuf/proto" + pb "github.com/google/protobuf/examples/tutorial" +) + +func promptForAddress(r io.Reader) (*pb.Person, error) { + // A protocol buffer can be created like any struct. + p := &pb.Person{} + + rd := bufio.NewReader(r) + fmt.Print("Enter person ID number: ") + // An int32 field in the .proto file is represented as an int32 field + // in the generated Go struct. + if _, err := fmt.Fscanf(rd, "%d\n", &p.Id); err != nil { + return p, err + } + + fmt.Print("Enter name: ") + name, err := rd.ReadString('\n') + if err != nil { + return p, err + } + // A string field in the .proto file results in a string field in Go. + // We trim the whitespace because rd.ReadString includes the trailing + // newline character in its output. + p.Name = strings.TrimSpace(name) + + fmt.Print("Enter email address (blank for none): ") + email, err := rd.ReadString('\n') + if err != nil { + return p, err + } + p.Email = strings.TrimSpace(email) + + for { + fmt.Print("Enter a phone number (or leave blank to finish): ") + phone, err := rd.ReadString('\n') + if err != nil { + return p, err + } + phone = strings.TrimSpace(phone) + if phone == "" { + break + } + // The PhoneNumber message type is nested within the Person + // message in the .proto file. This results in a Go struct + // named using the name of the parent prefixed to the name of + // the nested message. Just as with pb.Person, it can be + // created like any other struct. + pn := &pb.Person_PhoneNumber{ + Number: phone, + } + + fmt.Print("Is this a mobile, home, or work phone? ") + ptype, err := rd.ReadString('\n') + if err != nil { + return p, err + } + ptype = strings.TrimSpace(ptype) + + // A proto enum results in a Go constant for each enum value. + switch ptype { + case "mobile": + pn.Type = pb.Person_MOBILE + case "home": + pn.Type = pb.Person_HOME + case "work": + pn.Type = pb.Person_WORK + default: + fmt.Printf("Unknown phone type %q. Using default.\n", ptype) + } + + // A repeated proto field maps to a slice field in Go. We can + // append to it like any other slice. + p.Phones = append(p.Phones, pn) + } + + return p, nil +} + +// Main reads the entire address book from a file, adds one person based on +// user input, then writes it back out to the same file. +func main() { + if len(os.Args) != 2 { + log.Fatalf("Usage: %s ADDRESS_BOOK_FILE\n", os.Args[0]) + } + fname := os.Args[1] + + // Read the existing address book. + in, err := ioutil.ReadFile(fname) + if err != nil { + if os.IsNotExist(err) { + fmt.Printf("%s: File not found. Creating new file.\n", fname) + } else { + log.Fatalln("Error reading file:", err) + } + } + + // [START marshal_proto] + book := &pb.AddressBook{} + // [START_EXCLUDE] + if err := proto.Unmarshal(in, book); err != nil { + log.Fatalln("Failed to parse address book:", err) + } + + // Add an address. + addr, err := promptForAddress(os.Stdin) + if err != nil { + log.Fatalln("Error with address:", err) + } + book.People = append(book.People, addr) + // [END_EXCLUDE] + + // Write the new address book back to disk. + out, err := proto.Marshal(book) + if err != nil { + log.Fatalln("Failed to encode address book:", err) + } + if err := ioutil.WriteFile(fname, out, 0644); err != nil { + log.Fatalln("Failed to write address book:", err) + } + // [END marshal_proto] +} diff --git a/unity_protobuf_sample/protobuf_examples/add_person.py b/unity_protobuf_sample/protobuf_examples/add_person.py new file mode 100644 index 0000000..0b69857 --- /dev/null +++ b/unity_protobuf_sample/protobuf_examples/add_person.py @@ -0,0 +1,56 @@ +#! /usr/bin/env python + +# See README.txt for information and build instructions. + +import addressbook_pb2 +import sys + +# This function fills in a Person message based on user input. +def PromptForAddress(person): + person.id = int(raw_input("Enter person ID number: ")) + person.name = raw_input("Enter name: ") + + email = raw_input("Enter email address (blank for none): ") + if email != "": + person.email = email + + while True: + number = raw_input("Enter a phone number (or leave blank to finish): ") + if number == "": + break + + phone_number = person.phones.add() + phone_number.number = number + + type = raw_input("Is this a mobile, home, or work phone? ") + if type == "mobile": + phone_number.type = addressbook_pb2.Person.MOBILE + elif type == "home": + phone_number.type = addressbook_pb2.Person.HOME + elif type == "work": + phone_number.type = addressbook_pb2.Person.WORK + else: + print "Unknown phone type; leaving as default value." + +# Main procedure: Reads the entire address book from a file, +# adds one person based on user input, then writes it back out to the same +# file. +if len(sys.argv) != 2: + print "Usage:", sys.argv[0], "ADDRESS_BOOK_FILE" + sys.exit(-1) + +address_book = addressbook_pb2.AddressBook() + +# Read the existing address book. +try: + with open(sys.argv[1], "rb") as f: + address_book.ParseFromString(f.read()) +except IOError: + print sys.argv[1] + ": File not found. Creating a new file." + +# Add an address. +PromptForAddress(address_book.people.add()) + +# Write the new address book back to disk. +with open(sys.argv[1], "wb") as f: + f.write(address_book.SerializeToString()) diff --git a/unity_protobuf_sample/protobuf_examples/add_person_test.go b/unity_protobuf_sample/protobuf_examples/add_person_test.go new file mode 100644 index 0000000..0507db6 --- /dev/null +++ b/unity_protobuf_sample/protobuf_examples/add_person_test.go @@ -0,0 +1,58 @@ +package main + +import ( + "strings" + "testing" + + "github.com/golang/protobuf/proto" + pb "github.com/google/protobuf/examples/tutorial" +) + +func TestPromptForAddressReturnsAddress(t *testing.T) { + in := `12345 +Example Name +name@example.com +123-456-7890 +home +222-222-2222 +mobile +111-111-1111 +work +777-777-7777 +unknown + +` + got, err := promptForAddress(strings.NewReader(in)) + if err != nil { + t.Fatalf("promptForAddress(%q) had unexpected error: %s", in, err.Error()) + } + if got.Id != 12345 { + t.Errorf("promptForAddress(%q) got %d, want ID %d", in, got.Id, 12345) + } + if got.Name != "Example Name" { + t.Errorf("promptForAddress(%q) => want name %q, got %q", "Example Name", got.Name) + } + if got.Email != "name@example.com" { + t.Errorf("promptForAddress(%q) => want email %q, got %q", "name@example.com", got.Email) + } + + want := []*pb.Person_PhoneNumber{ + {Number: "123-456-7890", Type: pb.Person_HOME}, + {Number: "222-222-2222", Type: pb.Person_MOBILE}, + {Number: "111-111-1111", Type: pb.Person_WORK}, + {Number: "777-777-7777", Type: pb.Person_MOBILE}, + } + if len(got.Phones) != len(want) { + t.Errorf("want %d phone numbers, got %d", len(want), len(got.Phones)) + } + phones := len(got.Phones) + if phones > len(want) { + phones = len(want) + } + for i := 0; i < phones; i++ { + if !proto.Equal(got.Phones[i], want[i]) { + t.Errorf("want phone %q, got %q", *want[i], *got.Phones[i]) + } + + } +} diff --git a/unity_protobuf_sample/protobuf_examples/addressbook.proto b/unity_protobuf_sample/protobuf_examples/addressbook.proto new file mode 100644 index 0000000..23cc2f9 --- /dev/null +++ b/unity_protobuf_sample/protobuf_examples/addressbook.proto @@ -0,0 +1,47 @@ +// See README.txt for information and build instructions. +// +// Note: START and END tags are used in comments to define sections used in +// tutorials. They are not part of the syntax for Protocol Buffers. +// +// To get an in-depth walkthrough of this file and the related examples, see: +// https://developers.google.com/protocol-buffers/docs/tutorials + +// [START declaration] +syntax = "proto3"; +package tutorial; +// [END declaration] + +// [START java_declaration] +option java_package = "com.example.tutorial"; +option java_outer_classname = "AddressBookProtos"; +// [END java_declaration] + +// [START csharp_declaration] +option csharp_namespace = "Google.Protobuf.Examples.AddressBook"; +// [END csharp_declaration] + +// [START messages] +message Person { + string name = 1; + int32 id = 2; // Unique ID number for this person. + string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + string number = 1; + PhoneType type = 2; + } + + repeated PhoneNumber phones = 4; +} + +// Our address book file is just one of these. +message AddressBook { + repeated Person people = 1; +} +// [END messages] diff --git a/unity_protobuf_sample/protobuf_examples/list_people.cc b/unity_protobuf_sample/protobuf_examples/list_people.cc new file mode 100644 index 0000000..68e5666 --- /dev/null +++ b/unity_protobuf_sample/protobuf_examples/list_people.cc @@ -0,0 +1,68 @@ +// See README.txt for information and build instructions. + +#include +#include +#include +#include "addressbook.pb.h" +using namespace std; + +// Iterates though all people in the AddressBook and prints info about them. +void ListPeople(const tutorial::AddressBook& address_book) { + for (int i = 0; i < address_book.people_size(); i++) { + const tutorial::Person& person = address_book.people(i); + + cout << "Person ID: " << person.id() << endl; + cout << " Name: " << person.name() << endl; + if (person.email() != "") { + cout << " E-mail address: " << person.email() << endl; + } + + for (int j = 0; j < person.phones_size(); j++) { + const tutorial::Person::PhoneNumber& phone_number = person.phones(j); + + switch (phone_number.type()) { + case tutorial::Person::MOBILE: + cout << " Mobile phone #: "; + break; + case tutorial::Person::HOME: + cout << " Home phone #: "; + break; + case tutorial::Person::WORK: + cout << " Work phone #: "; + break; + } + cout << phone_number.number() << endl; + } + } +} + +// Main function: Reads the entire address book from a file and prints all +// the information inside. +int main(int argc, char* argv[]) { + // Verify that the version of the library that we linked against is + // compatible with the version of the headers we compiled against. + GOOGLE_PROTOBUF_VERIFY_VERSION; + + if (argc != 2) { + cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl; + return -1; + } + + tutorial::AddressBook address_book; + + { + // Read the existing address book. + fstream input(argv[1], ios::in | ios::binary); + if (!address_book.ParseFromIstream(&input)) { + cerr << "Failed to parse address book." << endl; + return -1; + } + } + + ListPeople(address_book); + + // Optional: Delete all global objects allocated by libprotobuf. + google::protobuf::ShutdownProtobufLibrary(); + + return 0; +} diff --git a/unity_protobuf_sample/protobuf_examples/list_people.go b/unity_protobuf_sample/protobuf_examples/list_people.go new file mode 100644 index 0000000..70bc589 --- /dev/null +++ b/unity_protobuf_sample/protobuf_examples/list_people.go @@ -0,0 +1,61 @@ +package main + +import ( + "fmt" + "io" + "io/ioutil" + "log" + "os" + + "github.com/golang/protobuf/proto" + pb "github.com/google/protobuf/examples/tutorial" +) + +func writePerson(w io.Writer, p *pb.Person) { + fmt.Fprintln(w, "Person ID:", p.Id) + fmt.Fprintln(w, " Name:", p.Name) + if p.Email != "" { + fmt.Fprintln(w, " E-mail address:", p.Email) + } + + for _, pn := range p.Phones { + switch pn.Type { + case pb.Person_MOBILE: + fmt.Fprint(w, " Mobile phone #: ") + case pb.Person_HOME: + fmt.Fprint(w, " Home phone #: ") + case pb.Person_WORK: + fmt.Fprint(w, " Work phone #: ") + } + fmt.Fprintln(w, pn.Number) + } +} + +func listPeople(w io.Writer, book *pb.AddressBook) { + for _, p := range book.People { + writePerson(w, p) + } +} + +// Main reads the entire address book from a file and prints all the +// information inside. +func main() { + if len(os.Args) != 2 { + log.Fatalf("Usage: %s ADDRESS_BOOK_FILE\n", os.Args[0]) + } + fname := os.Args[1] + + // [START unmarshal_proto] + // Read the existing address book. + in, err := ioutil.ReadFile(fname) + if err != nil { + log.Fatalln("Error reading file:", err) + } + book := &pb.AddressBook{} + if err := proto.Unmarshal(in, book); err != nil { + log.Fatalln("Failed to parse address book:", err) + } + // [END unmarshal_proto] + + listPeople(os.Stdout, book) +} diff --git a/unity_protobuf_sample/protobuf_examples/list_people.py b/unity_protobuf_sample/protobuf_examples/list_people.py new file mode 100644 index 0000000..f131872 --- /dev/null +++ b/unity_protobuf_sample/protobuf_examples/list_people.py @@ -0,0 +1,37 @@ +#! /usr/bin/env python + +# See README.txt for information and build instructions. + +import addressbook_pb2 +import sys + +# Iterates though all people in the AddressBook and prints info about them. +def ListPeople(address_book): + for person in address_book.people: + print "Person ID:", person.id + print " Name:", person.name + if person.email != "": + print " E-mail address:", person.email + + for phone_number in person.phones: + if phone_number.type == addressbook_pb2.Person.MOBILE: + print " Mobile phone #:", + elif phone_number.type == addressbook_pb2.Person.HOME: + print " Home phone #:", + elif phone_number.type == addressbook_pb2.Person.WORK: + print " Work phone #:", + print phone_number.number + +# Main procedure: Reads the entire address book from a file and prints all +# the information inside. +if len(sys.argv) != 2: + print "Usage:", sys.argv[0], "ADDRESS_BOOK_FILE" + sys.exit(-1) + +address_book = addressbook_pb2.AddressBook() + +# Read the existing address book. +with open(sys.argv[1], "rb") as f: + address_book.ParseFromString(f.read()) + +ListPeople(address_book) diff --git a/unity_protobuf_sample/protobuf_examples/list_people_test.go b/unity_protobuf_sample/protobuf_examples/list_people_test.go new file mode 100644 index 0000000..87d6ad6 --- /dev/null +++ b/unity_protobuf_sample/protobuf_examples/list_people_test.go @@ -0,0 +1,120 @@ +package main + +import ( + "bytes" + "strings" + "testing" + + pb "github.com/google/protobuf/examples/tutorial" +) + +func TestWritePersonWritesPerson(t *testing.T) { + buf := new(bytes.Buffer) + // [START populate_proto] + p := pb.Person{ + Id: 1234, + Name: "John Doe", + Email: "jdoe@example.com", + Phones: []*pb.Person_PhoneNumber{ + {Number: "555-4321", Type: pb.Person_HOME}, + }, + } + // [END populate_proto] + writePerson(buf, &p) + got := buf.String() + want := `Person ID: 1234 + Name: John Doe + E-mail address: jdoe@example.com + Home phone #: 555-4321 +` + if got != want { + t.Errorf("writePerson(%s) =>\n\t%q, want %q", p.String(), got, want) + } +} + +func TestListPeopleWritesList(t *testing.T) { + buf := new(bytes.Buffer) + in := pb.AddressBook{[]*pb.Person{ + { + Name: "John Doe", + Id: 101, + Email: "john@example.com", + }, + { + Name: "Jane Doe", + Id: 102, + }, + { + Name: "Jack Doe", + Id: 201, + Email: "jack@example.com", + Phones: []*pb.Person_PhoneNumber{ + {Number: "555-555-5555", Type: pb.Person_WORK}, + }, + }, + { + Name: "Jack Buck", + Id: 301, + Email: "buck@example.com", + Phones: []*pb.Person_PhoneNumber{ + {Number: "555-555-0000", Type: pb.Person_HOME}, + {Number: "555-555-0001", Type: pb.Person_MOBILE}, + {Number: "555-555-0002", Type: pb.Person_WORK}, + }, + }, + { + Name: "Janet Doe", + Id: 1001, + Email: "janet@example.com", + Phones: []*pb.Person_PhoneNumber{ + {Number: "555-777-0000"}, + {Number: "555-777-0001", Type: pb.Person_HOME}, + }, + }, + }} + listPeople(buf, &in) + want := strings.Split(`Person ID: 101 + Name: John Doe + E-mail address: john@example.com +Person ID: 102 + Name: Jane Doe +Person ID: 201 + Name: Jack Doe + E-mail address: jack@example.com + Work phone #: 555-555-5555 +Person ID: 301 + Name: Jack Buck + E-mail address: buck@example.com + Home phone #: 555-555-0000 + Mobile phone #: 555-555-0001 + Work phone #: 555-555-0002 +Person ID: 1001 + Name: Janet Doe + E-mail address: janet@example.com + Mobile phone #: 555-777-0000 + Home phone #: 555-777-0001 +`, "\n") + got := strings.Split(buf.String(), "\n") + if len(got) != len(want) { + t.Errorf( + "listPeople(%s) =>\n\t%q has %d lines, want %d", + in.String(), + buf.String(), + len(got), + len(want)) + } + lines := len(got) + if lines > len(want) { + lines = len(want) + } + for i := 0; i < lines; i++ { + if got[i] != want[i] { + t.Errorf( + "listPeople(%s) =>\n\tline %d %q, want %q", + in.String(), + i, + got[i], + want[i]) + } + } +}