Restructing the source layout to make it nicer.
This commit is contained in:
parent
fff182b457
commit
cc3bb171e1
14 changed files with 166 additions and 33 deletions
33
scratchpad/audiotest.cpp
Normal file
33
scratchpad/audiotest.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include <SFML/Audio.hpp>
|
||||
#include <thread> // for sleep_for
|
||||
#include <iostream>
|
||||
#include <fmt/core.h>
|
||||
#include <chrono>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
sf::SoundBuffer buffer;
|
||||
sf::Sound sound;
|
||||
|
||||
if(argc != 2) {
|
||||
fmt::println("USAGE: audiotest [FILE]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *in_file = argv[1];
|
||||
|
||||
if(!buffer.loadFromFile(in_file)) {
|
||||
fmt::println("Failed to load {}", in_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sound.setBuffer(buffer);
|
||||
|
||||
fmt::println("Playing {}. Hit ctrl-c to exit.", in_file);
|
||||
|
||||
sound.play();
|
||||
while(sound.getStatus() != sf::SoundSource::Status::Stopped) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
48
scratchpad/badref.cpp
Normal file
48
scratchpad/badref.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
#include <string>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
using std::string, std::unique_ptr,
|
||||
std::shared_ptr, std::make_unique;
|
||||
|
||||
class BadRef {
|
||||
string &name;
|
||||
|
||||
public:
|
||||
BadRef(string &name) : name(name) {}
|
||||
|
||||
void set_name(string &n) {
|
||||
name = n;
|
||||
}
|
||||
};
|
||||
|
||||
class GoodRef {
|
||||
string *name;
|
||||
|
||||
public:
|
||||
/*
|
||||
* After calling, name is owned.
|
||||
*/
|
||||
GoodRef(string *n) : name(n) {}
|
||||
|
||||
void print() {
|
||||
std::cout << "My name is " << *name << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
string my_name = "Zed";
|
||||
string your_name = "Alex";
|
||||
string &ref_test = my_name;
|
||||
string *ptr_name = new string("Pointer");
|
||||
|
||||
ref_test = your_name;
|
||||
|
||||
auto br = BadRef(my_name);
|
||||
br.set_name(your_name);
|
||||
|
||||
auto gr = GoodRef(ptr_name);
|
||||
gr.print();
|
||||
|
||||
return 0;
|
||||
}
|
52
scratchpad/corotest.cpp
Normal file
52
scratchpad/corotest.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
#include "../coro.hpp"
|
||||
#include <coroutine>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
using std::cout, std::endl;
|
||||
|
||||
Task<unsigned> task_test()
|
||||
{
|
||||
co_await Pass{};
|
||||
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
co_yield i;
|
||||
|
||||
co_return 1000;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const int task_count = 4;
|
||||
std::vector<Task<unsigned>> tasks;
|
||||
|
||||
for(int i = 0; i < task_count; i++) {
|
||||
auto t = task_test();
|
||||
tasks.push_back(std::move(t));
|
||||
}
|
||||
|
||||
int done_count = 0;
|
||||
while(done_count < task_count) {
|
||||
for(int i = 0; i < task_count; i++) {
|
||||
Task<unsigned> &t = tasks[i];
|
||||
|
||||
if(t.done()) {
|
||||
// remove it from the tasks
|
||||
// this cause crash I think?
|
||||
t.destroy();
|
||||
done_count++;
|
||||
} else {
|
||||
auto res = t();
|
||||
|
||||
if(t.state() == AWAIT) {
|
||||
cout << "AWAIT! " << t.state() << endl;
|
||||
} else if(t.state() != YIELD) {
|
||||
cout << "NOT YIELD: " << t.state() << endl;
|
||||
} else {
|
||||
cout << "T# " << i << " result "
|
||||
<< res << " STATE " << t.state() << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
48
scratchpad/fsmtest.cpp
Normal file
48
scratchpad/fsmtest.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
#include <fmt/core.h>
|
||||
#include "../fsm.hpp"
|
||||
|
||||
using namespace fmt;
|
||||
|
||||
enum MyState {
|
||||
START, RUNNING, END
|
||||
};
|
||||
|
||||
enum MyEvent {
|
||||
STARTED, PUSH, QUIT
|
||||
};
|
||||
|
||||
class MyFSM : DeadSimpleFSM<MyState, MyEvent> {
|
||||
public:
|
||||
void event(MyEvent ev) override {
|
||||
switch(_state) {
|
||||
FSM_STATE(START, start, ev);
|
||||
FSM_STATE(RUNNING, push, ev);
|
||||
FSM_STATE(END, quit, ev);
|
||||
}
|
||||
}
|
||||
|
||||
void start(MyEvent ev) {
|
||||
println("<<< START");
|
||||
state(RUNNING);
|
||||
}
|
||||
|
||||
void push(MyEvent ev) {
|
||||
println("<<< RUN");
|
||||
state(RUNNING);
|
||||
}
|
||||
|
||||
void quit(MyEvent ev) {
|
||||
println("<<< STOP");
|
||||
state(END);
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
MyFSM fsm;
|
||||
|
||||
fsm.event(STARTED);
|
||||
fsm.event(PUSH);
|
||||
fsm.event(PUSH);
|
||||
fsm.event(PUSH);
|
||||
fsm.event(QUIT);
|
||||
}
|
85
scratchpad/ftx_thread_test.cpp
Normal file
85
scratchpad/ftx_thread_test.cpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
#include <stdlib.h> // for EXIT_SUCCESS
|
||||
#include <chrono> // for milliseconds
|
||||
#include <thread> // for sleep_for, thread
|
||||
#include <fmt/core.h>
|
||||
#include <ftxui/component/event.hpp> // for Event
|
||||
#include <ftxui/component/mouse.hpp> // for ftxui
|
||||
#include <ftxui/dom/elements.hpp> // for text, separator, Element, operator|, vbox, border
|
||||
#include <memory> // for allocator, shared_ptr
|
||||
#include <string> // for operator+, to_string
|
||||
#include <thread> // for sleep_for
|
||||
|
||||
#include <ftxui/component/component.hpp> // for CatchEvent, Renderer, operator|=
|
||||
#include <ftxui/component/loop.hpp> // for Loop
|
||||
#include <ftxui/component/screen_interactive.hpp> // for ScreenInteractive
|
||||
|
||||
using namespace ftxui;
|
||||
|
||||
ButtonOption Style() {
|
||||
auto option = ButtonOption::Animated();
|
||||
option.transform = [](const EntryState& s) {
|
||||
auto element = text(s.label);
|
||||
if (s.focused) {
|
||||
element |= bold;
|
||||
}
|
||||
return element | center | borderEmpty | flex;
|
||||
};
|
||||
return option;
|
||||
}
|
||||
|
||||
int main() {
|
||||
auto screen = ScreenInteractive::Fullscreen();
|
||||
|
||||
// Create a component counting the number of frames drawn and event handled.
|
||||
int custom_loop_count = 0;
|
||||
int frame_count = 0;
|
||||
int event_count = 0;
|
||||
int hp = 100;
|
||||
int row = 0;
|
||||
auto hit_button = Button("Hit", [&] { hp -= 1; }, Style());
|
||||
auto hard_button = Button("Hard", [&] { hp -= 10; }, Style());
|
||||
auto heal_button = Button("Heal", [&] { hp += 10; }, Style());
|
||||
|
||||
auto buttons = Container::Horizontal({
|
||||
hit_button, hard_button, heal_button}, &row);
|
||||
|
||||
auto component = Renderer(buttons, [&] {
|
||||
frame_count++;
|
||||
|
||||
return vbox({
|
||||
paragraph("I'm baby mustache hammock squid, stumptown echo park lumbersexual PBR&B glossier iceland pabst irony mlkshk skateboard migas kombucha. Lyft meggings organic tacos. IPhone microdosing bodega boys, fit locavore jawn cloud bread neutral milk hotel trust fund live-edge selfies portland lyft vice. Pug swag af slow-carb."),
|
||||
separator(),
|
||||
paragraph(fmt::format("HP {} frames {} events {} custom {}",
|
||||
hp, frame_count, event_count, custom_loop_count)),
|
||||
separator(),
|
||||
hbox({
|
||||
text("HP"),
|
||||
gauge(hp / 100.0f),
|
||||
}),
|
||||
separator(),
|
||||
buttons->Render(),
|
||||
}) |
|
||||
border;
|
||||
});
|
||||
|
||||
component |= CatchEvent([&](Event) -> bool {
|
||||
event_count++;
|
||||
return false;
|
||||
});
|
||||
|
||||
Loop loop(&screen, component);
|
||||
|
||||
std::atomic<bool> refresh_ui_continue = true;
|
||||
std::thread refresh_ui([&] {
|
||||
while(refresh_ui_continue) {
|
||||
screen.Post(Event::Custom);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
});
|
||||
|
||||
screen.Loop(component);
|
||||
refresh_ui_continue = false;
|
||||
refresh_ui.join();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
91
scratchpad/ftxtest.cpp
Normal file
91
scratchpad/ftxtest.cpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include <stdlib.h> // for EXIT_SUCCESS
|
||||
#include <chrono> // for milliseconds
|
||||
#include <fmt/core.h>
|
||||
#include <ftxui/component/event.hpp> // for Event
|
||||
#include <ftxui/component/mouse.hpp> // for ftxui
|
||||
#include <ftxui/dom/elements.hpp> // for text, separator, Element, operator|, vbox, border
|
||||
#include <memory> // for allocator, shared_ptr
|
||||
#include <string> // for operator+, to_string
|
||||
#include <thread> // for sleep_for
|
||||
|
||||
#include <ftxui/component/component.hpp> // for CatchEvent, Renderer, operator|=
|
||||
#include <ftxui/component/loop.hpp> // for Loop
|
||||
#include <ftxui/component/screen_interactive.hpp> // for ScreenInteractive
|
||||
#include <vector>
|
||||
|
||||
using namespace ftxui;
|
||||
using namespace std;
|
||||
|
||||
ButtonOption Style() {
|
||||
auto option = ButtonOption::Animated();
|
||||
option.transform = [](const EntryState& s) {
|
||||
auto element = text(s.label);
|
||||
if (s.focused) {
|
||||
element |= bold;
|
||||
}
|
||||
return element | center | borderEmpty | flex;
|
||||
};
|
||||
return option;
|
||||
}
|
||||
|
||||
int main() {
|
||||
auto screen = ScreenInteractive::Fullscreen();
|
||||
screen.TrackMouse(true);
|
||||
vector<string> lines;
|
||||
|
||||
// Create a component counting the number of frames drawn and event handled.
|
||||
float scroll_x = 0.1;
|
||||
float scroll_y = 1.0;
|
||||
int hp = 100;
|
||||
|
||||
auto status = Renderer([&] {
|
||||
return vbox({
|
||||
paragraph(fmt::format("HP {}", hp)),
|
||||
separator(),
|
||||
hbox({
|
||||
text("HP"),
|
||||
gauge(hp / 100.0f),
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
auto content = Renderer([&] {
|
||||
vector<Element> output;
|
||||
|
||||
for(const auto line : lines) {
|
||||
output.push_back(text(line));
|
||||
}
|
||||
|
||||
return vbox(output);
|
||||
});
|
||||
|
||||
auto scrollable_content = Renderer(content,
|
||||
[&, content] {
|
||||
return content->Render()
|
||||
| focusPositionRelative(scroll_x, scroll_y)
|
||||
| frame | flex;
|
||||
});
|
||||
|
||||
auto component = Renderer(scrollable_content, [&] {
|
||||
return vbox({
|
||||
status->Render(),
|
||||
separator(),
|
||||
scrollable_content->Render() | vscroll_indicator | yframe | size(HEIGHT, LESS_THAN, 20),
|
||||
}) |
|
||||
border;
|
||||
});
|
||||
|
||||
component |= CatchEvent([&](Event) -> bool {
|
||||
return false;
|
||||
});
|
||||
|
||||
Loop loop(&screen, component);
|
||||
|
||||
while (!loop.HasQuitted()) {
|
||||
loop.RunOnce();
|
||||
screen.Post(Event::Custom);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
27
scratchpad/jsontest.cpp
Normal file
27
scratchpad/jsontest.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <fmt/core.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
using json = nlohmann::json;
|
||||
|
||||
using namespace fmt;
|
||||
using std::string, std::cout;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(argc != 2) {
|
||||
println("USAGE: jsontest [jsonfile]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::ifstream infile(argv[1]);
|
||||
json data = json::parse(infile);
|
||||
|
||||
json::string_t s2 = data["happy"].template get<string>();
|
||||
|
||||
for(auto &el : data.items()) {
|
||||
cout << el.key() << "=" << el.value() << "\n";
|
||||
}
|
||||
|
||||
println("DATA HAPPY {}", s2);
|
||||
return 0;
|
||||
}
|
23
scratchpad/meson.build
Normal file
23
scratchpad/meson.build
Normal file
|
@ -0,0 +1,23 @@
|
|||
executable('regtest', 'regtest.cpp',
|
||||
dependencies: [fmt])
|
||||
|
||||
executable('audiotest', 'audiotest.cpp',
|
||||
dependencies: dependencies)
|
||||
|
||||
executable('jsontest', 'jsontest.cpp',
|
||||
dependencies: dependencies)
|
||||
|
||||
executable('threadtest', 'threadtest.cpp',
|
||||
dependencies: dependencies)
|
||||
|
||||
executable('fsmtest', 'fsmtest.cpp',
|
||||
dependencies: dependencies)
|
||||
|
||||
executable('badref', 'badref.cpp',
|
||||
dependencies: dependencies)
|
||||
|
||||
executable('corotest', [
|
||||
'corotest.cpp'
|
||||
],
|
||||
dependencies: dependencies,
|
||||
cpp_args: '-fcoroutines')
|
27
scratchpad/regtest.cpp
Normal file
27
scratchpad/regtest.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include <fmt/core.h>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
using namespace fmt;
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
smatch matches;
|
||||
|
||||
if(argc != 3) {
|
||||
println("USAGE: regtest <regex> <line>");
|
||||
} else {
|
||||
regex to_test(argv[1]);
|
||||
string line(argv[2]);
|
||||
|
||||
if(regex_match(line, matches, to_test)) {
|
||||
println("MATCHED: ");
|
||||
|
||||
for(auto &match : matches) {
|
||||
println("\t{}", match.str());
|
||||
}
|
||||
} else {
|
||||
println("NO MATCH");
|
||||
}
|
||||
}
|
||||
}
|
37
scratchpad/threadtest.cpp
Normal file
37
scratchpad/threadtest.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include <chrono>
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::future<int> future = std::async(std::launch::async, []()
|
||||
{
|
||||
std::this_thread::sleep_for(3s);
|
||||
return 8;
|
||||
});
|
||||
|
||||
std::cout << "waiting...\n";
|
||||
std::future_status status;
|
||||
|
||||
do
|
||||
{
|
||||
status = future.wait_for(100ms);
|
||||
switch (status)
|
||||
{
|
||||
case std::future_status::deferred:
|
||||
std::cout << "deferred\n";
|
||||
break;
|
||||
case std::future_status::timeout:
|
||||
std::cout << "timeout\n";
|
||||
break;
|
||||
case std::future_status::ready:
|
||||
std::cout << "ready!\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (status != std::future_status::ready);
|
||||
|
||||
std::cout << "result is " << future.get() << '\n';
|
||||
}
|
130
scratchpad/uniqptrtest.cpp
Normal file
130
scratchpad/uniqptrtest.cpp
Normal file
|
@ -0,0 +1,130 @@
|
|||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <locale>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
// helper class for runtime polymorphism demo below
|
||||
struct B
|
||||
{
|
||||
virtual ~B() = default;
|
||||
|
||||
virtual void bar() { std::cout << "B::bar\n"; }
|
||||
};
|
||||
|
||||
struct D : B
|
||||
{
|
||||
D() { std::cout << "D::D\n"; }
|
||||
~D() { std::cout << "D::~D\n"; }
|
||||
|
||||
void bar() override { std::cout << "D::bar\n"; }
|
||||
};
|
||||
|
||||
// a function consuming a unique_ptr can take it by value or by rvalue reference
|
||||
std::unique_ptr<D> pass_through(std::unique_ptr<D> p)
|
||||
{
|
||||
p->bar();
|
||||
return p;
|
||||
}
|
||||
|
||||
// helper function for the custom deleter demo below
|
||||
void close_file(std::FILE* fp)
|
||||
{
|
||||
std::fclose(fp);
|
||||
}
|
||||
|
||||
// unique_ptr-based linked list demo
|
||||
struct List
|
||||
{
|
||||
struct Node
|
||||
{
|
||||
int data;
|
||||
std::unique_ptr<Node> next;
|
||||
};
|
||||
|
||||
std::unique_ptr<Node> head;
|
||||
|
||||
~List()
|
||||
{
|
||||
// destroy list nodes sequentially in a loop, the default destructor
|
||||
// would have invoked its `next`'s destructor recursively, which would
|
||||
// cause stack overflow for sufficiently large lists.
|
||||
while (head)
|
||||
{
|
||||
auto next = std::move(head->next);
|
||||
head = std::move(next);
|
||||
}
|
||||
}
|
||||
|
||||
void push(int data)
|
||||
{
|
||||
head = std::unique_ptr<Node>(new Node{data, std::move(head)});
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << "1) Unique ownership semantics demo\n";
|
||||
{
|
||||
// Create a (uniquely owned) resource
|
||||
std::unique_ptr<D> p = std::make_unique<D>();
|
||||
|
||||
// Transfer ownership to `pass_through`,
|
||||
// which in turn transfers ownership back through the return value
|
||||
std::unique_ptr<D> q = pass_through(std::move(p));
|
||||
|
||||
// p is now in a moved-from 'empty' state, equal to nullptr
|
||||
assert(!p);
|
||||
}
|
||||
|
||||
std::cout << "\n" "2) Runtime polymorphism demo\n";
|
||||
{
|
||||
// Create a derived resource and point to it via base type
|
||||
std::unique_ptr<B> p = std::make_unique<D>();
|
||||
|
||||
// Dynamic dispatch works as expected
|
||||
p->bar();
|
||||
}
|
||||
|
||||
std::cout << "\n" "3) Custom deleter demo\n";
|
||||
std::ofstream("demo.txt") << 'x'; // prepare the file to read
|
||||
{
|
||||
using unique_file_t = std::unique_ptr<std::FILE, decltype(&close_file)>;
|
||||
unique_file_t fp(std::fopen("demo.txt", "r"), &close_file);
|
||||
if (fp)
|
||||
std::cout << char(std::fgetc(fp.get())) << '\n';
|
||||
} // `close_file()` called here (if `fp` is not null)
|
||||
|
||||
std::cout << "\n" "4) Custom lambda-expression deleter and exception safety demo\n";
|
||||
try
|
||||
{
|
||||
std::unique_ptr<D, void(*)(D*)> p(new D, [](D* ptr)
|
||||
{
|
||||
std::cout << "destroying from a custom deleter...\n";
|
||||
delete ptr;
|
||||
});
|
||||
|
||||
throw std::runtime_error(""); // `p` would leak here if it were a plain pointer
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
std::cout << "Caught exception\n";
|
||||
}
|
||||
|
||||
std::cout << "\n" "5) Array form of unique_ptr demo\n";
|
||||
{
|
||||
std::unique_ptr<D[]> p(new D[3]);
|
||||
} // `D::~D()` is called 3 times
|
||||
|
||||
std::cout << "\n" "6) Linked list demo\n";
|
||||
{
|
||||
List wall;
|
||||
const int enough{1'000'000};
|
||||
for (int beer = 0; beer != enough; ++beer)
|
||||
wall.push(beer);
|
||||
|
||||
std::cout << enough << " bottles of beer on the wall...\n";
|
||||
} // destroys all the beers
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue