Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Demos / NativeClient / scripting_bridge.cc
1 // Copyright (c) 2011 The Native Client Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "scripting_bridge.h"
6
7 namespace {
8 const char* const kWhiteSpaceCharacters = " \t";
9
10 // Helper function to pull out the next token in |token_string|.  A token is
11 // delimited by whitespace.  Scanning begins at |*pos|, if pos goes beyond the
12 // end of |token_string|, it is set to std::string::npos and an empty string
13 // is returned.  On return, |*pos| will point to the beginning of the next
14 // token. |pos| must not be NULL.
15 const std::string ScanToken(const std::string& token_string, size_t* pos) {
16   std::string token;
17   if (*pos == std::string::npos) {
18     return token;
19   }
20   size_t token_start_pos = token_string.find_first_not_of(kWhiteSpaceCharacters,
21                                                           *pos);
22   size_t token_end_pos = token_string.find_first_of(kWhiteSpaceCharacters,
23                                                     token_start_pos);
24   if (token_start_pos != std::string::npos) {
25     token = token_string.substr(token_start_pos, token_end_pos);
26   }
27   *pos = token_end_pos;
28   return token;
29 }
30
31 // Take a string of the form 'name:value' and split it into two strings, one
32 // containing 'name' and the other 'value'.  If the ':' separator is missing,
33 // or is the last character in |parameter|, |parameter| is copied to
34 // |param_name|, |param_value| is left unchanged and false is returned.
35 bool ParseParameter(const std::string& parameter,
36                     std::string* param_name,
37                     std::string* param_value) {
38   bool success = false;
39   size_t sep_pos = parameter.find_first_of(':');
40   if (sep_pos != std::string::npos) {
41     *param_name = parameter.substr(0, sep_pos);
42     if (sep_pos < parameter.length() - 1) {
43       *param_value = parameter.substr(sep_pos + 1);
44       success = true;
45     } else {
46       success = false;
47     }
48   } else {
49     *param_name = parameter;
50     success = false;
51   }
52   return success;
53 }
54 }  // namespace
55
56 namespace tumbler {
57
58 bool ScriptingBridge::AddMethodNamed(const std::string& method_name,
59                                      SharedMethodCallbackExecutor method) {
60   if (method_name.size() == 0 || method == NULL)
61     return false;
62   method_dictionary_.insert(
63       std::pair<std::string, SharedMethodCallbackExecutor>(method_name,
64                                                            method));
65   return true;
66 }
67
68 bool ScriptingBridge::InvokeMethod(const std::string& method) {
69   size_t current_pos = 0;
70   const std::string method_name = ScanToken(method, &current_pos);
71   MethodDictionary::iterator method_iter;
72   method_iter = method_dictionary_.find(method_name);
73   if (method_iter != method_dictionary_.end()) {
74     // Pull out the method parameters and build a dictionary that maps
75     // parameter names to values.
76     std::map<std::string, std::string> param_dict;
77     while (current_pos != std::string::npos) {
78       const std::string parameter = ScanToken(method, &current_pos);
79       if (parameter.length()) {
80         std::string param_name;
81         std::string param_value;
82         if (ParseParameter(parameter, &param_name, &param_value)) {
83           // Note that duplicate parameter names will override each other.  The
84           // last one in the method string will be used.
85           param_dict[param_name] = param_value;
86         }
87       }
88     }
89     (*method_iter->second).Execute(*this, param_dict);
90     return true;
91   }
92   return false;
93 }
94
95 }  // namespace tumbler