aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorIvan Komissarov <ABBAPOH@gmail.com>2018-08-10 01:28:06 +0300
committerIvan Komissarov <ABBAPOH@gmail.com>2018-11-22 11:20:38 +0000
commit68578a4bc3f1667530f674db8d01933775ebc4ff (patch)
tree99b801bdce1b955b44ea5ba8b30dddc903ccf9a0 /examples
parent428cc6188fb4f99bca8522530ed400357cfe38ec (diff)
Add protobuf.cpp and protobuf.objc modules
These modules implement google protobuf support for QBS for c++ and objective-c languages [ChangeLog] Added protobuf support for C++ and Objective-C. Fixes: QBS-563 Change-Id: I4bb7e0bdfc1e09ea26c0cd3d3739a741ff834e5d Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'examples')
-rw-r--r--examples/examples.qbs2
-rw-r--r--examples/protobuf/cpp/README.md13
-rw-r--r--examples/protobuf/cpp/addressbook.qbs18
-rw-r--r--examples/protobuf/cpp/main.cpp171
-rw-r--r--examples/protobuf/objc/README.md5
-rw-r--r--examples/protobuf/objc/addressbook.qbs15
-rw-r--r--examples/protobuf/objc/main.m171
-rw-r--r--examples/protobuf/shared/addressbook.proto51
8 files changed, 446 insertions, 0 deletions
diff --git a/examples/examples.qbs b/examples/examples.qbs
index 0e4e5052c..4e51bdbaf 100644
--- a/examples/examples.qbs
+++ b/examples/examples.qbs
@@ -62,5 +62,7 @@ Project {
"helloworld-minimal/hello.qbs",
"helloworld-qt/hello.qbs",
"install-bundle/install-bundle.qbs",
+ "protobuf/cpp/addressbook.qbs",
+ "protobuf/objc/addressbook.qbs",
]
}
diff --git a/examples/protobuf/cpp/README.md b/examples/protobuf/cpp/README.md
new file mode 100644
index 000000000..f0e1b1a93
--- /dev/null
+++ b/examples/protobuf/cpp/README.md
@@ -0,0 +1,13 @@
+### Addressbook c++ example
+
+This example shows how to build a cpp application that uses Google protobuf.
+
+In order to build this example, you'll need to have a protobuf headers and library installed in the system in locations where QBS can find them.
+
+On Linux, you can install a package to the system.
+
+On macOS, you can use brew or compile and install protobuf manually:
+- to /usr/local/
+- to any folder, say /Users/<USER>/protobuf. Then you'll need to set protobuf.libraryPath: "/Users/<USER>/protobuf/lib" and protobuf.includePath: "/Users/<USER>/protobuf/include"
+
+On Windows, you have to compile and install protobuf manually to any folder and use libraryPath and includePath as shown above
diff --git a/examples/protobuf/cpp/addressbook.qbs b/examples/protobuf/cpp/addressbook.qbs
new file mode 100644
index 000000000..bd5afd377
--- /dev/null
+++ b/examples/protobuf/cpp/addressbook.qbs
@@ -0,0 +1,18 @@
+import qbs
+
+CppApplication {
+ name: "addressbook_cpp"
+ consoleApplication: true
+ condition: protobuf.present
+
+ Depends { name: "cpp" }
+ cpp.cxxLanguageVersion: "c++11"
+
+ Depends { id: protobuf; name: "protobuf.cpp"; required: false }
+
+ files: [
+ "../shared/addressbook.proto",
+ "main.cpp",
+ "README.md",
+ ]
+}
diff --git a/examples/protobuf/cpp/main.cpp b/examples/protobuf/cpp/main.cpp
new file mode 100644
index 000000000..703a9d302
--- /dev/null
+++ b/examples/protobuf/cpp/main.cpp
@@ -0,0 +1,171 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <ctime>
+#include <fstream>
+#include <google/protobuf/util/time_util.h>
+#include <iostream>
+#include <string>
+
+#include "addressbook.pb.h"
+
+using google::protobuf::util::TimeUtil;
+
+int printUsage(char *argv0)
+{
+ std::cerr << "Usage: " << argv0 << "add|list ADDRESS_BOOK_FILE" << std::endl;
+ return -1;
+}
+
+std::string readString(const std::string &promt)
+{
+ std::string result;
+ std::cout << promt;
+ std::getline(std::cin, result);
+ return result;
+}
+
+// This function fills in a Person message based on user input.
+void promptForAddress(tutorial::Person* person)
+{
+ std::cout << "Enter person ID number: ";
+ int id;
+ std::cin >> id;
+ person->set_id(id);
+ std::cin.ignore(256, '\n');
+
+ *person->mutable_name() = readString("Enter name: ");
+
+ const auto email = readString("Enter email address (blank for none): ");
+ if (!email.empty())
+ person->set_email(email);
+
+ while (true) {
+ const auto number = readString("Enter a phone number (or leave blank to finish): ");
+ if (number.empty())
+ break;
+
+ tutorial::Person::PhoneNumber *phone_number = person->add_phones();
+ phone_number->set_number(number);
+
+ const auto type = readString("Is this a mobile, home, or work phone? ");
+ 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
+ std::cout << "Unknown phone type. Using default." << std::endl;
+ }
+ *person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(NULL));
+}
+
+// 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);
+
+ std::cout << "Person ID: " << person.id() << std::endl;
+ std::cout << " Name: " << person.name() << std::endl;
+ if (person.email() != "") {
+ std::cout << " E-mail address: " << person.email() << std::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:
+ std::cout << " Mobile phone #: ";
+ break;
+ case tutorial::Person::HOME:
+ std::cout << " Home phone #: ";
+ break;
+ case tutorial::Person::WORK:
+ std::cout << " Work phone #: ";
+ break;
+ default:
+ std::cout << " Unknown phone #: ";
+ break;
+ }
+ std::cout << phone_number.number() << std::endl;
+ }
+ if (person.has_last_updated()) {
+ std::cout << " Updated: " << TimeUtil::ToString(person.last_updated()) << std::endl;
+ }
+ }
+}
+
+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 != 3)
+ return printUsage(argv[0]);
+
+ tutorial::AddressBook address_book;
+
+ // Read the existing address book.
+ std::fstream input(argv[2], std::ios::in | std::ios::binary);
+ if (!input) {
+ std::cout << argv[2] << ": File not found." << std::endl;
+ } else if (!address_book.ParseFromIstream(&input)) {
+ std::cerr << "Failed to parse address book." << std::endl;
+ return -1;
+ }
+
+ const std::string mode(argv[1]);
+ if (mode == "add") {
+ // Add an address.
+ promptForAddress(address_book.add_people());
+
+ if (!input)
+ std::cout << "Creating a new file." << std::endl;
+
+ // Write the new address book back to disk.
+ std::fstream output(argv[2], std::ios::out | std::ios::trunc | std::ios::binary);
+ if (!address_book.SerializeToOstream(&output)) {
+ std::cerr << "Failed to write address book." << std::endl;
+ return -1;
+ }
+ } else if (mode == "list") {
+ listPeople(address_book);
+ } else {
+ return printUsage(argv[0]);
+ }
+
+ // Optional: Delete all global objects allocated by libprotobuf.
+ google::protobuf::ShutdownProtobufLibrary();
+
+ return 0;
+}
diff --git a/examples/protobuf/objc/README.md b/examples/protobuf/objc/README.md
new file mode 100644
index 000000000..c0fc7c0e5
--- /dev/null
+++ b/examples/protobuf/objc/README.md
@@ -0,0 +1,5 @@
+### Addressbook objc example
+
+This example shows how to build an objective-c application that uses Google protobuf.
+
+In order to build this example, you'll need to have a ProtocolBuffers library or framework installed in the system.
diff --git a/examples/protobuf/objc/addressbook.qbs b/examples/protobuf/objc/addressbook.qbs
new file mode 100644
index 000000000..f087113d9
--- /dev/null
+++ b/examples/protobuf/objc/addressbook.qbs
@@ -0,0 +1,15 @@
+import qbs
+
+CppApplication {
+ name: "addressbook_objc"
+ consoleApplication: true
+ condition: protobuf.present && qbs.targetOS.contains("darwin")
+
+ Depends { name: "cpp" }
+ Depends { id: protobuf; name: "protobuf.objc"; required: false }
+
+ files: [
+ "../shared/addressbook.proto",
+ "main.m",
+ ]
+}
diff --git a/examples/protobuf/objc/main.m b/examples/protobuf/objc/main.m
new file mode 100644
index 000000000..903799fca
--- /dev/null
+++ b/examples/protobuf/objc/main.m
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Ivan Komissarov
+** Contact: abbapoh@gmail.com
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#import "Addressbook.pbobjc.h"
+
+#import <Foundation/Foundation.h>
+
+int printUsage(char *argv0)
+{
+ NSString *programName = [[NSString alloc] initWithUTF8String:argv0];
+ NSLog(@"%@", [[NSString alloc] initWithFormat:@"Usage: %@ add|list ADDRESS_BOOK_FILE", programName]);
+ [programName release];
+ return -1;
+}
+
+NSString *readString(NSString *promt)
+{
+ NSLog(@"%@", promt);
+ NSFileHandle *inputFile = [NSFileHandle fileHandleWithStandardInput];
+ NSData *inputData = [inputFile availableData];
+ NSString *result = [[[NSString alloc]initWithData:inputData encoding:NSUTF8StringEncoding] autorelease];
+ result = [[result stringByTrimmingCharactersInSet:
+ [NSCharacterSet whitespaceAndNewlineCharacterSet]] autorelease];
+ return result;
+}
+
+// This function fills in a Person message based on user input.
+void promptForAddress(Person* person)
+{
+ person.id_p = [readString(@"Enter person ID number:") intValue];
+ person.name = readString(@"Enter name:");
+
+ NSString *email = readString(@"Enter email address (blank for none):");
+ if ([email length] != 0)
+ person.email = email;
+
+ while (true) {
+ NSString *number = readString(@"Enter a phone number (or leave blank to finish):");
+ if ([number length] == 0)
+ break;
+
+ Person_PhoneNumber* phoneNumber = [[Person_PhoneNumber alloc] init];
+ phoneNumber.number = number;
+
+ NSString *type = readString(@"Is this a mobile, home, or work phone?:");
+ NSLog(@"\"%@\"", type);
+ if ([type compare:@"mobile"] == NSOrderedSame)
+ phoneNumber.type = Person_PhoneType_Mobile;
+ else if ([type compare:@"home"] == NSOrderedSame)
+ phoneNumber.type = Person_PhoneType_Home;
+ else if ([type compare:@"work"] == NSOrderedSame)
+ phoneNumber.type = Person_PhoneType_Work;
+ else
+ NSLog(@"%@", @"Unknown phone type. Using default.");
+
+ [person.phonesArray addObject:phoneNumber];
+ }
+}
+
+// Iterates though all people in the AddressBook and prints info about them.
+void listPeople(AddressBook *addressBook)
+{
+ NSArray *people = addressBook.peopleArray;
+ for (unsigned i = 0; i < [people count]; i++) {
+ Person *person = [people objectAtIndex:i];
+
+ NSLog(@"%@", [[[NSString alloc] initWithFormat:@"Person ID: %d", person.id_p] autorelease]);
+ NSLog(@"%@", [[[NSString alloc] initWithFormat:@"Person name: %@", person.name] autorelease]);
+
+ if ([person.email length] != 0) {
+ NSLog(@"%@", [[[NSString alloc] initWithFormat:@"E-mail address: %@", person.email] autorelease]);
+ }
+
+ NSArray *phones = person.phonesArray;
+ for (unsigned j = 0; j < [phones count]; j++) {
+ Person_PhoneNumber *phoneNumber = [phones objectAtIndex:j];
+ NSString *phonePrefix;
+
+ switch (phoneNumber.type) {
+ case Person_PhoneType_Mobile:
+ phonePrefix = @"Mobile phone";
+ break;
+ case Person_PhoneType_Home:
+ phonePrefix = @"Home phone";
+ break;
+ case Person_PhoneType_Work:
+ phonePrefix = @"Work phone";
+ break;
+ default:
+ phonePrefix = @"Unknown phone";
+ break;
+ }
+
+ NSLog(@"%@", [[[NSString alloc] initWithFormat:@" %@ #: %@", phonePrefix, phoneNumber.number] autorelease]);
+ }
+ printf("\n");
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc != 3)
+ return printUsage(argv[0]);
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ AddressBook *addressBook;// = [AddressBook alloc];
+ NSString *filePath = [[[NSString alloc] initWithUTF8String:argv[2]] autorelease];
+
+ // Read the existing address book.
+ NSData *data = [NSData dataWithContentsOfFile:filePath];
+ if (!data) {
+ NSLog(@"%@", [[NSString alloc] initWithFormat:@"%@ : File not found.", filePath]);
+ addressBook = [[[AddressBook alloc] init] autorelease];
+ } else {
+ NSError *error;
+ addressBook = [AddressBook parseFromData:data error:&error];
+ if (!addressBook) {
+ NSLog(@"%@", @"Failed to parse address book.");
+ [pool drain];
+ return -1;
+ }
+ }
+
+ if (strcmp(argv[1], "add") == 0) {
+ // Add an address.
+ Person *person = [[Person alloc] init];
+ promptForAddress(person);
+ [addressBook.peopleArray addObject:person];
+
+ if (!data) {
+ NSLog(@"%@", @"Creating a new file.");
+ }
+ [[addressBook data] writeToFile:filePath atomically:YES];
+ } else if (strcmp(argv[1], "list") == 0) {
+ listPeople(addressBook);
+ } else {
+ [pool drain];
+ return printUsage(argv[0]);
+ }
+
+ [pool drain];
+ return 0;
+}
diff --git a/examples/protobuf/shared/addressbook.proto b/examples/protobuf/shared/addressbook.proto
new file mode 100644
index 000000000..b4b33b4c6
--- /dev/null
+++ b/examples/protobuf/shared/addressbook.proto
@@ -0,0 +1,51 @@
+// 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;
+
+import "google/protobuf/timestamp.proto";
+// [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;
+
+ google.protobuf.Timestamp last_updated = 5;
+}
+
+// Our address book file is just one of these.
+message AddressBook {
+ repeated Person people = 1;
+}
+// [END messages]