github.com/stackb/rules_proto@v0.0.0-20240221195024-5428336c51f1/example/routeguide/cc/helper.cc (about) 1 /* 2 * 3 * Copyright 2015 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 #include "example/routeguide/routeguide.grpc.pb.h" 20 #include <algorithm> 21 #include <cctype> 22 #include <fstream> 23 #include <iostream> 24 #include <sstream> 25 #include <string> 26 #include <vector> 27 28 namespace example { 29 namespace routeguide { 30 31 std::string GetDbFileContent(int argc, char **argv) { 32 std::string db_path; 33 std::string arg_str("--db_path"); 34 if (argc > 1) { 35 std::string argv_1 = argv[1]; 36 size_t start_position = argv_1.find(arg_str); 37 if (start_position != std::string::npos) { 38 start_position += arg_str.size(); 39 if (argv_1[start_position] == ' ' || argv_1[start_position] == '=') { 40 db_path = argv_1.substr(start_position + 1); 41 } 42 } 43 } else { 44 db_path = "example/routeguide/features.json"; 45 } 46 std::ifstream db_file(db_path); 47 if (!db_file.is_open()) { 48 std::cout << "Failed to open " << db_path << std::endl; 49 return ""; 50 } 51 std::stringstream db; 52 db << db_file.rdbuf(); 53 return db.str(); 54 } 55 56 // A simple parser for the json db file. It requires the db file to have the 57 // exact form of [{"location": { "latitude": 123, "longitude": 456}, "name": 58 // "the name can be empty" }, { ... } ... The spaces will be stripped. 59 class Parser { 60 public: 61 explicit Parser(const std::string &db) : db_(db) { 62 // Remove all spaces. 63 db_.erase(std::remove_if(db_.begin(), db_.end(), isspace), db_.end()); 64 if (!Match("[")) { 65 SetFailedAndReturnFalse(); 66 } 67 } 68 69 bool Finished() { return current_ >= db_.size(); } 70 71 bool TryParseOne(Feature *feature) { 72 if (failed_ || Finished() || !Match("{")) { 73 return SetFailedAndReturnFalse(); 74 } 75 if (!Match(location_) || !Match("{") || !Match(latitude_)) { 76 return SetFailedAndReturnFalse(); 77 } 78 long temp = 0; 79 ReadLong(&temp); 80 feature->mutable_location()->set_latitude(temp); 81 if (!Match(",") || !Match(longitude_)) { 82 return SetFailedAndReturnFalse(); 83 } 84 ReadLong(&temp); 85 feature->mutable_location()->set_longitude(temp); 86 if (!Match("},") || !Match(name_) || !Match("\"")) { 87 return SetFailedAndReturnFalse(); 88 } 89 size_t name_start = current_; 90 while (current_ != db_.size() && db_[current_++] != '"') { 91 } 92 if (current_ == db_.size()) { 93 return SetFailedAndReturnFalse(); 94 } 95 feature->set_name(db_.substr(name_start, current_ - name_start - 1)); 96 if (!Match("},")) { 97 if (db_[current_ - 1] == ']' && current_ == db_.size()) { 98 return true; 99 } 100 return SetFailedAndReturnFalse(); 101 } 102 return true; 103 } 104 105 private: 106 bool SetFailedAndReturnFalse() { 107 failed_ = true; 108 return false; 109 } 110 111 bool Match(const std::string &prefix) { 112 bool eq = db_.substr(current_, prefix.size()) == prefix; 113 current_ += prefix.size(); 114 return eq; 115 } 116 117 void ReadLong(long *l) { 118 size_t start = current_; 119 while (current_ != db_.size() && db_[current_] != ',' && 120 db_[current_] != '}') { 121 current_++; 122 } 123 // It will throw an exception if fails. 124 *l = std::stol(db_.substr(start, current_ - start)); 125 } 126 127 bool failed_ = false; 128 std::string db_; 129 size_t current_ = 0; 130 const std::string location_ = "\"location\":"; 131 const std::string latitude_ = "\"latitude\":"; 132 const std::string longitude_ = "\"longitude\":"; 133 const std::string name_ = "\"name\":"; 134 }; 135 136 void ParseDb(const std::string &db, std::vector<Feature> *feature_list) { 137 feature_list->clear(); 138 std::string db_content(db); 139 db_content.erase( 140 std::remove_if(db_content.begin(), db_content.end(), isspace), 141 db_content.end()); 142 143 Parser parser(db_content); 144 Feature feature; 145 while (!parser.Finished()) { 146 feature_list->push_back(Feature()); 147 if (!parser.TryParseOne(&feature_list->back())) { 148 std::cout << "Error parsing the db file"; 149 feature_list->clear(); 150 break; 151 } 152 } 153 std::cout << "DB parsed, loaded " << feature_list->size() << " features." 154 << std::endl; 155 } 156 157 } // namespace routeguide 158 } // namespace example