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