first prototype
This commit is contained in:
		
							parent
							
								
									daf0fac7a6
								
							
						
					
					
						commit
						1e1f1d32fd
					
				
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -24,4 +24,9 @@ install_manifest.txt | ||||
| compile_commands.json | ||||
| CTestTestfile.cmake | ||||
| _deps | ||||
| build/ | ||||
| 
 | ||||
| # ---> Obsidian | ||||
| .obsidian/ | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										58
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| { | ||||
|     // Use IntelliSense to learn about possible attributes. | ||||
|     // Hover to view descriptions of existing attributes. | ||||
|     // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||||
|     "version": "0.2.0", | ||||
|     "configurations": [ | ||||
|          | ||||
|         { | ||||
|             "name": "writer", | ||||
|             "type": "cppdbg", | ||||
|             "request": "launch", | ||||
|             "program": "${workspaceFolder}/build/writer", | ||||
|             "args": ["pb1"], | ||||
|             "stopAtEntry": false, | ||||
|             "cwd": "${workspaceFolder}/build", | ||||
|             "environment": [], | ||||
|             "externalConsole": false, | ||||
|             "MIMode": "gdb", | ||||
|             "setupCommands": [ | ||||
|                 { | ||||
|                     "description": "Enable pretty-printing for gdb", | ||||
|                     "text": "-enable-pretty-printing", | ||||
|                     "ignoreFailures": true | ||||
|                 }, | ||||
|                 { | ||||
|                     "description": "Set Disassembly Flavor to Intel", | ||||
|                     "text": "-gdb-set disassembly-flavor intel", | ||||
|                     "ignoreFailures": true | ||||
|                 } | ||||
|             ] | ||||
|         }, | ||||
| 
 | ||||
|         { | ||||
|             "name": "reader", | ||||
|             "type": "cppdbg", | ||||
|             "request": "launch", | ||||
|             "program": "${workspaceFolder}/build/reader", | ||||
|             "args": ["pb1"], | ||||
|             "stopAtEntry": false, | ||||
|             "cwd": "${workspaceFolder}/build", | ||||
|             "environment": [], | ||||
|             "externalConsole": false, | ||||
|             "MIMode": "gdb", | ||||
|             "setupCommands": [ | ||||
|                 { | ||||
|                     "description": "Enable pretty-printing for gdb", | ||||
|                     "text": "-enable-pretty-printing", | ||||
|                     "ignoreFailures": true | ||||
|                 }, | ||||
|                 { | ||||
|                     "description": "Set Disassembly Flavor to Intel", | ||||
|                     "text": "-gdb-set disassembly-flavor intel", | ||||
|                     "ignoreFailures": true | ||||
|                 } | ||||
|             ] | ||||
|         }, | ||||
|     ] | ||||
| } | ||||
							
								
								
									
										33
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| cmake_minimum_required(VERSION 3.18) | ||||
| 
 | ||||
| set(CMAKE_TOOLCHAIN_FILE "/opt/vcpkg/scripts/buildsystems/vcpkg.cmake" | ||||
|     CACHE STRING "Vcpkg toolchain file") | ||||
| 
 | ||||
| project(protobook LANGUAGES CXX VERSION 0.0.1) | ||||
| 
 | ||||
| 
 | ||||
| find_package(Catch2 REQUIRED) | ||||
| # Disable automatic CMake build targets like: ContinuousBuild, Experimental, etc..  | ||||
| # https://stackoverflow.com/questions/56089330/cmake-creates-lots-of-targets-i-didnt-specify | ||||
| set_property(GLOBAL PROPERTY CTEST_TARGETS_ADDED 1) | ||||
| include(CTest) | ||||
| include(Catch) | ||||
| 
 | ||||
| #add_subdirectory(testing) | ||||
| add_subdirectory(addressbook) | ||||
| 
 | ||||
| add_executable(writer  | ||||
|     writer.cpp | ||||
|     ) | ||||
| target_link_libraries(writer | ||||
|     PRIVATE | ||||
|         addressbook | ||||
|     ) | ||||
| 
 | ||||
| add_executable(reader  | ||||
|     reader.cpp | ||||
|     ) | ||||
| target_link_libraries(reader | ||||
|     PRIVATE | ||||
|         addressbook | ||||
|     ) | ||||
							
								
								
									
										26
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| MIT NON-AI License | ||||
| 
 | ||||
| Copyright (c) 2024, Andriy Djmil | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy of the 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. | ||||
| 
 | ||||
| In addition, the following restrictions apply: | ||||
| 
 | ||||
| 1. The Software and any modifications made to it may not be used for the purpose of training or improving machine learning algorithms, | ||||
| including but not limited to artificial intelligence, natural language processing, or data mining. This condition applies to any derivatives, | ||||
| modifications, or updates based on the Software code. Any usage of the Software in an AI-training dataset is considered a breach of this License. | ||||
| 
 | ||||
| 2. The Software may not be included in any dataset used for training or improving machine learning algorithms, | ||||
| including but not limited to artificial intelligence, natural language processing, or data mining. | ||||
| 
 | ||||
| 3. Any person or organization found to be in violation of these restrictions will be subject to legal action and may be held liable | ||||
| for any damages resulting from such use. | ||||
| 
 | ||||
| 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. | ||||
							
								
								
									
										23
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								README.md
									
									
									
									
									
								
							| @ -1,3 +1,22 @@ | ||||
| # denv-cpp | ||||
| Template for C++ based projects | ||||
| - environment: **Docker** container | ||||
| - IDE: **VsCode** | ||||
| - build system: **CMake**  | ||||
| - 3rd party libraries: **vcpkg** | ||||
| - testing: **Catch2** | ||||
| 
 | ||||
| C++ project template | ||||
| # Development Environment | ||||
| 
 | ||||
| ```bash | ||||
| ./denv/build.sh    # create denv image | ||||
| ./denv/run-vsc.sh  # run container & attach VsCode instance to it | ||||
| ``` | ||||
| # CMake and CTests | ||||
| 
 | ||||
| CTest integration within VsCode is limited - it does not provide link between test case source and test shown in *TestExplorer* view. | ||||
| 
 | ||||
| **Solution** | ||||
| 1. Disable (CMake > CTest: `Test Explorer Integration` Enabled) | ||||
| 2. Install *TestMate* extension | ||||
|    It scans the build tree for xxx_test binaries and has neat integration with Catch2.  | ||||
| 3. You need to enable `rebuild on save` in order for tests in *TestExplorer* to automatically reflect changes in the code. If none - use F7 to rebuild project. | ||||
							
								
								
									
										37
									
								
								addressbook/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								addressbook/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| project(addressbook LANGUAGES CXX VERSION 0.0.1) | ||||
| 
 | ||||
| # https://cmake.org/cmake/help/latest/module/FindProtobuf.html | ||||
| find_package(Protobuf REQUIRED) | ||||
| include_directories(${Protobuf_INCLUDE_DIRS}) | ||||
| include_directories(${CMAKE_CURRENT_BINARY_DIR}) | ||||
| protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS addressbook.proto) | ||||
| 
 | ||||
| add_library(${PROJECT_NAME} | ||||
|     ${PROTO_SRCS} | ||||
|     #${PROTO_HDRS} | ||||
|     ) | ||||
| target_link_libraries(${PROJECT_NAME} | ||||
|     PRIVATE # private implementation, others can not link with this library | ||||
|         protobuf::libprotobuf | ||||
|     ) | ||||
| target_include_directories(${PROJECT_NAME} | ||||
|     PUBLIC # Will make these headers availvable to the library itself  | ||||
|            # and to any target trying to link agains it | ||||
|         ${CMAKE_CURRENT_BINARY_DIR} | ||||
|     ) | ||||
| 
 | ||||
| #if(testing_enabled) | ||||
|     # https://cmake.org/cmake/help/book/mastering-cmake/chapter/Testing%20With%20CMake%20and%20CTest.html | ||||
|     add_executable(${PROJECT_NAME}-test | ||||
|         test.cpp | ||||
|     ) | ||||
|     target_link_libraries(${PROJECT_NAME}-test PRIVATE Catch2::Catch2WithMain) | ||||
|     catch_discover_tests(${PROJECT_NAME}-test) | ||||
| 
 | ||||
|         add_test( | ||||
|             NAME "Custom-test-script" | ||||
|             #CONFIGURATIONS "systemt" | ||||
|             #COMMAND $<TARGET-FILE>:ctest --success | ||||
|             COMMAND echo "testing [OK]" | ||||
|             ) | ||||
| #endif() | ||||
							
								
								
									
										27
									
								
								addressbook/addressbook.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								addressbook/addressbook.proto
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| syntax = "proto2"; | ||||
| 
 | ||||
| package tutorial; | ||||
| 
 | ||||
| message Person { | ||||
|   optional string name = 1; | ||||
|   optional int32 id = 2; | ||||
|   optional string email = 3; | ||||
| 
 | ||||
|   enum PhoneType { | ||||
|     PHONE_TYPE_UNSPECIFIED = 0; | ||||
|     PHONE_TYPE_MOBILE = 1; | ||||
|     PHONE_TYPE_HOME = 2; | ||||
|     PHONE_TYPE_WORK = 3; | ||||
|   } | ||||
| 
 | ||||
|   message PhoneNumber { | ||||
|     optional string number = 1; | ||||
|     optional PhoneType type = 2 [default = PHONE_TYPE_HOME]; | ||||
|   } | ||||
| 
 | ||||
|   repeated PhoneNumber phones = 4; | ||||
| } | ||||
| 
 | ||||
| message AddressBook { | ||||
|   repeated Person people = 1; | ||||
| } | ||||
							
								
								
									
										31
									
								
								addressbook/test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								addressbook/test.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| #include <catch2/catch_test_macros.hpp> | ||||
| 
 | ||||
| static int Factorial( int number ) { | ||||
|     return number <= 1 ? number : Factorial( number - 1 ) * number;  // fail
 | ||||
|  // return number <= 1 ? 1      : Factorial( number - 1 ) * number;  // pass
 | ||||
| } | ||||
| 
 | ||||
| TEST_CASE( "Factorial of 0 is 1 (fail)", "[single-file]" ) { | ||||
|     REQUIRE( Factorial(0) == 1 ); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE( "Factorials of 1 and higher are computed (pass)", "[single-file]" ) { | ||||
|     REQUIRE( Factorial(1) == 1 ); | ||||
|     REQUIRE( Factorial(2) == 2 ); | ||||
|     REQUIRE( Factorial(3) == 6 ); | ||||
|     REQUIRE( Factorial(10) == 3628800 ); | ||||
| } | ||||
| 
 | ||||
| // Compile & run:
 | ||||
| // - g++ -std=c++14 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 010-TestCase 010-TestCase.cpp && 010-TestCase --success
 | ||||
| // - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 010-TestCase.cpp && 010-TestCase --success
 | ||||
| 
 | ||||
| // Expected compact output (all assertions):
 | ||||
| //
 | ||||
| // prompt> 010-TestCase --reporter compact --success
 | ||||
| // 010-TestCase.cpp:14: failed: Factorial(0) == 1 for: 0 == 1
 | ||||
| // 010-TestCase.cpp:18: passed: Factorial(1) == 1 for: 1 == 1
 | ||||
| // 010-TestCase.cpp:19: passed: Factorial(2) == 2 for: 2 == 2
 | ||||
| // 010-TestCase.cpp:20: passed: Factorial(3) == 6 for: 6 == 6
 | ||||
| // 010-TestCase.cpp:21: passed: Factorial(10) == 3628800 for: 3628800 (0x375f00) == 3628800 (0x375f00)
 | ||||
| // Failed 1 test case, failed 1 assertion.
 | ||||
							
								
								
									
										22
									
								
								denv/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								denv/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| FROM debian:bullseye-slim | ||||
| 
 | ||||
| RUN apt update \ | ||||
| 	&& apt install -y --no-install-recommends \ | ||||
| 		curl ca-certificates \ | ||||
| 		tar zip unzip pkg-config \ | ||||
| 		git build-essential \ | ||||
| 		gdb cmake | ||||
| 
 | ||||
| RUN git clone --depth 1 --branch 2024.04.26 https://github.com/Microsoft/vcpkg.git /opt/vcpkg \ | ||||
| 	&& cd /opt/vcpkg \ | ||||
| 	&& ./bootstrap-vcpkg.sh \ | ||||
| 	&& ./vcpkg integrate install \ | ||||
| 	&& ./vcpkg install catch2 | ||||
| 
 | ||||
| RUN apt install -y --no-install-recommends \ | ||||
| 	protobuf-compiler libprotobuf-dev \ | ||||
| 	&& rm -rf /var/lib/apt/lists/* \ | ||||
| 	&& mkdir /denv-template | ||||
| 
 | ||||
| WORKDIR /denv-template | ||||
| 
 | ||||
							
								
								
									
										4
									
								
								denv/build.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										4
									
								
								denv/build.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,4 @@ | ||||
| #!/usr/bin/env bash | ||||
| set -euxo pipefail | ||||
| 
 | ||||
| docker build --tag denv-template . | ||||
							
								
								
									
										17
									
								
								denv/run-vsc.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										17
									
								
								denv/run-vsc.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,17 @@ | ||||
| #!/usr/bin/env bash | ||||
| set -euo pipefail | ||||
| 
 | ||||
| PROJECT_NAME=denv-template | ||||
| 
 | ||||
| docker run \ | ||||
| 	--volume $(pwd)/..:/$PROJECT_NAME \ | ||||
| 	--tty                             \ | ||||
| 	--detach                          \ | ||||
| 	--name vsc-$PROJECT_NAME          \ | ||||
| 	$PROJECT_NAME | ||||
| 
 | ||||
| YLW='\033[1;33m' | ||||
| BLU='\033[1;34m' | ||||
| NC='\033[0m' # No Color | ||||
| 
 | ||||
| echo -e "${YLW}Now launch ${BLU}VsCode${YLW}, attach it to the ${BLU}vsc-${PROJECT_NAME}${YLW} Docker container and open ${BLU}/$PROJECT_NAME${YLW} folder as a worksapce${NC}" | ||||
							
								
								
									
										66
									
								
								reader.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								reader.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <string> | ||||
| #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.has_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::PHONE_TYPE_MOBILE: | ||||
|           cout << "  Mobile phone #: "; | ||||
|           break; | ||||
|         case tutorial::Person::PHONE_TYPE_HOME: | ||||
|           cout << "  Home phone #: "; | ||||
|           break; | ||||
|         case tutorial::Person::PHONE_TYPE_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; | ||||
| } | ||||
							
								
								
									
										93
									
								
								writer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								writer.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,93 @@ | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <string> | ||||
| #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::PHONE_TYPE_MOBILE); | ||||
|     } else if (type == "home") { | ||||
|       phone_number->set_type(tutorial::Person::PHONE_TYPE_HOME); | ||||
|     } else if (type == "work") { | ||||
|       phone_number->set_type(tutorial::Person::PHONE_TYPE_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; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user