• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <algorithm>
20 #include <cctype>
21 #include <fstream>
22 #include <iostream>
23 #include <sstream>
24 #include <string>
25 #include <vector>
26 #include "route_guide.grpc.pb.h"
27 
28 namespace routeguide {
29 
GetDbFileContent(int argc,char ** argv)30 std::string GetDbFileContent(int argc, char** argv) {
31   std::string db_path;
32   std::string arg_str("--db_path");
33   if (argc > 1) {
34     std::string argv_1 = argv[1];
35     size_t start_position = argv_1.find(arg_str);
36     if (start_position != std::string::npos) {
37       start_position += arg_str.size();
38       if (argv_1[start_position] == ' ' ||
39           argv_1[start_position] == '=') {
40         db_path = argv_1.substr(start_position + 1);
41       }
42     }
43   } else {
44     db_path = "route_guide_db.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:
Parser(const std::string & db)61   explicit Parser(const std::string& db) : db_(db) {
62     // Remove all spaces.
63     db_.erase(
64         std::remove_if(db_.begin(), db_.end(), isspace),
65         db_.end());
66     if (!Match("[")) {
67       SetFailedAndReturnFalse();
68     }
69   }
70 
Finished()71   bool Finished() {
72     return current_ >= db_.size();
73   }
74 
TryParseOne(Feature * feature)75   bool TryParseOne(Feature* feature) {
76     if (failed_ || Finished() || !Match("{")) {
77       return SetFailedAndReturnFalse();
78     }
79     if (!Match(location_) || !Match("{") || !Match(latitude_)) {
80       return SetFailedAndReturnFalse();
81     }
82     long temp = 0;
83     ReadLong(&temp);
84     feature->mutable_location()->set_latitude(temp);
85     if (!Match(",") || !Match(longitude_)) {
86       return SetFailedAndReturnFalse();
87     }
88     ReadLong(&temp);
89     feature->mutable_location()->set_longitude(temp);
90     if (!Match("},") || !Match(name_) || !Match("\"")) {
91       return SetFailedAndReturnFalse();
92     }
93     size_t name_start = current_;
94     while (current_ != db_.size() && db_[current_++] != '"') {
95     }
96     if (current_ == db_.size()) {
97       return SetFailedAndReturnFalse();
98     }
99     feature->set_name(db_.substr(name_start, current_-name_start-1));
100     if (!Match("},")) {
101       if (db_[current_ - 1] == ']' && current_ == db_.size()) {
102         return true;
103       }
104       return SetFailedAndReturnFalse();
105     }
106     return true;
107   }
108 
109  private:
110 
SetFailedAndReturnFalse()111   bool SetFailedAndReturnFalse() {
112     failed_ = true;
113     return false;
114   }
115 
Match(const std::string & prefix)116   bool Match(const std::string& prefix) {
117     bool eq = db_.substr(current_, prefix.size()) == prefix;
118     current_ += prefix.size();
119     return eq;
120   }
121 
ReadLong(long * l)122   void ReadLong(long* l) {
123     size_t start = current_;
124     while (current_ != db_.size() && db_[current_] != ',' && db_[current_] != '}') {
125       current_++;
126     }
127     // It will throw an exception if fails.
128     *l = std::stol(db_.substr(start, current_ - start));
129   }
130 
131   bool failed_ = false;
132   std::string db_;
133   size_t current_ = 0;
134   const std::string location_ = "\"location\":";
135   const std::string latitude_ = "\"latitude\":";
136   const std::string longitude_ = "\"longitude\":";
137   const std::string name_ = "\"name\":";
138 };
139 
ParseDb(const std::string & db,std::vector<Feature> * feature_list)140 void ParseDb(const std::string& db, std::vector<Feature>* feature_list) {
141   feature_list->clear();
142   std::string db_content(db);
143   db_content.erase(
144       std::remove_if(db_content.begin(), db_content.end(), isspace),
145       db_content.end());
146 
147   Parser parser(db_content);
148   Feature feature;
149   while (!parser.Finished()) {
150     feature_list->push_back(Feature());
151     if (!parser.TryParseOne(&feature_list->back())) {
152       std::cout << "Error parsing the db file";
153       feature_list->clear();
154       break;
155     }
156   }
157   std::cout << "DB parsed, loaded " << feature_list->size()
158             << " features." << std::endl;
159 }
160 
161 
162 }  // namespace routeguide
163 
164