commit
cdd8b4dc4f
@ -0,0 +1 @@
|
||||
export PATH=/home/garrettmills/.clone/emsdk:/home/garrettmills/.clone/emsdk/node/12.9.1_64bit/bin:/home/garrettmills/.clone/emsdk/upstream/emscripten:$PATH
|
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="CPP_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="ES6" />
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/cppjs.iml" filepath="$PROJECT_DIR$/.idea/cppjs.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
emcc main.cpp --std=c++14 \
|
||||
--shell-file shell_minimal.html \
|
||||
--emrun \
|
||||
-o hello.html \
|
||||
-s NO_EXIT_RUNTIME=1 \
|
||||
-s EXPORTED_FUNCTIONS="['_main', '_itest', '_str_pass_size', '_fire_event_bus']" \
|
||||
-s EXTRA_EXPORTED_RUNTIME_METHODS="['cwrap', 'ccall', 'stringToUTF8', 'setValue', 'getValue', 'UTF8ToString']" \
|
||||
-s WASM=1 \
|
||||
-s DISABLE_EXCEPTION_CATCHING=0 \
|
||||
--bind
|
@ -0,0 +1,61 @@
|
||||
var Module = {
|
||||
preRun: [],
|
||||
postRun: [],
|
||||
print: (function() {
|
||||
var element = document.getElementById('output');
|
||||
if (element) element.value = ''; // clear browser cache
|
||||
return function(text) {
|
||||
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
||||
// These replacements are necessary if you render to raw HTML
|
||||
//text = text.replace(/&/g, "&");
|
||||
//text = text.replace(/</g, "<");
|
||||
//text = text.replace(/>/g, ">");
|
||||
//text = text.replace('\n', '<br>', 'g');
|
||||
console.log(text);
|
||||
if (element) {
|
||||
element.value += text + "\n";
|
||||
element.scrollTop = element.scrollHeight; // focus on bottom
|
||||
}
|
||||
};
|
||||
})(),
|
||||
printErr: function(text) {
|
||||
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
||||
console.error(text);
|
||||
},
|
||||
/*canvas: (function() {
|
||||
var canvas = document.getElementById('canvas');
|
||||
|
||||
// As a default initial behavior, pop up an alert when webgl context is lost. To make your
|
||||
// application robust, you may want to override this behavior before shipping!
|
||||
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
|
||||
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
|
||||
|
||||
return canvas;
|
||||
})(),*/
|
||||
/*setStatus: function(text) {
|
||||
if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
|
||||
if (text === Module.setStatus.last.text) return;
|
||||
var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
|
||||
var now = Date.now();
|
||||
if (m && now - Module.setStatus.last.time < 30) return; // if this is a progress update, skip it if too soon
|
||||
Module.setStatus.last.time = now;
|
||||
Module.setStatus.last.text = text;
|
||||
if (m) {
|
||||
text = m[1];
|
||||
progressElement.value = parseInt(m[2])*100;
|
||||
progressElement.max = parseInt(m[4])*100;
|
||||
progressElement.hidden = false;
|
||||
spinnerElement.hidden = false;
|
||||
} else {
|
||||
progressElement.value = null;
|
||||
progressElement.max = null;
|
||||
progressElement.hidden = true;
|
||||
if (!text) spinnerElement.hidden = true;
|
||||
}
|
||||
statusElement.innerHTML = text;
|
||||
},*/
|
||||
totalDependencies: 0,
|
||||
monitorRunDependencies: function(left) {
|
||||
this.totalDependencies = Math.max(this.totalDependencies, left);
|
||||
}
|
||||
};
|
@ -0,0 +1,22 @@
|
||||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Emscripten-Generated Code</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- <div class="emscripten_border">
|
||||
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
|
||||
</div>
|
||||
-->
|
||||
<textarea class="emscripten" id="output" rows="8"></textarea>
|
||||
<br><br>
|
||||
<p id="foo" class="bar baz" data-test="3.141">Hello, world!</p>
|
||||
<script type='text/javascript' src="ems-core.js"></script>
|
||||
<script async type="text/javascript" src="hello.js"></script>
|
||||
<script type="text/javascript" src="init.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
Binary file not shown.
@ -0,0 +1,57 @@
|
||||
var itest;
|
||||
|
||||
function InitWrappers() {
|
||||
// itest = Module.cwrap('itest', 'string');
|
||||
itest = (str) => {
|
||||
const buffer = Module._malloc(str.length + 1)
|
||||
console.log({buffer})
|
||||
Module.stringToUTF8(str, buffer, str.length + 1)
|
||||
return Module.ccall('itest', 'string', ['number'], [buffer])
|
||||
}
|
||||
|
||||
window.read_str_pass = Module.cwrap('read_str_pass', 'void', ['number'])
|
||||
}
|
||||
|
||||
window.cjs = new (class {
|
||||
str_pass_size() {
|
||||
return Module.ccall('str_pass_size', 'number')
|
||||
}
|
||||
|
||||
write_string(string) {
|
||||
const buffer = Module._malloc(string.length + 1)
|
||||
Module.stringToUTF8(string, buffer, string.length + 1)
|
||||
return buffer
|
||||
}
|
||||
|
||||
set_string_pass(str_address, size, other = 0) {
|
||||
const offset = Module._malloc(this.str_pass_size())
|
||||
Module.setValue(offset, str_address, 'i32')
|
||||
Module.setValue(offset + 4, size, 'i32')
|
||||
Module.setValue(offset + 8, other, 'i32')
|
||||
return offset
|
||||
} // [START, SIZE, 0]
|
||||
|
||||
string_pass(string) {
|
||||
const str_address = this.write_string(string)
|
||||
return this.set_string_pass(str_address, string.length)
|
||||
}
|
||||
|
||||
receive(offset) {
|
||||
const { str_address, str_length, other } = this.get_string_pass(offset)
|
||||
const string = Module.UTF8ToString(str_address, str_length)
|
||||
Module._free(offset, this.str_pass_size())
|
||||
return string
|
||||
}
|
||||
|
||||
get_string_pass(offset) {
|
||||
const str_address = Module.getValue(offset, 'i32')
|
||||
const str_length = Module.getValue(offset + 4, 'i32')
|
||||
const other = Module.getValue(offset + 8, 'i32')
|
||||
return { str_address, str_length, other }
|
||||
}
|
||||
|
||||
fire_event_bus(key) {
|
||||
const key_pass = this.string_pass(key)
|
||||
Module.ccall('fire_event_bus', null, ['number'], [key_pass])
|
||||
}
|
||||
})
|
@ -0,0 +1,41 @@
|
||||
#include <iostream>
|
||||
#include <emscripten.h>
|
||||
#include <exception>
|
||||
|
||||
#include "src/class/Element.h"
|
||||
#include "src/proc/string.cpp"
|
||||
#include "src/class/EventBus.h"
|
||||
#include "src/proc/event.cpp"
|
||||
#include "src/proc/uuid.cpp"
|
||||
|
||||
extern "C" {
|
||||
char* itest();
|
||||
int str_pass_size();
|
||||
void fire_event_bus(int key_pass);
|
||||
}
|
||||
|
||||
void say_aye() {
|
||||
printf("Arrgh mates!\n");
|
||||
}
|
||||
|
||||
char* itest() {
|
||||
Element p_tag("#foo");
|
||||
p_tag.addEventListener("click", say_aye);
|
||||
|
||||
return "Hi, there";
|
||||
}
|
||||
|
||||
// These are REQUIRED.
|
||||
int str_pass_size() {
|
||||
return cjs::str::pass_size();
|
||||
}
|
||||
|
||||
void fire_event_bus(int string_pass) {
|
||||
return cjs::event::handle_bus_fire(string_pass);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
EM_ASM(InitWrappers());
|
||||
printf("C++.js has initialized!\n");
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Emscripten-Generated Code</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- <div class="emscripten_border">
|
||||
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
|
||||
</div>
|
||||
-->
|
||||
<textarea class="emscripten" id="output" rows="8"></textarea>
|
||||
<br><br>
|
||||
<p id="foo" class="bar baz" data-test="3.141">Hello, world!</p>
|
||||
<script type='text/javascript' src="ems-core.js"></script>
|
||||
{{{ SCRIPT }}}
|
||||
<script type="text/javascript" src="init.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by garrettmills on 5/6/20.
|
||||
//
|
||||
|
||||
#include "Component.h"
|
@ -0,0 +1,19 @@
|
||||
#ifndef CPPJS_COMPONENT_H
|
||||
#define CPPJS_COMPONENT_H
|
||||
|
||||
|
||||
class Component {
|
||||
private:
|
||||
|
||||
// =================== HTML TEMPLATE =================== //
|
||||
char* tmpl = R"V0G0N(
|
||||
<h1>Hello, world!</h1>
|
||||
<p>This is a test hello message!</p>
|
||||
)V0G0N";
|
||||
// ================= / HTML TEMPLATE =================== //
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //CPPJS_COMPONENT_H
|
@ -0,0 +1,161 @@
|
||||
#include <stdexcept>
|
||||
|
||||
#include "Element.h"
|
||||
#include "../proc/document.cpp"
|
||||
#include "../proc/string.cpp"
|
||||
#include "../proc/uuid.cpp"
|
||||
#include "../class/EventBus.h"
|
||||
|
||||
using namespace cjs;
|
||||
|
||||
void Element::_identify_and_rebase() {
|
||||
try {
|
||||
std::string uuid = this->getUUID();
|
||||
this->rebase("[data-cjs-uuid='"+uuid+"']");
|
||||
} catch (std::runtime_error& e) {
|
||||
std::string new_uuid = uuid::v4();
|
||||
this->setData("cjs-uuid", new_uuid);
|
||||
this->rebase("[data-cjs-uuid='"+new_uuid+"']");
|
||||
}
|
||||
}
|
||||
|
||||
Element::Element(std::string selector, int nth_elem) {
|
||||
this->_selector_ref = selector;
|
||||
this->_selector_nth_elem = nth_elem;
|
||||
this->_identify_and_rebase();
|
||||
}
|
||||
|
||||
Element::Element(Element& parent, std::string innerHTML, std::string selector, int nth_elem) {
|
||||
this->_selector_ref = selector;
|
||||
this->_selector_nth_elem = nth_elem;
|
||||
parent.append(innerHTML);
|
||||
this->_identify_and_rebase();
|
||||
}
|
||||
|
||||
std::string Element::getInnerHTML() {
|
||||
cjs_str* html = doc::get_inner_html_of(this->_selector_ref, this->_selector_nth_elem);
|
||||
std::string return_str = html->to_str();
|
||||
delete html;
|
||||
return return_str;
|
||||
}
|
||||
|
||||
std::string Element::getInnerText() {
|
||||
cjs_str* text = doc::get_inner_text_of(this->_selector_ref, this->_selector_nth_elem);
|
||||
std::string return_str = text->to_str();
|
||||
delete text;
|
||||
return return_str;
|
||||
}
|
||||
|
||||
std::string Element::getID() {
|
||||
cjs_str* html = doc::get_id_of(this->_selector_ref, this->_selector_nth_elem);
|
||||
std::string return_str = html->to_str();
|
||||
delete html;
|
||||
return return_str;
|
||||
}
|
||||
|
||||
std::string Element::getUUID() {
|
||||
return this->getData("cjs-uuid");
|
||||
}
|
||||
|
||||
std::string Element::getClassRaw() {
|
||||
cjs_str* html = doc::get_class_of(this->_selector_ref, this->_selector_nth_elem);
|
||||
std::string return_str = html->to_str();
|
||||
delete html;
|
||||
return return_str;
|
||||
}
|
||||
|
||||
std::vector<std::string> Element::getClasses() {
|
||||
cjs_str* html = doc::get_class_of(this->_selector_ref, this->_selector_nth_elem);
|
||||
std::vector<std::string> result = html->split();
|
||||
delete html;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Element::hasClass(std::string cls) {
|
||||
std::vector<std::string> classes = this->getClasses();
|
||||
for ( std::string s : classes )
|
||||
if ( s == cls ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string Element::getAttribute(std::string attr) {
|
||||
cjs_str* value = doc::_query_select_attribute(attr, this->_selector_ref, this->_selector_nth_elem);
|
||||
std::string return_str = value->to_str();
|
||||
delete value;
|
||||
return return_str;
|
||||
}
|
||||
|
||||
std::string Element::getData(std::string key) {
|
||||
return this->getAttribute("data-"+key);
|
||||
}
|
||||
|
||||
void Element::setInnerHTML(std::string html) {
|
||||
doc::set_inner_html_of(this->_selector_ref, html, this->_selector_nth_elem);
|
||||
}
|
||||
|
||||
void Element::setInnerText(std::string text) {
|
||||
doc::set_inner_text_of(this->_selector_ref, text, this->_selector_nth_elem);
|
||||
}
|
||||
|
||||
void Element::setID(std::string id) {
|
||||
doc::set_id_of(this->_selector_ref, id, this->_selector_nth_elem);
|
||||
}
|
||||
|
||||
void Element::setClassRaw(std::string cls) {
|
||||
doc::set_class_of(this->_selector_ref, cls, this->_selector_nth_elem);
|
||||
}
|
||||
|
||||
void Element::addClass(std::string cls) {
|
||||
if ( !this->hasClass(cls) ) {
|
||||
std::vector<std::string> classes = this->getClasses();
|
||||
classes.push_back(cls);
|
||||
this->setClassRaw(str::join(classes, " "));
|
||||
}
|
||||
}
|
||||
|
||||
void Element::removeClass(std::string cls) {
|
||||
if ( this->hasClass(cls) ) {
|
||||
std::vector<std::string> old_classes = this->getClasses();
|
||||
std::vector<std::string> new_classes;
|
||||
|
||||
for ( std::string maybe_cls : old_classes ) {
|
||||
if ( maybe_cls != cls )
|
||||
new_classes.push_back(maybe_cls);
|
||||
}
|
||||
|
||||
this->setClassRaw(str::join(new_classes, " "));
|
||||
}
|
||||
}
|
||||
|
||||
void Element::toggleClass(std::string cls) {
|
||||
if ( this->hasClass(cls) ) this->removeClass(cls);
|
||||
else this->addClass(cls);
|
||||
}
|
||||
|
||||
void Element::setAttribute(std::string attr, std::string value) {
|
||||
doc::_query_set_attribute(attr, value, this->_selector_ref, this->_selector_nth_elem);
|
||||
}
|
||||
|
||||
void Element::setData(std::string key, std::string value) {
|
||||
this->setAttribute("data-"+key, value);
|
||||
}
|
||||
|
||||
void Element::append(std::string html) {
|
||||
this->setInnerHTML(this->getInnerHTML()+html);
|
||||
}
|
||||
|
||||
void Element::addEventListener(std::string dom_event, void(*func)()) {
|
||||
// Generate the unique function key using the dom_event and uuid
|
||||
std::string event_key = this->getUUID() + "-" + dom_event;
|
||||
|
||||
// Add the function and the key to the event bus
|
||||
g_event_bus.addHandler(event_key, func);
|
||||
|
||||
// Add the event bus link to the element's dom event
|
||||
doc::link_event_bus(dom_event, event_key, this->_selector_ref, this->_selector_nth_elem);
|
||||
}
|
||||
|
||||
void Element::rebase(std::string query_selector, int nth_elem) {
|
||||
this->_selector_ref = query_selector;
|
||||
this->_selector_nth_elem = nth_elem;
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
#ifndef CPPJS_ELEMENT_H
|
||||
#define CPPJS_ELEMENT_H
|
||||
|
||||
|
||||
class Element {
|
||||
private:
|
||||
std::string _selector_ref = "";
|
||||
int _selector_nth_elem = 0;
|
||||
void _identify_and_rebase();
|
||||
|
||||
public:
|
||||
Element(std::string selector, int nth_elem = 0);
|
||||
Element(Element& parent, std::string innerHTML, std::string selector, int nth_elem = 0);
|
||||
|
||||
std::string getInnerHTML();
|
||||
std::string getInnerText();
|
||||
std::string getID();
|
||||
std::string getUUID();
|
||||
std::string getClassRaw();
|
||||
std::vector<std::string> getClasses();
|
||||
bool hasClass(std::string cls);
|
||||
std::string getAttribute(std::string attr);
|
||||
std::string getData(std::string key);
|
||||
|
||||
void setInnerHTML(std::string html);
|
||||
void setInnerText(std::string text);
|
||||
void setID(std::string id);
|
||||
void setClassRaw(std::string cls);
|
||||
void addClass(std::string cls);
|
||||
void removeClass(std::string cls);
|
||||
void toggleClass(std::string cls);
|
||||
void setAttribute(std::string attr, std::string value);
|
||||
void setData(std::string key, std::string value);
|
||||
void append(std::string html);
|
||||
|
||||
void addEventListener(std::string dom_event, void(*func)());
|
||||
|
||||
void rebase(std::string query_selector, int nth_elem = 0);
|
||||
};
|
||||
|
||||
#include "Element.cpp"
|
||||
|
||||
|
||||
#endif //CPPJS_ELEMENT_H
|
@ -0,0 +1,25 @@
|
||||
#include "EventBus.h"
|
||||
|
||||
void EventBus::addHandler(std::string key, void (*func)()) {
|
||||
// If the bus already has this key, add a handler
|
||||
auto search = this->_bus.find(key);
|
||||
if ( search != this->_bus.end() ) {
|
||||
std::vector<void (*)()> func_arr = this->_bus[key];
|
||||
func_arr.push_back(func);
|
||||
this->_bus[key] = func_arr;
|
||||
} else {
|
||||
std::vector<void (*)()> func_arr;
|
||||
func_arr.push_back(func);
|
||||
this->_bus[key] = func_arr;
|
||||
}
|
||||
}
|
||||
|
||||
void EventBus::fire(std::string key) {
|
||||
auto search = this->_bus.find(key);
|
||||
if ( search != this->_bus.end() ) {
|
||||
std::vector<void (*)()> func_arr = this->_bus[key];
|
||||
for ( void(*func)() : func_arr ) {
|
||||
(*func)();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
#ifndef CPPJS_EVENTBUS_H
|
||||
#define CPPJS_EVENTBUS_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class EventBus {
|
||||
private:
|
||||
std::map<std::string, std::vector<void (*)()>> _bus;
|
||||
|
||||
public:
|
||||
void addHandler(std::string key, void (*func)());
|
||||
void fire(std::string key);
|
||||
};
|
||||
|
||||
extern EventBus g_event_bus;
|
||||
EventBus g_event_bus;
|
||||
|
||||
#include "EventBus.cpp"
|
||||
|
||||
#endif //CPPJS_EVENTBUS_H
|
@ -0,0 +1,116 @@
|
||||
#ifndef CJS_PROC_DOCUMENT
|
||||
#define CJS_PROC_DOCUMENT
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include "string.cpp"
|
||||
|
||||
namespace cjs {
|
||||
namespace doc {
|
||||
#include <emscripten.h>
|
||||
|
||||
cjs_str* _query_select_property(std::string method, std::string query_selector, int nth_elem = 0) {
|
||||
int method_pass = cjs::str::pass(cjs::str::cpp_to_c(method), method.length());
|
||||
int query_pass = cjs::str::pass(cjs::str::cpp_to_c(query_selector), query_selector.length());
|
||||
|
||||
int return_str_pass = EM_ASM_INT({
|
||||
try {
|
||||
return cjs.string_pass(document.querySelectorAll(cjs.receive($1))[$2][cjs.receive($0)]);
|
||||
} catch (e) {
|
||||
return 0;
|
||||
}
|
||||
}, method_pass, query_pass, nth_elem);
|
||||
|
||||
if ( return_str_pass == 0 ) {
|
||||
throw std::runtime_error("The property or element is undefined.");
|
||||
}
|
||||
|
||||
cjs_str* return_str = cjs::str::receive(return_str_pass);
|
||||
return return_str;
|
||||
}
|
||||
|
||||
cjs_str* _query_select_attribute(std::string attribute, std::string query_selector, int nth_elem = 0) {
|
||||
int attribute_pass = cjs::str::pass(cjs::str::cpp_to_c(attribute), attribute.length());
|
||||
int query_pass = cjs::str::pass(cjs::str::cpp_to_c(query_selector), query_selector.length());
|
||||
|
||||
int return_str_pass = EM_ASM_INT({
|
||||
try {
|
||||
return cjs.string_pass(document.querySelectorAll(cjs.receive($1))[$2].getAttribute(cjs.receive($0)));
|
||||
} catch (e) {
|
||||
return 0;
|
||||
}
|
||||
}, attribute_pass, query_pass, nth_elem);
|
||||
|
||||
if ( return_str_pass == 0 ) {
|
||||
throw std::runtime_error("The attribute or element is undefined.");
|
||||
}
|
||||
|
||||
cjs_str* return_str = cjs::str::receive(return_str_pass);
|
||||
return return_str;
|
||||
}
|
||||
|
||||
void _query_set_property(std::string property, std::string value, std::string query_selector, int nth_elem = 0) {
|
||||
int property_pass = cjs::str::pass(cjs::str::cpp_to_c(property), property.length());
|
||||
int value_pass = cjs::str::pass(cjs::str::cpp_to_c(value), value.length());
|
||||
int query_pass = cjs::str::pass(cjs::str::cpp_to_c(query_selector), query_selector.length());
|
||||
|
||||
EM_ASM({
|
||||
document.querySelectorAll(cjs.receive($2))[$3][cjs.receive($0)] = cjs.receive($1);
|
||||
}, property_pass, value_pass, query_pass, nth_elem);
|
||||
}
|
||||
|
||||
void _query_set_attribute(std::string attribute, std::string value, std::string query_selector, int nth_elem = 0) {
|
||||
int attribute_pass = cjs::str::pass(cjs::str::cpp_to_c(attribute), attribute.length());
|
||||
int value_pass = cjs::str::pass(cjs::str::cpp_to_c(value), value.length());
|
||||
int query_pass = cjs::str::pass(cjs::str::cpp_to_c(query_selector), query_selector.length());
|
||||
|
||||
EM_ASM({
|
||||
document.querySelectorAll(cjs.receive($2))[$3].setAttribute(cjs.receive($0), cjs.receive($1));
|
||||
}, attribute_pass, value_pass, query_pass, nth_elem);
|
||||
}
|
||||
|
||||
void link_event_bus(std::string dom_event, std::string event_bus_key, std::string query_selector, int nth_elem = 0) {
|
||||
int dom_event_pass = cjs::str::pass(cjs::str::cpp_to_c(dom_event), dom_event.length());
|
||||
int event_bus_key_pass = cjs::str::pass(cjs::str::cpp_to_c(event_bus_key), event_bus_key.length());
|
||||
int query_pass = cjs::str::pass(cjs::str::cpp_to_c(query_selector), query_selector.length());
|
||||
|
||||
EM_ASM({
|
||||
document.querySelectorAll(cjs.receive($2))[$3].addEventListener(cjs.receive($0), () => cjs.fire_event_bus(cjs.receive($1)));
|
||||
}, dom_event_pass, event_bus_key_pass, query_pass, nth_elem);
|
||||
}
|
||||
|
||||
cjs_str* get_inner_html_of(std::string query_selector, int nth_elem = 0) {
|
||||
return _query_select_property("innerHTML", query_selector, nth_elem);
|
||||
}
|
||||
|
||||
void set_inner_html_of(std::string query_selector, std::string value, int nth_elem = 0) {
|
||||
_query_set_property("innerHTML", value, query_selector, nth_elem);
|
||||
}
|
||||
|
||||
cjs_str* get_inner_text_of(std::string query_selector, int nth_elem = 0) {
|
||||
return _query_select_property("innerText", query_selector, nth_elem);
|
||||
}
|
||||
|
||||
void set_inner_text_of(std::string query_selector, std::string value, int nth_elem = 0) {
|
||||
_query_set_property("innerText", value, query_selector, nth_elem);
|
||||
}
|
||||
|
||||
cjs_str* get_id_of(std::string query_selector, int nth_elem = 0) {
|
||||
return _query_select_property("id", query_selector, nth_elem);
|
||||
}
|
||||
|
||||
void set_id_of(std::string query_selector, std::string value, int nth_elem = 0) {
|
||||
_query_set_property("id", value, query_selector, nth_elem);
|
||||
}
|
||||
|
||||
cjs_str* get_class_of(std::string query_selector, int nth_elem = 0) {
|
||||
return _query_select_attribute("class", query_selector, nth_elem);
|
||||
}
|
||||
|
||||
void set_class_of(std::string query_selector, std::string cls, int nth_elem = 0) {
|
||||
return _query_set_attribute("class", cls, query_selector, nth_elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //CJS_PROC_DOCUMENT
|
@ -0,0 +1,18 @@
|
||||
#ifndef CJS_PROC_EVENT
|
||||
#define CJS_PROC_EVENT
|
||||
|
||||
#include <string>
|
||||
#include "string.cpp"
|
||||
|
||||
namespace cjs {
|
||||
namespace event {
|
||||
void handle_bus_fire(int key_pass) {
|
||||
cjs_str* key_str = cjs::str::receive(key_pass);
|
||||
std::string key = key_str->to_str();
|
||||
delete key_str;
|
||||
g_event_bus.fire(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //CJS_PROC_EVENT
|
@ -0,0 +1,102 @@
|
||||
#ifndef CJS_PROC_STRING
|
||||
#define CJS_PROC_STRING
|
||||
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <ostream>
|
||||
|
||||
struct cjs_str {
|
||||
int length;
|
||||
char* string;
|
||||
|
||||
std::string to_str() {
|
||||
std::string str(this->string);
|
||||
return str;
|
||||
}
|
||||
|
||||
void from_str(std::string str) {
|
||||
this->length = str.length();
|
||||
char* cstr = new char[str.length() + 1];
|
||||
strcpy(cstr, str.c_str());
|
||||
this->string = cstr;
|
||||
}
|
||||
|
||||
std::string c_str() {
|
||||
return this->to_str().c_str();
|
||||
}
|
||||
|
||||
std::vector<std::string> split() {
|
||||
std::string s = this->to_str();
|
||||
std::vector<std::string> result;
|
||||
std::istringstream iss(s);
|
||||
for(std::string s; iss >> s; )
|
||||
result.push_back(s);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
namespace cjs {
|
||||
namespace str {
|
||||
int pass_size() {
|
||||
return 3 * sizeof(int);
|
||||
}
|
||||
|
||||
char* cpp_to_c(std::string str) {
|
||||
char* cstr = new char[str.length() + 1];
|
||||
strcpy(cstr, str.c_str());
|
||||
return cstr;
|
||||
}
|
||||
|
||||
std::string join(const std::vector<std::string> strings, const char* by) {
|
||||
if ( strings.size() < 1 ) return "";
|
||||
else if ( strings.size() == 1 ) return strings.front();
|
||||
else {
|
||||
std::stringstream res;
|
||||
copy(strings.begin(), strings.end() - 1, std::ostream_iterator<std::string>(res, by));
|
||||
res << strings.back();
|
||||
return res.str();
|
||||
}
|
||||
}
|
||||
|
||||
cjs_str* cpp_to_cjs(std::string str) {
|
||||
return new cjs_str{ (int) str.length(), cpp_to_c(str) };
|
||||
}
|
||||
|
||||
cjs_str* c_to_cjs(char* string, int len) {
|
||||
return new cjs_str{ len, string };
|
||||
}
|
||||
|
||||
std::string c_to_cpp(char* string) {
|
||||
std::string str(string);
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string cjs_to_cpp(cjs_str* cjs) {
|
||||
return c_to_cpp(cjs->string);
|
||||
}
|
||||
|
||||
cjs_str* receive(int offset) {
|
||||
// Get the string pass information
|
||||
// Format: [ string offset, string length, (unused) ]
|
||||
int* str_pass = reinterpret_cast<int*>(offset);
|
||||
int length = str_pass[1];
|
||||
char* string = reinterpret_cast<char*>(str_pass[0]);
|
||||
free(str_pass);
|
||||
return new cjs_str{ length, string };
|
||||
}
|
||||
|
||||
int set_pass(int address, int size, int other = 0) {
|
||||
int* pass = new int[3];
|
||||
pass[0] = address;
|
||||
pass[1] = size;
|
||||
pass[2] = other;
|
||||
return (int) pass;
|
||||
}
|
||||
|
||||
int pass(char* string, int length) {
|
||||
return set_pass((int) string, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //CJS_PROC_STRING
|
@ -0,0 +1,44 @@
|
||||
#ifndef CJS_PROC_UUID
|
||||
#define CJS_PROC_UUID
|
||||
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
|
||||
namespace cjs {
|
||||
namespace uuid {
|
||||
static std::random_device rd;
|
||||
static std::mt19937 gen(rd());
|
||||
static std::uniform_int_distribution<> dis(0, 15);
|
||||
static std::uniform_int_distribution<> dis2(8, 11);
|
||||
|
||||
std::string v4() {
|
||||
std::stringstream ss;
|
||||
int i;
|
||||
ss << std::hex;
|
||||
for (i = 0; i < 8; i++) {
|
||||
ss << dis(gen);
|
||||
}
|
||||
ss << "-";
|
||||
for (i = 0; i < 4; i++) {
|
||||
ss << dis(gen);
|
||||
}
|
||||
ss << "-4";
|
||||
for (i = 0; i < 3; i++) {
|
||||
ss << dis(gen);
|
||||
}
|
||||
ss << "-";
|
||||
ss << dis2(gen);
|
||||
for (i = 0; i < 3; i++) {
|
||||
ss << dis(gen);
|
||||
}
|
||||
ss << "-";
|
||||
for (i = 0; i < 12; i++) {
|
||||
ss << dis(gen);
|
||||
};
|
||||
return ss.str();
|
||||
}
|
||||
}
|
||||
}
|
||||
// https://stackoverflow.com/questions/24365331/how-can-i-generate-uuid-in-c-without-using-boost-library
|
||||
|
||||
#endif // CJS_PROC_UUID
|
Loading…
Reference in new issue