From 34381a3bef9c92efdacf8681d5d7a2c4fb277e2c Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Sat, 27 Nov 2021 14:24:35 -0500 Subject: [PATCH 01/39] Update codestats --- proj/codestats.dat | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/proj/codestats.dat b/proj/codestats.dat index b7b24cc3..ecd0c862 100644 --- a/proj/codestats.dat +++ b/proj/codestats.dat @@ -228,3 +228,13 @@ 1627307838 xdl 16 2622 74483 1627307838 xp 10 996 28702 1627307838 total proj 265 23920 708059 + 1637736091 audio 2 355 9586 + 1637736091 csp 65 3419 93090 + 1637736091 data 13 1490 45643 + 1637736091 opengl 128 12775 409267 + 1637736091 util 44 4100 112694 + 1637736091 video 2 535 18206 + 1637736091 visualcs 5 303 8650 + 1637736091 xdl 19 3735 116146 + 1637736091 xp 10 939 23845 + 1637736091 total proj 288 27651 837127 From 7085f09f9a84a2b31a7c577435b07e0be15030db Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Sun, 19 Dec 2021 00:08:46 -0500 Subject: [PATCH 02/39] Remove stale vscode settings file --- src/opengl/.vscode/settings.json | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 src/opengl/.vscode/settings.json diff --git a/src/opengl/.vscode/settings.json b/src/opengl/.vscode/settings.json deleted file mode 100644 index c6cea3a4..00000000 --- a/src/opengl/.vscode/settings.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "files.associations": { - "array": "cpp", - "deque": "cpp", - "string": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "string_view": "cpp", - "initializer_list": "cpp", - "utility": "cpp" - } -} \ No newline at end of file From 0b35c5beeff271abbb7e5e333b2ff7b0963440b9 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Sun, 19 Dec 2021 00:10:54 -0500 Subject: [PATCH 03/39] Add sane C++ extension settings for VSCode The C/C++ extension has a setting that allows you to check for different versions of C/C++. This has been set to our project defaults in order to ensure that the project standards are being acknowledged by VSCode. --- Grail_Workspace.code-workspace | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Grail_Workspace.code-workspace b/Grail_Workspace.code-workspace index 6c0daeb3..f92790d3 100644 --- a/Grail_Workspace.code-workspace +++ b/Grail_Workspace.code-workspace @@ -3,5 +3,9 @@ { "path": "." } - ] + ], + "settings": { + "C_Cpp.default.cppStandard": "c++20", + "C_Cpp.default.cStandard": "c17", + } } \ No newline at end of file From 14d8cadb049e5f5608b5b6e6ed605fd6c3ec3e19 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Sun, 19 Dec 2021 00:13:43 -0500 Subject: [PATCH 04/39] Add C defaults, clang-tidy settings to CMakeLists.txt CmakeLists.txt now has defaults set for the C version and C extensions used in the project. Also, there is a new flag, GRAIL_TIDY, that runs clang-tidy checks during the compile process. --- CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e1add2e..a5899ecf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,8 +11,11 @@ set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}) set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/libs) set(CMAKE_FILES_DIRECTORY build) set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/modules) +set(CMAKE_C_STANDARD 17) set(CMAKE_CXX_STANDARD 20) +option(CMAKE_C_STANDARD_REQUIRED ON) option(CMAKE_CXX_STANDARD_REQUIRED ON) +option(CMAKE_C_EXTENSIONS OFF) option(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS ON @@ -82,6 +85,11 @@ if(GRAIL_WERROR) endif() endif() +if(GRAIL_TIDY) + message(STATUS "clang-tidy modern checks enabled") + set(CMAKE_CXX_CLANG_TIDY clang-tidy -checks=-modern* -extra-arg=-std=c++20) +endif() + include(FetchContent) include(GrailFunctions) From a5c27f1c6c4276cd865b124f4c4d74a0ca58a754 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Sun, 19 Dec 2021 00:17:07 -0500 Subject: [PATCH 05/39] Fix constexpr violations in Benchmark.hh and tests After running clang-tidy during the compile process, it became apparent that Benchmark.hh and testfmt.cc both had several constexpr violations (trying to create non-constexpr objects in constexpr functions, calling non-constexpr functions in constexpr functions, etc.). These should all be fixed now. --- src/util/Benchmark.hh | 11 +++++------ test/testfmt.cc | 10 +++++----- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/util/Benchmark.hh b/src/util/Benchmark.hh index 5bbf0ca8..7055c184 100644 --- a/src/util/Benchmark.hh +++ b/src/util/Benchmark.hh @@ -108,7 +108,7 @@ class CBenchmark { public: CBenchmark(const std::string& msg) : msg(msg) { reset(); } - void reset() { elapsedTime = 0; } + constexpr void reset() { elapsedTime = 0; } void start() { t0 = time_point_cast( @@ -116,13 +116,12 @@ class CBenchmark { } void end() { - std::chrono::time_point - t1 = time_point_cast( - std::chrono::steady_clock::now()); + auto t1 = time_point_cast( + std::chrono::steady_clock::now()); elapsedTime += (t1 - t0).count(); } - constexpr double elapsed() { return elapsedTime; } + constexpr double elapsed() const { return elapsedTime; } void display() const { fmt::print("{} elapsed time: {}\n", msg, elapsedTime); } @@ -131,7 +130,7 @@ class CBenchmark { } template - constexpr static void benchmark(const std::string& msg, + static void benchmark(const std::string& msg, uint64_t numIterations, Func func) { uint64_t iter = numIterations; CBenchmark b(msg); diff --git a/test/testfmt.cc b/test/testfmt.cc index fcb2aa9b..afbbc297 100644 --- a/test/testfmt.cc +++ b/test/testfmt.cc @@ -200,7 +200,7 @@ constexpr uint32_t _formatgrl(char destBuf[33], int printVal) { } constexpr inline char DECIMAL_POINT = '.'; -constexpr void _insertdec(char destBuf[33], uint32_t& i, uint32_t decimalLoc, +void _insertdec(char destBuf[33], uint32_t& i, uint32_t decimalLoc, uint32_t digit4) { // load the right 4 digits from the table 0000 to 9999 uint32_t digits = ((uint32_t*)dig4)[digit4]; @@ -252,7 +252,7 @@ constexpr void _insertdec(char destBuf[33], uint32_t& i, uint32_t decimalLoc, } // R to L, 4 at a time -constexpr uint32_t _formatgrlfloat(char destBuf[33], uint64_t printVal, +uint32_t _formatgrlfloat(char destBuf[33], uint64_t printVal, uint32_t precision, uint32_t decimalLoc) { uint32_t len; uint32_t i; @@ -284,7 +284,7 @@ constexpr uint32_t _formatgrl5(char destBuf[33], T data) { // 1234.567 // 12.34567 frexp(data, &ex); - constexpr double invLog2_10 = 1 / log2(10.0); + double invLog2_10 = 1 / log2(10.0); double powOf10 = ceil(ex * invLog2_10); T scale = pow(10, powOf10 - precision); T scaled = data / scale; @@ -298,7 +298,7 @@ constexpr uint32_t _formatgrl5(char destBuf[33], T data) { } template -constexpr void testboth(T data) { +void testboth(T data) { print(fg(color::steel_blue) | emphasis::bold, "Currently processing: {}\n", data); char dest[33]; @@ -312,7 +312,7 @@ constexpr void testboth(T data) { } template -constexpr void testAll(T data) { +void testAll(T data) { print(fg(color::steel_blue) | emphasis::bold, "Currently processing: {}\n", data); char dest[33]; From c5ab6122a1e67b5e2d7c49ebfa31686d12346339 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Sun, 19 Dec 2021 11:18:45 -0500 Subject: [PATCH 06/39] Set clang-tidy to use defaults instead of modern settings clang-tidy has a set of reasonable defaults that should be useful for preliminary static analysis. Once we have cleared up some of the issues in the codebase, we should consider using the modern checks. --- .clang-tidy | 45 +++++++++++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 .clang-tidy diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000..421d4280 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,45 @@ +--- +Checks: 'clang-diagnostic-*,clang-analyzer-*' +WarningsAsErrors: '' +HeaderFilterRegex: '' +AnalyzeTemporaryDtors: false +FormatStyle: none +CheckOptions: + - key: llvm-else-after-return.WarnOnConditionVariables + value: 'false' + - key: modernize-loop-convert.MinConfidence + value: reasonable + - key: modernize-replace-auto-ptr.IncludeStyle + value: llvm + - key: cert-str34-c.DiagnoseSignedUnsignedCharComparisons + value: 'false' + - key: google-readability-namespace-comments.ShortNamespaceLines + value: '10' + - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField + value: 'false' + - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: 'true' + - key: cert-dcl16-c.NewSuffixes + value: 'L;LL;LU;LLU' + - key: google-readability-braces-around-statements.ShortStatementLines + value: '1' + - key: modernize-pass-by-value.IncludeStyle + value: llvm + - key: google-readability-namespace-comments.SpacesBeforeComments + value: '2' + - key: modernize-loop-convert.MaxCopySize + value: '16' + - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors + value: 'true' + - key: modernize-use-nullptr.NullMacros + value: 'NULL' + - key: llvm-qualified-auto.AddConstToQualified + value: 'false' + - key: modernize-loop-convert.NamingStyle + value: CamelCase + - key: llvm-else-after-return.WarnOnUnfixable + value: 'false' + - key: google-readability-function-size.StatementThreshold + value: '800' +... + diff --git a/CMakeLists.txt b/CMakeLists.txt index a5899ecf..c2d133dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,7 +87,7 @@ endif() if(GRAIL_TIDY) message(STATUS "clang-tidy modern checks enabled") - set(CMAKE_CXX_CLANG_TIDY clang-tidy -checks=-modern* -extra-arg=-std=c++20) + set(CMAKE_CXX_CLANG_TIDY clang-tidy -extra-arg=-std=c++20) endif() include(FetchContent) From 31f7d4fc877f4445ab06c1d6d5e57b83e7a93ef9 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Sun, 19 Dec 2021 11:20:27 -0500 Subject: [PATCH 07/39] Turn SocketIO into a namespace Previously, SocketIO was a class containing static functions and constants. In a situation like this, it makes a bit more sense to use a namespace (eventually if at some point we want to allow argument dependent lookup for a function). --- src/csp/SocketIO.cc | 14 +++++++------- src/csp/SocketIO.hh | 19 ++++++++++--------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/csp/SocketIO.cc b/src/csp/SocketIO.cc index be9bd81b..3960b82b 100644 --- a/src/csp/SocketIO.cc +++ b/src/csp/SocketIO.cc @@ -6,22 +6,22 @@ // TODO: Look into logging WSAGetLastError and strerror(errno) // Using the logging object in csp.hh? -int SocketIO::send(socket_t sckt, const char *buf, int size, int flags) { +namespace SocketIO { +int send(socket_t sckt, const char *buf, int size, int flags) { uint32_t bytesSent; if ((bytesSent = ::send(sckt, (char *)buf, size, 0)) == err_code) { - if (errno != EBADF) - throw Ex1(Errcode::SOCKET_SEND); + if (errno != EBADF) throw Ex1(Errcode::SOCKET_SEND); perror("Warning on send(): "); } return bytesSent; } -int SocketIO::recv(socket_t sckt, const char *buf, int size, int flags) { +int recv(socket_t sckt, const char *buf, int size, int flags) { uint32_t bytesRecv; if ((bytesRecv = ::recv(sckt, (char *)buf, size, 0)) == err_code) { - if (errno != EBADF) - throw Ex1(Errcode::SOCKET_SEND); + if (errno != EBADF) throw Ex1(Errcode::SOCKET_SEND); perror("Warning on recv()"); } return bytesRecv; -} \ No newline at end of file +} +} // namespace SocketIO \ No newline at end of file diff --git a/src/csp/SocketIO.hh b/src/csp/SocketIO.hh index 7d1686d5..9415a2f1 100644 --- a/src/csp/SocketIO.hh +++ b/src/csp/SocketIO.hh @@ -14,7 +14,7 @@ #pragma comment(lib, "Mswsock.lib") #pragma comment(lib, "AdvApi32.lib") -//Compiler is not a fan of this define +// Compiler is not a fan of this define //#define errno WSAGetLastError() #else // linux @@ -25,14 +25,15 @@ using socket_t = decltype(socket(0, 0, 0)); -class SocketIO { - private: +namespace SocketIO { +namespace { #ifdef __linux__ - const static int err_code = -1; +constexpr static int err_code = -1; #elif _WIN32 - const static int err_code = SOCKET_ERROR; +constexpr static int err_code = SOCKET_ERROR; #endif - public: - static int send(socket_t sckt, const char *buf, int size, int flags); - static int recv(socket_t sckt, const char *buf, int size, int flags); -}; \ No newline at end of file +} // anonymous namespace for errors + +int send(socket_t sckt, const char *buf, int size, int flags); +int recv(socket_t sckt, const char *buf, int size, int flags); +}; // namespace SocketIO \ No newline at end of file From 904a009f3fad65301917b9756da84a40a60fd5e7 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Sun, 19 Dec 2021 11:24:16 -0500 Subject: [PATCH 08/39] Update .clang-tidy to use .clang-format for style --- .clang-tidy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-tidy b/.clang-tidy index 421d4280..b0273c20 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -3,7 +3,7 @@ Checks: 'clang-diagnostic-*,clang-analyzer-*' WarningsAsErrors: '' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false -FormatStyle: none +FormatStyle: file CheckOptions: - key: llvm-else-after-return.WarnOnConditionVariables value: 'false' From d4be2b8d393120f5987b0ccb8697c4a200f6e063 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Sun, 19 Dec 2021 11:46:43 -0500 Subject: [PATCH 09/39] Update .gitignore for intellij --- .gitignore | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ace21674..e5e03508 100644 --- a/.gitignore +++ b/.gitignore @@ -51,8 +51,9 @@ libs/libgrail.a *~ \#* -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 +# Source: https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # User-specific stuff .idea/**/workspace.xml @@ -61,6 +62,9 @@ libs/libgrail.a .idea/**/dictionaries .idea/**/shelf +# AWS User-specific +.idea/**/aws.xml + # Generated files .idea/**/contentModel.xml @@ -81,12 +85,52 @@ libs/libgrail.a # When using Gradle or Maven with auto-import, you should exclude module files, # since they will be recreated, and may cause churn. Uncomment if using # auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml # .idea/modules.xml # .idea/*.iml # .idea/modules # *.iml # *.ipr +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + + # CMake cmake-build-*/ cmake_install.cmake From bba6f1ad5cfb38525f89a449121b8732297f59df Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Sun, 19 Dec 2021 13:15:30 -0500 Subject: [PATCH 10/39] Clean up IPV4Socket Made some changes suggested by clang-tidy in IPV4Socket --- src/csp/IPV4Socket.cc | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/csp/IPV4Socket.cc b/src/csp/IPV4Socket.cc index fba7e660..36325c15 100644 --- a/src/csp/IPV4Socket.cc +++ b/src/csp/IPV4Socket.cc @@ -1,15 +1,10 @@ #include "IPV4Socket.hh" -#include -#include #include /* All encapsulation for different operating systems networking code is done here */ -#include -#include - //#include "csp/HTTPRequest.hh" #include "csp/SocketIO.hh" #include "csp/csp.hh" @@ -41,7 +36,6 @@ void Socket::classInit() { testResult(WSAStartup(MAKEWORD(2, 2), &wsaData), __FILE__, __LINE__, Errcode::SOCKET); #endif - return; } // Takes care of allocations made by Winsock @@ -60,7 +54,7 @@ IPV4Socket::IPV4Socket(uint16_t port) : Socket(port) { testResult(setsockopt(sckt, SOL_SOCKET, SO_REUSEADDR, (const char *)&yes, sizeof(yes)), __FILE__, __LINE__, Errcode::SETSOCKOPT); memset(sockaddress, 0, sizeof(sockaddress)); - sockaddr_in *sockAddr = (sockaddr_in *)sockaddress; + auto *sockAddr = (sockaddr_in *)sockaddress; sockAddr->sin_family = AF_INET; sockAddr->sin_addr.s_addr = INADDR_ANY; sockAddr->sin_port = htons(port); @@ -79,7 +73,7 @@ IPV4Socket::IPV4Socket(const char *addr, uint16_t port) : Socket(addr, port) { throw Ex(__FILE__, __LINE__, Errcode::SERVER_INVALID); } - sockaddr_in *sockAddr = (sockaddr_in *)sockaddress; + auto *sockAddr = (sockaddr_in *)sockaddress; sockAddr->sin_family = AF_INET; // bcopy((char *)server->h_addr, (char *)&sockaddress.sin_addr.s_addr, // server->h_length); From 2885ccb7aac02698c35431ea89ad7a1a8fd9d4ba Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Sun, 19 Dec 2021 13:16:27 -0500 Subject: [PATCH 11/39] Add CPPCoreGuidelines checks to .clang-tidy The CPPCoreGuidelines are an open-source list of suggestions for safety and simplicity in the latest standards (currently C++ 11, 14, and 17) led by Bjarne Stroustrup. clang-tidy happens to have a set of checks to look for compliance with these guidelines, so they have been turned on for the time being. --- .clang-tidy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-tidy b/.clang-tidy index b0273c20..00fce9b6 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,5 +1,5 @@ --- -Checks: 'clang-diagnostic-*,clang-analyzer-*' +Checks: 'clang-diagnostic-*,clang-analyzer-*','cppcoreguidelines-*' WarningsAsErrors: '' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false From e01ecbc036d5140eabe8453d0a567bd68411c72e Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Tue, 21 Dec 2021 00:29:41 -0500 Subject: [PATCH 12/39] Update codestats --- .clang-tidy | 2 +- proj/codestats.dat | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/.clang-tidy b/.clang-tidy index 00fce9b6..bf0f8e8c 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,5 +1,5 @@ --- -Checks: 'clang-diagnostic-*,clang-analyzer-*','cppcoreguidelines-*' +Checks: 'clang-diagnostic-*,clang-analyzer-*,cppcoreguidelines-*' WarningsAsErrors: '' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false diff --git a/proj/codestats.dat b/proj/codestats.dat index ecd0c862..270a67b6 100644 --- a/proj/codestats.dat +++ b/proj/codestats.dat @@ -238,3 +238,23 @@ 1637736091 xdl 19 3735 116146 1637736091 xp 10 939 23845 1637736091 total proj 288 27651 837127 + 1640003220 audio 2 355 9586 + 1640003220 csp 65 3414 93042 + 1640003220 data 13 1490 45643 + 1640003220 opengl 124 12651 406169 + 1640003220 util 44 4114 113111 + 1640003220 video 2 535 18206 + 1640003220 visualcs 5 303 8650 + 1640003220 xdl 19 3757 117202 + 1640003220 xp 8 821 20958 + 1640003220 total proj 282 27440 832567 + 1640060389 audio 2 355 9586 + 1640060389 csp 65 3414 93042 + 1640060389 data 13 1490 45643 + 1640060389 opengl 124 12651 406169 + 1640060389 util 44 4114 113111 + 1640060389 video 2 535 18206 + 1640060389 visualcs 5 303 8650 + 1640060389 xdl 19 3757 117202 + 1640060389 xp 8 821 20958 + 1640060389 total proj 282 27440 832567 From a4bb2b7a12560b3da50d3c7ac8f1baabd5856823 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Tue, 21 Dec 2021 00:32:00 -0500 Subject: [PATCH 13/39] Add emplace_back capability for DynArray DynArray now has emplace_back and push_back functionality. While DynArray::push_back seems to act the same as DynArray::add, DynArray::emplace_back uses an implementation of std::construct_at written in DynArray and std::forward to construct the object in-place in the DynArray. testDynArrayPerf currently has several test checking the performance of adding or emplacing raw pointers vs unique_ptrs. More testing is needed. As of right now, it looks like a DynArray of unique_ptrs has roughly the same performance as a DynArray of raw pointers (besides the initial overhead in the constructor, but that is unavoidable). --- src/util/DynArray.hh | 15 ++++++ test/testDynArrayPerf.cc | 105 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 test/testDynArrayPerf.cc diff --git a/src/util/DynArray.hh b/src/util/DynArray.hh index 718e076d..9a160a71 100644 --- a/src/util/DynArray.hh +++ b/src/util/DynArray.hh @@ -60,6 +60,14 @@ class DynArray { return s; } + template + T& emplace_back(Args&&... args) { + checkGrow(); + return *construct_at(data + size_++, std::forward(args)...); + } + + void push_back(T&& elem) { emplace_back(std::move(elem)); } + constexpr bool find(T& t) { for (T& item : data) { if (item == t) { @@ -68,4 +76,11 @@ class DynArray { } return false; } + + // Roughly equivalent of std::construct_at. Used to reduce class footprint + template + constexpr T* construct_at(T* p, Args&&... args) { + return ::new (const_cast(static_cast(p))) + T(std::forward(args)...); + } }; diff --git a/test/testDynArrayPerf.cc b/test/testDynArrayPerf.cc new file mode 100644 index 00000000..f73ac3f1 --- /dev/null +++ b/test/testDynArrayPerf.cc @@ -0,0 +1,105 @@ +#include +#include +#include + +#include "util/Benchmark.hh" +#include "util/DynArray.hh" + +using namespace std; + +class PtrObject { + private: + vector data; + string name; + + public: + PtrObject(int initialSize, string name) : data(initialSize), name(name) {} + + int& get(int index) { return data[index]; } + void add(int index, int value) { data.insert(data.begin() + index, value); } +}; + +class Vec3d { + private: + double x, y, z; + + public: + Vec3d(double x, double y, double z) : x(x), y(y), z(z) {} + void set(double x, double y, double z) { + this->x = x; + this->y = y; + this->z = z; + } +}; + +int main() { + auto add_raw_ptr_object = [] { + DynArray a(100); + for (int i = 0; i < 100; i++) { + a.add(new PtrObject(50, "fred")); + for (int j = 0; j < 50; j++) { + a[i]->add(j, i); + } + for (int j = 0; j < 50; j++) { + for (int k = 0; k < 1000; k++) { + a[i]->get(j)++; + } + } + } + for (int i = 0; i < 100; i++) { + delete a[i]; + } + }; + + auto emplace_raw_ptr_object = [] { + DynArray a(100); + for (int i = 0; i < 100; i++) { + a.emplace_back(new PtrObject(50, "fred")); + for (int j = 0; j < 50; j++) { + a[i]->add(j, i); + } + + for (int j = 0; j < 50; j++) { + for (int k = 0; k < 1000; k++) { + a[i]->get(j)++; + } + } + } + for (int i = 0; i < 100; i++) { + delete a[i]; + } + }; + + /* auto add_unique_ptr_object = [] { + DynArray> a(10); + for (int i = 0; i < 10; i++) { + a.add(make_unique(50, "fred")); + for (int j = 0; j < 50; j++) { + a[j]->add(j, i); + } + } + }; + */ + auto emplace_unique_ptr_object = [] { + DynArray> a(100); + for (int i = 0; i < 100; i++) { + a.emplace_back(make_unique(50, "fred")); + for (int j = 0; j < 50; j++) { + a[i]->add(j, i); + } + for (int j = 0; j < 50; j++) { + for (int k = 0; k < 1000; k++) { + a[i]->get(j)++; + } + } + } + }; + + CBenchmark::benchmark("PtrObject raw ptr add", 1e3, bind(add_raw_ptr_object)); + CBenchmark::benchmark("PtrObject raw ptr emplace", 1e3, + bind(emplace_raw_ptr_object)); + // CBenchmark::benchmark("PtrObject unique add", 1e6, + // bind(add_unique_ptr_object)); + CBenchmark::benchmark("PtrObject unique emplace", 1e3, + bind(emplace_unique_ptr_object)); +} \ No newline at end of file From 46b8d34b957592be7d9a6850e719add7958da333 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Tue, 21 Dec 2021 00:37:19 -0500 Subject: [PATCH 14/39] Add CMake build for testDynArrayPerf --- test/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9ea12f22..4c4705b3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -33,6 +33,7 @@ add_grail_executable(SRC testfmt.cc LIBS grail) # add_grail_executable(SRC loadESRIShapefile.cc LIBS grail) add_grail_executable(SRC testXDLButton.cc LIBS grail) add_grail_executable(SRC testMultiTab.cc LIBS grail) +add_grail_executable(SRC testDynArrayPerf.cc LIBS grail) if(${MPV_FOUND}) add_grail_executable(SRC testSingleAudio.cc LIBS grail) From 63bdb290a8cdc449d1e2ce606d96ee3f473030de Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Tue, 21 Dec 2021 20:18:45 -0500 Subject: [PATCH 15/39] Update codestats --- proj/codestats.dat | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/proj/codestats.dat b/proj/codestats.dat index 270a67b6..0f8e15b2 100644 --- a/proj/codestats.dat +++ b/proj/codestats.dat @@ -258,3 +258,13 @@ 1640060389 xdl 19 3757 117202 1640060389 xp 8 821 20958 1640060389 total proj 282 27440 832567 + 1640132855 audio 2 355 9586 + 1640132855 csp 65 3414 93042 + 1640132855 data 13 1490 45643 + 1640132855 opengl 124 12653 406228 + 1640132855 util 45 4142 113563 + 1640132855 video 2 535 18206 + 1640132855 visualcs 5 303 8650 + 1640132855 xdl 19 3757 117250 + 1640132855 xp 8 821 20958 + 1640132855 total proj 283 27470 833126 From c35ed23bb4b9ee001d35529ddf51023fefde6e92 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Fri, 24 Dec 2021 15:18:00 -0500 Subject: [PATCH 16/39] Add clang-tidy suggestions SolarSystem has some imports removed and now moves copies of names instead of passing by reference. Constructor is now explicit to prevent accidental implicit conversion. TestDrawBlockMap now implements move constructor and move operator=. --- test/SolarSystem.cc | 13 +++++-------- test/testDrawBlockMap.cc | 13 +++++++++++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/test/SolarSystem.cc b/test/SolarSystem.cc index 5e9244d3..7eb46789 100644 --- a/test/SolarSystem.cc +++ b/test/SolarSystem.cc @@ -1,13 +1,10 @@ #include -#include #include -#include "opengl/Errcode.hh" #include "opengl/GrailGUI.hh" #include "opengl/MultiShape3D.hh" #include "opengl/util/Transformation.hh" #include "util/DynArray.hh" -#include "util/Ex.hh" using namespace std; @@ -27,18 +24,18 @@ class Body { Transformation* trans; public: - Body(Canvas* c, const Style* s, Camera* cam, const std::string& name, + Body(Canvas* c, const Style* s, Camera* cam, std::string name, const char textureFile[], double r, double orbitalRadius, double orbitalPeriod, double rotationalPeriod, double axialTilt, double startTime, Body* orbits = nullptr); void update(double time); }; -Body::Body(Canvas* c, const Style* s, Camera* cam, const std::string& name, +Body::Body(Canvas* c, const Style* s, Camera* cam, std::string name, const char textureFile[], double r, double orbitalRadius, double orbitalPeriod, double rotationalPeriod, double axialTilt, double startTime, Body* orbits) - : name(name), + : name(move(name)), r(r), orbitalRadius(orbitalRadius), orbitalFreq(1.0 / orbitalPeriod), @@ -86,7 +83,7 @@ class SolarSystem : public Member { constexpr static double SIDEREAL_DAY = 0.9972; // number of 24-hour "days" it takes earth to rotate once public: - SolarSystem(Tab* tab) : Member(tab, 0, .0125), bodies(10) { + explicit SolarSystem(Tab* tab) : Member(tab, 0, .0125), bodies(10) { cam = c->setLookAtProjection(2, 3, 40, 0, 0, 0, 0, 0, 1); GLWin* w = tab->getParentWin(); const Style* s = w->getDefaultStyle(); @@ -131,7 +128,7 @@ class SolarSystem : public Member { void panRight(); void panLeft(); - void update() { + void update() override { double t = tab->time(); for (int i = 0; i < bodies.size(); i++) bodies[i]->update(t); } diff --git a/test/testDrawBlockMap.cc b/test/testDrawBlockMap.cc index d2b7ceee..9c91c462 100644 --- a/test/testDrawBlockMap.cc +++ b/test/testDrawBlockMap.cc @@ -39,6 +39,19 @@ class TestDrawBlockMap : public Member { ~TestDrawBlockMap() { delete mv; } TestDrawBlockMap(const TestDrawBlockMap& orig) = delete; TestDrawBlockMap& operator=(const TestDrawBlockMap& orig) = delete; + TestDrawBlockMap(TestDrawBlockMap&& orig) + : Member(orig), filename(orig.filename), mv(orig.mv) { + orig.mv = nullptr; // TODO: should filename be set to nullptr? + } + TestDrawBlockMap& operator=(const TestDrawBlockMap&& orig) { + if (this != &orig) { + delete mv; // TODO: Not deleting filename as its usually passed on the + // stack + mv = orig.mv; + filename = orig.filename; + } + return *this; + } constexpr static float zoomVal = 1.2; void mapZoomIn() { From c0b26c6a06209894d72a9ae830d52df9a275fd05 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Fri, 24 Dec 2021 15:24:09 -0500 Subject: [PATCH 17/39] Update cmake action to test tabbed-windows --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 976f8d43..18687925 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -2,7 +2,7 @@ name: CMake on: push: - branches: [ main ] + branches: [ main, tabbed-windows ] pull_request: branches: [ main ] workflow_dispatch: From 1e0e56cea959cff52304848f6c9038c628cf23ac Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Fri, 24 Dec 2021 15:39:54 -0500 Subject: [PATCH 18/39] Clean up Callbacks at suggestion of clang-tidy TODO: consider making callbacks a namespace. Everything in there seems static anyway. --- src/util/Callbacks.cc | 21 ++++++++++----------- src/util/Callbacks.hh | 16 ++++++++-------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/util/Callbacks.cc b/src/util/Callbacks.cc index 77f0e213..9d7428e3 100644 --- a/src/util/Callbacks.cc +++ b/src/util/Callbacks.cc @@ -5,15 +5,15 @@ using namespace std; CallbackHandler::CallbackHandler() { - for (int i = 0; i < 3; i++) numActions[i] = 1; + for (uint8_t i = 0; i < 3; i++) {numActions[i] = 1;} } HashMap CallbackHandler::actionNameMap(64, 4096); std::array inputMap(); -uint32_t CallbackHandler::internalRegisterAction(const char name[], Security s, - function action) { - uint32_t securityIndex = uint32_t(s); +uint32_t CallbackHandler::internalRegisterAction(const char name[], const Security s, + const function action) { + auto securityIndex = uint32_t(s); // SAFE = 0..999, RESTRICTED=1000.1999, ASK=2000..2999 uint32_t actNum = 1000 * securityIndex + numActions[securityIndex]++; // TODO: do something if 1000 action functions exceeded. For now, completely @@ -23,14 +23,14 @@ uint32_t CallbackHandler::internalRegisterAction(const char name[], Security s, << '\n'; } // cout << "Setting action " << actNum << " for action " << name << '\n'; - setAction(actNum, action); + setAction(actNum, move(action)); actionNameMap.add(name, actNum); return actNum; } -uint32_t CallbackHandler::lookupAction(const char actionName[]) { +auto CallbackHandler::lookupAction(const char actionName[]) -> uint32_t { uint32_t *act_code = actionNameMap.get(actionName); - if (act_code) return *act_code; + if (act_code) {return *act_code;} cerr << "Input binding failed: " << actionName << '\n'; return 0; } @@ -40,9 +40,9 @@ void CallbackHandler::bind(uint32_t input, const char actionName[]) { } uint32_t CallbackHandler::registerCallback(uint32_t input, const char name[], - Security s, + const Security s, function action) { - uint32_t securityIndex = uint32_t(s); + auto securityIndex = uint32_t(s); // SAFE = 0..999, RESTRICTED=1000.1999, ASK=2000..2999 uint32_t actNum = 1000 * securityIndex + numActions[securityIndex]++; // TODO: do something if 1000 action functions exceeded. For now, completely @@ -57,8 +57,7 @@ uint32_t CallbackHandler::registerCallback(uint32_t input, const char name[], setEvent(input, lookupAction(name)); return actNum; } - -void CallbackHandler::doit(uint32_t input) { + auto CallbackHandler::doit(uint32_t input) -> void { uint32_t act = CallbackHandler::inputMap[input]; if (act == 0) return; auto a = CallbackHandler::actionMap[act]; diff --git a/src/util/Callbacks.hh b/src/util/Callbacks.hh index c237cf8e..b4af2441 100644 --- a/src/util/Callbacks.hh +++ b/src/util/Callbacks.hh @@ -29,21 +29,21 @@ class CallbackHandler { */ inline static std::array, 4096> actionMap; static HashMap actionNameMap; - uint32_t lookupAction(const char actionName[]); + static uint32_t lookupAction(const char actionName[]); // static GLWin* w; - void setEvent(uint32_t e, uint32_t a) { inputMap[e] = a; } + static void setEvent(uint32_t e, uint32_t a) { inputMap.at(e) = a; } - void setEvent(uint32_t key, uint32_t mod, uint32_t a) { + static void setEvent(uint32_t key, uint32_t mod, uint32_t a) { setEvent((mod << 9) | key, a); } - void setAction(uint32_t a, std::function action) { - actionMap[a] = action; + static void setAction(uint32_t a, std::function action) { + actionMap[a] = move(action); } enum class Security { SAFE, // safe for a remote server to trigger this function RESTRICTED, // only the local user can execute this function - ASK // a remote user or server may request this but it will trigger a popup + ASK // a remote user or server may request this, but it will trigger a popup // asking local user to approve }; std::array numActions; // keep track of how many of each kind of @@ -58,7 +58,7 @@ class CallbackHandler { } // registerAction("myFunc", Security::RESTRICTED, myFunc) // bind an input event to an action Name. looks up offsets into arrays - void bind(uint32_t input, const char actionName[]); + static void bind(uint32_t input, const char actionName[]); void bind(const char inputCmd[], const char actionName[]); #define quote(a) #a @@ -80,7 +80,7 @@ class CallbackHandler { registerCallback(inp, quote(func), Security::SAFE, func, ptr); } - void doit(uint32_t input); + static doit(uint32_t input); void bind2DOrtho(); void bind3D(); From 1118086d42516f9f7e5fcbd639ed0efd81a4530b Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Fri, 24 Dec 2021 15:41:12 -0500 Subject: [PATCH 19/39] Add big five to Member clang-tidy was complaining about a non-virtual public destructor, but fixing that required implementing a destructor. After some more bargaining with clang-tidy, I had to implement the big five. --- src/opengl/Member.cc | 23 ++++++++++++++++++++++- src/opengl/Member.hh | 10 +++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/opengl/Member.cc b/src/opengl/Member.cc index 0dd6b3ad..55aa3979 100644 --- a/src/opengl/Member.cc +++ b/src/opengl/Member.cc @@ -1,4 +1,6 @@ +#include "Member.hh" + #include "opengl/GrailGUI.hh" using namespace std; @@ -25,4 +27,23 @@ void Member::render() {} void Member::update() {} Tab* Member::getParentTab() { return tab; } -MainCanvas* Member::getParentCanvas() { return c; } \ No newline at end of file +MainCanvas* Member::getParentCanvas() { return c; } +Member::Member(const Member& orig) = default; +Member::Member(Member&& orig) noexcept : tab(orig.tab), c(orig.c) { + orig.tab = nullptr; + orig.c = nullptr; +} +Member& Member::operator=(Member orig) { swap(*this, orig); return *this; } +Member& Member::operator=(Member&& orig) noexcept { + if (this != &orig) { + tab = orig.tab; + c = orig.c; + } + return *this; +} + +void swap(Member& a, Member& b){ + using std::swap; + swap(a.tab,b.tab); + swap(a.c,b.c); +} diff --git a/src/opengl/Member.hh b/src/opengl/Member.hh index e5a14802..9301ccf5 100644 --- a/src/opengl/Member.hh +++ b/src/opengl/Member.hh @@ -13,7 +13,15 @@ class Member { MainCanvas* c; public: - Member(Tab* tab, double frameRate = -1, double dt = 0.0001); + explicit Member(Tab* tab, double frameRate = -1, double dt = 0.0001); + Member(const Member& orig); + Member(Member&& orig) noexcept; + + Member& operator=(Member orig); + Member& operator=(Member&& orig) noexcept; + + virtual ~Member() = default; + friend void swap(Member& a, Member& b); void setFrameRate(double frameRate); void setModelDt(double dt, double defaultDt); From 274addf1bf51ca465373202b097e2e890aad56dc Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Fri, 24 Dec 2021 15:43:30 -0500 Subject: [PATCH 20/39] Add readability checks, update codestats --- .clang-tidy | 2 +- proj/codestats.dat | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.clang-tidy b/.clang-tidy index bf0f8e8c..d8dbcac6 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,5 +1,5 @@ --- -Checks: 'clang-diagnostic-*,clang-analyzer-*,cppcoreguidelines-*' +Checks: 'clang-diagnostic-*,clang-analyzer-*,cppcoreguidelines-*,readability-*' WarningsAsErrors: '' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false diff --git a/proj/codestats.dat b/proj/codestats.dat index 0f8e15b2..5055b594 100644 --- a/proj/codestats.dat +++ b/proj/codestats.dat @@ -268,3 +268,13 @@ 1640132855 xdl 19 3757 117250 1640132855 xp 8 821 20958 1640132855 total proj 283 27470 833126 + 1640199563 audio 2 355 9586 + 1640199563 csp 65 3414 93042 + 1640199563 data 13 1490 45643 + 1640199563 opengl 124 12653 406228 + 1640199563 util 45 4142 113563 + 1640199563 video 2 535 18206 + 1640199563 visualcs 5 303 8650 + 1640199563 xdl 19 3757 117250 + 1640199563 xp 8 821 20958 + 1640199563 total proj 283 27470 833126 From aa8e9868126909b1acc1d9c0c4be95a598c313a6 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Fri, 24 Dec 2021 15:53:46 -0500 Subject: [PATCH 21/39] Separate compile action for ubuntu due to dependency changes --- .github/workflows/cmake.yml | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 18687925..5493e12c 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -8,13 +8,43 @@ on: workflow_dispatch: jobs: - build-ubuntu: + build-ubuntu18: strategy: matrix: - ubuntu-version: [ubuntu-18.04, ubuntu-latest] build-type: [Debug, Release] - runs-on: ${{matrix.ubuntu-version}} + runs-on: ubuntu-18.04 + + steps: + - uses: actions/checkout@v2 + - uses: seanmiddleditch/gha-setup-ninja@master + + - name: Set up GCC 11 + run: sudo add-apt-repository ppa:ubuntu-toolchain-r/test + - run: sudo apt-get update + - run: sudo apt-get install gcc-11 g++-11 + - run: sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 999 + - run: sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-11 999 + + + - name: Install Grail dependencies + run: sudo apt install libglfw3-dev libfreetype6-dev mpv libmpv-dev liblzma-dev + + - name: Configure CMake + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: cmake -S . -B build -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} + + - name: Build + # Build your program with the given configuration + run: cmake --build build --config ${{ matrix.build-type }} + + build-ubuntu-latest: + strategy: + matrix: + build-type: [Debug, Release] + + runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 From 2679f786841e8f2a823e158960293d18110f404f Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Mon, 10 Jan 2022 00:10:02 -0500 Subject: [PATCH 22/39] Fix inconsistencies in SocketIO SocketIO explicitly declared err_code as static, but this is already implicity done due to err_code being in an anonymous namespace. The explicit use of static has been removed. SocketIO send and recv have new type signatures. Each function now returns a ssize_t to be in line with Linux's function signatures. Given that the functions originally returned an int. No functionality should change. SocketIO recv used to take in a const char* buffer and cast to a char*. Given that recv does modify the buffer, the buffer is now explicitly a char* and then will be either kept a char* (on Windows) or implicitly cast to a void* (on Linux). Given that void* and char* have the same size, this should not present any issues. SocketIO send and recv now use the flags provided. Previously, each function passed 0 as the only flag. Be aware that Grail is designed to be cross-platform and, as such, any flags used should be avaiable on Windows or Linux. --- src/csp/SocketIO.cc | 20 ++++++++++++-------- src/csp/SocketIO.hh | 8 ++++---- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/csp/SocketIO.cc b/src/csp/SocketIO.cc index 3960b82b..a49571fa 100644 --- a/src/csp/SocketIO.cc +++ b/src/csp/SocketIO.cc @@ -7,19 +7,23 @@ // TODO: Look into logging WSAGetLastError and strerror(errno) // Using the logging object in csp.hh? namespace SocketIO { -int send(socket_t sckt, const char *buf, int size, int flags) { - uint32_t bytesSent; - if ((bytesSent = ::send(sckt, (char *)buf, size, 0)) == err_code) { - if (errno != EBADF) throw Ex1(Errcode::SOCKET_SEND); +ssize_t send(socket_t sckt, const char *buf, int size, int flags) { + ssize_t bytesSent = 0; + if ((bytesSent = ::send(sckt, buf, size, flags)) == err_code) { + if (errno != EBADF) { + throw Ex1(Errcode::SOCKET_SEND); + } perror("Warning on send(): "); } return bytesSent; } -int recv(socket_t sckt, const char *buf, int size, int flags) { - uint32_t bytesRecv; - if ((bytesRecv = ::recv(sckt, (char *)buf, size, 0)) == err_code) { - if (errno != EBADF) throw Ex1(Errcode::SOCKET_SEND); +ssize_t recv(socket_t sckt, char *buf, int size, int flags) { + ssize_t bytesRecv = 0; + if ((bytesRecv = ::recv(sckt, buf, size, flags)) == err_code) { + if (errno != EBADF) { + throw Ex1(Errcode::SOCKET_SEND); + } perror("Warning on recv()"); } return bytesRecv; diff --git a/src/csp/SocketIO.hh b/src/csp/SocketIO.hh index 9415a2f1..70bb60df 100644 --- a/src/csp/SocketIO.hh +++ b/src/csp/SocketIO.hh @@ -28,12 +28,12 @@ using socket_t = decltype(socket(0, 0, 0)); namespace SocketIO { namespace { #ifdef __linux__ -constexpr static int err_code = -1; +constexpr int err_code = -1; #elif _WIN32 -constexpr static int err_code = SOCKET_ERROR; +constexpr int err_code = SOCKET_ERROR; #endif } // anonymous namespace for errors -int send(socket_t sckt, const char *buf, int size, int flags); -int recv(socket_t sckt, const char *buf, int size, int flags); +ssize_t send(socket_t sckt, const char *buf, int size, int flags); +ssize_t recv(socket_t sckt, char *buf, int size, int flags); }; // namespace SocketIO \ No newline at end of file From f29452d39fadf5d8875734c349accc31d2306697 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Mon, 10 Jan 2022 00:17:06 -0500 Subject: [PATCH 23/39] Clean up minor issues XDLRequest had an unnecessary import which was removed. The function buildData is also commented out, as it is the base case for a function which is also commented out. GLWinFonts had a few loops where the counter is guarenteed to never be negative, so int was replaced with uint32_t. Callbacks had a static void function that was never given a void type when it was declared. The implementation gave the correct type, but the declaration needed to be fixed. --- src/csp/XDLRequest.cc | 7 +++---- src/opengl/GLWinFonts.cc | 14 +++++++------- src/util/Callbacks.hh | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/csp/XDLRequest.cc b/src/csp/XDLRequest.cc index 038fcec2..d89fb9fd 100644 --- a/src/csp/XDLRequest.cc +++ b/src/csp/XDLRequest.cc @@ -6,7 +6,6 @@ #include #include -#include #include //#include "util/TypeAlias.hh" @@ -19,7 +18,7 @@ using namespace std; // base case -void buildData(Buffer& out, char meta[]) {} +// void buildData(Buffer& out, char meta[]) {} // template // void buildData(Buffer& out, Buffer& meta, T first, const Args&... args) { @@ -43,10 +42,10 @@ void buildData2(ArrayOfBytes* a, const T& arg) { } template -void buildData(DynArray a, const Args&... args) { +void buildData(DynArray data, const Args&... args) { ArrayOfBytes* bytes = new ArrayOfBytes(); (buildData2(bytes, args), ...); - a.add(bytes); + data.add(bytes); } #if 0 template diff --git a/src/opengl/GLWinFonts.cc b/src/opengl/GLWinFonts.cc index 032beb8f..0d5efb0a 100644 --- a/src/opengl/GLWinFonts.cc +++ b/src/opengl/GLWinFonts.cc @@ -88,7 +88,7 @@ Font* Font::getDefault() { // TODO: can be made a private method of font static uint32_t hashGlyph(const uint8_t glyphBuffer[], uint32_t len) { uint32_t hash = len; - for (int i = 0; i < len; i++) + for (uint32_t i = 0; i < len; i++) hash = ((hash << 17) | (hash >> 13)) ^ ((hash << 5) | (hash >> 27)) ^ glyphBuffer[i]; return hash; @@ -367,7 +367,7 @@ Font::Font(istream& fastfont) { uint32_t numGlyphs = glyphs.size(); fastfont.read((char*)&numGlyphs, sizeof(uint32_t)); glyphs.reserve(numGlyphs); - for (int i = 0; i < numGlyphs; i++) { + for (uint32_t i = 0; i < numGlyphs; i++) { Glyph g; fastfont.read((char*)&g, sizeof(Glyph)); glyphs.push_back(g); @@ -515,25 +515,25 @@ void FontFace::initAll() { maxFontSize, bitmap, sizeX, sizeY, currX, currY, rowSize); } } - for (int i = 1400; i < sizeY; i++) { + for (uint32_t i = 1400; i < sizeY; i++) { int r = i * sizeX; - for (int j = 0; j < sizeX / 4; j += 2) { + for (uint32_t j = 0; j < sizeX / 4; j += 2) { bitmap[r + j] = 255; bitmap[r + j + 1] = 0; } - for (int j = sizeX / 4; j < sizeX / 2; j += 4) { + for (uint32_t j = sizeX / 4; j < sizeX / 2; j += 4) { bitmap[r + j] = 255; bitmap[r + j + 1] = 255; bitmap[r + j + 2] = 255; bitmap[r + j + 3] = 255; } - for (int j = sizeX / 2; j < sizeX * 3 / 4; j += 8) { + for (uint32_t j = sizeX / 2; j < sizeX * 3 / 4; j += 8) { bitmap[r + j] = 255; bitmap[r + j + 1] = 0; bitmap[r + j + 2] = 0; bitmap[r + j + 3] = 0; } - for (int j = sizeX * 3 / 4; j < sizeX; j++) { + for (uint32_t j = sizeX * 3 / 4; j < sizeX; j++) { bitmap[r + j] = 255; } } diff --git a/src/util/Callbacks.hh b/src/util/Callbacks.hh index b4af2441..1506ff1b 100644 --- a/src/util/Callbacks.hh +++ b/src/util/Callbacks.hh @@ -80,7 +80,7 @@ class CallbackHandler { registerCallback(inp, quote(func), Security::SAFE, func, ptr); } - static doit(uint32_t input); + static void doit(uint32_t input); void bind2DOrtho(); void bind3D(); From 50ceb082d5106b307b452c0eba031619cc7f92dd Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Mon, 10 Jan 2022 00:21:59 -0500 Subject: [PATCH 24/39] Change clang-tidy readability option Currently, there are many places where an if-statement with only one line following it is used without providing any braces. This is primarily done out of convenience, however it also means many flags by clang-tidy for readability issues. We solved this with indentation, however if it ever becomes an issue we can always revert the setting so any if-statement without braces triggers a warning. --- .clang-tidy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.clang-tidy b/.clang-tidy index d8dbcac6..b51bcbd1 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -41,5 +41,7 @@ CheckOptions: value: 'false' - key: google-readability-function-size.StatementThreshold value: '800' + - key: readability-braces-around-statements.ShortStatementLines + value: '1' ... From 746a791cca6958e0fcd5130fbdfb95c5e7dc7810 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Mon, 10 Jan 2022 00:40:32 -0500 Subject: [PATCH 25/39] Clean up DynArray DynArray has several spots it could use uint32_t and was instead using int. This has been fixed. Adds in a comment asking for feedback on what operator new does. It seems to just return one of the parameters without doing anything. Converts DynArray::find(T&) to a const function, as contents of the array nor the key are ever modified. Adds comments that should be recognized by clang-tidy to remove any warnings about pointer arithmetic. This is a container implementation and some pointer arithmetic seems unavoidable. --- src/util/DynArray.hh | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/util/DynArray.hh b/src/util/DynArray.hh index 9a160a71..4f9c54b0 100644 --- a/src/util/DynArray.hh +++ b/src/util/DynArray.hh @@ -3,12 +3,20 @@ #include #include + +// The following disables clang-tidy from warning about pointer arithmetic +// Since this is a container implementation, it is unavoidable that pointer +// arithmetic is used +// NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) + template class DynArray { private: uint32_t capacity; uint32_t size_; T* data; + + // TODO: What is the point of this? We do nothing with either parameter. void* operator new(size_t sz, T* place) { return place; } // TODO: Objects containing pointers may be unable to move // DynArray of Strings seems to break after 2 Strings are added @@ -25,11 +33,11 @@ class DynArray { DynArray(uint32_t capacity) : capacity(capacity), size_(0), data((T*)malloc(capacity * sizeof(T))) {} ~DynArray() { - for (int i = 0; i < size_; i++) data[i].~T(); + for (uint32_t i = 0; i < size_; i++) data[i].~T(); free((void*)data); } void clear() { - for (int i = 0; i < size_; i++) data[i].~T(); + for (uint32_t i = 0; i < size_; i++) data[i].~T(); size_ = 0; } DynArray(const DynArray& orig) @@ -56,7 +64,7 @@ class DynArray { uint32_t size() const { return size_; } const T& last() const { return data[size_ - 1]; } friend std::ostream& operator<<(std::ostream& s, const DynArray& d) { - for (int i = 0; i < d.size_; i++) s << d.data[i] << ' '; + for (uint32_t i = 0; i < d.size_; i++) s << d.data[i] << ' '; return s; } @@ -68,8 +76,8 @@ class DynArray { void push_back(T&& elem) { emplace_back(std::move(elem)); } - constexpr bool find(T& t) { - for (T& item : data) { + constexpr bool find(T& t) const { + for (const T& item : data) { if (item == t) { return true; } @@ -84,3 +92,5 @@ class DynArray { T(std::forward(args)...); } }; + +// NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) \ No newline at end of file From dccf88310a4fa1668dcfe6df364a363ff7ad783c Mon Sep 17 00:00:00 2001 From: Alice Huston Date: Mon, 17 Jan 2022 23:56:40 -0500 Subject: [PATCH 26/39] Synchronizing older Windows commits There are several modifications that were made for compatbility reasons, however these changes are all several months old by now. These changes are being added in all at once. Fixes will be made as the CI/CD system reports errors. AxisWidget: Include cstring to provide strlen MultiText/MultiText2: Remove functions that have "unsigned long long" as a parameter. Using functions with byte-specific types end up being better for cross-platform compatbility. Benchmark: Remove sys/times include. MSYS does not provide this and we do not need it anymore. DynArray: Add DynArray::removeAt(uint32_t index) -> T. This removes a particular element from the array and returns it. Warning: This currently achieves this by copying the object to a temp variable, sliding all other elements forward by one (without moving?), and then returning the copy. For some reason, this invokes the original object's destructor if its the last element in the array? I believe this needs to be rewritten a bit before it is ready for use. testDynArray: This runs through a couple test cases for DynArrays (adding and removing integers, strings, and Tabs). This was originally done as a way to test how adding and removing tabs worked out, but could be useful in the future. This should eventually turn into a compile-time test using static_assert, as DynArray should be able to be made into an entirely constexpr class. testfmt: Removes constexpr specifier on functions that call sprintf. constexpr cannot be used on non-constexpr functions and sprintf is not constexpr. --- src/opengl/AxisWidget.cc | 4 ++- src/opengl/MultiText.hh | 5 ---- src/opengl/MultiText2.hh | 38 +++++++++++++------------- src/util/Benchmark.hh | 1 - src/util/DynArray.hh | 11 ++++++++ test/CMakeLists.txt | 2 ++ test/testDynArray.cc | 59 ++++++++++++++++++++++++++++++++++++++++ test/testfmt.cc | 20 ++++---------- 8 files changed, 100 insertions(+), 40 deletions(-) create mode 100644 test/testDynArray.cc diff --git a/src/opengl/AxisWidget.cc b/src/opengl/AxisWidget.cc index 9ef1a4cc..7b77a583 100644 --- a/src/opengl/AxisWidget.cc +++ b/src/opengl/AxisWidget.cc @@ -1,5 +1,7 @@ #include "opengl/AxisWidget.hh" +#include + using namespace std; AxisWidget::AxisWidget(StyledMultiShape2D* m, MultiText* t, double x, double y, @@ -16,7 +18,7 @@ AxisWidget::AxisWidget(StyledMultiShape2D* m, MultiText* t, double x, double y, showTicks(showTicks), isVert(isVert), axisTitle(axisTitle), - tickFormat({.width = tickFormatWidth, .precision = tickFormatPrecision}), + tickFormat({.width = tickFormatWidth, .precision = tickFormatPrecision}), bottomOffset(bottomOffset) {} AxisWidget::~AxisWidget() {} diff --git a/src/opengl/MultiText.hh b/src/opengl/MultiText.hh index 4dda1359..cba01544 100644 --- a/src/opengl/MultiText.hh +++ b/src/opengl/MultiText.hh @@ -61,7 +61,6 @@ class MultiText : public Shape { uint32_t numDigits(uint32_t) { return 10; } uint32_t numDigits(uint16_t) { return 5; } uint32_t numDigits(uint8_t) { return 3; } - uint32_t numDigits(unsigned long long x) { return numDigits(uint64_t(x)); } uint32_t numDigits(int) { return 10; } uint32_t numDigits(float) { return 10; } uint32_t numDigits(double) { return 21; } @@ -69,10 +68,6 @@ class MultiText : public Shape { uint32_t biggestpow10(uint32_t) { return 1000000000U; } uint32_t biggestpow10(uint16_t) { return 10000U; } uint32_t biggestpow10(uint8_t) { return 10000U; } - uint64_t biggestpow10(unsigned long long x) { - return biggestpow10(uint64_t(x)); - } - uint64_t unsignit(unsigned long long int v) { return uint64_t(v); } uint64_t unsignit(int64_t v) { return uint64_t(v); } uint32_t unsignit(int32_t v) { return uint32_t(v); } uint16_t unsignit(int16_t v) { return uint16_t(v); } diff --git a/src/opengl/MultiText2.hh b/src/opengl/MultiText2.hh index fc037569..5f83b9ae 100644 --- a/src/opengl/MultiText2.hh +++ b/src/opengl/MultiText2.hh @@ -1,8 +1,9 @@ #pragma once +#include + #include "opengl/GLWin.hh" #include "opengl/GLWinFonts.hh" #include "opengl/Shape.hh" -#include class Style; class MultiText2 : public Shape { @@ -23,14 +24,15 @@ class MultiText2 : public Shape { vert.push_back(v); } float velX = 1, velY = 1; - void internalAdd(float x, float y, const Font* f, const char s[], uint32_t len); + void internalAdd(float x, float y, const Font* f, const char s[], + uint32_t len); uint32_t formatLead0(char destBuf[], uint8_t printVal) { uint32_t d0 = printVal / 100; destBuf[0] = '0' + d0; uint32_t rest = printVal - d0 * 100; uint32_t d1 = rest / 10; destBuf[1] = '0' + d1; - uint32_t d2 = rest - d1*10; + uint32_t d2 = rest - d1 * 10; destBuf[2] = '0' + d2; return 3; } @@ -52,14 +54,13 @@ class MultiText2 : public Shape { printVal %= 100; uint32_t d0 = printVal / 10; destBuf[3] = '0' + d0; - destBuf[4] = '0' + (printVal - d0*10); + destBuf[4] = '0' + (printVal - d0 * 10); return 5; } uint32_t numDigits(uint64_t) { return 18; } uint32_t numDigits(uint32_t) { return 10; } uint32_t numDigits(uint16_t) { return 5; } uint32_t numDigits(uint8_t) { return 3; } - uint32_t numDigits(unsigned long long x) { return numDigits(uint64_t(x)); } uint32_t numDigits(int) { return 10; } uint32_t numDigits(float) { return 10; } uint32_t numDigits(double) { return 21; } @@ -67,8 +68,6 @@ class MultiText2 : public Shape { uint32_t biggestpow10(uint32_t) { return 1000000000U; } uint32_t biggestpow10(uint16_t) { return 10000U; } uint32_t biggestpow10(uint8_t) { return 10000U; } - uint64_t biggestpow10(unsigned long long x) { return biggestpow10(uint64_t(x)); } - uint64_t unsignit(unsigned long long int v) { return uint64_t(v); } uint64_t unsignit(int64_t v) { return uint64_t(v); } uint32_t unsignit(int32_t v) { return uint32_t(v); } uint16_t unsignit(int16_t v) { return uint16_t(v); } @@ -78,7 +77,7 @@ class MultiText2 : public Shape { uint16_t unsignit(uint16_t v) { return v; } uint8_t unsignit(uint8_t v) { return v; } - template + template uint32_t format(char destBuf[], T printVal) { uint32_t len = numDigits(printVal); T leadingDigit = biggestpow10(printVal); @@ -94,11 +93,10 @@ class MultiText2 : public Shape { } destBuf[len] = '0' + printVal; return len; - } + } uint32_t format(char destBuf[], int printVal) { - if (printVal < 0) - destBuf[0] = '-'; - return format(destBuf+1, uint32_t(printVal)); + if (printVal < 0) destBuf[0] = '-'; + return format(destBuf + 1, uint32_t(printVal)); } uint32_t format(char destBuf[], float printVal) { return sprintf(destBuf, "%f", printVal); @@ -113,21 +111,22 @@ class MultiText2 : public Shape { MultiText2(Canvas* c, const Style* style, uint32_t size); MultiText2(Canvas* c, const Style* style, float angle, float x, float y); MultiText2(Canvas* c, const Style* style, uint32_t size, float angle, float x, - float y); + float y); ~MultiText2(); - template + template void addx(float x, float y, const Font* f, T printVal) { char buf[32]; uint32_t len = format(buf, printVal); internalAdd(x, y, f, buf, len); } - template + template void addHex0(float x, float y, const Font* f, T printVal) { - constexpr uint32_t len = sizeof(T)*2; + constexpr uint32_t len = sizeof(T) * 2; char buf[len]; - auto v = unsignit(printVal); // use unsigned value so sign doesn't mess up as we rotate bits + auto v = unsignit(printVal); // use unsigned value so sign doesn't mess up + // as we rotate bits for (uint32_t i = 0; i < len; i++) { - v = (v << 4) | (v >> (len*4 - 4)); // rotate 4 bits left + v = (v << 4) | (v >> (len * 4 - 4)); // rotate 4 bits left uint32_t hexDig = v & 0xF; buf[i] = (hexDig > 9 ? 'A' - 10 : '0') + hexDig; } @@ -137,7 +136,8 @@ class MultiText2 : public Shape { // a 16-bit unicode character like Java void addChar(float x, float y, const Font* f, const uint16_t c); void add(float x, float y, const char s[], uint32_t len); - void add(float x, float y, float ang, const Font* f, const char s[], uint32_t len); + void add(float x, float y, float ang, const Font* f, const char s[], + uint32_t len); void add(float x, float y, const Font* f, const std::string& s); void add(float x, float y, const Font* f, const char s[], uint32_t len); void add(float x, float y, uint32_t v); diff --git a/src/util/Benchmark.hh b/src/util/Benchmark.hh index 5bbf0ca8..25734048 100644 --- a/src/util/Benchmark.hh +++ b/src/util/Benchmark.hh @@ -1,6 +1,5 @@ #pragma once #include -#include #include #include diff --git a/src/util/DynArray.hh b/src/util/DynArray.hh index a4c49dbd..3986dff7 100644 --- a/src/util/DynArray.hh +++ b/src/util/DynArray.hh @@ -59,4 +59,15 @@ class DynArray { for (int i = 0; i < d.size_; i++) s << d.data[i] << ' '; return s; } + + constexpr T removeAt(uint32_t index) { + T temp = data[index]; + + for (int i = index; i < size_ - 1; ++i) { + data[i] = data[i + 1]; + } + if (index == size_ - 1) data[index].~T(); + --size_; + return temp; + } }; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 52eae14c..73b746bf 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -34,6 +34,8 @@ add_grail_executable(SRC testfmt.cc LIBS grail) #add_grail_executable(BINNAME testSolar SRC DrawNASAEphemerisSolarSystem2d.cc LIBS grail) add_grail_executable(SRC loadESRIShapefile.cc LIBS grail) add_grail_executable(SRC testXDLButton.cc LIBS grail) +add_grail_executable(SRC testDynArray.cc LIBS grail) + if(${MPV_FOUND}) add_grail_executable(SRC testSingleAudio.cc LIBS grail) diff --git a/test/testDynArray.cc b/test/testDynArray.cc new file mode 100644 index 00000000..7f1e1b6b --- /dev/null +++ b/test/testDynArray.cc @@ -0,0 +1,59 @@ +#include "fmt/core.h" +#include "opengl/GrailGUI.hh" +#include "util/DynArray.hh" + +using namespace std; + +template +constexpr void printarr(string msg, uint32_t size, DynArray arr) { + fmt::print("{}", msg); + for (int i = 0; i < size; ++i) { + cout << arr[i] << ","; + } + fmt::print("\n"); +} + +template +constexpr void printarr(string msg, uint32_t size, DynArray arr) { + fmt::print("{}", msg); + for (int i = 0; i < size; ++i) { + fmt::print("{},", arr[i]); + } + fmt::print("\n"); +} + +int main() { + DynArray arr(10); + for (int i = 0; i < 10; i++) { + arr.add(i); + } + + printarr("new array of uint32_t: \n", 10, arr); + + int removedInt = arr.removeAt(5); + fmt::print("Removed value {} at index 5\n", removedInt); + + printarr("array of uint32_t after deletion: \n", 9, arr); + + GLWin w(1024, 800, 0xFFFFFFFF, 0x000000FF, "gw"); + DynArray tabs(4); + for (int i = 0; i < 4; i++) { + tabs.add(new Tab(&w)); + } + + printarr("new array of tabs: \n", 4, tabs); + + Tab* removedTab = tabs.removeAt(2); + cout << "Removed value " << removedTab << " at index 2\n"; + + printarr("array of tabs after deletion: \n", 3, tabs); + + DynArray strs(4); + strs.add("a"); + strs.add("B"); + strs.add("c"); + printarr("new array of strings: \n", 3, strs); + string removedString = strs.removeAt(1); + fmt::print("Removed value {} at index 1\n", removedString); + printarr("array of tabs after deletion: \n", 2, strs); +} \ No newline at end of file diff --git a/test/testfmt.cc b/test/testfmt.cc index fcb2aa9b..3e83ecd8 100644 --- a/test/testfmt.cc +++ b/test/testfmt.cc @@ -18,27 +18,19 @@ constexpr uint32_t test_format(C destBuf, T fmt_val) { return destBuf.size(); // size of the formatted data } -constexpr uint32_t formatspf(char data[33], float f) { - return sprintf(data, "%f", f); -} +uint32_t formatspf(char data[33], float f) { return sprintf(data, "%f", f); } -constexpr int32_t formatspf(char data[33], double f) { - return sprintf(data, "%lf", f); -} +int32_t formatspf(char data[33], double f) { return sprintf(data, "%lf", f); } -constexpr uint32_t formatspf(char data[33], int f) { - return sprintf(data, "%d", f); -} +uint32_t formatspf(char data[33], int f) { return sprintf(data, "%d", f); } -constexpr uint32_t formatspf(char data[33], uint32_t f) { - return sprintf(data, "%u", f); -} +uint32_t formatspf(char data[33], uint32_t f) { return sprintf(data, "%u", f); } -constexpr uint32_t formatspf(char data[33], uint64_t f) { +uint32_t formatspf(char data[33], uint64_t f) { return sprintf(data, "%lu", f); } -constexpr uint32_t formatspf(char data[33], const char* f) { +uint32_t formatspf(char data[33], const char* f) { return sprintf(data, "%s", f); } From 7961c23ea4eeb613445275833afbe9fb8e063585 Mon Sep 17 00:00:00 2001 From: Alice Huston Date: Tue, 18 Jan 2022 00:20:01 -0500 Subject: [PATCH 27/39] Add testDynArray and testfmt I think these changes should have already been added in a previous commit. Hopefully there is nothing funky going on here, but I'll investigate the commit history after the merge is completed. --- test/testDynArray.cc | 116 ++++---- test/testfmt.cc | 692 +++++++++++++++++++++---------------------- 2 files changed, 404 insertions(+), 404 deletions(-) diff --git a/test/testDynArray.cc b/test/testDynArray.cc index 7f1e1b6b..5db6131e 100644 --- a/test/testDynArray.cc +++ b/test/testDynArray.cc @@ -1,59 +1,59 @@ -#include "fmt/core.h" -#include "opengl/GrailGUI.hh" -#include "util/DynArray.hh" - -using namespace std; - -template -constexpr void printarr(string msg, uint32_t size, DynArray arr) { - fmt::print("{}", msg); - for (int i = 0; i < size; ++i) { - cout << arr[i] << ","; - } - fmt::print("\n"); -} - -template -constexpr void printarr(string msg, uint32_t size, DynArray arr) { - fmt::print("{}", msg); - for (int i = 0; i < size; ++i) { - fmt::print("{},", arr[i]); - } - fmt::print("\n"); -} - -int main() { - DynArray arr(10); - for (int i = 0; i < 10; i++) { - arr.add(i); - } - - printarr("new array of uint32_t: \n", 10, arr); - - int removedInt = arr.removeAt(5); - fmt::print("Removed value {} at index 5\n", removedInt); - - printarr("array of uint32_t after deletion: \n", 9, arr); - - GLWin w(1024, 800, 0xFFFFFFFF, 0x000000FF, "gw"); - DynArray tabs(4); - for (int i = 0; i < 4; i++) { - tabs.add(new Tab(&w)); - } - - printarr("new array of tabs: \n", 4, tabs); - - Tab* removedTab = tabs.removeAt(2); - cout << "Removed value " << removedTab << " at index 2\n"; - - printarr("array of tabs after deletion: \n", 3, tabs); - - DynArray strs(4); - strs.add("a"); - strs.add("B"); - strs.add("c"); - printarr("new array of strings: \n", 3, strs); - string removedString = strs.removeAt(1); - fmt::print("Removed value {} at index 1\n", removedString); - printarr("array of tabs after deletion: \n", 2, strs); +#include "fmt/core.h" +#include "opengl/GrailGUI.hh" +#include "util/DynArray.hh" + +using namespace std; + +template +constexpr void printarr(string msg, uint32_t size, DynArray arr) { + fmt::print("{}", msg); + for (int i = 0; i < size; ++i) { + cout << arr[i] << ","; + } + fmt::print("\n"); +} + +template +constexpr void printarr(string msg, uint32_t size, DynArray arr) { + fmt::print("{}", msg); + for (int i = 0; i < size; ++i) { + fmt::print("{},", arr[i]); + } + fmt::print("\n"); +} + +int main() { + DynArray arr(10); + for (int i = 0; i < 10; i++) { + arr.add(i); + } + + printarr("new array of uint32_t: \n", 10, arr); + + int removedInt = arr.removeAt(5); + fmt::print("Removed value {} at index 5\n", removedInt); + + printarr("array of uint32_t after deletion: \n", 9, arr); + + GLWin w(1024, 800, 0xFFFFFFFF, 0x000000FF, "gw"); + DynArray tabs(4); + for (int i = 0; i < 4; i++) { + tabs.add(new Tab(&w)); + } + + printarr("new array of tabs: \n", 4, tabs); + + Tab* removedTab = tabs.removeAt(2); + cout << "Removed value " << removedTab << " at index 2\n"; + + printarr("array of tabs after deletion: \n", 3, tabs); + + DynArray strs(4); + strs.add("a"); + strs.add("B"); + strs.add("c"); + printarr("new array of strings: \n", 3, strs); + string removedString = strs.removeAt(1); + fmt::print("Removed value {} at index 1\n", removedString); + printarr("array of tabs after deletion: \n", 2, strs); } \ No newline at end of file diff --git a/test/testfmt.cc b/test/testfmt.cc index 3e83ecd8..5db763b9 100644 --- a/test/testfmt.cc +++ b/test/testfmt.cc @@ -1,346 +1,346 @@ -#include -#include -#include - -#include "digits.h" -#include "fmt/color.h" -#include "fmt/compile.h" -#include "fmt/core.h" -#include "fmt/format.h" -#include "util/Benchmark.hh" - -using namespace std; -using namespace fmt; - -template -constexpr uint32_t test_format(C destBuf, T fmt_val) { - format_to(back_inserter(destBuf), FMT_COMPILE("{}"), fmt_val); - return destBuf.size(); // size of the formatted data -} - -uint32_t formatspf(char data[33], float f) { return sprintf(data, "%f", f); } - -int32_t formatspf(char data[33], double f) { return sprintf(data, "%lf", f); } - -uint32_t formatspf(char data[33], int f) { return sprintf(data, "%d", f); } - -uint32_t formatspf(char data[33], uint32_t f) { return sprintf(data, "%u", f); } - -uint32_t formatspf(char data[33], uint64_t f) { - return sprintf(data, "%lu", f); -} - -uint32_t formatspf(char data[33], const char* f) { - return sprintf(data, "%s", f); -} - -template -constexpr void test_sprintf(char dest[33], T data) { - formatspf(dest, data); -} - -// R to L, 1 at a time -template -constexpr uint32_t _formatgrl(char destBuf[33], T printVal) { - uint32_t len; - int i; - for (i = 31; i >= 0; i--) { - T temp = printVal / 10; - uint32_t digit = printVal - temp * 10; - destBuf[i] = '0' + digit; - if (printVal == 0) break; - printVal = temp; - } - return 31 - i; -} - -// R to L, 2 at a time -template -constexpr uint32_t _formatgrl2(char destBuf[33], T printVal) { - uint32_t len; - int i; - for (i = 30; printVal >= 100; i -= 2) { - T temp = printVal / 100; - uint32_t digit2 = printVal - temp * 100; - *(uint16_t*)&destBuf[i] = ((uint16_t*)dig2)[digit2]; - printVal = temp; - } - if (printVal >= 10) { - *(uint16_t*)&destBuf[i] = ((uint16_t*)dig2)[printVal]; - } else if (printVal > 0) { - destBuf[++i] = '0' + printVal; - } - return 32 - i; -} - -// R to L, 4 at a time, in pairs -template -constexpr uint32_t _formatgrl3(char destBuf[33], T printVal) { - uint32_t len; - int i; - for (i = 28; printVal >= 10000; i -= 4) { - T temp = printVal / 10000; - uint32_t digit4 = printVal - temp * 10000; - uint32_t digit2 = digit4 / 100; - *(uint16_t*)&destBuf[i + 2] = ((uint16_t*)dig2)[digit4 - digit2 * 100]; - *(uint16_t*)&destBuf[i] = ((uint16_t*)dig2)[digit2]; - printVal = temp; - } - if (printVal >= 100) { - if (printVal >= 1000) { - uint32_t digit2 = printVal / 100; - *(uint16_t*)&destBuf[i] = ((uint16_t*)dig2)[digit2]; - *(uint16_t*)&destBuf[i + 2] = ((uint16_t*)dig2)[printVal - digit2 * 100]; - } else { - uint32_t digit = printVal / 100; - *(uint16_t*)&destBuf[i + 2] = ((uint16_t*)dig2)[printVal - digit * 100]; - destBuf[i += 1] = '0' + digit; - } - } else { - if (printVal >= 10) { - *(uint16_t*)&destBuf[i += 2] = ((uint16_t*)dig2)[printVal]; - } else if (printVal > 0) { - destBuf[i += 3] = '0' + printVal; - } - } - return 32 - i; -} - -// R to L, 4 at a time -template -constexpr uint32_t _formatgrl4(char destBuf[33], T printVal) { - uint32_t len; - int i; - for (i = 28; printVal >= 10000; i -= 4) { - T temp = printVal / 10000; - uint32_t digit4 = printVal - temp * 10000; - *(uint32_t*)&destBuf[i] = ((uint32_t*)dig4)[digit4]; - printVal = temp; - } - if (printVal >= 100) { - if (printVal >= 1000) { - *(uint32_t*)&destBuf[i] = ((uint32_t*)dig4)[printVal]; - } else { - *(uint16_t*)&destBuf[i + 2] = ((uint32_t*)dig4)[printVal]; - destBuf[i += 1] = (dig4)[(printVal << 2) + 2]; - } - } else { - if (printVal >= 10) { - *(uint16_t*)&destBuf[i += 2] = ((uint16_t*)dig2)[printVal]; - } else if (printVal > 0) { - destBuf[i += 3] = '0' + printVal; - } - } - return 32 - i; -} - -constexpr uint32_t _formatgrl4signed(char destBuf[33], int32_t v) { - if (v < 0) { - if (v == INT32_MIN) { - // 24 ... 28 29 30 31 "-21 47483648" - // 16 17 18 .. 21 22 23 - constexpr uint64_t INT32_MIN_LAST8DIGITS = - '8' | ('4' << 8) | ('6' << 16) | ('3' << 24) | (uint64_t('8') << 32) | - (uint64_t('4') << 40) | (uint64_t('7') << 48) | (uint64_t('4') << 56); - constexpr uint32_t INT32_MIN_FIRST_DIGITS = - ('1' | ('2' << 8) | ('-' << 16)) << 8; - *(uint64_t*)(destBuf + 24) = INT32_MIN_LAST8DIGITS; - *(uint32_t*)(destBuf + 20) = INT32_MIN_FIRST_DIGITS; - return 21; - } - uint32_t size = _formatgrl4(destBuf, (uint32_t)-v); - destBuf[size - 1] = '-'; - return size - 1; - } - return _formatgrl4(destBuf, v); -} - -constexpr uint32_t _formatgrl4signed(char destBuf[33], int64_t v) { - if (v < 0) { - if (v == INT64_MIN) { - // 24 ... 28 29 30 31 "-922 33720368 54775808" - // 16 17 18 .. 21 22 23 - constexpr uint64_t INT64_MIN_LAST8DIGITS = - '8' | ('0' << 8) | ('8' << 16) | ('5' << 24) | (uint64_t('7') << 32) | - (uint64_t('7') << 40) | (uint64_t('4') << 48) | (uint64_t('5') << 56); - constexpr uint64_t INT64_MIN_MID8DIGITS = - '8' | ('6' << 8) | ('3' << 16) | ('0' << 24) | (uint64_t('2') << 32) | - (uint64_t('7') << 40) | (uint64_t('3') << 48) | (uint64_t('3') << 56); - constexpr uint32_t INT64_MIN_FIRST_DIGITS = - '2' | ('2' << 8) | ('9' << 16) | ('-' << 24); - *(uint64_t*)(destBuf + 24) = INT64_MIN_LAST8DIGITS; - *(uint64_t*)(destBuf + 16) = INT64_MIN_MID8DIGITS; - *(uint32_t*)(destBuf + 12) = INT64_MIN_FIRST_DIGITS; - return 12; - } - uint32_t size = _formatgrl4(destBuf, (uint32_t)-v); - destBuf[size - 1] = '-'; - return size - 1; - } - return _formatgrl4(destBuf, v); -} - -constexpr uint32_t _formatgrl(char destBuf[33], int printVal) { - if (printVal < 0) { - // TODO: this will not work for -intmax?!? - uint32_t len = _formatgrl(destBuf, uint32_t(-printVal)); - destBuf[32 - len] = '-'; - return len + 1; - } else { - return _formatgrl(destBuf, uint32_t(printVal)); - } -} - -constexpr inline char DECIMAL_POINT = '.'; -constexpr void _insertdec(char destBuf[33], uint32_t& i, uint32_t decimalLoc, - uint32_t digit4) { - // load the right 4 digits from the table 0000 to 9999 - uint32_t digits = ((uint32_t*)dig4)[digit4]; - if (decimalLoc >= 4) { - *(uint32_t*)&destBuf[i] = digits; - } else { - switch (decimalLoc) { - case 0: - destBuf[i + 3] = DECIMAL_POINT; - *(uint32_t*)&destBuf[--i] = digits; - break; - case 1: - destBuf[i + 3] = digits; - destBuf[i + 2] = DECIMAL_POINT; - i -= 2; - digits <<= 8; - // now there are only 3 bytes in the word, low byte is 0 - *(uint32_t*)&destBuf[i] = digits; - // just wrote 4 bytes, but there were only 3 - // still, it's faster because writing 16 bits then 8 bits as two - // separate memory writes and 2 separate instructions to do it. - i++; - break; - case 2: - // i-1 i i+1 i+2 i+3 - // d d . d d - *(uint16_t*)&destBuf[i + 2] = digits; - destBuf[i + 1] = DECIMAL_POINT; - i--; - digits <<= 16; - *(uint16_t*)&destBuf[i] = digits; - break; - case 3: - // i-1 i i+1 i+2 i+3 - // d . d d d - // write 4 bytes, one will get thrown out - // rotate left by 8 bits so the first 3 numbers are in low 3 bytes first - // time - // digits = (digits << 8) | - // (digits >> 24); // 11111111222222223333333300000000 - *(uint32_t*)&destBuf[i] = digits; - destBuf[i] = DECIMAL_POINT; // overwrite high byte with decimal point - i--; - // write out remaining 1 byte in the word - destBuf[i] = digits; - break; - } - } -} - -// R to L, 4 at a time -constexpr uint32_t _formatgrlfloat(char destBuf[33], uint64_t printVal, - uint32_t precision, uint32_t decimalLoc) { - uint32_t len; - uint32_t i; - for (i = 28; precision >= 4; i -= 4, precision -= 4, decimalLoc -= 4) { - uint64_t temp = printVal / 10000; - // get the 4 digits from memory - uint32_t digit4 = printVal - temp * 10000; - printVal = temp; - _insertdec(destBuf, i, decimalLoc, digit4); - } - _insertdec(destBuf, i, decimalLoc, printVal); - i += - (printVal >= 100 ? (printVal >= 1000 ? 0 : 1) : (printVal >= 10 ? 2 : 3)); - - return i; -} - -template -constexpr uint32_t _formatgrl5(char destBuf[33], T data) { - int ex; - constexpr int precision = 6; - // 1.234567 - // 123.4567 - // .1234567e+23 - // .9923456 - // .9999999 - - // 1234567. - // 1234.567 - // 12.34567 - frexp(data, &ex); - constexpr double invLog2_10 = 1 / log2(10.0); - double powOf10 = ceil(ex * invLog2_10); - T scale = pow(10, powOf10 - precision); - T scaled = data / scale; - // cout << "Scaled: " << scaled << '\n'; // .123456789 or 123456789 - uint64_t printVal = uint64_t(scaled); - // cout << "Integer value" << printVal << '\n'; - // 123.450 - // 0.345 - uint32_t decimalLoc = precision - uint32_t(powOf10); - return _formatgrlfloat(destBuf, printVal, precision, decimalLoc); -} - -template -constexpr void testboth(T data) { - print(fg(color::steel_blue) | emphasis::bold, "Currently processing: {}\n", - data); - char dest[33]; - vector out(33); - constexpr uint64_t n = 1000000; - CBenchmark::benchmark("fmtlib format", n, - bind(test_format, T>, out, data)); - CBenchmark::benchmark("sprintf format", n, bind(test_sprintf, dest, data)); - CBenchmark::benchmark("Grail float", n, bind(_formatgrl5, dest, data)); - print("{}\n", data); -} - -template -constexpr void testAll(T data) { - print(fg(color::steel_blue) | emphasis::bold, "Currently processing: {}\n", - data); - char dest[33]; - vector out(33); - constexpr uint64_t n = 1000000; - - CBenchmark::benchmark("fmtlib format", n, - bind(test_format, T>, out, data)); - CBenchmark::benchmark("sprintf format", n, bind(test_sprintf, dest, data)); - CBenchmark::benchmark("grail format RtoL 1 char", n, - bind(_formatgrl, dest, data)); - CBenchmark::benchmark("grail format RtoL 2 char", n, - bind(_formatgrl2, dest, data)); - CBenchmark::benchmark("grail format RtoL 4 char pairs", n, - bind(_formatgrl3, dest, data)); - CBenchmark::benchmark("grail format RtoL 4 char", n, - bind(_formatgrl4, dest, data)); - // Benchmark::benchmark("grail format RtoL 4char, sys benchmark", n, - // bind(_formatgrl4, dest, data)); - print("{}\n", data); -} - -int main() { - testboth(1.0f); - testboth(135567.362626); - - testAll(11); - testAll((uint32_t)-134135); - testAll(UINT64_MAX); - - char dest[33]; - // s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm - // 10000000 - dest[32] = '\0'; - uint8_t size = _formatgrl5(dest, 12323452345.45); - cout << dest + size << '\n'; - testboth(123.45); - // testboth("hello test"); -} +#include +#include +#include + +#include "digits.h" +#include "fmt/color.h" +#include "fmt/compile.h" +#include "fmt/core.h" +#include "fmt/format.h" +#include "util/Benchmark.hh" + +using namespace std; +using namespace fmt; + +template +constexpr uint32_t test_format(C destBuf, T fmt_val) { + format_to(back_inserter(destBuf), FMT_COMPILE("{}"), fmt_val); + return destBuf.size(); // size of the formatted data +} + +uint32_t formatspf(char data[33], float f) { return sprintf(data, "%f", f); } + +int32_t formatspf(char data[33], double f) { return sprintf(data, "%lf", f); } + +uint32_t formatspf(char data[33], int f) { return sprintf(data, "%d", f); } + +uint32_t formatspf(char data[33], uint32_t f) { return sprintf(data, "%u", f); } + +uint32_t formatspf(char data[33], uint64_t f) { + return sprintf(data, "%lu", f); +} + +uint32_t formatspf(char data[33], const char* f) { + return sprintf(data, "%s", f); +} + +template +constexpr void test_sprintf(char dest[33], T data) { + formatspf(dest, data); +} + +// R to L, 1 at a time +template +constexpr uint32_t _formatgrl(char destBuf[33], T printVal) { + uint32_t len; + int i; + for (i = 31; i >= 0; i--) { + T temp = printVal / 10; + uint32_t digit = printVal - temp * 10; + destBuf[i] = '0' + digit; + if (printVal == 0) break; + printVal = temp; + } + return 31 - i; +} + +// R to L, 2 at a time +template +constexpr uint32_t _formatgrl2(char destBuf[33], T printVal) { + uint32_t len; + int i; + for (i = 30; printVal >= 100; i -= 2) { + T temp = printVal / 100; + uint32_t digit2 = printVal - temp * 100; + *(uint16_t*)&destBuf[i] = ((uint16_t*)dig2)[digit2]; + printVal = temp; + } + if (printVal >= 10) { + *(uint16_t*)&destBuf[i] = ((uint16_t*)dig2)[printVal]; + } else if (printVal > 0) { + destBuf[++i] = '0' + printVal; + } + return 32 - i; +} + +// R to L, 4 at a time, in pairs +template +constexpr uint32_t _formatgrl3(char destBuf[33], T printVal) { + uint32_t len; + int i; + for (i = 28; printVal >= 10000; i -= 4) { + T temp = printVal / 10000; + uint32_t digit4 = printVal - temp * 10000; + uint32_t digit2 = digit4 / 100; + *(uint16_t*)&destBuf[i + 2] = ((uint16_t*)dig2)[digit4 - digit2 * 100]; + *(uint16_t*)&destBuf[i] = ((uint16_t*)dig2)[digit2]; + printVal = temp; + } + if (printVal >= 100) { + if (printVal >= 1000) { + uint32_t digit2 = printVal / 100; + *(uint16_t*)&destBuf[i] = ((uint16_t*)dig2)[digit2]; + *(uint16_t*)&destBuf[i + 2] = ((uint16_t*)dig2)[printVal - digit2 * 100]; + } else { + uint32_t digit = printVal / 100; + *(uint16_t*)&destBuf[i + 2] = ((uint16_t*)dig2)[printVal - digit * 100]; + destBuf[i += 1] = '0' + digit; + } + } else { + if (printVal >= 10) { + *(uint16_t*)&destBuf[i += 2] = ((uint16_t*)dig2)[printVal]; + } else if (printVal > 0) { + destBuf[i += 3] = '0' + printVal; + } + } + return 32 - i; +} + +// R to L, 4 at a time +template +constexpr uint32_t _formatgrl4(char destBuf[33], T printVal) { + uint32_t len; + int i; + for (i = 28; printVal >= 10000; i -= 4) { + T temp = printVal / 10000; + uint32_t digit4 = printVal - temp * 10000; + *(uint32_t*)&destBuf[i] = ((uint32_t*)dig4)[digit4]; + printVal = temp; + } + if (printVal >= 100) { + if (printVal >= 1000) { + *(uint32_t*)&destBuf[i] = ((uint32_t*)dig4)[printVal]; + } else { + *(uint16_t*)&destBuf[i + 2] = ((uint32_t*)dig4)[printVal]; + destBuf[i += 1] = (dig4)[(printVal << 2) + 2]; + } + } else { + if (printVal >= 10) { + *(uint16_t*)&destBuf[i += 2] = ((uint16_t*)dig2)[printVal]; + } else if (printVal > 0) { + destBuf[i += 3] = '0' + printVal; + } + } + return 32 - i; +} + +constexpr uint32_t _formatgrl4signed(char destBuf[33], int32_t v) { + if (v < 0) { + if (v == INT32_MIN) { + // 24 ... 28 29 30 31 "-21 47483648" + // 16 17 18 .. 21 22 23 + constexpr uint64_t INT32_MIN_LAST8DIGITS = + '8' | ('4' << 8) | ('6' << 16) | ('3' << 24) | (uint64_t('8') << 32) | + (uint64_t('4') << 40) | (uint64_t('7') << 48) | (uint64_t('4') << 56); + constexpr uint32_t INT32_MIN_FIRST_DIGITS = + ('1' | ('2' << 8) | ('-' << 16)) << 8; + *(uint64_t*)(destBuf + 24) = INT32_MIN_LAST8DIGITS; + *(uint32_t*)(destBuf + 20) = INT32_MIN_FIRST_DIGITS; + return 21; + } + uint32_t size = _formatgrl4(destBuf, (uint32_t)-v); + destBuf[size - 1] = '-'; + return size - 1; + } + return _formatgrl4(destBuf, v); +} + +constexpr uint32_t _formatgrl4signed(char destBuf[33], int64_t v) { + if (v < 0) { + if (v == INT64_MIN) { + // 24 ... 28 29 30 31 "-922 33720368 54775808" + // 16 17 18 .. 21 22 23 + constexpr uint64_t INT64_MIN_LAST8DIGITS = + '8' | ('0' << 8) | ('8' << 16) | ('5' << 24) | (uint64_t('7') << 32) | + (uint64_t('7') << 40) | (uint64_t('4') << 48) | (uint64_t('5') << 56); + constexpr uint64_t INT64_MIN_MID8DIGITS = + '8' | ('6' << 8) | ('3' << 16) | ('0' << 24) | (uint64_t('2') << 32) | + (uint64_t('7') << 40) | (uint64_t('3') << 48) | (uint64_t('3') << 56); + constexpr uint32_t INT64_MIN_FIRST_DIGITS = + '2' | ('2' << 8) | ('9' << 16) | ('-' << 24); + *(uint64_t*)(destBuf + 24) = INT64_MIN_LAST8DIGITS; + *(uint64_t*)(destBuf + 16) = INT64_MIN_MID8DIGITS; + *(uint32_t*)(destBuf + 12) = INT64_MIN_FIRST_DIGITS; + return 12; + } + uint32_t size = _formatgrl4(destBuf, (uint32_t)-v); + destBuf[size - 1] = '-'; + return size - 1; + } + return _formatgrl4(destBuf, v); +} + +constexpr uint32_t _formatgrl(char destBuf[33], int printVal) { + if (printVal < 0) { + // TODO: this will not work for -intmax?!? + uint32_t len = _formatgrl(destBuf, uint32_t(-printVal)); + destBuf[32 - len] = '-'; + return len + 1; + } else { + return _formatgrl(destBuf, uint32_t(printVal)); + } +} + +constexpr inline char DECIMAL_POINT = '.'; +constexpr void _insertdec(char destBuf[33], uint32_t& i, uint32_t decimalLoc, + uint32_t digit4) { + // load the right 4 digits from the table 0000 to 9999 + uint32_t digits = ((uint32_t*)dig4)[digit4]; + if (decimalLoc >= 4) { + *(uint32_t*)&destBuf[i] = digits; + } else { + switch (decimalLoc) { + case 0: + destBuf[i + 3] = DECIMAL_POINT; + *(uint32_t*)&destBuf[--i] = digits; + break; + case 1: + destBuf[i + 3] = digits; + destBuf[i + 2] = DECIMAL_POINT; + i -= 2; + digits <<= 8; + // now there are only 3 bytes in the word, low byte is 0 + *(uint32_t*)&destBuf[i] = digits; + // just wrote 4 bytes, but there were only 3 + // still, it's faster because writing 16 bits then 8 bits as two + // separate memory writes and 2 separate instructions to do it. + i++; + break; + case 2: + // i-1 i i+1 i+2 i+3 + // d d . d d + *(uint16_t*)&destBuf[i + 2] = digits; + destBuf[i + 1] = DECIMAL_POINT; + i--; + digits <<= 16; + *(uint16_t*)&destBuf[i] = digits; + break; + case 3: + // i-1 i i+1 i+2 i+3 + // d . d d d + // write 4 bytes, one will get thrown out + // rotate left by 8 bits so the first 3 numbers are in low 3 bytes first + // time + // digits = (digits << 8) | + // (digits >> 24); // 11111111222222223333333300000000 + *(uint32_t*)&destBuf[i] = digits; + destBuf[i] = DECIMAL_POINT; // overwrite high byte with decimal point + i--; + // write out remaining 1 byte in the word + destBuf[i] = digits; + break; + } + } +} + +// R to L, 4 at a time +constexpr uint32_t _formatgrlfloat(char destBuf[33], uint64_t printVal, + uint32_t precision, uint32_t decimalLoc) { + uint32_t len; + uint32_t i; + for (i = 28; precision >= 4; i -= 4, precision -= 4, decimalLoc -= 4) { + uint64_t temp = printVal / 10000; + // get the 4 digits from memory + uint32_t digit4 = printVal - temp * 10000; + printVal = temp; + _insertdec(destBuf, i, decimalLoc, digit4); + } + _insertdec(destBuf, i, decimalLoc, printVal); + i += + (printVal >= 100 ? (printVal >= 1000 ? 0 : 1) : (printVal >= 10 ? 2 : 3)); + + return i; +} + +template +constexpr uint32_t _formatgrl5(char destBuf[33], T data) { + int ex; + constexpr int precision = 6; + // 1.234567 + // 123.4567 + // .1234567e+23 + // .9923456 + // .9999999 + + // 1234567. + // 1234.567 + // 12.34567 + frexp(data, &ex); + constexpr double invLog2_10 = 1 / log2(10.0); + double powOf10 = ceil(ex * invLog2_10); + T scale = pow(10, powOf10 - precision); + T scaled = data / scale; + // cout << "Scaled: " << scaled << '\n'; // .123456789 or 123456789 + uint64_t printVal = uint64_t(scaled); + // cout << "Integer value" << printVal << '\n'; + // 123.450 + // 0.345 + uint32_t decimalLoc = precision - uint32_t(powOf10); + return _formatgrlfloat(destBuf, printVal, precision, decimalLoc); +} + +template +constexpr void testboth(T data) { + print(fg(color::steel_blue) | emphasis::bold, "Currently processing: {}\n", + data); + char dest[33]; + vector out(33); + constexpr uint64_t n = 1000000; + CBenchmark::benchmark("fmtlib format", n, + bind(test_format, T>, out, data)); + CBenchmark::benchmark("sprintf format", n, bind(test_sprintf, dest, data)); + CBenchmark::benchmark("Grail float", n, bind(_formatgrl5, dest, data)); + print("{}\n", data); +} + +template +constexpr void testAll(T data) { + print(fg(color::steel_blue) | emphasis::bold, "Currently processing: {}\n", + data); + char dest[33]; + vector out(33); + constexpr uint64_t n = 1000000; + + CBenchmark::benchmark("fmtlib format", n, + bind(test_format, T>, out, data)); + CBenchmark::benchmark("sprintf format", n, bind(test_sprintf, dest, data)); + CBenchmark::benchmark("grail format RtoL 1 char", n, + bind(_formatgrl, dest, data)); + CBenchmark::benchmark("grail format RtoL 2 char", n, + bind(_formatgrl2, dest, data)); + CBenchmark::benchmark("grail format RtoL 4 char pairs", n, + bind(_formatgrl3, dest, data)); + CBenchmark::benchmark("grail format RtoL 4 char", n, + bind(_formatgrl4, dest, data)); + // Benchmark::benchmark("grail format RtoL 4char, sys benchmark", n, + // bind(_formatgrl4, dest, data)); + print("{}\n", data); +} + +int main() { + testboth(1.0f); + testboth(135567.362626); + + testAll(11); + testAll((uint32_t)-134135); + testAll(UINT64_MAX); + + char dest[33]; + // s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm + // 10000000 + dest[32] = '\0'; + uint8_t size = _formatgrl5(dest, 12323452345.45); + cout << dest + size << '\n'; + testboth(123.45); + // testboth("hello test"); +} From 61a098c943f88d0b764d4e79309e54c853e38e2d Mon Sep 17 00:00:00 2001 From: Alice Huston Date: Tue, 18 Jan 2022 14:32:30 -0500 Subject: [PATCH 28/39] Remove miscellaneous newline from code generator CMake checks the hash of several json files during configuration and runs a python script for that json file if it has been updated since the last configuration. The messages emitted from this code generation step had an extra newline at the end. This has been removed to keep all CMake messages uniformly spaced --- modules/GrailFunctions.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/GrailFunctions.cmake b/modules/GrailFunctions.cmake index aa7eb6dc..ccdfa604 100644 --- a/modules/GrailFunctions.cmake +++ b/modules/GrailFunctions.cmake @@ -43,7 +43,7 @@ function(load_python) if(GRAIL_${fileName}) message(STATUS "${fileName} updated") message(STATUS "[old ${hashType}]: ${GRAIL_${fileName}}") - message(STATUS "[new ${hashType}]: ${fileHash}\n") + message(STATUS "[new ${hashType}]: ${fileHash}") endif() set(GRAIL_${fileName} ${fileHash} CACHE INTERNAL "SHA512 hash of file ${fileName}") execute_process(COMMAND ${scriptPath} WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}) From 88e4dd57046cc34c090dff24f40c5633da27886f Mon Sep 17 00:00:00 2001 From: Alice Huston Date: Tue, 18 Jan 2022 14:41:19 -0500 Subject: [PATCH 29/39] Remove constexpr from some non-constexpr functions testfmt: sprintf is a C function and therefore cannot be used in a constexpr function. As such, the functions using sprintf are no longer marked as constexpr. --- test/testfmt.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/testfmt.cc b/test/testfmt.cc index afbbc297..40613b8d 100644 --- a/test/testfmt.cc +++ b/test/testfmt.cc @@ -18,27 +18,27 @@ constexpr uint32_t test_format(C destBuf, T fmt_val) { return destBuf.size(); // size of the formatted data } -constexpr uint32_t formatspf(char data[33], float f) { +uint32_t formatspf(char data[33], float f) { return sprintf(data, "%f", f); } -constexpr int32_t formatspf(char data[33], double f) { +int32_t formatspf(char data[33], double f) { return sprintf(data, "%lf", f); } -constexpr uint32_t formatspf(char data[33], int f) { +uint32_t formatspf(char data[33], int f) { return sprintf(data, "%d", f); } -constexpr uint32_t formatspf(char data[33], uint32_t f) { +uint32_t formatspf(char data[33], uint32_t f) { return sprintf(data, "%u", f); } -constexpr uint32_t formatspf(char data[33], uint64_t f) { +uint32_t formatspf(char data[33], uint64_t f) { return sprintf(data, "%lu", f); } -constexpr uint32_t formatspf(char data[33], const char* f) { +uint32_t formatspf(char data[33], const char* f) { return sprintf(data, "%s", f); } From 76a8f8d4a20df39f9d26eb1c17815130967c5a21 Mon Sep 17 00:00:00 2001 From: Alice Huston Date: Tue, 18 Jan 2022 18:02:45 -0500 Subject: [PATCH 30/39] Fix CI after renaming branch Build CI depends on the name of the branch, which has been changed since the last commit. This should update that information. --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 5493e12c..e44ba4f4 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -2,7 +2,7 @@ name: CMake on: push: - branches: [ main, tabbed-windows ] + branches: [ main, tabbed_windows ] pull_request: branches: [ main ] workflow_dispatch: From d816eef88bdf9de1ae4ea5c63ee5f00105cb143a Mon Sep 17 00:00:00 2001 From: Alice Huston Date: Wed, 19 Jan 2022 19:05:33 -0500 Subject: [PATCH 31/39] Remove tabbed_windows from CI tabbed_windows is now a part of a PR, so every test is getting run twice. This has been fixed to only have one test set running per commit. --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index e44ba4f4..843b8932 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -2,7 +2,7 @@ name: CMake on: push: - branches: [ main, tabbed_windows ] + branches: [ main ] pull_request: branches: [ main ] workflow_dispatch: From 6dcc3ccb4d51acd111233fda9cae671144927f2b Mon Sep 17 00:00:00 2001 From: Dov Kruger Date: Tue, 1 Feb 2022 10:21:30 -0500 Subject: [PATCH 32/39] added extraction to ASCII for ESRI files --- test/data/CMakeLists.txt | 1 + test/data/convert_ESRI_to_ASCII.cc | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 test/data/convert_ESRI_to_ASCII.cc diff --git a/test/data/CMakeLists.txt b/test/data/CMakeLists.txt index 35c3889d..37b0730c 100644 --- a/test/data/CMakeLists.txt +++ b/test/data/CMakeLists.txt @@ -3,3 +3,4 @@ add_grail_executable(SRC testGapMinderWidget.cc LIBS grail) #add_grail_executable(SRC testGapMinder.cc LIBS grail) add_grail_executable(SRC loadESRIShapefile.cc LIBS grail) +add_grail_executable(SRC convert_ESRI_to_ASCII.cc LIBS grail) diff --git a/test/data/convert_ESRI_to_ASCII.cc b/test/data/convert_ESRI_to_ASCII.cc new file mode 100644 index 00000000..fe35562c --- /dev/null +++ b/test/data/convert_ESRI_to_ASCII.cc @@ -0,0 +1,24 @@ +#include + +#include + +#include "data/BlockMapLoader.hh" +#include "opengl/GLWin.hh" + +std::string getFile(const char defaultDir[], const char defaultFilename[], + int argc, char *argv[]) { + const char *grail = getenv("GRAIL"); + if (grail == nullptr || defaultDir == nullptr) + return std::string(argc > 1 ? argv[1] : defaultFilename); + std::string dir = std::string(grail) + std::string(defaultDir); + return dir + (argc > 1 ? argv[1] : defaultFilename); +} + +int main(int argc, char **argv) { + std::string shapefile = + getFile("/test/res/maps/", "USA_Counties.shp", argc, argv); + + BlockMapLoader bml(shapefile.c_str(), "ESRI"); + for (int i = 0; i < bml.getNumSegments(); i++) + bml.dumpSegment(seg); +} From c659e2e5c2789cbc739d5350cda0d743719265f2 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Tue, 1 Feb 2022 10:40:49 -0500 Subject: [PATCH 33/39] Remove mpv dependency from Ubuntu 18.04 build Ubuntu 18.04 cannot use video at the moment due to a dependency bug, so MPV should be removed to prevent building video components. A more permanent fix should be implemented for making video optional. --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 843b8932..dbd19dd4 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -28,7 +28,7 @@ jobs: - name: Install Grail dependencies - run: sudo apt install libglfw3-dev libfreetype6-dev mpv libmpv-dev liblzma-dev + run: sudo apt install libglfw3-dev libfreetype6-dev liblzma-dev - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. From 8ef87b8aaa4bf4deb83241dd0cf287360624cd4d Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Tue, 1 Feb 2022 11:13:48 -0500 Subject: [PATCH 34/39] Remove ESRI-to-ASCII converter from build The converter is not 100% complete yet and does not currently build. Once this is fixed, it can be added back in. --- test/data/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/data/CMakeLists.txt b/test/data/CMakeLists.txt index 37b0730c..7d640c76 100644 --- a/test/data/CMakeLists.txt +++ b/test/data/CMakeLists.txt @@ -3,4 +3,4 @@ add_grail_executable(SRC testGapMinderWidget.cc LIBS grail) #add_grail_executable(SRC testGapMinder.cc LIBS grail) add_grail_executable(SRC loadESRIShapefile.cc LIBS grail) -add_grail_executable(SRC convert_ESRI_to_ASCII.cc LIBS grail) +#add_grail_executable(SRC convert_ESRI_to_ASCII.cc LIBS grail) From db1437143bfa9e11618458e487dcfe4bdfef4c8b Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Fri, 27 May 2022 01:24:37 -0400 Subject: [PATCH 35/39] Run clang-format on all files Signed-off-by: ahuston-0 --- src/CAD/Transformation.cc | 5 ++- src/csp/SocketIO.hh | 2 +- src/opengl/Member.cc | 11 ++++-- src/util/Callbacks.cc | 14 ++++--- src/util/Callbacks.hh | 4 +- src/util/DynArray.hh | 6 +-- test/graph/convert_ESRI_to_ASCII.cc | 3 +- test/xp/testHashMap.cc | 60 +++++++++++++++-------------- test/xp/testfmt.cc | 4 +- 9 files changed, 59 insertions(+), 50 deletions(-) diff --git a/src/CAD/Transformation.cc b/src/CAD/Transformation.cc index 5b8dbd6c..82e578d5 100644 --- a/src/CAD/Transformation.cc +++ b/src/CAD/Transformation.cc @@ -1,7 +1,8 @@ #include "CAD/Transformation.hh" + #include -// DO NOT REMOVE THIS COMMENT. IDIOTIC SORTING FORMAT WILL MOVE glad.h after glfw3 and screw up the build. -// What genius made the headers order-dependent? +// DO NOT REMOVE THIS COMMENT. IDIOTIC SORTING FORMAT WILL MOVE glad.h after +// glfw3 and screw up the build. What genius made the headers order-dependent? #include diff --git a/src/csp/SocketIO.hh b/src/csp/SocketIO.hh index 70bb60df..630ff740 100644 --- a/src/csp/SocketIO.hh +++ b/src/csp/SocketIO.hh @@ -32,7 +32,7 @@ constexpr int err_code = -1; #elif _WIN32 constexpr int err_code = SOCKET_ERROR; #endif -} // anonymous namespace for errors +} // namespace ssize_t send(socket_t sckt, const char *buf, int size, int flags); ssize_t recv(socket_t sckt, char *buf, int size, int flags); diff --git a/src/opengl/Member.cc b/src/opengl/Member.cc index 55aa3979..b4af6ff3 100644 --- a/src/opengl/Member.cc +++ b/src/opengl/Member.cc @@ -33,7 +33,10 @@ Member::Member(Member&& orig) noexcept : tab(orig.tab), c(orig.c) { orig.tab = nullptr; orig.c = nullptr; } -Member& Member::operator=(Member orig) { swap(*this, orig); return *this; } +Member& Member::operator=(Member orig) { + swap(*this, orig); + return *this; +} Member& Member::operator=(Member&& orig) noexcept { if (this != &orig) { tab = orig.tab; @@ -42,8 +45,8 @@ Member& Member::operator=(Member&& orig) noexcept { return *this; } -void swap(Member& a, Member& b){ +void swap(Member& a, Member& b) { using std::swap; - swap(a.tab,b.tab); - swap(a.c,b.c); + swap(a.tab, b.tab); + swap(a.c, b.c); } diff --git a/src/util/Callbacks.cc b/src/util/Callbacks.cc index 9d7428e3..7103cfd2 100644 --- a/src/util/Callbacks.cc +++ b/src/util/Callbacks.cc @@ -5,14 +5,16 @@ using namespace std; CallbackHandler::CallbackHandler() { - for (uint8_t i = 0; i < 3; i++) {numActions[i] = 1;} + for (uint8_t i = 0; i < 3; i++) { + numActions[i] = 1; + } } HashMap CallbackHandler::actionNameMap(64, 4096); std::array inputMap(); -uint32_t CallbackHandler::internalRegisterAction(const char name[], const Security s, - const function action) { +uint32_t CallbackHandler::internalRegisterAction( + const char name[], const Security s, const function action) { auto securityIndex = uint32_t(s); // SAFE = 0..999, RESTRICTED=1000.1999, ASK=2000..2999 uint32_t actNum = 1000 * securityIndex + numActions[securityIndex]++; @@ -30,7 +32,9 @@ uint32_t CallbackHandler::internalRegisterAction(const char name[], const Securi auto CallbackHandler::lookupAction(const char actionName[]) -> uint32_t { uint32_t *act_code = actionNameMap.get(actionName); - if (act_code) {return *act_code;} + if (act_code) { + return *act_code; + } cerr << "Input binding failed: " << actionName << '\n'; return 0; } @@ -57,7 +61,7 @@ uint32_t CallbackHandler::registerCallback(uint32_t input, const char name[], setEvent(input, lookupAction(name)); return actNum; } - auto CallbackHandler::doit(uint32_t input) -> void { +auto CallbackHandler::doit(uint32_t input) -> void { uint32_t act = CallbackHandler::inputMap[input]; if (act == 0) return; auto a = CallbackHandler::actionMap[act]; diff --git a/src/util/Callbacks.hh b/src/util/Callbacks.hh index 1506ff1b..fbe14050 100644 --- a/src/util/Callbacks.hh +++ b/src/util/Callbacks.hh @@ -43,8 +43,8 @@ class CallbackHandler { enum class Security { SAFE, // safe for a remote server to trigger this function RESTRICTED, // only the local user can execute this function - ASK // a remote user or server may request this, but it will trigger a popup - // asking local user to approve + ASK // a remote user or server may request this, but it will trigger a + // popup asking local user to approve }; std::array numActions; // keep track of how many of each kind of // operations there are diff --git a/src/util/DynArray.hh b/src/util/DynArray.hh index 71b4aa3b..16b3d9b7 100644 --- a/src/util/DynArray.hh +++ b/src/util/DynArray.hh @@ -5,7 +5,7 @@ #include // The following disables clang-tidy from warning about pointer arithmetic -// Since this is a container implementation, it is unavoidable that pointer +// Since this is a container implementation, it is unavoidable that pointer // arithmetic is used // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -77,8 +77,8 @@ class DynArray { if (index == size_ - 1) data[index].~T(); --size_; return temp; -} - template + } + template T& emplace_back(Args&&... args) { checkGrow(); return *construct_at(data + size_++, std::forward(args)...); diff --git a/test/graph/convert_ESRI_to_ASCII.cc b/test/graph/convert_ESRI_to_ASCII.cc index fe35562c..ebf4aa50 100644 --- a/test/graph/convert_ESRI_to_ASCII.cc +++ b/test/graph/convert_ESRI_to_ASCII.cc @@ -19,6 +19,5 @@ int main(int argc, char **argv) { getFile("/test/res/maps/", "USA_Counties.shp", argc, argv); BlockMapLoader bml(shapefile.c_str(), "ESRI"); - for (int i = 0; i < bml.getNumSegments(); i++) - bml.dumpSegment(seg); + for (int i = 0; i < bml.getNumSegments(); i++) bml.dumpSegment(seg); } diff --git a/test/xp/testHashMap.cc b/test/xp/testHashMap.cc index 7b8d09d3..7d09f24c 100644 --- a/test/xp/testHashMap.cc +++ b/test/xp/testHashMap.cc @@ -1,42 +1,44 @@ #include + #include "util/HashMap.hh" // make a copy of util/Hashmap.hh into src/xp void convertAsciiDictionaryToBlockLoader() { - HashMap dict; + HashMap dict; // while (!f.getline()) { - dict.add(word, count++); - } - - uint32_t val; - if (dict.get("apple", &val)) { - cout << val - - } else { - cout << "Apple not found"; - } - // first create a hashmap and load dictionary in with a unique integer for each word - //for (each word) dict.add(word, count++); - // now, modify hash map to save the dictionary into a single block loader - - // class HashMapBase : BlockLoader { ??? - // write out the block loader format - // 4 bytes magic number, 2 bytes type , .... - // save here as "fastloaddict.bld" - - // allocate assuming each word = 2 bytes. - // length of file = header + number of bytes in words - // conservative estimate of words = (length of file - header) / 2 - // use: malloc() to allocate the memory - // read in the file into the memory you allocated - // calculate the 3 pointers: symbols, table, nodes - // use realloc() to give back the excess (because you had to over-estimate) - // add and fill in the table + dict.add(word, count++); +} + +uint32_t val; +if (dict.get("apple", &val)) { + cout << val + +} else { + cout << "Apple not found"; +} +// first create a hashmap and load dictionary in with a unique integer for each +// word +// for (each word) dict.add(word, count++); +// now, modify hash map to save the dictionary into a single block loader + +// class HashMapBase : BlockLoader { ??? +// write out the block loader format +// 4 bytes magic number, 2 bytes type , .... +// save here as "fastloaddict.bld" + +// allocate assuming each word = 2 bytes. +// length of file = header + number of bytes in words +// conservative estimate of words = (length of file - header) / 2 +// use: malloc() to allocate the memory +// read in the file into the memory you allocated +// calculate the 3 pointers: symbols, table, nodes +// use realloc() to give back the excess (because you had to over-estimate) +// add and fill in the table } int main() { convertAsciiDictionaryToBlockLoader(); -// make a fast dictionary loader that loads from the format you saved + // make a fast dictionary loader that loads from the format you saved HashMap dict("fastloaddict.bld"); } \ No newline at end of file diff --git a/test/xp/testfmt.cc b/test/xp/testfmt.cc index 371951fd..5d0f8748 100644 --- a/test/xp/testfmt.cc +++ b/test/xp/testfmt.cc @@ -194,7 +194,7 @@ constexpr uint32_t _formatgrl(char destBuf[33], int printVal) { constexpr inline char DECIMAL_POINT = '.'; void _insertdec(char destBuf[33], uint32_t& i, uint32_t decimalLoc, - uint32_t digit4) { + uint32_t digit4) { // load the right 4 digits from the table 0000 to 9999 uint32_t digits = ((uint32_t*)dig4)[digit4]; if (decimalLoc >= 4) { @@ -246,7 +246,7 @@ void _insertdec(char destBuf[33], uint32_t& i, uint32_t decimalLoc, // R to L, 4 at a time uint32_t _formatgrlfloat(char destBuf[33], uint64_t printVal, - uint32_t precision, uint32_t decimalLoc) { + uint32_t precision, uint32_t decimalLoc) { uint32_t len; uint32_t i; for (i = 28; precision >= 4; i -= 4, precision -= 4, decimalLoc -= 4) { From e12b64c2061249ce58aa77fb4c7f66dd686dee8a Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Fri, 27 May 2022 01:29:39 -0400 Subject: [PATCH 36/39] CMake compile will now run on all pull requests Signed-off-by: ahuston-0 --- .github/workflows/cmake.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 74186349..8e94749f 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -4,7 +4,6 @@ on: push: branches: [main] pull_request: - branches: [main] workflow_dispatch: jobs: From 4d5d8de7d852edbc75196825456dfb673f5ca6b7 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Fri, 10 Jun 2022 13:33:31 -0400 Subject: [PATCH 37/39] add git attributes --- .gitattributes | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..c2dbd15e --- /dev/null +++ b/.gitattributes @@ -0,0 +1,13 @@ +# Allow custom line endings during checkout, but enforce LF on checkin +*.cc text +*.c text +*.hh text +*.h text + +*.py text +*.md text + +*.txt text + +*.bml binary + From e7c74bba9f4b177f7a1e31c689aaf5049708067a Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Thu, 16 Jun 2022 20:47:07 -0400 Subject: [PATCH 38/39] add revised clang-tidy config --- .clang-tidy | 337 ++++++++++++++++++++++++++++++--- Grail_Workspace.code-workspace | 2 - 2 files changed, 315 insertions(+), 24 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index b51bcbd1..eff78aac 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,47 +1,340 @@ --- -Checks: 'clang-diagnostic-*,clang-analyzer-*,cppcoreguidelines-*,readability-*' +# Taken from Suven-p/Pacman_OpenGL +Checks: 'clang-diagnostic-*,clang-analyzer-*,-*,bugprone-*,-bugprone-narrowing-conversions,cppcoreguidelines-*,-cppcoreguidelines-avoid-non-const-global-variables,-cppcoreguidelines-avoid-c-arrays,-cppcoreguidelines-narrowing-conversions,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-non-private-member-variables-in-classes,-cppcoreguidelines-avoid-magic-numbers,modernize-*,-modernize-use-trailing-return-type,-modernize-avoid-c-arrays,performance-*,-performance-no-int-to-ptr,readability-*,-readability-magic-numbers,portability-*,clang-analyzer-*' WarningsAsErrors: '' -HeaderFilterRegex: '' +# The following seeems to filter out headers. I'll leave it in case we need it +# HeaderFilterRegex: '.*\.h+(pp)?' AnalyzeTemporaryDtors: false FormatStyle: file CheckOptions: - - key: llvm-else-after-return.WarnOnConditionVariables - value: 'false' - - key: modernize-loop-convert.MinConfidence - value: reasonable - key: modernize-replace-auto-ptr.IncludeStyle value: llvm + - key: cppcoreguidelines-no-malloc.Reallocations + value: '::realloc' + - key: cppcoreguidelines-owning-memory.LegacyResourceConsumers + value: '::free;::realloc;::freopen;::fclose' + - key: readability-static-accessed-through-instance.NameSpecifierNestingThreshold + value: '3' + - key: readability-function-size.VariableThreshold + value: '4294967295' + - key: modernize-use-auto.MinTypeNameLength + value: '5' + - key: bugprone-reserved-identifier.Invert + value: 'false' + - key: performance-move-const-arg.CheckTriviallyCopyableMove + value: 'true' + - key: cert-dcl16-c.NewSuffixes + value: 'L;LL;LU;LLU' + - key: cppcoreguidelines-macro-usage.CheckCapsOnly + value: 'false' + - key: readability-identifier-naming.GetConfigPerFile + value: 'true' + - key: readability-inconsistent-declaration-parameter-name.Strict + value: 'false' + - key: bugprone-unused-return-value.CheckedFunctions + value: '::std::async;::std::launder;::std::remove;::std::remove_if;::std::unique;::std::unique_ptr::release;::std::basic_string::empty;::std::vector::empty;::std::back_inserter;::std::distance;::std::find;::std::find_if;::std::inserter;::std::lower_bound;::std::make_pair;::std::map::count;::std::map::find;::std::map::lower_bound;::std::multimap::equal_range;::std::multimap::upper_bound;::std::set::count;::std::set::find;::std::setfill;::std::setprecision;::std::setw;::std::upper_bound;::std::vector::at;::bsearch;::ferror;::feof;::isalnum;::isalpha;::isblank;::iscntrl;::isdigit;::isgraph;::islower;::isprint;::ispunct;::isspace;::isupper;::iswalnum;::iswprint;::iswspace;::isxdigit;::memchr;::memcmp;::strcmp;::strcoll;::strncmp;::strpbrk;::strrchr;::strspn;::strstr;::wcscmp;::access;::bind;::connect;::difftime;::dlsym;::fnmatch;::getaddrinfo;::getopt;::htonl;::htons;::iconv_open;::inet_addr;::isascii;::isatty;::mmap;::newlocale;::openat;::pathconf;::pthread_equal;::pthread_getspecific;::pthread_mutex_trylock;::readdir;::readlink;::recvmsg;::regexec;::scandir;::semget;::setjmp;::shm_open;::shmget;::sigismember;::strcasecmp;::strsignal;::ttyname' + - key: modernize-use-default-member-init.UseAssignment + value: 'false' + - key: readability-function-size.NestingThreshold + value: '4294967295' + - key: modernize-use-override.AllowOverrideAndFinal + value: 'false' + - key: readability-function-size.ParameterThreshold + value: '4294967295' + - key: modernize-pass-by-value.ValuesOnly + value: 'false' + - key: modernize-loop-convert.IncludeStyle + value: llvm - key: cert-str34-c.DiagnoseSignedUnsignedCharComparisons + value: '0' + - key: bugprone-suspicious-string-compare.WarnOnLogicalNotComparison + value: 'false' + - key: cppcoreguidelines-explicit-virtual-functions.AllowOverrideAndFinal + value: 'false' + - key: readability-redundant-smartptr-get.IgnoreMacros + value: 'true' + - key: readability-identifier-naming.AggressiveDependentMemberLookup value: 'false' + - key: bugprone-suspicious-string-compare.WarnOnImplicitComparison + value: 'true' + - key: modernize-use-emplace.TupleTypes + value: '::std::pair;::std::tuple' + - key: modernize-use-emplace.TupleMakeFunctions + value: '::std::make_pair;::std::make_tuple' + - key: cppcoreguidelines-owning-memory.LegacyResourceProducers + value: '::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile' + - key: bugprone-argument-comment.CommentNullPtrs + value: '0' + - key: bugprone-argument-comment.StrictMode + value: '0' + - key: cppcoreguidelines-init-variables.IncludeStyle + value: llvm + - key: modernize-use-nodiscard.ReplacementString + value: '[[nodiscard]]' + - key: modernize-replace-random-shuffle.IncludeStyle + value: llvm + - key: modernize-loop-convert.MakeReverseRangeHeader + value: '' + - key: modernize-use-bool-literals.IgnoreMacros + value: 'true' + - key: bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField + value: 'true' - key: google-readability-namespace-comments.ShortNamespaceLines value: '10' + - key: bugprone-suspicious-string-compare.StringCompareLikeFunctions + value: '' + - key: modernize-avoid-bind.PermissiveParameterList + value: 'false' + - key: modernize-use-override.FinalSpelling + value: final + - key: performance-move-constructor-init.IncludeStyle + value: llvm + - key: modernize-loop-convert.UseCxx20ReverseRanges + value: 'true' + - key: modernize-use-noexcept.ReplacementString + value: '' + - key: modernize-use-using.IgnoreMacros + value: 'true' + - key: performance-type-promotion-in-math-fn.IncludeStyle + value: llvm + - key: cppcoreguidelines-explicit-virtual-functions.FinalSpelling + value: final + - key: modernize-loop-convert.NamingStyle + value: CamelCase + - key: bugprone-suspicious-include.ImplementationFileExtensions + value: 'c;cc;cpp;cxx' + - key: cppcoreguidelines-pro-type-member-init.UseAssignment + value: 'false' + - key: modernize-loop-convert.MakeReverseRangeFunction + value: '' + - key: bugprone-suspicious-include.HeaderFileExtensions + value: ';h;hh;hpp;hxx' + - key: performance-no-automatic-move.AllowedTypes + value: '' + - key: performance-for-range-copy.WarnOnAllAutoCopies + value: 'false' + - key: bugprone-argument-comment.CommentIntegerLiterals + value: '0' + - key: bugprone-suspicious-missing-comma.SizeThreshold + value: '5' + - key: readability-inconsistent-declaration-parameter-name.IgnoreMacros + value: 'true' + - key: readability-identifier-naming.IgnoreFailedSplit + value: 'false' + - key: modernize-pass-by-value.IncludeStyle + value: llvm + - key: bugprone-sizeof-expression.WarnOnSizeOfThis + value: 'true' + - key: bugprone-argument-comment.CommentFloatLiterals + value: '0' + - key: bugprone-string-constructor.WarnOnLargeLength + value: 'true' + - key: bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit + value: '16' + - key: readability-qualified-auto.AddConstToQualified + value: 'true' + - key: cppcoreguidelines-explicit-virtual-functions.OverrideSpelling + value: override + - key: readability-simplify-boolean-expr.ChainedConditionalReturn + value: 'false' + - key: readability-else-after-return.WarnOnConditionVariables + value: 'true' + - key: readability-uppercase-literal-suffix.IgnoreMacros + value: 'true' + - key: modernize-use-nullptr.NullMacros + value: 'NULL' + - key: modernize-make-shared.IgnoreMacros + value: 'true' + - key: bugprone-dynamic-static-initializers.HeaderFileExtensions + value: ';h;hh;hpp;hxx' + - key: bugprone-suspicious-enum-usage.StrictMode + value: 'false' + - key: performance-unnecessary-copy-initialization.AllowedTypes + value: '' + - key: bugprone-suspicious-missing-comma.MaxConcatenatedTokens + value: '5' + - key: modernize-use-transparent-functors.SafeMode + value: 'false' + - key: cppcoreguidelines-macro-usage.AllowedRegexp + value: '^DEBUG_*' + - key: modernize-make-shared.IgnoreDefaultInitialization + value: 'true' + - key: bugprone-argument-comment.CommentCharacterLiterals + value: '0' + - key: bugprone-not-null-terminated-result.WantToUseSafeFunctions + value: 'true' + - key: modernize-make-shared.IncludeStyle + value: llvm + - key: bugprone-string-constructor.LargeLengthThreshold + value: '8388608' + - key: readability-simplify-boolean-expr.ChainedConditionalAssignment + value: 'false' + - key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions + value: 'false' - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField + value: '0' + - key: bugprone-exception-escape.FunctionsThatShouldNotThrow + value: '' + - key: performance-inefficient-vector-operation.EnableProto value: 'false' - - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + - key: readability-function-size.LineThreshold + value: '4294967295' + - key: modernize-loop-convert.MaxCopySize + value: '16' + - key: bugprone-argument-comment.CommentStringLiterals + value: '0' + - key: modernize-make-shared.MakeSmartPtrFunction + value: 'std::make_shared' + - key: bugprone-signed-char-misuse.CharTypdefsToIgnore + value: '' + - key: portability-simd-intrinsics.Suggest + value: 'false' + - key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader + value: '' + - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors + value: 'true' + - key: modernize-make-unique.IgnoreMacros + value: 'true' + - key: performance-for-range-copy.AllowedTypes + value: '' + - key: modernize-make-shared.MakeSmartPtrFunctionHeader + value: '' + - key: modernize-use-override.IgnoreDestructors + value: 'false' + - key: bugprone-sizeof-expression.WarnOnSizeOfConstant + value: 'true' + - key: readability-redundant-string-init.StringNames + value: '::std::basic_string_view;::std::basic_string' + - key: modernize-make-unique.IgnoreDefaultInitialization + value: 'true' + - key: modernize-use-emplace.ContainersWithPushBack + value: '::std::vector;::std::list;::std::deque' + - key: modernize-make-unique.IncludeStyle + value: llvm + - key: readability-braces-around-statements.ShortStatementLines + value: '0' + - key: bugprone-argument-comment.CommentUserDefinedLiterals + value: '0' + - key: bugprone-argument-comment.CommentBoolLiterals + value: '0' + - key: modernize-use-override.OverrideSpelling + value: override + - key: performance-inefficient-string-concatenation.StrictMode + value: 'false' + - key: readability-implicit-bool-conversion.AllowPointerConditions + value: 'false' + - key: readability-redundant-declaration.IgnoreMacros value: 'true' - - key: cert-dcl16-c.NewSuffixes - value: 'L;LL;LU;LLU' - key: google-readability-braces-around-statements.ShortStatementLines value: '1' - - key: modernize-pass-by-value.IncludeStyle + - key: modernize-make-unique.MakeSmartPtrFunction + value: 'std::make_unique' + - key: cppcoreguidelines-pro-type-member-init.IgnoreArrays + value: 'false' + - key: readability-else-after-return.WarnOnUnfixable + value: 'true' + - key: bugprone-reserved-identifier.AllowedIdentifiers + value: '' + - key: modernize-use-emplace.IgnoreImplicitConstructors + value: 'false' + - key: modernize-make-unique.MakeSmartPtrFunctionHeader + value: '' + - key: portability-restrict-system-includes.Includes + value: '*' + - key: modernize-use-equals-delete.IgnoreMacros + value: 'true' + - key: cppcoreguidelines-pro-bounds-constant-array-index.IncludeStyle value: llvm + - key: cppcoreguidelines-macro-usage.IgnoreCommandLineMacros + value: 'true' + - key: bugprone-misplaced-widening-cast.CheckImplicitCasts + value: 'false' + - key: readability-uppercase-literal-suffix.NewSuffixes + value: '' + - key: modernize-loop-convert.MinConfidence + value: reasonable + - key: performance-unnecessary-value-param.AllowedTypes + value: '' + - key: bugprone-suspicious-missing-comma.RatioThreshold + value: '0.200000' + - key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted + value: 'false' + - key: modernize-use-noexcept.UseNoexceptFalse + value: 'true' - key: google-readability-namespace-comments.SpacesBeforeComments value: '2' - - key: modernize-loop-convert.MaxCopySize - value: '16' - - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors + - key: readability-function-cognitive-complexity.Threshold + value: '25' + - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: '1' + - key: bugprone-argument-comment.IgnoreSingleArgument + value: '0' + - key: cppcoreguidelines-no-malloc.Allocations + value: '::malloc;::calloc' + - key: bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression + value: 'false' + - key: performance-faster-string-find.StringLikeClasses + value: '::std::basic_string;::std::basic_string_view' + - key: bugprone-assert-side-effect.CheckFunctionCalls + value: 'false' + - key: readability-function-size.BranchThreshold + value: '4294967295' + - key: bugprone-string-constructor.StringNames + value: '::std::basic_string;::std::basic_string_view' + - key: bugprone-assert-side-effect.AssertMacros + value: assert + - key: bugprone-exception-escape.IgnoredExceptions + value: '' + - key: readability-function-size.StatementThreshold + value: '800' + - key: modernize-use-default-member-init.IgnoreMacros value: 'true' - - key: modernize-use-nullptr.NullMacros - value: 'NULL' - key: llvm-qualified-auto.AddConstToQualified + value: '0' + - key: bugprone-signed-char-misuse.DiagnoseSignedUnsignedCharComparisons + value: 'true' + - key: readability-identifier-naming.IgnoreMainLikeFunctions value: 'false' - - key: modernize-loop-convert.NamingStyle - value: CamelCase - - key: llvm-else-after-return.WarnOnUnfixable + - key: readability-implicit-bool-conversion.AllowIntegerConditions value: 'false' + - key: cppcoreguidelines-init-variables.MathHeader + value: '' - key: google-readability-function-size.StatementThreshold value: '800' - - key: readability-braces-around-statements.ShortStatementLines - value: '1' -... - + - key: llvm-else-after-return.WarnOnConditionVariables + value: '0' + - key: bugprone-sizeof-expression.WarnOnSizeOfCompareToConstant + value: 'true' + - key: bugprone-reserved-identifier.AggressiveDependentMemberLookup + value: 'false' + - key: modernize-raw-string-literal.DelimiterStem + value: lit + - key: modernize-use-equals-default.IgnoreMacros + value: 'true' + - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor + value: 'false' + - key: modernize-raw-string-literal.ReplaceShorterLiterals + value: 'false' + - key: modernize-use-emplace.SmartPointers + value: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr' + - key: cppcoreguidelines-no-malloc.Deallocations + value: '::free' + - key: modernize-use-auto.RemoveStars + value: 'false' + - key: bugprone-dangling-handle.HandleClasses + value: 'std::basic_string_view;std::experimental::basic_string_view' + - key: performance-inefficient-vector-operation.VectorLikeClasses + value: '::std::vector' + - key: portability-simd-intrinsics.Std + value: '' + - key: performance-unnecessary-value-param.IncludeStyle + value: llvm + - key: readability-redundant-member-init.IgnoreBaseInCopyConstructors + value: 'false' + - key: modernize-replace-disallow-copy-and-assign-macro.MacroName + value: DISALLOW_COPY_AND_ASSIGN + - key: llvm-else-after-return.WarnOnUnfixable + value: '0' + - key: readability-simplify-subscript-expr.Types + value: '::std::basic_string;::std::basic_string_view;::std::vector;::std::array' +... \ No newline at end of file diff --git a/Grail_Workspace.code-workspace b/Grail_Workspace.code-workspace index a5c7be03..3795588d 100644 --- a/Grail_Workspace.code-workspace +++ b/Grail_Workspace.code-workspace @@ -26,8 +26,6 @@ "*.c": "c", "**/stdhpp/**": "cpp" }, - "C_Cpp.default.cppStandard": "c++20", - "C_Cpp.default.cStandard": "c17", }, "launch": { "configurations": [ From 5c40d6909f0a7047966740224bf16062262c5cb3 Mon Sep 17 00:00:00 2001 From: ahuston-0 Date: Thu, 16 Jun 2022 20:49:53 -0400 Subject: [PATCH 39/39] adding files with changed line endings --- src/CAD/RectangularPrism.cc | 246 +++++------ src/opengl/GLWin.hh | 5 +- test/testDynArray.cc | 116 ++--- test/util/DateDemo.cc | 42 +- test/xdl/GenericXDLClient.cc | 118 +++--- test/xdl/GraphicalXDLClient.cc | 752 ++++++++++++++++----------------- test/xdl/SimpleXDLServer.cc | 58 +-- test/xdl/StockDemo.cc | 146 +++---- test/xp/plot.cc | 512 +++++++++++----------- 9 files changed, 999 insertions(+), 996 deletions(-) diff --git a/src/CAD/RectangularPrism.cc b/src/CAD/RectangularPrism.cc index e673ec7b..bf97523f 100644 --- a/src/CAD/RectangularPrism.cc +++ b/src/CAD/RectangularPrism.cc @@ -1,123 +1,123 @@ -#include "CAD/RectangularPrism.hh" -// #include "opengl/GLMath.hh" -#include "glad/glad.h" -#include "opengl/Canvas.hh" -#include "opengl/GLWin.hh" -#include "opengl/Shader.hh" -#include "opengl/Style.hh" - -RectangularPrism::RectangularPrism(Canvas* c, const Style* s, float xsize, - float ysize, float zsize, float x, float y, - float z) - : Shape(c), - style(s), - xsize(xsize), - ysize(ysize), - zsize(zsize), - x(x), - y(y), - z(z) {} -RectangularPrism::~RectangularPrism() {} -inline void RectangularPrism::addVert(float x, float y, float z) { - vert.push_back(x); - vert.push_back(y); - vert.push_back(z); -} -// Best for GL_TRIANGLES -// inline void RectangularPrism::addRect(uint32_t i1, uint32_t i2, uint32_t i3, -// uint32_t i4) { -// ind.push_back(i1); ind.push_back(i2); ind.push_back(i3); -// ind.push_back(i1); ind.push_back(i3); ind.push_back(i4); -// } - -// Best for GL_LINES -inline void RectangularPrism::addRect(uint32_t i1, uint32_t i2, uint32_t i3, - uint32_t i4) { - ind.push_back(i1); - ind.push_back(i2); - ind.push_back(i2); - ind.push_back(i3); - ind.push_back(i3); - ind.push_back(i4); - ind.push_back(i4); - ind.push_back(i1); -} - -inline void RectangularPrism::addTri(uint32_t i1, uint32_t i2, uint32_t i3) { - ind.push_back(i1); - ind.push_back(i2); - ind.push_back(i3); -} - -void RectangularPrism::init() { - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - // Width = xsize - - addVert(x, y, z); // 0 - addVert(x + xsize, y, z); // 1 - addVert(x + xsize, y + ysize, z); // 2 - addVert(x, y + ysize, z); // 3 - addVert(x, y, z + zsize); // 4 - addVert(x + xsize, y, z + zsize); // 5 - addVert(x + xsize, y + ysize, z + zsize); // 6 - addVert(x, y + ysize, z + zsize); // 7 - - // front - addRect(0, 1, 2, 3); - - // back - addRect(4, 5, 6, 7); - - // sides - addRect(1, 5, 6, 2); - - addRect(4, 0, 3, 7); - - // Top - addRect(3, 2, 6, 7); - - // Bottom - addRect(0, 1, 5, 4); - - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vert.size(), &vert[0], - GL_STATIC_DRAW); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); - - glGenBuffers(1, &lbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lbo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * ind.size(), &ind[0], - GL_STATIC_DRAW); - - // use if you want points to be drawn as well - // glGenBuffers(1,&pbo); - // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,pbo); - // glBufferData(GL_ELEMENT_ARRAY_BUFFER, - // sizeof(GLuint)*ind.size(),&ind[0],GL_STATIC_DRAW); -} - -void RectangularPrism::render() { - // const Shader* shader = Shader::useShader(style->getShaderIndex()); - // shader->setMat4("projection",*(parentCanvas->getProjection())); - // shader->setVec4("solidColor",style->getFgColor()); - - // glDrawArrays(GL_LINE_LOOP, 0, vert.size()); - glBindVertexArray(vao); - glEnableVertexAttribArray(0); - glLineWidth(style->getLineWidth()); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lbo); - glDrawElements(GL_LINES, ind.size(), GL_UNSIGNED_INT, 0); - // for points - // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pbo); - // glDrawElements(GL_POINTS, ind.size(), GL_UNSIGNED_INT, 0); - - glDisableVertexAttribArray(0); - glBindVertexArray(0); -} - -void RectangularPrism::cleanup() {} - -void RectangularPrism::update() {} +#include "CAD/RectangularPrism.hh" +// #include "opengl/GLMath.hh" +#include "glad/glad.h" +#include "opengl/Canvas.hh" +#include "opengl/GLWin.hh" +#include "opengl/Shader.hh" +#include "opengl/Style.hh" + +RectangularPrism::RectangularPrism(Canvas* c, const Style* s, float xsize, + float ysize, float zsize, float x, float y, + float z) + : Shape(c), + style(s), + xsize(xsize), + ysize(ysize), + zsize(zsize), + x(x), + y(y), + z(z) {} +RectangularPrism::~RectangularPrism() {} +inline void RectangularPrism::addVert(float x, float y, float z) { + vert.push_back(x); + vert.push_back(y); + vert.push_back(z); +} +// Best for GL_TRIANGLES +// inline void RectangularPrism::addRect(uint32_t i1, uint32_t i2, uint32_t i3, +// uint32_t i4) { +// ind.push_back(i1); ind.push_back(i2); ind.push_back(i3); +// ind.push_back(i1); ind.push_back(i3); ind.push_back(i4); +// } + +// Best for GL_LINES +inline void RectangularPrism::addRect(uint32_t i1, uint32_t i2, uint32_t i3, + uint32_t i4) { + ind.push_back(i1); + ind.push_back(i2); + ind.push_back(i2); + ind.push_back(i3); + ind.push_back(i3); + ind.push_back(i4); + ind.push_back(i4); + ind.push_back(i1); +} + +inline void RectangularPrism::addTri(uint32_t i1, uint32_t i2, uint32_t i3) { + ind.push_back(i1); + ind.push_back(i2); + ind.push_back(i3); +} + +void RectangularPrism::init() { + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + // Width = xsize + + addVert(x, y, z); // 0 + addVert(x + xsize, y, z); // 1 + addVert(x + xsize, y + ysize, z); // 2 + addVert(x, y + ysize, z); // 3 + addVert(x, y, z + zsize); // 4 + addVert(x + xsize, y, z + zsize); // 5 + addVert(x + xsize, y + ysize, z + zsize); // 6 + addVert(x, y + ysize, z + zsize); // 7 + + // front + addRect(0, 1, 2, 3); + + // back + addRect(4, 5, 6, 7); + + // sides + addRect(1, 5, 6, 2); + + addRect(4, 0, 3, 7); + + // Top + addRect(3, 2, 6, 7); + + // Bottom + addRect(0, 1, 5, 4); + + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vert.size(), &vert[0], + GL_STATIC_DRAW); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); + + glGenBuffers(1, &lbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lbo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * ind.size(), &ind[0], + GL_STATIC_DRAW); + + // use if you want points to be drawn as well + // glGenBuffers(1,&pbo); + // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,pbo); + // glBufferData(GL_ELEMENT_ARRAY_BUFFER, + // sizeof(GLuint)*ind.size(),&ind[0],GL_STATIC_DRAW); +} + +void RectangularPrism::render() { + // const Shader* shader = Shader::useShader(style->getShaderIndex()); + // shader->setMat4("projection",*(parentCanvas->getProjection())); + // shader->setVec4("solidColor",style->getFgColor()); + + // glDrawArrays(GL_LINE_LOOP, 0, vert.size()); + glBindVertexArray(vao); + glEnableVertexAttribArray(0); + glLineWidth(style->getLineWidth()); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lbo); + glDrawElements(GL_LINES, ind.size(), GL_UNSIGNED_INT, 0); + // for points + // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pbo); + // glDrawElements(GL_POINTS, ind.size(), GL_UNSIGNED_INT, 0); + + glDisableVertexAttribArray(0); + glBindVertexArray(0); +} + +void RectangularPrism::cleanup() {} + +void RectangularPrism::update() {} diff --git a/src/opengl/GLWin.hh b/src/opengl/GLWin.hh index d9bdc860..6afdf67d 100644 --- a/src/opengl/GLWin.hh +++ b/src/opengl/GLWin.hh @@ -160,7 +160,10 @@ Shape* pick(int x, int y, Shape*); // click on (x,y), get Shape behind void mainLoop(); void setUpdate() { needsUpdate = true; } void setRender() { needsRender = true; } - const Style* getDefaultStyle() const { return defaultStyle; } + const Style* getDefaultStyle() const { + auto a = new int[10]; + return defaultStyle; + } const Style* getGuiStyle() const { return guiStyle; } const Style* getGuiTextStyle() const { return guiTextStyle; } const Style* getMenuStyle() const { return menuStyle; } diff --git a/test/testDynArray.cc b/test/testDynArray.cc index 5db6131e..7f1e1b6b 100644 --- a/test/testDynArray.cc +++ b/test/testDynArray.cc @@ -1,59 +1,59 @@ -#include "fmt/core.h" -#include "opengl/GrailGUI.hh" -#include "util/DynArray.hh" - -using namespace std; - -template -constexpr void printarr(string msg, uint32_t size, DynArray arr) { - fmt::print("{}", msg); - for (int i = 0; i < size; ++i) { - cout << arr[i] << ","; - } - fmt::print("\n"); -} - -template -constexpr void printarr(string msg, uint32_t size, DynArray arr) { - fmt::print("{}", msg); - for (int i = 0; i < size; ++i) { - fmt::print("{},", arr[i]); - } - fmt::print("\n"); -} - -int main() { - DynArray arr(10); - for (int i = 0; i < 10; i++) { - arr.add(i); - } - - printarr("new array of uint32_t: \n", 10, arr); - - int removedInt = arr.removeAt(5); - fmt::print("Removed value {} at index 5\n", removedInt); - - printarr("array of uint32_t after deletion: \n", 9, arr); - - GLWin w(1024, 800, 0xFFFFFFFF, 0x000000FF, "gw"); - DynArray tabs(4); - for (int i = 0; i < 4; i++) { - tabs.add(new Tab(&w)); - } - - printarr("new array of tabs: \n", 4, tabs); - - Tab* removedTab = tabs.removeAt(2); - cout << "Removed value " << removedTab << " at index 2\n"; - - printarr("array of tabs after deletion: \n", 3, tabs); - - DynArray strs(4); - strs.add("a"); - strs.add("B"); - strs.add("c"); - printarr("new array of strings: \n", 3, strs); - string removedString = strs.removeAt(1); - fmt::print("Removed value {} at index 1\n", removedString); - printarr("array of tabs after deletion: \n", 2, strs); +#include "fmt/core.h" +#include "opengl/GrailGUI.hh" +#include "util/DynArray.hh" + +using namespace std; + +template +constexpr void printarr(string msg, uint32_t size, DynArray arr) { + fmt::print("{}", msg); + for (int i = 0; i < size; ++i) { + cout << arr[i] << ","; + } + fmt::print("\n"); +} + +template +constexpr void printarr(string msg, uint32_t size, DynArray arr) { + fmt::print("{}", msg); + for (int i = 0; i < size; ++i) { + fmt::print("{},", arr[i]); + } + fmt::print("\n"); +} + +int main() { + DynArray arr(10); + for (int i = 0; i < 10; i++) { + arr.add(i); + } + + printarr("new array of uint32_t: \n", 10, arr); + + int removedInt = arr.removeAt(5); + fmt::print("Removed value {} at index 5\n", removedInt); + + printarr("array of uint32_t after deletion: \n", 9, arr); + + GLWin w(1024, 800, 0xFFFFFFFF, 0x000000FF, "gw"); + DynArray tabs(4); + for (int i = 0; i < 4; i++) { + tabs.add(new Tab(&w)); + } + + printarr("new array of tabs: \n", 4, tabs); + + Tab* removedTab = tabs.removeAt(2); + cout << "Removed value " << removedTab << " at index 2\n"; + + printarr("array of tabs after deletion: \n", 3, tabs); + + DynArray strs(4); + strs.add("a"); + strs.add("B"); + strs.add("c"); + printarr("new array of strings: \n", 3, strs); + string removedString = strs.removeAt(1); + fmt::print("Removed value {} at index 1\n", removedString); + printarr("array of tabs after deletion: \n", 2, strs); } \ No newline at end of file diff --git a/test/util/DateDemo.cc b/test/util/DateDemo.cc index 50807ec5..28822ad7 100644 --- a/test/util/DateDemo.cc +++ b/test/util/DateDemo.cc @@ -1,21 +1,21 @@ -#include - -#include "../src/util/JulianDate.hh" -#include "opengl/GrailGUI.hh" -using namespace std; -using namespace grail; - -class DateDemo : public GLWin { - public: - DateDemo() : GLWin(0x000000, 0xCCCCCC, "Test Date") {} - - void init() { - MainCanvas* c = currentTab()->getMainCanvas(); - StyledMultiShape2D* gui = c->getGui(); - MultiText* guiText = c->getGuiText(); - - JulianDate a(12, 1, 12); - } -}; - -int main(int argc, char* argv[]) { return GLWin::init(new DateDemo()); } +#include + +#include "../src/util/JulianDate.hh" +#include "opengl/GrailGUI.hh" +using namespace std; +using namespace grail; + +class DateDemo : public GLWin { + public: + DateDemo() : GLWin(0x000000, 0xCCCCCC, "Test Date") {} + + void init() { + MainCanvas* c = currentTab()->getMainCanvas(); + StyledMultiShape2D* gui = c->getGui(); + MultiText* guiText = c->getGuiText(); + + JulianDate a(12, 1, 12); + } +}; + +int main(int argc, char* argv[]) { return GLWin::init(new DateDemo()); } diff --git a/test/xdl/GenericXDLClient.cc b/test/xdl/GenericXDLClient.cc index 95317ea2..2e2ac9c2 100644 --- a/test/xdl/GenericXDLClient.cc +++ b/test/xdl/GenericXDLClient.cc @@ -1,59 +1,59 @@ -#include "csp/IPV4Socket.hh" -#include "csp/csp.hh" -//#include -#include "opengl/GLWin.hh" -#include "xdl/XDLCompiler.hh" -#include "xdl/std.hh" -using namespace std; - -Log srvlog; // log all important events for security and debugging - -/* - This generic client demonstrates the ability to send a request to an XDL - server, and get in response metadata and then data By reading the metadata, - the client can then print out ASCII views of the data. - - This is a standalone demo that does not require Grail graphics. - The next step after this is to display the data directly on a Grail window - - Known issues at this time: - 1. Not all data types are implemented yet, ie don't send JPEG or BLOB. - We focus mostly on numbers, strings, lists and struct for proof of concept. - - 2. Formatting is very ad hoc and not efficient. We need to come up with a way - to define good formatting that is fast. C++ recently added format, we should - take a look - -*/ -int main(int argc, char* argv[]) { - const char* ip = argc > 1 ? argv[1] : "127.0.0.1"; - int port = argc > 2 ? atoi(argv[2]) : 8060; - uint32_t req = argc > 3 ? atoi(argv[3]) : 0; - GLWin::classInit(); - try { - IPV4Socket s(ip, port); - s.send(req); - Buffer& in = s.getIn(); - in.displayRawRead(); - XDLCompiler compiler(""); - SymbolTable* st = new SymbolTable(&compiler); - const XDLType* metadata = XDLType::readMeta(&compiler, in); - Buffer out("client.txt", 32768); - - metadata->display(in, out); - /* - const Struct* root = (Struct*)st.getRoot(); - // dump all metadata, whether used in the data or not - for (int i = 0; i < root->getMemberCount(); i++) - cout << root->getMemberName(i) << '\t'; - cout << '\n'; - - root->display(in, out); - out.displayText(cout); -*/ - } catch (const Ex& e) { - cerr << e << '\n'; - } - GLWin::classCleanup(); - return 0; -} +#include "csp/IPV4Socket.hh" +#include "csp/csp.hh" +//#include +#include "opengl/GLWin.hh" +#include "xdl/XDLCompiler.hh" +#include "xdl/std.hh" +using namespace std; + +Log srvlog; // log all important events for security and debugging + +/* + This generic client demonstrates the ability to send a request to an XDL + server, and get in response metadata and then data By reading the metadata, + the client can then print out ASCII views of the data. + + This is a standalone demo that does not require Grail graphics. + The next step after this is to display the data directly on a Grail window + + Known issues at this time: + 1. Not all data types are implemented yet, ie don't send JPEG or BLOB. + We focus mostly on numbers, strings, lists and struct for proof of concept. + + 2. Formatting is very ad hoc and not efficient. We need to come up with a way + to define good formatting that is fast. C++ recently added format, we should + take a look + +*/ +int main(int argc, char* argv[]) { + const char* ip = argc > 1 ? argv[1] : "127.0.0.1"; + int port = argc > 2 ? atoi(argv[2]) : 8060; + uint32_t req = argc > 3 ? atoi(argv[3]) : 0; + GLWin::classInit(); + try { + IPV4Socket s(ip, port); + s.send(req); + Buffer& in = s.getIn(); + in.displayRawRead(); + XDLCompiler compiler(""); + SymbolTable* st = new SymbolTable(&compiler); + const XDLType* metadata = XDLType::readMeta(&compiler, in); + Buffer out("client.txt", 32768); + + metadata->display(in, out); + /* + const Struct* root = (Struct*)st.getRoot(); + // dump all metadata, whether used in the data or not + for (int i = 0; i < root->getMemberCount(); i++) + cout << root->getMemberName(i) << '\t'; + cout << '\n'; + + root->display(in, out); + out.displayText(cout); +*/ + } catch (const Ex& e) { + cerr << e << '\n'; + } + GLWin::classCleanup(); + return 0; +} diff --git a/test/xdl/GraphicalXDLClient.cc b/test/xdl/GraphicalXDLClient.cc index 6c662602..b94c3683 100644 --- a/test/xdl/GraphicalXDLClient.cc +++ b/test/xdl/GraphicalXDLClient.cc @@ -1,376 +1,376 @@ -#include "csp/IPV4Socket.hh" -#include "csp/XDLRequest.hh" -//#include "csp/csp.hh" -//#include -#include - -#include "opengl/GrailGUI.hh" -#include "util/Buffer.hh" -#include "util/DynArray.hh" -#include "util/HashMap.hh" -#include "xdl/XDLCompiler.hh" -#include "xdl/std.hh" -using namespace std; - -/** - * @brief Renders incoming data based on the metadata from Buffer to screen - * - * Renderer has state to track current location on the screen (visual cursor) - * and iterators within the object to track position within the data. - * For a large object such as a list, the renderer might only display the - * visible subset and stop. - * - */ -class Renderer { - public: - /** - * @brief A struct containing the top-left corner, width, and height of a - * bounding box - */ - struct BoundBox { - float x0, y0; - uint32_t width, height; - - BoundBox(float x, float y, uint32_t w, uint32_t h) - : x0(x), y0(y), width(w), height(h) {} - }; - typedef void (Renderer::*Method)(XDLIterator&); - - private: - XDLType* it; /**< the iterator to the XDLType to be drawn */ - XDLIterator* lastPage; /**< Stores the start of the current page*/ - XDLIterator* endPage; /**< Stores the end of the current page*/ - StyledMultiShape2D* m; /**< Stores and renders graphics onto the screen */ - MultiText* t; /**< Stores and renders text onto the screen */ - - /**< A dynamic array of top level structures, used for iterating between - * top-level structures */ - DynArray& requests; - - /**< A hashmap of the top-level structures, used for quick lookups */ - HashMap& byName; - std::unordered_map renderMap; - - Buffer& in; /**< A buffer containing the data to be rendered */ - - /**< Store the data for this object so we can go backwards and possibly save - * locally */ - DynArray dataBuffer; - BoundBox bounds; - - /**< Size for each row of data, related to font + spacing if it's text */ - float rowSize; - float x, y; /**< Current render position */ - - void registerRenderers() { - registerRenderer(DataType::STRUCT8, &Renderer::renderStructAcross); - registerRenderer(DataType::LIST16, &Renderer::renderListDown); - registerRenderer(DataType::U32, &Renderer::renderU32); - registerRenderer(DataType::U64, &Renderer::renderU64); - registerRenderer(DataType::F32, &Renderer::renderF32); - registerRenderer(DataType::F64, &Renderer::renderF64); - } - - public: - /** - * @brief Construct a new Renderer object - * - * @param it An XDLIterator to iterate through the data - * @param c A Canvas to draw on - * @param requests A dynamic array of top-level structures - * @param byName A hashmap of top-level structures - * @param in A buffer containing the data to be rendered - */ - Renderer(XDLType* it, MainCanvas* c, DynArray& requests, - HashMap& byName, Buffer& in) - : it(it), - m(c->getGui()), - t(c->getGuiText()), - dataBuffer(65536), - requests(requests), - byName(byName), - renderMap(65536), - in(in), - bounds(0, 0, c->getWidth(), c->getHeight()), - rowSize(20), - x(bounds.x0), - y(bounds.y0 + rowSize) { - // registerIterator(it); - registerRenderers(); - } - - /** - * @brief Construct a new Renderer object - * - * @param it An XDLIterator to iterate through the data - * @param c A Canvas to draw on - * @param requests A dynamic array of top-level structures - * @param byName A hashmap of top-level structures - * @param in A buffer containing the data to be rendered - * @param b A bounding box containing the top-left corner, width, and height - */ - Renderer(XDLType* it, MainCanvas* c, DynArray& requests, - HashMap& byName, Buffer& in, const BoundBox& b) - : it(it), - m(c->getGui()), - t(c->getGuiText()), - requests(requests), - byName(byName), - renderMap(65536), - in(in), - dataBuffer(65536), - bounds(b) { - // registerIterator(it); - registerRenderers(); - } - - /** - * @brief Construct a new Renderer object - * - * @param it An XDLIterator to iterate through the data - * @param c A Canvas to draw on - * @param requests A dynamic array of top-level structures - * @param byName A hashmap of top-level structures - * @param in A buffer containing the data to be rendered - * @param x0 The top-left x coordinate of the bounding box - * @param y0 The top-left y coordinate of the bounding box - * @param width The width of the bounding box - * @param height The height of the bounding box - */ - Renderer(XDLType* it, MainCanvas* c, DynArray& requests, - HashMap& byName, Buffer& in, const float& x0, - const float& y0, const uint32_t& width, const uint32_t& height) - : Renderer(it, c, requests, byName, in, BoundBox(x0, y0, width, height)) { - } - - Method* rendererFind(DataType t) { - auto i = renderMap.find(t); - if (i == renderMap.end()) return nullptr; - return &i->second; - } - - Method* rendererFind(XDLType* t) { - XDLIterator* comp = dynamic_cast(t); - if (comp) { - auto i = renderMap.find((comp->getUnderlying()->getDataType())); - if (i != renderMap.end()) return &i->second; - } - return nullptr; - } - - void registerRenderer(DataType t, Method m) { renderMap[t] = m; } - void renderListDown(XDLIterator& parentIterator); - void renderStructAcross(XDLIterator& parentIterator); - void renderSubStructAcross(Struct* s); - void renderStructNameValue(); - void renderObjectMetadataAcross(XDLIterator& parentIterator); - void renderU32(XDLIterator&); - void renderU64(XDLIterator&); - void renderF32(XDLIterator&); - void renderF64(XDLIterator&); - void nextPage(); - void prevPage(); - void update(); -}; - -void Renderer::update() { - t->clear(); - m->clear(); - Method* elementRenderer = rendererFind(it); - if (!elementRenderer) { - cerr << "bad renderer"; - return; - } - XDLIterator* i = dynamic_cast(it); - if (i == nullptr) { - cerr << "the page iterator is not an iterator, not drawing"; - return; - } - (this->**elementRenderer)(*i); -} - -void Renderer::nextPage() { - lastPage = ((XDLIterator*)it)->clone(); - it = endPage; -} - -void Renderer::prevPage() { it = lastPage; } - -void Renderer::renderListDown(XDLIterator& parentIterator) { - GenericList::Iterator* currentPage = - dynamic_cast(&parentIterator); - if (currentPage == nullptr) { - cerr << "Expected generic list!"; - return; - } - GenericList::Iterator i = - *currentPage; // make a copy to work with to draw this screenful - XDLType* elementType = i.getListType(); - Method* elementRenderer = rendererFind(elementType->getDataType()); - if (!elementRenderer) { - cerr << "bad renderer"; - return; - } - for (; !i && y < bounds.height; ++i, y += rowSize) { - x = bounds.x0; - XDLIterator* childIterator = (XDLIterator*)((GenericList*)i.getUnderlying()) - ->getListType() - ->begin(in); - // call the appropriate renderer for this object - (this->**elementRenderer)(*childIterator); - delete childIterator; - } - endPage = new GenericList::Iterator(i); -} - -void Renderer::renderObjectMetadataAcross(XDLIterator& parentIterator) { - Struct::Iterator* i = dynamic_cast(&parentIterator); - Struct* s = i->getStruct(); - if (i == nullptr) { - cerr << "Expected generic list!"; - return; - } - for (uint32_t i = 0; i < s->getMemberCount(); i++) { - /* - * Struct::Member is protected, need to use s->getMembers(i).type to get - * XDLType - */ - // const Struct::Member& m = s->getMembers(i); - // string memberName = s->getMemberName(); - // TODO: print across page - } - // endPage = current iterator position; -} - -void Renderer::renderStructAcross(XDLIterator& parentIterator) { - Struct::Iterator* currentPosition = - dynamic_cast(&parentIterator); - if (currentPosition == nullptr) { - cerr << "Expected structure!"; - return; - } - Struct* s = currentPosition->getStruct(); - Method elementRenderer; - - for (Struct::Iterator j = *currentPosition; !j; ++j) { - const XDLType* m = *j; - if (m->getDataType() == DataType::STRUCT8) { - renderSubStructAcross((Struct*)m); - } else { - Method* elementRenderer = rendererFind(m->getDataType()); - if (!elementRenderer) { - cerr << "bad renderer datatype=" << uint32_t(m->getDataType()) - << " typename=" << m->getTypeName() << '\n'; - } - (this->**elementRenderer)(j); - x += 150; - } - } -} - -void Renderer::renderSubStructAcross(Struct* s) { - Method elementRenderer; - - for (Struct::Iterator j(s); !j; ++j) { - const XDLType* m = *j; - if (m->getDataType() == DataType::STRUCT8) { - renderSubStructAcross((Struct*)m); - } else { - Method* elementRenderer = rendererFind(m->getDataType()); - if (!elementRenderer) { - cerr << "bad renderer datatype=" << uint32_t(m->getDataType()) - << " typename=" << m->getTypeName() << '\n'; - } - (this->**elementRenderer)(j); - } - x += 150; - } -} - -void Renderer::renderStructNameValue() { return; } -void Renderer::renderU32(XDLIterator&) { - Buffer& incpy = in; - t->add(x, y, in.readU32()); -} -void Renderer::renderU64(XDLIterator&) { t->add(x, y, in.readU64()); } -void Renderer::renderF32(XDLIterator&) { t->add(x, y, in.readF32()); } -void Renderer::renderF64(XDLIterator&) { t->add(x, y, in.readF64()); } - -/* - This generic client demonstrates the ability to send a request to an XDL - server, and draw the data returned on screen, paging through the data - if it's too big. - - Known issues at this time: - 1. Not all data types are implemented yet, ie don't send JPEG or BLOB. - We focus mostly on numbers, strings, lists and struct for proof of concept. - - 2. Formatting is very ad hoc and not efficient. We need to come up with a - way to define good formatting that is fast. C++ recently added format, we - should take a look -*/ - -class GraphicalXDLClient : public GLWin { - private: - IPV4Socket s; - uint32_t reqID; - const XDLType* latest; - DynArray requests; - HashMap byName; - XDLIterator* currentPos; - Renderer* r; - - set structTypes = {DataType::STRUCT8, DataType::STRUCT16, - DataType::STRUCT32}; - - void add(const XDLType* t) { - requests.add(t); - byName.add(t->getTypeName().c_str(), t->getTypeName().length(), t); - } - - public: - GraphicalXDLClient(const char* const ip, int port, uint32_t req) - : GLWin(0x000000, 0xCCCCCC, "Grail Graphical Generic Client"), - s(ip, port), - reqID(req), - requests(64), - byName(64) {} - void readData(uint32_t req) { - s.send(req); - Buffer& in = s.getIn(); - in.displayRawRead(); - XDLCompiler compiler(""); - // SymbolTable st(&compiler); - XDLType* latest = (XDLType*)XDLType::readMeta(&compiler, in); - add(latest); - float rowSize = 20; - - r = new Renderer(latest->begin(in), currentTab()->getMainCanvas(), requests, - byName, in); - // TODO: if we call readData multiple times, delete the old renderer before - // replacing it - } - void init() { - readData(reqID); - bindEvent(Inputs::PAGEDOWN, &GraphicalXDLClient::pageDown, this); - update(); - } - - void update() { r->update(); } - void pageDown() { - r->nextPage(); - setDirty(); - } - - void pageUp() { - r->prevPage(); - setDirty(); - } -}; -int main(int argc, char* argv[]) { - const char* const ip = argc > 1 ? argv[1] : "127.0.0.1"; - int port = argc > 2 ? atoi(argv[2]) : 8060; - uint32_t req = argc > 3 ? atoi(argv[3]) : 0; - GLWin::init(new GraphicalXDLClient(ip, port, req)); - return 0; -} +#include "csp/IPV4Socket.hh" +#include "csp/XDLRequest.hh" +//#include "csp/csp.hh" +//#include +#include + +#include "opengl/GrailGUI.hh" +#include "util/Buffer.hh" +#include "util/DynArray.hh" +#include "util/HashMap.hh" +#include "xdl/XDLCompiler.hh" +#include "xdl/std.hh" +using namespace std; + +/** + * @brief Renders incoming data based on the metadata from Buffer to screen + * + * Renderer has state to track current location on the screen (visual cursor) + * and iterators within the object to track position within the data. + * For a large object such as a list, the renderer might only display the + * visible subset and stop. + * + */ +class Renderer { + public: + /** + * @brief A struct containing the top-left corner, width, and height of a + * bounding box + */ + struct BoundBox { + float x0, y0; + uint32_t width, height; + + BoundBox(float x, float y, uint32_t w, uint32_t h) + : x0(x), y0(y), width(w), height(h) {} + }; + typedef void (Renderer::*Method)(XDLIterator&); + + private: + XDLType* it; /**< the iterator to the XDLType to be drawn */ + XDLIterator* lastPage; /**< Stores the start of the current page*/ + XDLIterator* endPage; /**< Stores the end of the current page*/ + StyledMultiShape2D* m; /**< Stores and renders graphics onto the screen */ + MultiText* t; /**< Stores and renders text onto the screen */ + + /**< A dynamic array of top level structures, used for iterating between + * top-level structures */ + DynArray& requests; + + /**< A hashmap of the top-level structures, used for quick lookups */ + HashMap& byName; + std::unordered_map renderMap; + + Buffer& in; /**< A buffer containing the data to be rendered */ + + /**< Store the data for this object so we can go backwards and possibly save + * locally */ + DynArray dataBuffer; + BoundBox bounds; + + /**< Size for each row of data, related to font + spacing if it's text */ + float rowSize; + float x, y; /**< Current render position */ + + void registerRenderers() { + registerRenderer(DataType::STRUCT8, &Renderer::renderStructAcross); + registerRenderer(DataType::LIST16, &Renderer::renderListDown); + registerRenderer(DataType::U32, &Renderer::renderU32); + registerRenderer(DataType::U64, &Renderer::renderU64); + registerRenderer(DataType::F32, &Renderer::renderF32); + registerRenderer(DataType::F64, &Renderer::renderF64); + } + + public: + /** + * @brief Construct a new Renderer object + * + * @param it An XDLIterator to iterate through the data + * @param c A Canvas to draw on + * @param requests A dynamic array of top-level structures + * @param byName A hashmap of top-level structures + * @param in A buffer containing the data to be rendered + */ + Renderer(XDLType* it, MainCanvas* c, DynArray& requests, + HashMap& byName, Buffer& in) + : it(it), + m(c->getGui()), + t(c->getGuiText()), + dataBuffer(65536), + requests(requests), + byName(byName), + renderMap(65536), + in(in), + bounds(0, 0, c->getWidth(), c->getHeight()), + rowSize(20), + x(bounds.x0), + y(bounds.y0 + rowSize) { + // registerIterator(it); + registerRenderers(); + } + + /** + * @brief Construct a new Renderer object + * + * @param it An XDLIterator to iterate through the data + * @param c A Canvas to draw on + * @param requests A dynamic array of top-level structures + * @param byName A hashmap of top-level structures + * @param in A buffer containing the data to be rendered + * @param b A bounding box containing the top-left corner, width, and height + */ + Renderer(XDLType* it, MainCanvas* c, DynArray& requests, + HashMap& byName, Buffer& in, const BoundBox& b) + : it(it), + m(c->getGui()), + t(c->getGuiText()), + requests(requests), + byName(byName), + renderMap(65536), + in(in), + dataBuffer(65536), + bounds(b) { + // registerIterator(it); + registerRenderers(); + } + + /** + * @brief Construct a new Renderer object + * + * @param it An XDLIterator to iterate through the data + * @param c A Canvas to draw on + * @param requests A dynamic array of top-level structures + * @param byName A hashmap of top-level structures + * @param in A buffer containing the data to be rendered + * @param x0 The top-left x coordinate of the bounding box + * @param y0 The top-left y coordinate of the bounding box + * @param width The width of the bounding box + * @param height The height of the bounding box + */ + Renderer(XDLType* it, MainCanvas* c, DynArray& requests, + HashMap& byName, Buffer& in, const float& x0, + const float& y0, const uint32_t& width, const uint32_t& height) + : Renderer(it, c, requests, byName, in, BoundBox(x0, y0, width, height)) { + } + + Method* rendererFind(DataType t) { + auto i = renderMap.find(t); + if (i == renderMap.end()) return nullptr; + return &i->second; + } + + Method* rendererFind(XDLType* t) { + XDLIterator* comp = dynamic_cast(t); + if (comp) { + auto i = renderMap.find((comp->getUnderlying()->getDataType())); + if (i != renderMap.end()) return &i->second; + } + return nullptr; + } + + void registerRenderer(DataType t, Method m) { renderMap[t] = m; } + void renderListDown(XDLIterator& parentIterator); + void renderStructAcross(XDLIterator& parentIterator); + void renderSubStructAcross(Struct* s); + void renderStructNameValue(); + void renderObjectMetadataAcross(XDLIterator& parentIterator); + void renderU32(XDLIterator&); + void renderU64(XDLIterator&); + void renderF32(XDLIterator&); + void renderF64(XDLIterator&); + void nextPage(); + void prevPage(); + void update(); +}; + +void Renderer::update() { + t->clear(); + m->clear(); + Method* elementRenderer = rendererFind(it); + if (!elementRenderer) { + cerr << "bad renderer"; + return; + } + XDLIterator* i = dynamic_cast(it); + if (i == nullptr) { + cerr << "the page iterator is not an iterator, not drawing"; + return; + } + (this->**elementRenderer)(*i); +} + +void Renderer::nextPage() { + lastPage = ((XDLIterator*)it)->clone(); + it = endPage; +} + +void Renderer::prevPage() { it = lastPage; } + +void Renderer::renderListDown(XDLIterator& parentIterator) { + GenericList::Iterator* currentPage = + dynamic_cast(&parentIterator); + if (currentPage == nullptr) { + cerr << "Expected generic list!"; + return; + } + GenericList::Iterator i = + *currentPage; // make a copy to work with to draw this screenful + XDLType* elementType = i.getListType(); + Method* elementRenderer = rendererFind(elementType->getDataType()); + if (!elementRenderer) { + cerr << "bad renderer"; + return; + } + for (; !i && y < bounds.height; ++i, y += rowSize) { + x = bounds.x0; + XDLIterator* childIterator = (XDLIterator*)((GenericList*)i.getUnderlying()) + ->getListType() + ->begin(in); + // call the appropriate renderer for this object + (this->**elementRenderer)(*childIterator); + delete childIterator; + } + endPage = new GenericList::Iterator(i); +} + +void Renderer::renderObjectMetadataAcross(XDLIterator& parentIterator) { + Struct::Iterator* i = dynamic_cast(&parentIterator); + Struct* s = i->getStruct(); + if (i == nullptr) { + cerr << "Expected generic list!"; + return; + } + for (uint32_t i = 0; i < s->getMemberCount(); i++) { + /* + * Struct::Member is protected, need to use s->getMembers(i).type to get + * XDLType + */ + // const Struct::Member& m = s->getMembers(i); + // string memberName = s->getMemberName(); + // TODO: print across page + } + // endPage = current iterator position; +} + +void Renderer::renderStructAcross(XDLIterator& parentIterator) { + Struct::Iterator* currentPosition = + dynamic_cast(&parentIterator); + if (currentPosition == nullptr) { + cerr << "Expected structure!"; + return; + } + Struct* s = currentPosition->getStruct(); + Method elementRenderer; + + for (Struct::Iterator j = *currentPosition; !j; ++j) { + const XDLType* m = *j; + if (m->getDataType() == DataType::STRUCT8) { + renderSubStructAcross((Struct*)m); + } else { + Method* elementRenderer = rendererFind(m->getDataType()); + if (!elementRenderer) { + cerr << "bad renderer datatype=" << uint32_t(m->getDataType()) + << " typename=" << m->getTypeName() << '\n'; + } + (this->**elementRenderer)(j); + x += 150; + } + } +} + +void Renderer::renderSubStructAcross(Struct* s) { + Method elementRenderer; + + for (Struct::Iterator j(s); !j; ++j) { + const XDLType* m = *j; + if (m->getDataType() == DataType::STRUCT8) { + renderSubStructAcross((Struct*)m); + } else { + Method* elementRenderer = rendererFind(m->getDataType()); + if (!elementRenderer) { + cerr << "bad renderer datatype=" << uint32_t(m->getDataType()) + << " typename=" << m->getTypeName() << '\n'; + } + (this->**elementRenderer)(j); + } + x += 150; + } +} + +void Renderer::renderStructNameValue() { return; } +void Renderer::renderU32(XDLIterator&) { + Buffer& incpy = in; + t->add(x, y, in.readU32()); +} +void Renderer::renderU64(XDLIterator&) { t->add(x, y, in.readU64()); } +void Renderer::renderF32(XDLIterator&) { t->add(x, y, in.readF32()); } +void Renderer::renderF64(XDLIterator&) { t->add(x, y, in.readF64()); } + +/* + This generic client demonstrates the ability to send a request to an XDL + server, and draw the data returned on screen, paging through the data + if it's too big. + + Known issues at this time: + 1. Not all data types are implemented yet, ie don't send JPEG or BLOB. + We focus mostly on numbers, strings, lists and struct for proof of concept. + + 2. Formatting is very ad hoc and not efficient. We need to come up with a + way to define good formatting that is fast. C++ recently added format, we + should take a look +*/ + +class GraphicalXDLClient : public GLWin { + private: + IPV4Socket s; + uint32_t reqID; + const XDLType* latest; + DynArray requests; + HashMap byName; + XDLIterator* currentPos; + Renderer* r; + + set structTypes = {DataType::STRUCT8, DataType::STRUCT16, + DataType::STRUCT32}; + + void add(const XDLType* t) { + requests.add(t); + byName.add(t->getTypeName().c_str(), t->getTypeName().length(), t); + } + + public: + GraphicalXDLClient(const char* const ip, int port, uint32_t req) + : GLWin(0x000000, 0xCCCCCC, "Grail Graphical Generic Client"), + s(ip, port), + reqID(req), + requests(64), + byName(64) {} + void readData(uint32_t req) { + s.send(req); + Buffer& in = s.getIn(); + in.displayRawRead(); + XDLCompiler compiler(""); + // SymbolTable st(&compiler); + XDLType* latest = (XDLType*)XDLType::readMeta(&compiler, in); + add(latest); + float rowSize = 20; + + r = new Renderer(latest->begin(in), currentTab()->getMainCanvas(), requests, + byName, in); + // TODO: if we call readData multiple times, delete the old renderer before + // replacing it + } + void init() { + readData(reqID); + bindEvent(Inputs::PAGEDOWN, &GraphicalXDLClient::pageDown, this); + update(); + } + + void update() { r->update(); } + void pageDown() { + r->nextPage(); + setDirty(); + } + + void pageUp() { + r->prevPage(); + setDirty(); + } +}; +int main(int argc, char* argv[]) { + const char* const ip = argc > 1 ? argv[1] : "127.0.0.1"; + int port = argc > 2 ? atoi(argv[2]) : 8060; + uint32_t req = argc > 3 ? atoi(argv[3]) : 0; + GLWin::init(new GraphicalXDLClient(ip, port, req)); + return 0; +} diff --git a/test/xdl/SimpleXDLServer.cc b/test/xdl/SimpleXDLServer.cc index 0abcffc1..1dd64d13 100644 --- a/test/xdl/SimpleXDLServer.cc +++ b/test/xdl/SimpleXDLServer.cc @@ -1,29 +1,29 @@ -#include "csp/csp.hh" -// our application errors must be defined before Ex.hh -#include "csp/IPV4Socket.hh" -#include "csp/XDLRequest.hh" -#include "opengl/GLWin.hh" -//#include "XDLServlet.hh" -#include -using namespace std; - -Log srvlog; // log all important events for security and debugging - -// Signal Handlers will not work see below: -// https://stackoverflow.com/questions/51169357/unable-to-catch-sigint-sent-by-clion -// However the solution there introduces other issues so code is left as is - -int main(int argc, char* argv[]) { - int port = argc > 1 ? atoi(argv[1]) : 8060; - GLWin::classInit(); - try { - IPV4Socket s(port); - XDLRequest req("conf/test1.xdl"); - s.attach(&req); - s.wait(); // main server wait loop - } catch (const Ex& e) { - cerr << e << '\n'; - } - GLWin::classCleanup(); - return 0; -} +#include "csp/csp.hh" +// our application errors must be defined before Ex.hh +#include "csp/IPV4Socket.hh" +#include "csp/XDLRequest.hh" +#include "opengl/GLWin.hh" +//#include "XDLServlet.hh" +#include +using namespace std; + +Log srvlog; // log all important events for security and debugging + +// Signal Handlers will not work see below: +// https://stackoverflow.com/questions/51169357/unable-to-catch-sigint-sent-by-clion +// However the solution there introduces other issues so code is left as is + +int main(int argc, char* argv[]) { + int port = argc > 1 ? atoi(argv[1]) : 8060; + GLWin::classInit(); + try { + IPV4Socket s(port); + XDLRequest req("conf/test1.xdl"); + s.attach(&req); + s.wait(); // main server wait loop + } catch (const Ex& e) { + cerr << e << '\n'; + } + GLWin::classCleanup(); + return 0; +} diff --git a/test/xdl/StockDemo.cc b/test/xdl/StockDemo.cc index 5abec01a..4312bd00 100644 --- a/test/xdl/StockDemo.cc +++ b/test/xdl/StockDemo.cc @@ -1,73 +1,73 @@ -#include -#include -#include -#include -#include -#include - -#include "opengl/ButtonWidget.hh" -#include "opengl/GrailGUI.hh" -#include "opengl/LineGraphWidget.hh" -using namespace std; -using namespace grail; - -class StockDemo : public GLWin { - public: - StockDemo() : GLWin(0x000000, 0xCCCCCC, "Stock Demo") {} - - vector openFile(const char name[]) { - fstream file; - vector v; - // Read file - file.open(name, ios::in); // Open file - if (file.is_open()) { // If file has correctly opened... - // Output debug message - cout << "File correctly opened" << endl; - - string temp; - float x, y; - // Dynamically store data into array - while (file.peek() != EOF) { // ... and while there are no errors, - getline(file, temp, '\n'); - v.push_back(atof(temp.c_str())); - } - } else - cout << "Unable to open file" << endl; - file.close(); - return v; - } - - void init() { - MainCanvas* c = currentTab()->getMainCanvas(); - StyledMultiShape2D* gui = c->getGui(); - MultiText* guiText = c->getGuiText(); - - vector GME = openFile("GME.csv"); - vector AAPL = openFile("AAPL.csv"); - vector NTDOY = openFile("NTDOY.csv"); - vector AMC = openFile("AMC.csv"); - - vector day; - for (int i = 0; i < AMC.size(); i++) day.push_back(i); - -#if 0 - LineGraphWidget chart(gui, guiText, 100, 320, 800, 400); - chart.axes("Days",4,"Price ($)",9,day.size(),75,day.size()-100,0,10,10,day.size()-100,day.size()); - chart.add(day, GME, blue, "GME"); - //chart.add(day, AAPL, red, "AAPL"); - chart.add(day, NTDOY, green, "NTDOY"); - chart.add(day, AMC, purple, "AMC"); - chart.title("Daily High of GME, and NTDOY Stocks Since 2010"); - chart.legend(100,800); - chart.init(); - //TODO:Add xAxis and yAxis label funcs - //TODO:Add legend to all graphwidgets - //TODO:Fix chart axis ticker in chart(), maybe move to init() - //TODO:Iterations of chart funcs - //TODO:Custom Locations of axes labels - //TODO:Comment code -#endif - } -}; - -int main(int argc, char* argv[]) { return GLWin::init(new StockDemo()); } +#include +#include +#include +#include +#include +#include + +#include "opengl/ButtonWidget.hh" +#include "opengl/GrailGUI.hh" +#include "opengl/LineGraphWidget.hh" +using namespace std; +using namespace grail; + +class StockDemo : public GLWin { + public: + StockDemo() : GLWin(0x000000, 0xCCCCCC, "Stock Demo") {} + + vector openFile(const char name[]) { + fstream file; + vector v; + // Read file + file.open(name, ios::in); // Open file + if (file.is_open()) { // If file has correctly opened... + // Output debug message + cout << "File correctly opened" << endl; + + string temp; + float x, y; + // Dynamically store data into array + while (file.peek() != EOF) { // ... and while there are no errors, + getline(file, temp, '\n'); + v.push_back(atof(temp.c_str())); + } + } else + cout << "Unable to open file" << endl; + file.close(); + return v; + } + + void init() { + MainCanvas* c = currentTab()->getMainCanvas(); + StyledMultiShape2D* gui = c->getGui(); + MultiText* guiText = c->getGuiText(); + + vector GME = openFile("GME.csv"); + vector AAPL = openFile("AAPL.csv"); + vector NTDOY = openFile("NTDOY.csv"); + vector AMC = openFile("AMC.csv"); + + vector day; + for (int i = 0; i < AMC.size(); i++) day.push_back(i); + +#if 0 + LineGraphWidget chart(gui, guiText, 100, 320, 800, 400); + chart.axes("Days",4,"Price ($)",9,day.size(),75,day.size()-100,0,10,10,day.size()-100,day.size()); + chart.add(day, GME, blue, "GME"); + //chart.add(day, AAPL, red, "AAPL"); + chart.add(day, NTDOY, green, "NTDOY"); + chart.add(day, AMC, purple, "AMC"); + chart.title("Daily High of GME, and NTDOY Stocks Since 2010"); + chart.legend(100,800); + chart.init(); + //TODO:Add xAxis and yAxis label funcs + //TODO:Add legend to all graphwidgets + //TODO:Fix chart axis ticker in chart(), maybe move to init() + //TODO:Iterations of chart funcs + //TODO:Custom Locations of axes labels + //TODO:Comment code +#endif + } +}; + +int main(int argc, char* argv[]) { return GLWin::init(new StockDemo()); } diff --git a/test/xp/plot.cc b/test/xp/plot.cc index b0aaa9d2..01aafd99 100644 --- a/test/xp/plot.cc +++ b/test/xp/plot.cc @@ -1,256 +1,256 @@ -#include "plot.hh" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "opengl/GLMath.hh" -#include "opengl/GLWin.hh" -#include "opengl/GLWinFonts.hh" -#include "opengl/MultiShape2D.hh" -#include "opengl/Style.hh" -#include "opengl/Tab.hh" -#include "opengl/Text.hh" -using namespace std; - -PointPlot::PointPlot(shared_ptr tab, float x, float y, float w, float h) { - const Font *font = FontFace::get("TIMES", 30, FontFace::BOLD); - srand(time(NULL)); - - float r = (float)((rand() % (10 - 4 + 1) + 4) / 10.0); - float g = (float)((rand() % (10 - 4 + 1) + 4) / 10.0); - float b = (float)((rand() % (10 - 4 + 1) + 4) / 10.0); - - s = new Style(font, 1, 0, 0, 0, 0.3, 1); - s->setLineWidth(2); - s->setShaderIndex(GLWin::COMMON_SHADER); - textStyle = new Style(font, 0, 0, 0, 0, 0, 0); - textStyle->setShaderIndex(GLWin::TEXT_SHADER); - c = cw->addCanvas(s, x, y, w, h); - m = c->addLayer(new MultiShape2D(s)); - cWidth = c->getWidth(); - cHeight = c->getHeight(); -} - -void PointPlot::add_Point(float add_x, float add_y) { - X.push_back(add_x); - Y.push_back(add_y); -} -// void pointPlot::remove_point(float x, float y){ -// vector::iterator it_x = find(X.begin(), X.end(), x); -// vector::iterator it_y = find(Y.begin(), Y.end(), y); -// int index_x = distance(X.begin(), it_x) -// } -void PointPlot::add_Points(vector &x, vector &y) { - X.insert(X.end(), x.begin(), x.end()); - Y.insert(Y.end(), y.begin(), y.end()); -} -void PointPlot::linePlot(vector &X, vector &Y) { - if ((X.size() == Y.size()) && (X.size() > 1)) { - for (int i = 1; i < X.size(); i++) { - m->drawLine(X[i - 1] + cWidth / 2, cHeight / 2 - Y[i - 1], - X[i] + cWidth / 2, cHeight / 2 - Y[i]); - } - } else { - // Figure out what to place here. - // m->drawPoint(X[i]+40, cHeight-Y[i]-40); - } -} -void PointPlot::scatterPlot(vector &X, vector &Y) { - if (X.size() == Y.size()) { - for (int i = 0; i < X.size(); i++) { - // Figure out what drawPoint is - m->drawPoint(X[i] + cWidth / 2, cHeight / 2 - Y[i]); - } - } else if (X.size() < Y.size()) { - for (int i = 0; i < X.size(); i++) { - // Figure out what drawPoint is - m->drawPoint(X[i] + cWidth / 2, cHeight / 2 - Y[i]); - } - } else { - for (int i = 0; i < Y.size(); i++) { - // Figure out what drawPoint is - m->drawPoint(X[i] + cWidth / 2, cHeight / 2 - Y[i]); - } - } -} -float PointPlot::maxWidth(vector &X) { - float maxValue = std::numeric_limits::min(); - for (int i = 0; i < X.size(); i++) { - if (X[i] > maxValue) { - maxValue = X[i]; - } - } - return maxValue; -} -float PointPlot::minWidth(vector &X) { - float minValue = std::numeric_limits::max(); - for (int i = 0; i < X.size(); i++) { - if (X[i] < minValue) { - minValue = X[i]; - } - } - return minValue; -} - -float PointPlot::maxHeight(vector &Y) { - float maxHeight = std::numeric_limits::min(); - for (int i = 0; i < Y.size(); i++) { - if (Y[i] > maxHeight) { - maxHeight = Y[i]; - } - } - return maxHeight; -} -float PointPlot::minHeight(vector &Y) { - float minHeight = std::numeric_limits::max(); - for (int i = 0; i < Y.size(); i++) { - if (Y[i] < minHeight) { - minHeight = Y[i]; - } - } - return minHeight; -} - -void PointPlot::linearRegression(vector &X, vector &Y) { - if (X.size() != Y.size()) { - throw "Vectors are not the same size."; - } - float n = X.size(); - float X_sum = accumulate(X.begin(), X.end(), 0); - float Y_sum = accumulate(Y.begin(), Y.end(), 0); - cout << "X total: " << X_sum << endl; - - float X_squared = 0; - for (int i = 0; i < X.size(); i++) { - X_squared += X[i] * X[i]; - } - - float Y_squared = 0; - for (int i = 0; i < Y.size(); i++) { - Y_squared += Y[i] * Y[i]; - } - float XY_sum = 0; - for (int i = 0; i < X.size(); i++) { - XY_sum += X[i] * Y[i]; - } - - float a = (n * XY_sum - X_sum * Y_sum) / (n * X_squared - X_sum * X_sum); - float b = (Y_sum - a * X_sum) / n; - - cout << "a: " << a << '\t' << "b: " << b << endl; - - float p1_x = 0; - float p1_y = b; - float p2_x = maxWidth(X); - float p2_y = p2_x * a + b; - m->drawLine(p1_x + cWidth / 2, cHeight / 2 - p1_y, p2_x + cWidth / 2, - cHeight / 2 - p2_y); -} - -void PointPlot::drawAxes() { - m->drawLine(0, cHeight / 2, cWidth, cHeight / 2); - m->drawLine(cWidth / 2, 0, cWidth / 2, cHeight); -} -void PointPlot::drawTicks() { - float x_pos = 0; - float y_pos = 0; - for (int i = 0; i <= 10; i++) { - m->drawLine(x_pos, cHeight / 2 - (.01 * cHeight), x_pos, - cHeight / 2 + (.01 * cHeight)); - x_pos += cWidth / 10; - } - for (int i = 0; i <= 10; i++) { - m->drawLine(cWidth / 2 - .01 * cWidth, y_pos, cWidth / 2 + .01 * cWidth, - y_pos); - y_pos += cHeight / 10; - } -} -void PointPlot::tickValues(vector &X, vector &Y) { - float increment_x = (maxWidth(X) + minWidth(X)) / 5; - float increment_y = (maxHeight(Y) + minHeight(Y)) / 5; - // c->addLayer(new Text(5,cHeight-5,textStyle, "0,0")); - int tickPos_x = -10; - int tickPos_y = cHeight - 25; - float tickNum_x = 0; - float tickNum_y = 0; - - for (int i = 0; i <= 5; i++) { - stringstream ss; - ss << fixed << setprecision(1) << tickNum_x; - string text_x = ss.str(); - // change r=the round function later to work for decimals. - c->addLayer(new Text(tickPos_x, tickPos_y, textStyle, text_x)); - tickNum_x += increment_x; - tickPos_x += cWidth / 5; - } - for (int i = 0; i <= 5; i++) { - stringstream ss; - ss << fixed << setprecision(1) << tickNum_y; - string text_y = ss.str(); - // change r=the round function later to work for decimals. - c->addLayer(new Text(0, tickPos_y, textStyle, text_y)); - tickNum_y += increment_y; - tickPos_y -= cHeight / 5; - } -} -void PointPlot::chartTitle(string title) { - const Font *font = FontFace::get("TIMES", 30, FontFace::BOLD); - Style *titleStyle = new Style(font, 0, 0, 0, 0, 0, 0); - titleStyle->setShaderIndex(CompiledWebWindow::TEXT_SHADER); - c->addLayer(new Text(cWidth / 2 - 150, 40, titleStyle, title)); -} - -void PointPlot::drawFunc(double x_min, double x_max, double y_min, double y_max, - FuncOneVar f, uint32_t pixXMin, uint32_t pixXMax, - uint32_t pixYMin, uint32_t pixYMax, - uint32_t numPoints) { - const double x_step = (x_max - x_min) / numPoints; - - vector X_points{}; - vector Y_points{}; - int y_pixel = 0; - double y_func = 0; - double ratioX = pixXMax / x_max; - double ratioY = pixYMax / y_max; - for (double i = x_min; i <= x_max; i += x_step) { - y_func = f(i); - X_points.push_back(i * ratioX); - y_pixel = y_func * ratioY + pixYMin; - Y_points.push_back(y_pixel); - } - linePlot(X_points, Y_points); -} -void PointPlot::drawTwoFunc(double val_min, double val_max, double step, - FuncOneVar f, FuncOneVar g, int scaleF, - int scaleG) { - vector Points_X{}; - vector Points_Y{}; - double x_func = 0; - double x_pixel = 0; - double FUNC2PIX_X = cWidth / val_max; - for (double i = val_min; i <= val_max; i += step) { - x_func = f(scaleF * i); - x_pixel = x_func * FUNC2PIX_X; - Points_X.push_back(x_pixel); - } - double y_func = 0; - double y_pixel = 0; - double FUNC2PIX_Y = cHeight / val_max; - for (double i = val_min; i <= val_max; i += step) { - y_func = g(scaleG * i); - y_pixel = y_func * FUNC2PIX_Y; - Points_Y.push_back(y_pixel); - } - linePlot(Points_X, Points_Y); -} -// following method will only work for months as julian calendar is not fully -// working pointPlot::monthPlot(vector date, vector price){ -// } +#include "plot.hh" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "opengl/GLMath.hh" +#include "opengl/GLWin.hh" +#include "opengl/GLWinFonts.hh" +#include "opengl/MultiShape2D.hh" +#include "opengl/Style.hh" +#include "opengl/Tab.hh" +#include "opengl/Text.hh" +using namespace std; + +PointPlot::PointPlot(shared_ptr tab, float x, float y, float w, float h) { + const Font *font = FontFace::get("TIMES", 30, FontFace::BOLD); + srand(time(NULL)); + + float r = (float)((rand() % (10 - 4 + 1) + 4) / 10.0); + float g = (float)((rand() % (10 - 4 + 1) + 4) / 10.0); + float b = (float)((rand() % (10 - 4 + 1) + 4) / 10.0); + + s = new Style(font, 1, 0, 0, 0, 0.3, 1); + s->setLineWidth(2); + s->setShaderIndex(GLWin::COMMON_SHADER); + textStyle = new Style(font, 0, 0, 0, 0, 0, 0); + textStyle->setShaderIndex(GLWin::TEXT_SHADER); + c = cw->addCanvas(s, x, y, w, h); + m = c->addLayer(new MultiShape2D(s)); + cWidth = c->getWidth(); + cHeight = c->getHeight(); +} + +void PointPlot::add_Point(float add_x, float add_y) { + X.push_back(add_x); + Y.push_back(add_y); +} +// void pointPlot::remove_point(float x, float y){ +// vector::iterator it_x = find(X.begin(), X.end(), x); +// vector::iterator it_y = find(Y.begin(), Y.end(), y); +// int index_x = distance(X.begin(), it_x) +// } +void PointPlot::add_Points(vector &x, vector &y) { + X.insert(X.end(), x.begin(), x.end()); + Y.insert(Y.end(), y.begin(), y.end()); +} +void PointPlot::linePlot(vector &X, vector &Y) { + if ((X.size() == Y.size()) && (X.size() > 1)) { + for (int i = 1; i < X.size(); i++) { + m->drawLine(X[i - 1] + cWidth / 2, cHeight / 2 - Y[i - 1], + X[i] + cWidth / 2, cHeight / 2 - Y[i]); + } + } else { + // Figure out what to place here. + // m->drawPoint(X[i]+40, cHeight-Y[i]-40); + } +} +void PointPlot::scatterPlot(vector &X, vector &Y) { + if (X.size() == Y.size()) { + for (int i = 0; i < X.size(); i++) { + // Figure out what drawPoint is + m->drawPoint(X[i] + cWidth / 2, cHeight / 2 - Y[i]); + } + } else if (X.size() < Y.size()) { + for (int i = 0; i < X.size(); i++) { + // Figure out what drawPoint is + m->drawPoint(X[i] + cWidth / 2, cHeight / 2 - Y[i]); + } + } else { + for (int i = 0; i < Y.size(); i++) { + // Figure out what drawPoint is + m->drawPoint(X[i] + cWidth / 2, cHeight / 2 - Y[i]); + } + } +} +float PointPlot::maxWidth(vector &X) { + float maxValue = std::numeric_limits::min(); + for (int i = 0; i < X.size(); i++) { + if (X[i] > maxValue) { + maxValue = X[i]; + } + } + return maxValue; +} +float PointPlot::minWidth(vector &X) { + float minValue = std::numeric_limits::max(); + for (int i = 0; i < X.size(); i++) { + if (X[i] < minValue) { + minValue = X[i]; + } + } + return minValue; +} + +float PointPlot::maxHeight(vector &Y) { + float maxHeight = std::numeric_limits::min(); + for (int i = 0; i < Y.size(); i++) { + if (Y[i] > maxHeight) { + maxHeight = Y[i]; + } + } + return maxHeight; +} +float PointPlot::minHeight(vector &Y) { + float minHeight = std::numeric_limits::max(); + for (int i = 0; i < Y.size(); i++) { + if (Y[i] < minHeight) { + minHeight = Y[i]; + } + } + return minHeight; +} + +void PointPlot::linearRegression(vector &X, vector &Y) { + if (X.size() != Y.size()) { + throw "Vectors are not the same size."; + } + float n = X.size(); + float X_sum = accumulate(X.begin(), X.end(), 0); + float Y_sum = accumulate(Y.begin(), Y.end(), 0); + cout << "X total: " << X_sum << endl; + + float X_squared = 0; + for (int i = 0; i < X.size(); i++) { + X_squared += X[i] * X[i]; + } + + float Y_squared = 0; + for (int i = 0; i < Y.size(); i++) { + Y_squared += Y[i] * Y[i]; + } + float XY_sum = 0; + for (int i = 0; i < X.size(); i++) { + XY_sum += X[i] * Y[i]; + } + + float a = (n * XY_sum - X_sum * Y_sum) / (n * X_squared - X_sum * X_sum); + float b = (Y_sum - a * X_sum) / n; + + cout << "a: " << a << '\t' << "b: " << b << endl; + + float p1_x = 0; + float p1_y = b; + float p2_x = maxWidth(X); + float p2_y = p2_x * a + b; + m->drawLine(p1_x + cWidth / 2, cHeight / 2 - p1_y, p2_x + cWidth / 2, + cHeight / 2 - p2_y); +} + +void PointPlot::drawAxes() { + m->drawLine(0, cHeight / 2, cWidth, cHeight / 2); + m->drawLine(cWidth / 2, 0, cWidth / 2, cHeight); +} +void PointPlot::drawTicks() { + float x_pos = 0; + float y_pos = 0; + for (int i = 0; i <= 10; i++) { + m->drawLine(x_pos, cHeight / 2 - (.01 * cHeight), x_pos, + cHeight / 2 + (.01 * cHeight)); + x_pos += cWidth / 10; + } + for (int i = 0; i <= 10; i++) { + m->drawLine(cWidth / 2 - .01 * cWidth, y_pos, cWidth / 2 + .01 * cWidth, + y_pos); + y_pos += cHeight / 10; + } +} +void PointPlot::tickValues(vector &X, vector &Y) { + float increment_x = (maxWidth(X) + minWidth(X)) / 5; + float increment_y = (maxHeight(Y) + minHeight(Y)) / 5; + // c->addLayer(new Text(5,cHeight-5,textStyle, "0,0")); + int tickPos_x = -10; + int tickPos_y = cHeight - 25; + float tickNum_x = 0; + float tickNum_y = 0; + + for (int i = 0; i <= 5; i++) { + stringstream ss; + ss << fixed << setprecision(1) << tickNum_x; + string text_x = ss.str(); + // change r=the round function later to work for decimals. + c->addLayer(new Text(tickPos_x, tickPos_y, textStyle, text_x)); + tickNum_x += increment_x; + tickPos_x += cWidth / 5; + } + for (int i = 0; i <= 5; i++) { + stringstream ss; + ss << fixed << setprecision(1) << tickNum_y; + string text_y = ss.str(); + // change r=the round function later to work for decimals. + c->addLayer(new Text(0, tickPos_y, textStyle, text_y)); + tickNum_y += increment_y; + tickPos_y -= cHeight / 5; + } +} +void PointPlot::chartTitle(string title) { + const Font *font = FontFace::get("TIMES", 30, FontFace::BOLD); + Style *titleStyle = new Style(font, 0, 0, 0, 0, 0, 0); + titleStyle->setShaderIndex(CompiledWebWindow::TEXT_SHADER); + c->addLayer(new Text(cWidth / 2 - 150, 40, titleStyle, title)); +} + +void PointPlot::drawFunc(double x_min, double x_max, double y_min, double y_max, + FuncOneVar f, uint32_t pixXMin, uint32_t pixXMax, + uint32_t pixYMin, uint32_t pixYMax, + uint32_t numPoints) { + const double x_step = (x_max - x_min) / numPoints; + + vector X_points{}; + vector Y_points{}; + int y_pixel = 0; + double y_func = 0; + double ratioX = pixXMax / x_max; + double ratioY = pixYMax / y_max; + for (double i = x_min; i <= x_max; i += x_step) { + y_func = f(i); + X_points.push_back(i * ratioX); + y_pixel = y_func * ratioY + pixYMin; + Y_points.push_back(y_pixel); + } + linePlot(X_points, Y_points); +} +void PointPlot::drawTwoFunc(double val_min, double val_max, double step, + FuncOneVar f, FuncOneVar g, int scaleF, + int scaleG) { + vector Points_X{}; + vector Points_Y{}; + double x_func = 0; + double x_pixel = 0; + double FUNC2PIX_X = cWidth / val_max; + for (double i = val_min; i <= val_max; i += step) { + x_func = f(scaleF * i); + x_pixel = x_func * FUNC2PIX_X; + Points_X.push_back(x_pixel); + } + double y_func = 0; + double y_pixel = 0; + double FUNC2PIX_Y = cHeight / val_max; + for (double i = val_min; i <= val_max; i += step) { + y_func = g(scaleG * i); + y_pixel = y_func * FUNC2PIX_Y; + Points_Y.push_back(y_pixel); + } + linePlot(Points_X, Points_Y); +} +// following method will only work for months as julian calendar is not fully +// working pointPlot::monthPlot(vector date, vector price){ +// }