Empirical
Main Page
Related Pages
Namespaces
Classes
Files
File List
File Members
source
web
d3
utils.h
Go to the documentation of this file.
1
// This file is part of Empirical, https://github.com/devosoft/Empirical
2
// Copyright (C) Michigan State University, 2015-2017.
3
// Released under the MIT Software license; see doc/LICENSE
4
//
5
// This file contains macros used to build Empirical's C++ wrapper for D3
6
7
#ifndef __UTILS_H__
8
#define __UTILS_H__
9
10
#include <map>
11
#include <string>
12
13
#include "../../base/macros.h"
14
#include "../init.h"
15
#include "../js_utils.h"
16
#include "../JSWrap.h"
17
18
// Helper macros
19
21
#define IS_JS_FUNCTION(FN) (typeof FN === "function")
22
26
#define CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_WINDOW() \
27
do { \
28
if IS_JS_FUNCTION(window[func_string]) { \
29
func_string = window[func_string]; \
30
} \
31
} while (0);
32
33
//Check if func_string is in a single namespace
34
#define CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_NAMESPACE_1(A1) \
35
if IS_JS_FUNCTION(window[A1][func_string]){ \
36
func_string = window[A1][func_string]; \
37
}
38
39
//Check 2 namespaces
40
#define CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_NAMESPACE_2(A1, A2) \
41
CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_NAMESPACE_1(A1) \
42
else CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_NAMESPACE_1(A2)
43
44
//Check 3 namespaces
45
#define CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_NAMESPACE_3(A1, A2, A3) \
46
CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_NAMESPACE_2(A1, A2) \
47
else CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_NAMESPACE_1(A3)
48
53
#define CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_NAMESPACE(...) \
54
do {EMP_ASSEMBLE_MACRO(CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_NAMESPACE_, __VA_ARGS__);} while (0);
55
61
#define CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_NAMESPACE_OR_WINDOW(...) \
62
CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_NAMESPACE( __VA_ARGS__) \
63
CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_WINDOW()
64
65
//Functions that accept callback functions
66
69
#define D3_CALLBACK_FUNCTION_1_ARG(FUNC, CALLBACK) \
70
EM_ASM_ARGS({ \
71
var func_string = Pointer_stringify($0); \
72
CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_NAMESPACE_OR_WINDOW("d3", "emp"); \
73
emp.__new_object = FUNC(func_string); \
74
}, CALLBACK);
75
78
#define D3_CALLBACK_FUNCTION_2_ARGS(FUNC, CALLBACK, ARG1) \
79
EM_ASM_ARGS({ \
80
var arg1 = Pointer_stringify($0); \
81
var func_string = Pointer_stringify($1); \
82
CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_NAMESPACE_OR_WINDOW("d3", "emp"); \
83
emp.__new_object = FUNC(arg1, func_string); \
84
}, ARG1, CALLBACK);
85
86
//Methods that accept callback functions (intended to be used within methods for d3 objects)
87
88
//Layer of indirection so macro gets expanded
89
#define D3_CALLBACK_METHOD_2_ARGS_IMPL(MACRO, FUNC, ARG1, ARG2) \
90
EM_ASM_ARGS({ \
91
var arg1 = Pointer_stringify($1); \
92
var func_string = Pointer_stringify($2); \
93
MACRO; \
94
emp.__new_object = js.objects[$0].FUNC(arg1, func_string); \
95
}, this->id, ARG1, ARG2);
96
97
//This macro finds a function specified by ARG2 in either the d3, emp, or
98
//window namespace and feeds it to FUNC, which is called on the current
99
//d3 object. ARG1 is the first argument to FUNC. If ARG2 is not found to
100
//be a function, it will be passed to FUNC as a string.
101
#define D3_CALLBACK_METHOD_2_ARGS(FUNC, ARG1, ARG2) \
102
D3_CALLBACK_METHOD_2_ARGS_IMPL(CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_NAMESPACE_OR_WINDOW("d3", "emp"), FUNC, ARG1, ARG2);
103
104
//Layer of indirection so macro gets expanded
105
#define D3_CALLBACK_METHOD_1_ARG_IMPL(MACRO, FUNC, ARG1) \
106
EM_ASM_ARGS({ \
107
var func_string = Pointer_stringify($1); \
108
MACRO; \
109
emp.__new_object = js.objects[$0].FUNC(func_string); \
110
}, this->id, ARG1);
111
115
#define D3_CALLBACK_METHOD_1_ARG(FUNC, ARG1) \
116
D3_CALLBACK_METHOD_1_ARG_IMPL(CONVERT_FUNCSTRING_TO_FUNCTION_IF_IN_NAMESPACE_OR_WINDOW("d3", "emp"), FUNC, ARG1);
117
118
//Wraps CPP_FUN (a C++ function pointer, std::function object, or lambda) with
119
//JSWrap and passes it to the FUNC method of the current d3 object, along with an argument
120
#define D3_CALLBACK_METHOD_CPP_FUNCTION_2_ARGS(FUNC, ARG1, CPP_FUN) \
121
uint32_t fun_id = emp::JSWrap(CPP_FUN, "", false); \
122
EM_ASM_ARGS({ \
123
emp.__new_object = js.objects[$0].FUNC(Pointer_stringify($1), \
124
function(d, i, j) { \
125
return emp.Callback($2, d, i, j); \
126
}); \
127
}, this->id, ARG1, fun_id); \
128
emp::JSDelete(fun_id);
129
130
//Wraps CPP_FUN (a C++ function pointer, std::function object, or lambda) with
131
//JSWrap and passes it to the FUNC method of the current d3 object, along with an argument
132
#define D3_CALLBACK_METHOD_CPP_FUNCTION_1_ARG(FUNC, CPP_FUN) \
133
uint32_t fun_id = emp::JSWrap(CPP_FUN, "", false); \
134
EM_ASM_ARGS({ \
135
emp.__new_object = js.objects[$0].FUNC(function(d, i, j) { \
136
return emp.Callback($1, d, i, j);\
137
}); \
138
}, this->id, fun_id); \
139
emp::JSDelete(fun_id);
140
141
//Store return of one of the above functions in js.objects
142
void
StoreNewObject
(
int
id
){
143
EM_ASM_ARGS({
144
js.objects[$0] =
emp
.__new_object;
145
146
}, id);
147
}
148
149
150
#endif
StoreNewObject
void StoreNewObject(int id)
Definition:
utils.h:142
emp
If we are in emscripten, make sure to include the header.
Definition:
array.h:37
Generated by
1.8.11