Welcome to mirror list, hosted at ThFree Co, Russian Federation.

options.h « core « draco « src « draco « draco « extern - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9dc22ce16c2cac6edc0e4cb82a3274746847ae07 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright 2016 The Draco Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef DRACO_CORE_OPTIONS_H_
#define DRACO_CORE_OPTIONS_H_

#include <cstdlib>
#include <map>
#include <string>

namespace draco {

// Class for storing generic options as a <name, value> pair in a string map.
// The API provides helper methods for directly storing values of various types
// such as ints and bools. One named option should be set with only a single
// data type.
class Options {
 public:
  Options();

  // Merges |other_options| on top of the existing options of this instance
  // replacing all entries that are present in both options instances.
  void MergeAndReplace(const Options &other_options);

  void SetInt(const std::string &name, int val);
  void SetFloat(const std::string &name, float val);
  void SetBool(const std::string &name, bool val);
  void SetString(const std::string &name, const std::string &val);
  template <class VectorT>
  void SetVector(const std::string &name, const VectorT &vec) {
    SetVector(name, &vec[0], VectorT::dimension);
  }
  template <typename DataTypeT>
  void SetVector(const std::string &name, const DataTypeT *vec, int num_dims);

  // Getters will return a default value if the entry is not found. The default
  // value can be specified in the overloaded version of each function.
  int GetInt(const std::string &name) const;
  int GetInt(const std::string &name, int default_val) const;
  float GetFloat(const std::string &name) const;
  float GetFloat(const std::string &name, float default_val) const;
  bool GetBool(const std::string &name) const;
  bool GetBool(const std::string &name, bool default_val) const;
  std::string GetString(const std::string &name) const;
  std::string GetString(const std::string &name,
                        const std::string &default_val) const;
  template <class VectorT>
  VectorT GetVector(const std::string &name, const VectorT &default_val) const;
  // Unlike other Get functions, this function returns false if the option does
  // not exist, otherwise it fills |out_val| with the vector values. If a
  // default value is needed, it can be set in |out_val|.
  template <typename DataTypeT>
  bool GetVector(const std::string &name, int num_dims,
                 DataTypeT *out_val) const;

  bool IsOptionSet(const std::string &name) const {
    return options_.count(name) > 0;
  }

 private:
  // All entries are internally stored as strings and converted to the desired
  // return type based on the used Get* method.
  std::map<std::string, std::string> options_;
};

template <typename DataTypeT>
void Options::SetVector(const std::string &name, const DataTypeT *vec,
                        int num_dims) {
  std::string out;
  for (int i = 0; i < num_dims; ++i) {
    if (i > 0) {
      out += " ";
    }

// GNU STL on android doesn't include a proper std::to_string, but the libc++
// version does
#if defined(ANDROID) && !defined(_LIBCPP_VERSION)
    out += to_string(vec[i]);
#else
    out += std::to_string(vec[i]);
#endif
  }
  options_[name] = out;
}

template <class VectorT>
VectorT Options::GetVector(const std::string &name,
                           const VectorT &default_val) const {
  VectorT ret = default_val;
  GetVector(name, VectorT::dimension, &ret[0]);
  return ret;
}

template <typename DataTypeT>
bool Options::GetVector(const std::string &name, int num_dims,
                        DataTypeT *out_val) const {
  const auto it = options_.find(name);
  if (it == options_.end()) {
    return false;
  }
  const std::string value = it->second;
  if (value.length() == 0) {
    return true;  // Option set but no data is present
  }
  const char *act_str = value.c_str();
  char *next_str;
  for (int i = 0; i < num_dims; ++i) {
    if (std::is_integral<DataTypeT>::value) {
#ifdef ANDROID
      const int val = strtol(act_str, &next_str, 10);
#else
      const int val = static_cast<int>(std::strtol(act_str, &next_str, 10));
#endif
      if (act_str == next_str) {
        return true;  // End reached.
      }
      act_str = next_str;
      out_val[i] = static_cast<DataTypeT>(val);
    } else {
#ifdef ANDROID
      const float val = strtof(act_str, &next_str);
#else
      const float val = std::strtof(act_str, &next_str);
#endif
      if (act_str == next_str) {
        return true;  // End reached.
      }
      act_str = next_str;
      out_val[i] = static_cast<DataTypeT>(val);
    }
  }
  return true;
}

}  // namespace draco

#endif  // DRACO_CORE_OPTIONS_H_