From 4abc21c92a47aab7010cff12eb4f00201ea11428 Mon Sep 17 00:00:00 2001 From: "@Nurullah.Damla" Date: Sat, 19 Oct 2019 17:12:14 +0200 Subject: [PATCH 01/49] die Dateien um benannt --- main/main.cpp | 2 +- src/SharedMemory.cpp | 5 +++++ src/{demo.h => SharedMemory.h} | 0 src/demo.cpp | 5 ----- test/test_demo.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 src/SharedMemory.cpp rename src/{demo.h => SharedMemory.h} (100%) delete mode 100644 src/demo.cpp diff --git a/main/main.cpp b/main/main.cpp index 53edc26..8b085d4 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,4 +1,4 @@ -#include "../src/demo.h" +#include "../src/SharedMemory.h" int main() { return test(); diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp new file mode 100644 index 0000000..ec11168 --- /dev/null +++ b/src/SharedMemory.cpp @@ -0,0 +1,5 @@ +#include "SharedMemory.h" + +int test() { + return 41; +} diff --git a/src/demo.h b/src/SharedMemory.h similarity index 100% rename from src/demo.h rename to src/SharedMemory.h diff --git a/src/demo.cpp b/src/demo.cpp deleted file mode 100644 index 1cc01fc..0000000 --- a/src/demo.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "demo.h" - -int test() { - return 42; -} diff --git a/test/test_demo.cpp b/test/test_demo.cpp index 7cb240e..cc7e234 100644 --- a/test/test_demo.cpp +++ b/test/test_demo.cpp @@ -1,5 +1,5 @@ #include -#include "../src/demo.h" +#include "../src/SharedMemory.h" TEST_CASE("Demo test") { REQUIRE(test() == 42); From 4d6678e0a4a09d0e8c876b1405f336f1e8aeac0e Mon Sep 17 00:00:00 2001 From: "@Nurullah.Damla" Date: Sat, 19 Oct 2019 19:18:34 +0200 Subject: [PATCH 02/49] Im Header die Funktionen und Variablen Definiert In der cpp Datei die init Funktion definiert --- src/SharedMemory.cpp | 6 ++++-- src/SharedMemory.h | 27 +++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index ec11168..cf5a2ac 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -1,5 +1,7 @@ #include "SharedMemory.h" -int test() { - return 41; +//Shared-Memory-Segment erstellen oder öffnen – shmget() +void shared-memory-init(){ + memmory-id = shmget(IPC_PRIVATE, SHMMAXSIZE, IPC_CREAT | IPC_EXCL); } + diff --git a/src/SharedMemory.h b/src/SharedMemory.h index 9b77cb9..8f92d67 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -1,8 +1,27 @@ -#ifndef SHARED_MEMORY_DEMO_H -#define SHARED_MEMORY_DEMO_H +#ifndef SHARED_MEMORY_H +#define SHARED_MEMORY_H + +#include +#include +#include + +//ID-Speicherbereich +#define int speicher-id +//Größe des Speicherbereichs hier 8MB (64bit) +#define SHMMAXSIZE 64 -int test(); +//Shared-Memory-Segment erstellen oder öffnen – shmget() +void shared-memory-init(); +//Ein Shared-Memory-Segment abfragen, ändern oder löschen +void delet-shared-memory(); +int shmctl(int shm_id, int kommando, struct shmid_ds *buf); -#endif //SHARED_MEMORY_DEMO_H +//Shared-Memory-Segment an einen Prozess anbinden (attach) +void *shmat(int shm_id, const void *adresse, int flag); + +// Ein Shared-Memory-Segment loslösen – shmdt() +int shmdt(void *adresse); + +#endif //SHARED_MEMORY_H From b0f99af8d7afab7be86f351bbd72ae70467b50eb Mon Sep 17 00:00:00 2001 From: "@Nurullah.Damla" Date: Sun, 20 Oct 2019 20:38:12 +0200 Subject: [PATCH 03/49] Funktionen deklariert und definiert --- src/SharedMemory.cpp | 22 ++++++++++++++++++++++ src/SharedMemory.h | 11 +++++------ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index cf5a2ac..8d89064 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -5,3 +5,25 @@ void shared-memory-init(){ memmory-id = shmget(IPC_PRIVATE, SHMMAXSIZE, IPC_CREAT | IPC_EXCL); } +//Ein Shared-Memory-Segment abfragen, ändern oder löschen – shmctl() +void delet-shared-memory(){ + int shmctl(memmory-id, IPC_RMID, 0); +} + +//Shared-Memory-Segment an einen Prozess anbinden (attach) – shmat() +void attach-process(char *myProcess){ + if(( myProcess = shmat( memmory-id, (char *)0, 0 )) < (char *)0 ){ + perror("Fehler beim Ankoppeln des gemeinsamen Speicher Segments"); + exit(-1); + } +} + +//Ein Shared-Memory-Segment loslösen – shmdt() +void release-memory‚(){ + int shmdt(void *myProcess); +} + + + + + diff --git a/src/SharedMemory.h b/src/SharedMemory.h index 8f92d67..a4f4fa9 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -14,14 +14,13 @@ //Shared-Memory-Segment erstellen oder öffnen – shmget() void shared-memory-init(); -//Ein Shared-Memory-Segment abfragen, ändern oder löschen +//Ein Shared-Memory-Segment abfragen, ändern oder löschen – shmctl() void delet-shared-memory(); -int shmctl(int shm_id, int kommando, struct shmid_ds *buf); -//Shared-Memory-Segment an einen Prozess anbinden (attach) -void *shmat(int shm_id, const void *adresse, int flag); +//Shared-Memory-Segment an einen Prozess anbinden (attach) – shmat() +void attach-process(char *myProcess); -// Ein Shared-Memory-Segment loslösen – shmdt() -int shmdt(void *adresse); +//Ein Shared-Memory-Segment loslösen – shmdt() +void release-memory(); #endif //SHARED_MEMORY_H From 8bdee40ef3ddf7d99d8190e40c299776eecccc77 Mon Sep 17 00:00:00 2001 From: "@Nurullah.Damla" Date: Wed, 23 Oct 2019 11:53:07 +0200 Subject: [PATCH 04/49] Syntaktische korektur --- src/SharedMemory.cpp | 14 +++++++------- src/SharedMemory.h | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index 8d89064..367b123 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -1,25 +1,25 @@ #include "SharedMemory.h" //Shared-Memory-Segment erstellen oder öffnen – shmget() -void shared-memory-init(){ - memmory-id = shmget(IPC_PRIVATE, SHMMAXSIZE, IPC_CREAT | IPC_EXCL); +void shared_memory_init(){ + memory_id = shmget(IPC_PRIVATE, SHMMAXSIZE, IPC_CREAT | IPC_EXCL); } //Ein Shared-Memory-Segment abfragen, ändern oder löschen – shmctl() -void delet-shared-memory(){ - int shmctl(memmory-id, IPC_RMID, 0); +void delet_shared_memory(){ + int shmctl(memory_id, IPC_RMID, 0); } //Shared-Memory-Segment an einen Prozess anbinden (attach) – shmat() -void attach-process(char *myProcess){ - if(( myProcess = shmat( memmory-id, (char *)0, 0 )) < (char *)0 ){ +void attach_process(char *myProcess){ + if(( myProcess = shmat( memmory_id, (char *)0, 0 )) < (char *)0 ){ perror("Fehler beim Ankoppeln des gemeinsamen Speicher Segments"); exit(-1); } } //Ein Shared-Memory-Segment loslösen – shmdt() -void release-memory‚(){ +void release_memory(){ int shmdt(void *myProcess); } diff --git a/src/SharedMemory.h b/src/SharedMemory.h index a4f4fa9..74eca9b 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -6,21 +6,21 @@ #include //ID-Speicherbereich -#define int speicher-id +#define int memory_id //Größe des Speicherbereichs hier 8MB (64bit) #define SHMMAXSIZE 64 //Shared-Memory-Segment erstellen oder öffnen – shmget() -void shared-memory-init(); +void shared_memory_init(); //Ein Shared-Memory-Segment abfragen, ändern oder löschen – shmctl() -void delet-shared-memory(); +void delet_shared_memory(); //Shared-Memory-Segment an einen Prozess anbinden (attach) – shmat() -void attach-process(char *myProcess); +void attach_process(char *myProcess); //Ein Shared-Memory-Segment loslösen – shmdt() -void release-memory(); +void release_memory(); #endif //SHARED_MEMORY_H From e787cbe35558b85ae2ceb8a7778b832b2e4cf6de Mon Sep 17 00:00:00 2001 From: "@Nurullah.Damla" Date: Wed, 23 Oct 2019 12:34:11 +0200 Subject: [PATCH 05/49] Groesse auf 8MB erhoeht --- src/SharedMemory.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SharedMemory.h b/src/SharedMemory.h index 74eca9b..471cfe5 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -7,8 +7,8 @@ //ID-Speicherbereich #define int memory_id -//Größe des Speicherbereichs hier 8MB (64bit) -#define SHMMAXSIZE 64 +//Größe des Speicherbereichs hier 8MB (8000) +#define SHMMAXSIZE 8000 //Shared-Memory-Segment erstellen oder öffnen – shmget() From e565c065505338eaf5c0e5c139be3bf28d5c300b Mon Sep 17 00:00:00 2001 From: "@Nurullah.Damla" Date: Wed, 23 Oct 2019 21:39:09 +0200 Subject: [PATCH 06/49] bugfix --- main/main.cpp | 3 ++- src/SharedMemory.cpp | 8 +++++--- src/SharedMemory.h | 4 ++-- test/test_demo.cpp | 3 ++- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/main/main.cpp b/main/main.cpp index 8b085d4..d812c4f 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,5 +1,6 @@ #include "../src/SharedMemory.h" int main() { - return test(); + shared_memory_init(); + //return main(); } \ No newline at end of file diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index 367b123..551e997 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -1,3 +1,5 @@ +#include +#include #include "SharedMemory.h" //Shared-Memory-Segment erstellen oder öffnen – shmget() @@ -7,12 +9,12 @@ void shared_memory_init(){ //Ein Shared-Memory-Segment abfragen, ändern oder löschen – shmctl() void delet_shared_memory(){ - int shmctl(memory_id, IPC_RMID, 0); + memory_id = shmctl(memory_id, IPC_RMID, 0); } //Shared-Memory-Segment an einen Prozess anbinden (attach) – shmat() -void attach_process(char *myProcess){ - if(( myProcess = shmat( memmory_id, (char *)0, 0 )) < (char *)0 ){ +void attach_process(void *myProcess){ + if(( myProcess = shmat( memory_id, (char *)0, 0 )) < (char *)0 ){ perror("Fehler beim Ankoppeln des gemeinsamen Speicher Segments"); exit(-1); } diff --git a/src/SharedMemory.h b/src/SharedMemory.h index 471cfe5..bf09c50 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -6,7 +6,7 @@ #include //ID-Speicherbereich -#define int memory_id +extern int memory_id; //Größe des Speicherbereichs hier 8MB (8000) #define SHMMAXSIZE 8000 @@ -18,7 +18,7 @@ void shared_memory_init(); void delet_shared_memory(); //Shared-Memory-Segment an einen Prozess anbinden (attach) – shmat() -void attach_process(char *myProcess); +void attach_process(void *myProcess); //Ein Shared-Memory-Segment loslösen – shmdt() void release_memory(); diff --git a/test/test_demo.cpp b/test/test_demo.cpp index cc7e234..23ec771 100644 --- a/test/test_demo.cpp +++ b/test/test_demo.cpp @@ -3,4 +3,5 @@ TEST_CASE("Demo test") { REQUIRE(test() == 42); -} \ No newline at end of file +} + From 85b3cc67c57ba0191cc7462f81e738f0f671172a Mon Sep 17 00:00:00 2001 From: "@Nurullah.Damla" Date: Sun, 27 Oct 2019 19:46:00 +0100 Subject: [PATCH 07/49] deklarartion und definition der Ausgabe Shared Memory Segment id --- src/SharedMemory.cpp | 5 +++++ src/SharedMemory.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index 551e997..fa0bc3c 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -7,6 +7,11 @@ void shared_memory_init(){ memory_id = shmget(IPC_PRIVATE, SHMMAXSIZE, IPC_CREAT | IPC_EXCL); } +//Shared-Memory-Segment id weiterreichen +int get_shared_memory_id(){ + return memory_id; +} + //Ein Shared-Memory-Segment abfragen, ändern oder löschen – shmctl() void delet_shared_memory(){ memory_id = shmctl(memory_id, IPC_RMID, 0); diff --git a/src/SharedMemory.h b/src/SharedMemory.h index bf09c50..82204f2 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -14,6 +14,9 @@ extern int memory_id; //Shared-Memory-Segment erstellen oder öffnen – shmget() void shared_memory_init(); +//Shared-Memory-Segment id weiterreichen +int get_shared_memory_id(); + //Ein Shared-Memory-Segment abfragen, ändern oder löschen – shmctl() void delet_shared_memory(); From 72a050c6201dfe8da57e2cd994973ed9f56b865e Mon Sep 17 00:00:00 2001 From: Zakarya Boudouar Date: Thu, 31 Oct 2019 22:31:28 +0000 Subject: [PATCH 08/49] =?UTF-8?q?=C3=9Cberpr=C3=BCfung=20ob=20speicher=20g?= =?UTF-8?q?ut=20erstellt=20wurde=20oder=20nicht?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SharedMemory.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index fa0bc3c..6d26b61 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -5,6 +5,10 @@ //Shared-Memory-Segment erstellen oder öffnen – shmget() void shared_memory_init(){ memory_id = shmget(IPC_PRIVATE, SHMMAXSIZE, IPC_CREAT | IPC_EXCL); + if(memory_id<0){ + perror("Fehler bei der Erstellung des gemeinsamen Speicher"); + exit(1); + } } //Shared-Memory-Segment id weiterreichen @@ -29,8 +33,3 @@ void attach_process(void *myProcess){ void release_memory(){ int shmdt(void *myProcess); } - - - - - From 37f4c3087754cd6c8672a411e06152ba81557f3a Mon Sep 17 00:00:00 2001 From: Zakarya Boudouar Date: Mon, 4 Nov 2019 19:48:53 +0000 Subject: [PATCH 09/49] Update SharedMemory.h --- src/SharedMemory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SharedMemory.h b/src/SharedMemory.h index 82204f2..4308935 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -12,7 +12,7 @@ extern int memory_id; //Shared-Memory-Segment erstellen oder öffnen – shmget() -void shared_memory_init(); +void shared_memory_init(key_t key); //Shared-Memory-Segment id weiterreichen int get_shared_memory_id(); From 75fcc01d98c501a3ea66bb74271da652f93d5a75 Mon Sep 17 00:00:00 2001 From: Zakarya Boudouar Date: Mon, 4 Nov 2019 19:56:13 +0000 Subject: [PATCH 10/49] Update SharedMemory.h --- src/SharedMemory.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SharedMemory.h b/src/SharedMemory.h index 4308935..98be853 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -9,6 +9,7 @@ extern int memory_id; //Größe des Speicherbereichs hier 8MB (8000) #define SHMMAXSIZE 8000 +key_t key 1234; //Shared-Memory-Segment erstellen oder öffnen – shmget() From 734d2e4f28f9ac5875f8c69a608811bbc7a9237d Mon Sep 17 00:00:00 2001 From: Zakarya Boudouar Date: Mon, 4 Nov 2019 20:02:27 +0000 Subject: [PATCH 11/49] Rekursive Funktion, die das Key inkrementiert wenn Shared-Memory nicht erstellt wurde --- src/SharedMemory.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index 6d26b61..d1b4b31 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -2,13 +2,17 @@ #include #include "SharedMemory.h" + //Shared-Memory-Segment erstellen oder öffnen – shmget() -void shared_memory_init(){ - memory_id = shmget(IPC_PRIVATE, SHMMAXSIZE, IPC_CREAT | IPC_EXCL); - if(memory_id<0){ - perror("Fehler bei der Erstellung des gemeinsamen Speicher"); - exit(1); - } +int shared_memory_init(key_t key){ + + memory_id = shmget(key, SHMMAXSIZE, IPC_CREAT | 0666); + if(shmid == -1){ + key++; + shmfnk(key); + return memory_id; + } + return 0; } //Shared-Memory-Segment id weiterreichen From f69810898ca319b7518a471b748aa7113b2ffbfc Mon Sep 17 00:00:00 2001 From: "@Nurullah.Damla" Date: Wed, 6 Nov 2019 13:03:13 +0100 Subject: [PATCH 12/49] Syntaktische korektur --- src/SharedMemory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index d1b4b31..d1df9a0 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -7,9 +7,9 @@ int shared_memory_init(key_t key){ memory_id = shmget(key, SHMMAXSIZE, IPC_CREAT | 0666); - if(shmid == -1){ + if(memory_id == -1){ key++; - shmfnk(key); + shared_memory_init(key); return memory_id; } return 0; From b8773350a9ba55ac7c22bb5d2ba91dd0b4a64b12 Mon Sep 17 00:00:00 2001 From: cigerxwinchaker Date: Wed, 6 Nov 2019 13:07:33 +0100 Subject: [PATCH 13/49] aktuelle version --- main/main.cpp | 19 +++++++++++-- src/SharedMemory.cpp | 68 +++++++++++++++++++++++++------------------- src/SharedMemory.h | 25 +++------------- test/test_demo.cpp | 2 +- 4 files changed, 59 insertions(+), 55 deletions(-) diff --git a/main/main.cpp b/main/main.cpp index d812c4f..ff1ca5d 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,6 +1,19 @@ #include "../src/SharedMemory.h" +#include +#include +#include +#include -int main() { - shared_memory_init(); - //return main(); + +int main(int argc, char** argv) +{ + sharedMemoryInit(); + struct sigaction sigIntHandler; + sigIntHandler.sa_handler = deleteSharedMemory; + sigemptyset(&sigIntHandler.sa_mask); + sigIntHandler.sa_flags = 0; + sigaction(SIGINT, &sigIntHandler, NULL); + sleep(3); // TODO: warte auf eingabe + std::atexit(deleteSharedMemory); + return 0; } \ No newline at end of file diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index d1b4b31..aaebf18 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -1,39 +1,47 @@ #include -#include +#include +#include #include "SharedMemory.h" +#include +#include +#include +#define Max_Memory_Size 8000 +int memoryAccessKey = 12345; +int memID; //Shared-Memory-Segment erstellen oder öffnen – shmget() -int shared_memory_init(key_t key){ - - memory_id = shmget(key, SHMMAXSIZE, IPC_CREAT | 0666); - if(shmid == -1){ - key++; - shmfnk(key); - return memory_id; - } - return 0; -} - -//Shared-Memory-Segment id weiterreichen -int get_shared_memory_id(){ - return memory_id; -} - -//Ein Shared-Memory-Segment abfragen, ändern oder löschen – shmctl() -void delet_shared_memory(){ - memory_id = shmctl(memory_id, IPC_RMID, 0); -} - -//Shared-Memory-Segment an einen Prozess anbinden (attach) – shmat() -void attach_process(void *myProcess){ - if(( myProcess = shmat( memory_id, (char *)0, 0 )) < (char *)0 ){ - perror("Fehler beim Ankoppeln des gemeinsamen Speicher Segments"); - exit(-1); +void sharedMemoryInit() +{ + if((memID = shmget(memoryAccessKey, Max_Memory_Size, IPC_CREAT | IPC_EXCL | 0666)) < 0) + { + std::cerr << "Shared memory with Key: " << memoryAccessKey << " already exists. Delete by Hand before starting vKFM" << std::endl; + exit(0); + } else { + std::cout << "Shared memory with Key: " << memoryAccessKey << " allocated" << std::endl; } } -//Ein Shared-Memory-Segment loslösen – shmdt() -void release_memory(){ - int shmdt(void *myProcess); +void deleteSharedMemory(int s) +{ + if (shmctl(memID, IPC_RMID, NULL) < 0 ) + { + std::cerr << "Failed to remove shared Memory, maybe not existing: try cmd: ipcs " << std::endl; + } else { + std::cout << "shared Memory deleted" << std::endl; + } + exit(0); } + +void deleteSharedMemory(void) +{ + if (shmctl(memID, IPC_RMID, NULL) < 0 ) + { + std::cerr << "Failed to remove shared Memory, maybe not existing: try cmd: ipcs " << std::endl; + } else { + std::cout << "shared Memory deleted" << std::endl; + } + exit(0); +} + + diff --git a/src/SharedMemory.h b/src/SharedMemory.h index 98be853..a4f0406 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -1,30 +1,13 @@ #ifndef SHARED_MEMORY_H #define SHARED_MEMORY_H -#include -#include -#include - //ID-Speicherbereich -extern int memory_id; //Größe des Speicherbereichs hier 8MB (8000) -#define SHMMAXSIZE 8000 -key_t key 1234; - +#define shmMaxSize 8000 //Shared-Memory-Segment erstellen oder öffnen – shmget() -void shared_memory_init(key_t key); - -//Shared-Memory-Segment id weiterreichen -int get_shared_memory_id(); - -//Ein Shared-Memory-Segment abfragen, ändern oder löschen – shmctl() -void delet_shared_memory(); - -//Shared-Memory-Segment an einen Prozess anbinden (attach) – shmat() -void attach_process(void *myProcess); - -//Ein Shared-Memory-Segment loslösen – shmdt() -void release_memory(); +void sharedMemoryInit(); +void deleteSharedMemory(int s); +void deleteSharedMemory(void); #endif //SHARED_MEMORY_H diff --git a/test/test_demo.cpp b/test/test_demo.cpp index 23ec771..4021d86 100644 --- a/test/test_demo.cpp +++ b/test/test_demo.cpp @@ -2,6 +2,6 @@ #include "../src/SharedMemory.h" TEST_CASE("Demo test") { - REQUIRE(test() == 42); + // REQUIRE(test() == 42); } From a28014305f033c48169dc76c42a0787c17e559de Mon Sep 17 00:00:00 2001 From: Zakarya Date: Wed, 6 Nov 2019 13:16:04 +0100 Subject: [PATCH 14/49] Merge branch 'dev' of /home/zakarya/CLionProjects/vkvm/shared-memory with conflicts. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ad5a2dd..961aac1 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,3 @@ Use the installation script provided in the Scripts repository to install the full package. Installing a single component is currently not supported. - From da3d8c8b73817da072a5cf805740374b4254038b Mon Sep 17 00:00:00 2001 From: cigerxwinchaker Date: Wed, 6 Nov 2019 13:19:08 +0100 Subject: [PATCH 15/49] aktuell --- src/SharedMemory.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index aaebf18..5c47251 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -3,8 +3,6 @@ #include #include "SharedMemory.h" #include -#include -#include #define Max_Memory_Size 8000 int memoryAccessKey = 12345; From 22aea91ecf2314e8e01ce4f817c013f12dfe4499 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Thu, 7 Nov 2019 13:51:23 +0000 Subject: [PATCH 16/49] + ci pipeline --- .ci/clang-tidy.sh | 32 ++++++++++++++++++++++ .gitlab-ci.yml | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 .ci/clang-tidy.sh create mode 100644 .gitlab-ci.yml diff --git a/.ci/clang-tidy.sh b/.ci/clang-tidy.sh new file mode 100644 index 0000000..eae5b12 --- /dev/null +++ b/.ci/clang-tidy.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +echo "Doing clang-tidy..." +bool=false +# explicitly set IFS to contain only a line feed +IFS=' +' +filelist="$(find . -not \( -path './client/cpptoml/*' -prune \) -type f ! -name "$(printf "*\n*")")" +for file in $filelist; do + if echo "$file" | grep -q -E ".*\.cpp$" ; then + #Extra check missing dependencies due to clang-tidy doesn't toggle exit code. + clang_tidy_lib_check="$(clang-tidy -warnings-as-errors='*' -header-filter='.*,-cpptoml.hpp' -checks='*,-llvm-header-guard,-fuchsia-statically-constructed-objects,-fuchsia-default-arguments,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-hicpp-signed-bitwise,-bugprone-exception-escape,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-cstyle-cast,-hicpp-member-init' "$file" -- -I. -std=c++14 2>&1)" + for tidy_line in $clang_tidy_lib_check; do + echo "$tidy_line" | grep -q -v -E "^Error while processing*" + if [ $? -eq 1 ]; then + bool=true + fi + echo "$tidy_line" | grep -q -v -E ".* error: .*" + if [ $? -eq 1 ]; then + bool=true + fi + echo "$tidy_line" + done + fi +done +if $bool; then + exit 1 +else + echo "No clang-tidy errors found." +fi + +exit 0 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..eb1309a --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,68 @@ +--- + +image: samueldebruyn/debian-git:latest + +stages: + - style + - test + - build + + +clang_tidy: + image: jhasse/clang-tidy + stage: style + tags: + - docker-ci + script: + - sh .ci/clang-tidy.sh; + +make_test: + stage: test + tags: + - docker-ci + script: + - apt-get update + - apt-get install -y g++ make cmake clang-tidy + - mkdir current + - ls | grep -v current | xargs mv -t current + - git clone https://github.com/catchorg/Catch2.git + - cd Catch2 + - cmake -Bbuild -H. -DBUILD_TESTING=OFF + - cmake --build build/ --target install + - cd .. + - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.repo.digitech.hs-emden-leer.de/link/projekte/ws19/vkvm-new/library.git + - mkdir library/build + - cd library/build + - cmake .. + - make + - cd ../../current + - mkdir build + - cd build + - cmake .. + - make + - make test + +cmake_build: + stage: build + tags: + - docker-ci + script: + - apt-get update + - apt-get install -y g++ make cmake clang-tidy + - mkdir current + - ls | grep -v current | xargs mv -t current + - git clone https://github.com/catchorg/Catch2.git + - cd Catch2 + - cmake -Bbuild -H. -DBUILD_TESTING=OFF + - cmake --build build/ --target install + - cd .. + - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.repo.digitech.hs-emden-leer.de/link/projekte/ws19/vkvm-new/library.git + - mkdir library/build + - cd library/build + - cmake .. + - make + - cd ../../current + - mkdir build + - cd build + - cmake .. + - make \ No newline at end of file From bda7955726ef6141b3721e2d5a3fb56d412314da Mon Sep 17 00:00:00 2001 From: cigerxwinchaker Date: Thu, 7 Nov 2019 17:59:06 +0100 Subject: [PATCH 17/49] aktuelle version. getestet. Es fehlen noch evtl Feature. aber shared memory wird bereit gestellt. Key weitergabe muss noch besprochen werden. --- main/main.cpp | 25 ++++++++++++---- src/SharedMemory.cpp | 70 +++++++++++++++++++++++++++++++++----------- src/SharedMemory.h | 8 +++-- test/test_demo.cpp | 2 +- 4 files changed, 79 insertions(+), 26 deletions(-) diff --git a/main/main.cpp b/main/main.cpp index ff1ca5d..261829f 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,19 +1,34 @@ -#include "../src/SharedMemory.h" -#include #include -#include #include +#include "../src/SharedMemory.h" +#include +#include int main(int argc, char** argv) { - sharedMemoryInit(); + initSharedMemory(); struct sigaction sigIntHandler; sigIntHandler.sa_handler = deleteSharedMemory; sigemptyset(&sigIntHandler.sa_mask); sigIntHandler.sa_flags = 0; sigaction(SIGINT, &sigIntHandler, NULL); - sleep(3); // TODO: warte auf eingabe + std::atexit(deleteSharedMemory); + std::string eingabe = ""; + while(eingabe != "exit") { + std::cout << "cmd# "; + std::cin >> eingabe; + //if verschieden information ausgaben + if(eingabe == "info") + { + std::cout << "OUTPUT ------------------------ OUTPUT" << std::endl; + std::cout << "memory ID: " << shmget(impl.sharedMemoryKey, 0, 0) << std::endl; + std::cout << "Max memory Size: " << Max_Memory_Size << std::endl; + std::cout << "OUTPUT ------------------------ OUTPUT" << std::endl; + //Memory that is used now + //outprint of all memory + } + } return 0; } \ No newline at end of file diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index 0e36071..3f7c3cc 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -1,44 +1,80 @@ #include -#include -#include #include "SharedMemory.h" #include -#define Max_Memory_Size 8000 -int memoryAccessKey = 12345; -int memID; +key_t changedKey() +{ + int newKey; + std::cout << "Type in a new Key for the Shared Memory Segment" << std::endl; + std::cout << "new Key#"; + std::cin >> newKey; + std::cout <<"New Key is -> " << newKey << std::endl; + return key_t(newKey); +} -void sharedMemoryInit() { - if ((memID = shmget(memoryAccessKey, Max_Memory_Size, IPC_CREAT | IPC_EXCL | 0666)) < 0) { - std::cerr << "Shared memory with Key: " << memoryAccessKey - << " already exists. Delete by Hand before starting vKFM" << std::endl; - exit(0); +std::string getAnswerFromUser() +{ + std::cout <<"answer# "; + std::string answer; + std::cin >> answer; + if(answer.compare("y") == 0 || answer.compare("n") == 0|| answer.compare("override") == 0) { + return answer; } else { - std::cout << "Shared memory with Key: " << memoryAccessKey << " allocated" << std::endl; + std::cout << "wrong input: pls answer with (y) for yes, (n) for no, or (override)\n"; + getAnswerFromUser(); } } +void initSharedMemory(void) { + if(impl.sharedMemoryKey != key_t(0)) { + if (shmget(impl.sharedMemoryKey, Max_Memory_Size, IPC_CREAT | IPC_EXCL | 0666) < 0) + { + std::cout << "Shared Memory with Key: " << impl.sharedMemoryKey << " is already in use\n" + <<"You can change the Key( type -> y or n ), or you can override the shared memory Segment(type -> override)\n"; + std::string answer = getAnswerFromUser(); + if(answer.compare("y") == 0) + { + std::cout << "Please type in a new Key:\n"; + std::cout << "#"; + std::cin >> impl.sharedMemoryKey; + std::cout << "new Try with Key:c " << impl.sharedMemoryKey << std::endl; + initSharedMemory(); + } else if(answer.compare("n") == 0) { + std::cout << "This will end shared memory" < " << impl.sharedMemoryKey << " is not allowed here " << std::endl; + impl.sharedMemoryKey = changedKey(); + initSharedMemory(); + } +} + void deleteSharedMemory(int s) { - if (shmctl(memID, IPC_RMID, NULL) < 0 ) + std::cerr << "programm ended with Code: " << s << std::endl; + if (shmctl(shmget(impl.sharedMemoryKey, 0, 0), IPC_RMID, 0) < 0 ) { - std::cerr << "Failed to remove shared Memory, maybe not existing: try cmd: ipcs " << std::endl; + std::cerr << "Failed to remove shared Memory, maybe not existing: try cmd: ipcs, then delete with ipcrm -m $memID " << std::endl; } else { std::cout << "shared Memory deleted" << std::endl; } - exit(0); } void deleteSharedMemory(void) { - if (shmctl(memID, IPC_RMID, NULL) < 0 ) + if (shmctl(shmget(impl.sharedMemoryKey, 0, 0), IPC_RMID, 0) < 0 ) { std::cerr << "Failed to remove shared Memory, maybe not existing: try cmd: ipcs " << std::endl; } else { std::cout << "shared Memory deleted" << std::endl; } - exit(0); } - diff --git a/src/SharedMemory.h b/src/SharedMemory.h index a4f0406..96aefca 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -1,13 +1,15 @@ #ifndef SHARED_MEMORY_H #define SHARED_MEMORY_H +#include +#include +#include "internal.h" //ID-Speicherbereich //Größe des Speicherbereichs hier 8MB (8000) #define shmMaxSize 8000 - //Shared-Memory-Segment erstellen oder öffnen – shmget() -void sharedMemoryInit(); +#define Max_Memory_Size 8000 void deleteSharedMemory(int s); void deleteSharedMemory(void); - +void initSharedMemory(void); #endif //SHARED_MEMORY_H diff --git a/test/test_demo.cpp b/test/test_demo.cpp index 4021d86..fde1445 100644 --- a/test/test_demo.cpp +++ b/test/test_demo.cpp @@ -2,6 +2,6 @@ #include "../src/SharedMemory.h" TEST_CASE("Demo test") { - // REQUIRE(test() == 42); + //REQUIRE(test() == 42); } From 121ae391c03e502f4a5243e5bf4fd8ea06799927 Mon Sep 17 00:00:00 2001 From: cigerxwinchaker Date: Thu, 7 Nov 2019 18:05:59 +0100 Subject: [PATCH 18/49] test push der aktuellen quelldateien --- main/main.cpp | 4 ++-- src/SharedMemory.cpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/main/main.cpp b/main/main.cpp index 261829f..fdf836c 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -22,10 +22,10 @@ int main(int argc, char** argv) //if verschieden information ausgaben if(eingabe == "info") { - std::cout << "OUTPUT ------------------------ OUTPUT" << std::endl; + std::cout << "OUTPUT ------------------------ OUTPUT\n" << std::endl; std::cout << "memory ID: " << shmget(impl.sharedMemoryKey, 0, 0) << std::endl; std::cout << "Max memory Size: " << Max_Memory_Size << std::endl; - std::cout << "OUTPUT ------------------------ OUTPUT" << std::endl; + std::cout << "OUTPUT ------------------------ OUTPUT\n" << std::endl; //Memory that is used now //outprint of all memory } diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index 3f7c3cc..77520f6 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -23,6 +23,7 @@ std::string getAnswerFromUser() std::cout << "wrong input: pls answer with (y) for yes, (n) for no, or (override)\n"; getAnswerFromUser(); } + return "-0"; } @@ -48,7 +49,7 @@ void initSharedMemory(void) { initSharedMemory(); } } else { - std::cout << "Shared Memory ist (Re-) allocated with Key: " << impl.sharedMemoryKey << std::endl; + std::cout << "Shared Memory is (Re-) allocated with Key: " << impl.sharedMemoryKey << std::endl; } } else { std::cerr <<"key -> " << impl.sharedMemoryKey << " is not allowed here " << std::endl; From bf6546e3b851d1e03c5e3173fd3ece5ad0ea6598 Mon Sep 17 00:00:00 2001 From: Shaohua Tong Date: Fri, 8 Nov 2019 18:31:42 +0100 Subject: [PATCH 19/49] test for write and read of shared memory in main.cpp --- CMakeLists.txt | 1 + main/main.cpp | 39 +++++++++++++++++++++++++++++---------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c40c64..6c14a86 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ set(LIB_PATH "${CMAKE_SOURCE_DIR}/../library") include_directories(${LIB_PATH}/include) add_executable(SharedMemory ${SOURCES} ${HEADERS} main/main.cpp) + target_link_libraries(SharedMemory ${LIB_PATH}/lib/liblibrary.a) diff --git a/main/main.cpp b/main/main.cpp index fdf836c..4ea5b9f 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -3,6 +3,8 @@ #include "../src/SharedMemory.h" #include #include +#include +#include int main(int argc, char** argv) @@ -19,16 +21,33 @@ int main(int argc, char** argv) while(eingabe != "exit") { std::cout << "cmd# "; std::cin >> eingabe; - //if verschieden information ausgaben - if(eingabe == "info") - { - std::cout << "OUTPUT ------------------------ OUTPUT\n" << std::endl; - std::cout << "memory ID: " << shmget(impl.sharedMemoryKey, 0, 0) << std::endl; - std::cout << "Max memory Size: " << Max_Memory_Size << std::endl; - std::cout << "OUTPUT ------------------------ OUTPUT\n" << std::endl; - //Memory that is used now - //outprint of all memory - } + //if verschieden information ausgaben + if(eingabe == "info") + { + std::cout << "OUTPUT ------------------------ OUTPUT\n" << std::endl; + std::cout << "memory ID: " << shmget(impl.sharedMemoryKey, 0, 0) << std::endl; + std::cout << "Max memory Size: " << Max_Memory_Size << std::endl; + std::cout << "OUTPUT ------------------------ OUTPUT\n" << std::endl; + //Memory that is used now + //outprint of all memory + } + + //Test for write and read + if(eingabe == "write") { + //write a bitMap for example 2 (width) * 2 (high) * 3 (color) in Schared Memory + char bitMap[12] = {0}; + for(int i = 0; i < sizeof(bitMap); i++) + bitMap[i] = 'y'; + writeSharedMemory(bitMap, sizeof(bitMap),1); + } + + if(eingabe == "read") { + char content[12] = {0}; + std::cout << "key "<< impl.sharedMemoryKey << std::endl; + getSharedMemory(content, sizeof(content), 1); + + std::cout << content << std::endl; + } } return 0; } \ No newline at end of file From 6eda059c5135b4275aef890313278bb45d5a65d8 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Tue, 12 Nov 2019 11:08:10 +0000 Subject: [PATCH 20/49] ~ CI: clang_tidy step now contains catch2 & fltk --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index eb1309a..522f05f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,7 +9,7 @@ stages: clang_tidy: - image: jhasse/clang-tidy + image: joethei/clang_tidy stage: style tags: - docker-ci From f89d2ef5b682a82a6a6fbf02042a6332a0b0ae09 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Tue, 12 Nov 2019 11:40:52 +0000 Subject: [PATCH 21/49] ~ default argument calls are now allowed --- .ci/clang-tidy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/clang-tidy.sh b/.ci/clang-tidy.sh index eae5b12..c20c8fb 100644 --- a/.ci/clang-tidy.sh +++ b/.ci/clang-tidy.sh @@ -9,7 +9,7 @@ filelist="$(find . -not \( -path './client/cpptoml/*' -prune \) -type f ! -name for file in $filelist; do if echo "$file" | grep -q -E ".*\.cpp$" ; then #Extra check missing dependencies due to clang-tidy doesn't toggle exit code. - clang_tidy_lib_check="$(clang-tidy -warnings-as-errors='*' -header-filter='.*,-cpptoml.hpp' -checks='*,-llvm-header-guard,-fuchsia-statically-constructed-objects,-fuchsia-default-arguments,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-hicpp-signed-bitwise,-bugprone-exception-escape,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-cstyle-cast,-hicpp-member-init' "$file" -- -I. -std=c++14 2>&1)" + clang_tidy_lib_check="$(clang-tidy -warnings-as-errors='*' -header-filter='.*,-cpptoml.hpp' -checks='*,-llvm-header-guard,-fuchsia-statically-constructed-objects,-fuchsia-default-arguments,-fuchsia-default-argument-calls,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-hicpp-signed-bitwise,-bugprone-exception-escape,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-cstyle-cast,-hicpp-member-init' "$file" -- -I. -std=c++14 2>&1)" for tidy_line in $clang_tidy_lib_check; do echo "$tidy_line" | grep -q -v -E "^Error while processing*" if [ $? -eq 1 ]; then From 80ae989b2ba64d8d3a0ee052e56b48758ca8bfbd Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Tue, 12 Nov 2019 15:23:14 +0100 Subject: [PATCH 22/49] ~clang tidy checks all fies now --- .ci/clang-tidy.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.ci/clang-tidy.sh b/.ci/clang-tidy.sh index c20c8fb..913c79a 100644 --- a/.ci/clang-tidy.sh +++ b/.ci/clang-tidy.sh @@ -5,11 +5,11 @@ bool=false # explicitly set IFS to contain only a line feed IFS=' ' -filelist="$(find . -not \( -path './client/cpptoml/*' -prune \) -type f ! -name "$(printf "*\n*")")" +filelist="$(find . -not \( -path './*build*' -prune \) -type f ! -name "$(printf "*\n*")")" for file in $filelist; do - if echo "$file" | grep -q -E ".*\.cpp$" ; then + if echo "$file" | grep -q -E ".*(\.cpp|\.h|\.hpp)$" ; then #Extra check missing dependencies due to clang-tidy doesn't toggle exit code. - clang_tidy_lib_check="$(clang-tidy -warnings-as-errors='*' -header-filter='.*,-cpptoml.hpp' -checks='*,-llvm-header-guard,-fuchsia-statically-constructed-objects,-fuchsia-default-arguments,-fuchsia-default-argument-calls,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-hicpp-signed-bitwise,-bugprone-exception-escape,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-cstyle-cast,-hicpp-member-init' "$file" -- -I. -std=c++14 2>&1)" + clang_tidy_lib_check="$(clang-tidy -warnings-as-errors='*' -header-filter='.*,-cpptoml.hpp' -checks='*,-llvm-header-guard,-fuchsia-statically-constructed-objects,-fuchsia-default-arguments,-fuchsia-default-arguments-calls,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-hicpp-signed-bitwise,-bugprone-exception-escape,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-cstyle-cast,-hicpp-member-init' "$file" -- -I. -std=c++14 2>&1)" for tidy_line in $clang_tidy_lib_check; do echo "$tidy_line" | grep -q -v -E "^Error while processing*" if [ $? -eq 1 ]; then From 3671c2c3e1bcb41c4ac57a6794e39ed1550cd1ee Mon Sep 17 00:00:00 2001 From: Julian Hinxlage Date: Tue, 12 Nov 2019 16:22:55 +0100 Subject: [PATCH 23/49] + write and read text in shared memory ~ initialize library --- main/main.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/main/main.cpp b/main/main.cpp index 4ea5b9f..476abf9 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -5,19 +5,23 @@ #include #include #include +#include "vkvm.h" -int main(int argc, char** argv) -{ +int main(int argc, char** argv) { + initialize(0); + initSharedMemory(); struct sigaction sigIntHandler; sigIntHandler.sa_handler = deleteSharedMemory; sigemptyset(&sigIntHandler.sa_mask); sigIntHandler.sa_flags = 0; - sigaction(SIGINT, &sigIntHandler, NULL); + sigaction(SIGINT, &sigIntHandler, nullptr); + + setDefaultValues(); std::atexit(deleteSharedMemory); - std::string eingabe = ""; + std::string eingabe; while(eingabe != "exit") { std::cout << "cmd# "; std::cin >> eingabe; @@ -34,19 +38,28 @@ int main(int argc, char** argv) //Test for write and read if(eingabe == "write") { + std::cout << "text: "; + std::cin >> eingabe; + setText(eingabe); //write a bitMap for example 2 (width) * 2 (high) * 3 (color) in Schared Memory + /* char bitMap[12] = {0}; for(int i = 0; i < sizeof(bitMap); i++) bitMap[i] = 'y'; writeSharedMemory(bitMap, sizeof(bitMap),1); + */ } if(eingabe == "read") { + auto str = getText(); + std::cout << str << std::endl; + /* char content[12] = {0}; std::cout << "key "<< impl.sharedMemoryKey << std::endl; getSharedMemory(content, sizeof(content), 1); std::cout << content << std::endl; + */ } } return 0; From 0c248186141f1eb58cf107024160385afc7c1520 Mon Sep 17 00:00:00 2001 From: cigerxwinchaker Date: Tue, 12 Nov 2019 17:26:21 +0100 Subject: [PATCH 24/49] =?UTF-8?q?=C3=A4nderungen=20f=C3=BCr=20den=20memory?= =?UTF-8?q?access=20key=20Cigerxwin=20Chaker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/main.cpp | 2 ++ src/SharedMemory.cpp | 10 +++++++--- src/SharedMemory.h | 2 ++ src/key.log | 1 + 4 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 src/key.log diff --git a/main/main.cpp b/main/main.cpp index fdf836c..1bef42a 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -28,6 +28,8 @@ int main(int argc, char** argv) std::cout << "OUTPUT ------------------------ OUTPUT\n" << std::endl; //Memory that is used now //outprint of all memory + } else if (eingabe != "exit"){ + std::cout << eingabe << " <- is not a known command" << std::endl; } } return 0; diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index 77520f6..ff81723 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -1,14 +1,20 @@ #include #include "SharedMemory.h" #include +#include key_t changedKey() { + std::ofstream keyFile; + keyFile.open("key.log", std::ofstream::out | std::ofstream::trunc); + keyFile.clear(); int newKey; std::cout << "Type in a new Key for the Shared Memory Segment" << std::endl; std::cout << "new Key#"; std::cin >> newKey; std::cout <<"New Key is -> " << newKey << std::endl; + keyFile << newKey; + keyFile.close(); return key_t(newKey); } @@ -36,9 +42,7 @@ void initSharedMemory(void) { std::string answer = getAnswerFromUser(); if(answer.compare("y") == 0) { - std::cout << "Please type in a new Key:\n"; - std::cout << "#"; - std::cin >> impl.sharedMemoryKey; + impl.sharedMemoryKey = changedKey(); std::cout << "new Try with Key:c " << impl.sharedMemoryKey << std::endl; initSharedMemory(); } else if(answer.compare("n") == 0) { diff --git a/src/SharedMemory.h b/src/SharedMemory.h index 96aefca..344aacc 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -12,4 +12,6 @@ void deleteSharedMemory(int s); void deleteSharedMemory(void); void initSharedMemory(void); +key_t changedKey(); +std::string getAnswerFromUser(); #endif //SHARED_MEMORY_H diff --git a/src/key.log b/src/key.log new file mode 100644 index 0000000..bd41cba --- /dev/null +++ b/src/key.log @@ -0,0 +1 @@ +12345 \ No newline at end of file From 5fd9a70a7231140901b043808292ecac86a6a9f7 Mon Sep 17 00:00:00 2001 From: Zakarya Boudouar Date: Tue, 12 Nov 2019 21:54:38 +0000 Subject: [PATCH 25/49] Update README.md --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index ad5a2dd..d4f2712 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,13 @@ # vKVM Shared Memory +Shared memory is a kernel-managed memory area that can be read and written by the graphical user interface , Text Renderer and the Library. + +## Features + +- set shared memory keys +- Manage the shared memory + + ## Installation Use the installation script provided in the Scripts repository @@ -7,3 +15,17 @@ to install the full package. Installing a single component is currently not supported. +## Usage + +mkdir build +cd build +cmake .. +make + +## Description + +changedKey(): create new Key for the Shared Memory. +getAnswerFromUser(): ask the User if he want to chgange the Key of Shared Memory. +initSharedMemory(): create Shared Memory and make it available t o use it +deleteSharedMemory(int s): delete the Shared memory. +deleteSharedMemory(): delete the Shared memory. From e99eaa8a255f3b12c08468e106cd3f017427441f Mon Sep 17 00:00:00 2001 From: zakarya Date: Wed, 13 Nov 2019 12:54:31 +0100 Subject: [PATCH 26/49] Update README --- README.md | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index d4f2712..acfbdec 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,14 @@ # vKVM Shared Memory -Shared memory is a kernel-managed memory area that can be read and written by the graphical user interface , Text Renderer and the Library. +Shared memory is a kernel-managed memory area that can be read and written by the Library. ## Features -- set shared memory keys - Manage the shared memory - + - Create new key for the shared memory. + - Ask the user if he want to change the key of shared memory. + - Create shared memory and make it available to use it + - Delete the shared memory. ## Installation @@ -15,17 +17,10 @@ to install the full package. Installing a single component is currently not supported. -## Usage +## Usage mkdir build cd build cmake .. make -## Description - -changedKey(): create new Key for the Shared Memory. -getAnswerFromUser(): ask the User if he want to chgange the Key of Shared Memory. -initSharedMemory(): create Shared Memory and make it available t o use it -deleteSharedMemory(int s): delete the Shared memory. -deleteSharedMemory(): delete the Shared memory. From dc30cc142b1e52f53edff006fe32390f18051f6f Mon Sep 17 00:00:00 2001 From: zakarya Date: Wed, 13 Nov 2019 12:56:24 +0100 Subject: [PATCH 27/49] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index acfbdec..d692491 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Shared memory is a kernel-managed memory area that can be read and written by the Library. -## Features +## Featuress - Manage the shared memory - Create new key for the shared memory. From 7483627e59d8fd4d5b076c630a6ac8853662b804 Mon Sep 17 00:00:00 2001 From: zakarya Date: Wed, 13 Nov 2019 12:57:08 +0100 Subject: [PATCH 28/49] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d692491..acfbdec 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Shared memory is a kernel-managed memory area that can be read and written by the Library. -## Featuress +## Features - Manage the shared memory - Create new key for the shared memory. From 7935cddd71405c80e7c13b942556da8273457c3b Mon Sep 17 00:00:00 2001 From: Julian Hinxlage Date: Wed, 13 Nov 2019 13:49:02 +0100 Subject: [PATCH 29/49] ~ vkvm namespace --- main/main.cpp | 14 ++++++++------ src/SharedMemory.cpp | 20 ++++++++++---------- src/SharedMemory.h | 2 +- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/main/main.cpp b/main/main.cpp index 33b3f4e..752fcef 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -3,20 +3,22 @@ #include "../src/SharedMemory.h" #include #include -#include "vkvm.h" +#include "vkvm.hpp" int main(int argc, char** argv) { - initialize(0); + vkvm::initialize(0); initSharedMemory(); struct sigaction sigIntHandler; sigIntHandler.sa_handler = deleteSharedMemory; sigemptyset(&sigIntHandler.sa_mask); sigIntHandler.sa_flags = 0; sigaction(SIGINT, &sigIntHandler, nullptr); - setDefaultValues(); + vkvm::setDefaultValues(); std::atexit(deleteSharedMemory); std::string eingabe; + + while(eingabe != "exit") { std::cout << "cmd# "; std::cin >> eingabe; @@ -24,7 +26,7 @@ int main(int argc, char** argv) { if(eingabe == "info") { std::cout << "OUTPUT ------------------------ OUTPUT\n" << std::endl; - std::cout << "memory ID: " << shmget(impl.sharedMemoryKey, 0, 0) << std::endl; + std::cout << "memory ID: " << shmget(vkvm::impl.sharedMemoryKey, 0, 0) << std::endl; std::cout << "Max memory Size: " << Max_Memory_Size << std::endl; std::cout << "OUTPUT ------------------------ OUTPUT\n" << std::endl; //Memory that is used now @@ -32,7 +34,7 @@ int main(int argc, char** argv) { } else if(eingabe == "write") { std::cout << "text: "; std::cin >> eingabe; - setText(eingabe); + vkvm::setText(eingabe); //write a bitMap for example 2 (width) * 2 (high) * 3 (color) in Schared Memory /* char bitMap[12] = {0}; @@ -41,7 +43,7 @@ int main(int argc, char** argv) { writeSharedMemory(bitMap, sizeof(bitMap),1); */ } else if(eingabe == "read") { - auto str = getText(); + auto str = vkvm::getText(); std::cout << str << std::endl; /* char content[12] = {0}; diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index ff81723..558c602 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -34,16 +34,16 @@ std::string getAnswerFromUser() void initSharedMemory(void) { - if(impl.sharedMemoryKey != key_t(0)) { - if (shmget(impl.sharedMemoryKey, Max_Memory_Size, IPC_CREAT | IPC_EXCL | 0666) < 0) + if(vkvm::impl.sharedMemoryKey != key_t(0)) { + if (shmget(vkvm::impl.sharedMemoryKey, Max_Memory_Size, IPC_CREAT | IPC_EXCL | 0666) < 0) { - std::cout << "Shared Memory with Key: " << impl.sharedMemoryKey << " is already in use\n" + std::cout << "Shared Memory with Key: " << vkvm::impl.sharedMemoryKey << " is already in use\n" <<"You can change the Key( type -> y or n ), or you can override the shared memory Segment(type -> override)\n"; std::string answer = getAnswerFromUser(); if(answer.compare("y") == 0) { - impl.sharedMemoryKey = changedKey(); - std::cout << "new Try with Key:c " << impl.sharedMemoryKey << std::endl; + vkvm::impl.sharedMemoryKey = changedKey(); + std::cout << "new Try with Key:c " << vkvm::impl.sharedMemoryKey << std::endl; initSharedMemory(); } else if(answer.compare("n") == 0) { std::cout << "This will end shared memory" < " << impl.sharedMemoryKey << " is not allowed here " << std::endl; - impl.sharedMemoryKey = changedKey(); + std::cerr <<"key -> " << vkvm::impl.sharedMemoryKey << " is not allowed here " << std::endl; + vkvm::impl.sharedMemoryKey = changedKey(); initSharedMemory(); } } @@ -65,7 +65,7 @@ void initSharedMemory(void) { void deleteSharedMemory(int s) { std::cerr << "programm ended with Code: " << s << std::endl; - if (shmctl(shmget(impl.sharedMemoryKey, 0, 0), IPC_RMID, 0) < 0 ) + if (shmctl(shmget(vkvm::impl.sharedMemoryKey, 0, 0), IPC_RMID, 0) < 0 ) { std::cerr << "Failed to remove shared Memory, maybe not existing: try cmd: ipcs, then delete with ipcrm -m $memID " << std::endl; } else { @@ -75,7 +75,7 @@ void deleteSharedMemory(int s) void deleteSharedMemory(void) { - if (shmctl(shmget(impl.sharedMemoryKey, 0, 0), IPC_RMID, 0) < 0 ) + if (shmctl(shmget(vkvm::impl.sharedMemoryKey, 0, 0), IPC_RMID, 0) < 0 ) { std::cerr << "Failed to remove shared Memory, maybe not existing: try cmd: ipcs " << std::endl; } else { diff --git a/src/SharedMemory.h b/src/SharedMemory.h index 344aacc..26a4d1d 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -2,7 +2,7 @@ #define SHARED_MEMORY_H #include #include -#include "internal.h" +#include "internal.hpp" //ID-Speicherbereich //Größe des Speicherbereichs hier 8MB (8000) From 4a63787d11265ddc77530f23eba30d3ebb3062e4 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Sat, 16 Nov 2019 18:29:00 +0000 Subject: [PATCH 30/49] ~ update clang tidy checks --- .ci/clang-tidy.sh | 2 +- .clang-tidy | 2 ++ CMakeLists.txt | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 .clang-tidy diff --git a/.ci/clang-tidy.sh b/.ci/clang-tidy.sh index 913c79a..1c3d7b3 100644 --- a/.ci/clang-tidy.sh +++ b/.ci/clang-tidy.sh @@ -9,7 +9,7 @@ filelist="$(find . -not \( -path './*build*' -prune \) -type f ! -name "$(printf for file in $filelist; do if echo "$file" | grep -q -E ".*(\.cpp|\.h|\.hpp)$" ; then #Extra check missing dependencies due to clang-tidy doesn't toggle exit code. - clang_tidy_lib_check="$(clang-tidy -warnings-as-errors='*' -header-filter='.*,-cpptoml.hpp' -checks='*,-llvm-header-guard,-fuchsia-statically-constructed-objects,-fuchsia-default-arguments,-fuchsia-default-arguments-calls,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-hicpp-signed-bitwise,-bugprone-exception-escape,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-cstyle-cast,-hicpp-member-init' "$file" -- -I. -std=c++14 2>&1)" + clang_tidy_lib_check="$(clang-tidy -warnings-as-errors='*' -header-filter='.*,-cpptoml.hpp' "$file" -- -I. -std=c++14 2>&1)" for tidy_line in $clang_tidy_lib_check; do echo "$tidy_line" | grep -q -v -E "^Error while processing*" if [ $? -eq 1 ]; then diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..b0965ca --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,2 @@ +Checks: '*,-llvm-header-guard,-fuchsia*,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-hicpp-signed-bitwise,-bugprone-exception-escape,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-cstyle-cast,-hicpp-member-init,-google-readability-namespace-comments,-llvm-namespace-comment,-cppcoreguidelines-pro-type-vararg,-hicpp-vararg,-modernize-use-trailing-return-type' +WarningsAsErrors: 'true' diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c14a86..55b3da3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ project(Shared_Memory) set(CMAKE_CXX_STANDARD 14) file(GLOB_RECURSE SOURCES src/*.cpp) -file(GLOB_RECURSE HEADERS src/*.h) +file(GLOB_RECURSE HEADERS src/*.hpp) file(GLOB_RECURSE TESTS test/*.cpp) set(LIB_PATH "${CMAKE_SOURCE_DIR}/../library") From b39a1943193c25f01894f473679b2424fe2e8778 Mon Sep 17 00:00:00 2001 From: "@Nurullah.Damla" Date: Thu, 21 Nov 2019 12:54:50 +0100 Subject: [PATCH 31/49] Toml eingebunden, Configfile erstellt und configuriert, Bugfix --- CMakeLists.txt | 5 +++++ res/config.toml | 15 +++++++++++++++ src/SharedMemory.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++ src/SharedMemory.h | 2 ++ 4 files changed, 68 insertions(+) create mode 100644 res/config.toml diff --git a/CMakeLists.txt b/CMakeLists.txt index 55b3da3..8b6b4ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,8 @@ set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "bin" "doc" " project(Shared_Memory) set(CMAKE_CXX_STANDARD 14) +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") +set(CMAKE_CXX_COMPILER "clang++") file(GLOB_RECURSE SOURCES src/*.cpp) file(GLOB_RECURSE HEADERS src/*.hpp) @@ -32,3 +34,6 @@ target_link_libraries(UnitTests Catch2::Catch2) include(CTest) include(Catch) catch_discover_tests(UnitTests) + +#toml +include_directories(lib/toml) diff --git a/res/config.toml b/res/config.toml new file mode 100644 index 0000000..e91e65f --- /dev/null +++ b/res/config.toml @@ -0,0 +1,15 @@ +#defaultKey = 12345 +newKey = 0 +layoutVersion = 0 +width = 0 +height = 0 +mode = 0 +redrawInterval = 0 +timerInterruptInterval = 0 +backgroundColor = 0 +foregroundColor = 0 +charactersPerRow = 0 +charactersPerColumn = 0 +font = 0 +mousePositionX = 0 +mousePositionY = 0 \ No newline at end of file diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index 558c602..81a43a2 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -2,6 +2,11 @@ #include "SharedMemory.h" #include #include +#include +#include + + + key_t changedKey() { @@ -15,6 +20,10 @@ key_t changedKey() std::cout <<"New Key is -> " << newKey << std::endl; keyFile << newKey; keyFile.close(); + + auto config = cpptoml::parse_file("res/config.toml"); + newKey = config->get_as("newKey").value_or(0); //toml + return key_t(newKey); } @@ -83,3 +92,40 @@ void deleteSharedMemory(void) } } +void getConfig(){ + auto config = cpptoml::parse_file("res/config.toml"); + + int layoutVersion = config->get_as("layoutVersion").value_or(0); + int width = config->get_as("width").value_or(0); + int height = config->get_as("height").value_or(0); + int mode = config->get_as("mode").value_or(0); + int timerInterruptInterval = config->get_as("timerInterruptInterval").value_or(0); + int backgroundColor = config->get_as("backgroundColor").value_or(0); + int foregroundColor = config->get_as("foregroundColor").value_or(0); + int charactersPerRow = config->get_as("charactersPerRow").value_or(0); + int charactersPerColumn = config->get_as("charactersPerColumn").value_or(0); + int font = config->get_as("font").value_or(0); + int mousePositionX = config->get_as("mousePositionX").value_or(0); + int mousePositionY = config->get_as("mousePositionY").value_or(0); + + /* + //convert to hex + std::string result; + std::stringstream ss; + ss << std::hex << result; + ss >> result; + */ + + vkvm::setLayoutVersion((vkvm::LayoutVersion) layoutVersion); + vkvm::setWidth(width); + vkvm::setHeight(height); + vkvm::setMode((vkvm::GraphicMode) mode); + vkvm::setTimerInterruptInterval(timerInterruptInterval); + vkvm::setBackgroundColor(vkvm::Color(backgroundColor)); + vkvm::setForegroundColor(vkvm::Color(foregroundColor)); + vkvm::setCharactersPerRow(charactersPerRow); + vkvm::setCharactersPerColumn(charactersPerColumn); + vkvm::setFont(vkvm::FontType(font,"",0,0)); + vkvm::setMousePosition(mousePositionX, mousePositionY); +} + diff --git a/src/SharedMemory.h b/src/SharedMemory.h index 26a4d1d..32732d4 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -14,4 +14,6 @@ void deleteSharedMemory(void); void initSharedMemory(void); key_t changedKey(); std::string getAnswerFromUser(); +//Config File +#define configFile "res/config.toml"; #endif //SHARED_MEMORY_H From 2ab027c9019b9d49fae9a56afb4fcfdee1dfe21d Mon Sep 17 00:00:00 2001 From: "@Nurullah.Damla" Date: Thu, 21 Nov 2019 13:00:08 +0100 Subject: [PATCH 32/49] Configfile Pfad im Header eingebunden (nun aenderung an einer stell moeglich) --- src/SharedMemory.cpp | 4 ++-- src/SharedMemory.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index 81a43a2..2619e92 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -21,7 +21,7 @@ key_t changedKey() keyFile << newKey; keyFile.close(); - auto config = cpptoml::parse_file("res/config.toml"); + auto config = cpptoml::parse_file(configFile); newKey = config->get_as("newKey").value_or(0); //toml return key_t(newKey); @@ -93,7 +93,7 @@ void deleteSharedMemory(void) } void getConfig(){ - auto config = cpptoml::parse_file("res/config.toml"); + auto config = cpptoml::parse_file(configFile); int layoutVersion = config->get_as("layoutVersion").value_or(0); int width = config->get_as("width").value_or(0); diff --git a/src/SharedMemory.h b/src/SharedMemory.h index 32732d4..e747abb 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -15,5 +15,5 @@ void initSharedMemory(void); key_t changedKey(); std::string getAnswerFromUser(); //Config File -#define configFile "res/config.toml"; +#define configFile "res/config.toml" #endif //SHARED_MEMORY_H From 62c22f0f41f52ce1389381fb5d876490c19aba8a Mon Sep 17 00:00:00 2001 From: "@Nurullah.Damla" Date: Wed, 27 Nov 2019 12:25:19 +0100 Subject: [PATCH 33/49] pushen der toml-file jetzt moeglich --- .gitignore | 1 - CMakeLists.txt | 8 +- lib/toml/cpptoml.h | 3668 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 3674 insertions(+), 3 deletions(-) create mode 100644 lib/toml/cpptoml.h diff --git a/.gitignore b/.gitignore index e8eb7d3..2504fb3 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,5 @@ CmakeCache.txt bin/ -lib/ include/ build/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b6b4ec..aee2325 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,10 +8,14 @@ if ("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") endif() set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "bin" "doc" "CMakeFiles" "lib" "include") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") +#set(CMAKE_CXX_COMPILER "clang++") + +#set(CMAKE_C_COMPILER "/usr/bin/clang") +#set(CMAKE_CXX_COMPILER "/usr/bin/clang++") + project(Shared_Memory) set(CMAKE_CXX_STANDARD 14) -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") -set(CMAKE_CXX_COMPILER "clang++") file(GLOB_RECURSE SOURCES src/*.cpp) file(GLOB_RECURSE HEADERS src/*.hpp) diff --git a/lib/toml/cpptoml.h b/lib/toml/cpptoml.h new file mode 100644 index 0000000..5a00da3 --- /dev/null +++ b/lib/toml/cpptoml.h @@ -0,0 +1,3668 @@ +/** + * @file cpptoml.h + * @author Chase Geigle + * @date May 2013 + */ + +#ifndef CPPTOML_H +#define CPPTOML_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __cplusplus > 201103L +#define CPPTOML_DEPRECATED(reason) [[deprecated(reason)]] +#elif defined(__clang__) +#define CPPTOML_DEPRECATED(reason) __attribute__((deprecated(reason))) +#elif defined(__GNUG__) +#define CPPTOML_DEPRECATED(reason) __attribute__((deprecated)) +#elif defined(_MSC_VER) +#if _MSC_VER < 1910 +#define CPPTOML_DEPRECATED(reason) __declspec(deprecated) +#else +#define CPPTOML_DEPRECATED(reason) [[deprecated(reason)]] +#endif +#endif + +namespace cpptoml +{ +class writer; // forward declaration +class base; // forward declaration +#if defined(CPPTOML_USE_MAP) +// a std::map will ensure that entries a sorted, albeit at a slight +// performance penalty relative to the (default) unordered_map +using string_to_base_map = std::map>; +#else +// by default an unordered_map is used for best performance as the +// toml specification does not require entries to be sorted +using string_to_base_map + = std::unordered_map>; +#endif + +// if defined, `base` will retain type information in form of an enum class +// such that static_cast can be used instead of dynamic_cast +// #define CPPTOML_NO_RTTI + +template +class option +{ + public: + option() : empty_{true} + { + // nothing + } + + option(T value) : empty_{false}, value_(std::move(value)) + { + // nothing + } + + explicit operator bool() const + { + return !empty_; + } + + const T& operator*() const + { + return value_; + } + + const T* operator->() const + { + return &value_; + } + + template + T value_or(U&& alternative) const + { + if (!empty_) + return value_; + return static_cast(std::forward(alternative)); + } + + private: + bool empty_; + T value_; +}; + +struct local_date +{ + int year = 0; + int month = 0; + int day = 0; +}; + +struct local_time +{ + int hour = 0; + int minute = 0; + int second = 0; + int microsecond = 0; +}; + +struct zone_offset +{ + int hour_offset = 0; + int minute_offset = 0; +}; + +struct local_datetime : local_date, local_time +{ +}; + +struct offset_datetime : local_datetime, zone_offset +{ + static inline struct offset_datetime from_zoned(const struct tm& t) + { + offset_datetime dt; + dt.year = t.tm_year + 1900; + dt.month = t.tm_mon + 1; + dt.day = t.tm_mday; + dt.hour = t.tm_hour; + dt.minute = t.tm_min; + dt.second = t.tm_sec; + + char buf[16]; + strftime(buf, 16, "%z", &t); + + int offset = std::stoi(buf); + dt.hour_offset = offset / 100; + dt.minute_offset = offset % 100; + return dt; + } + + CPPTOML_DEPRECATED("from_local has been renamed to from_zoned") + static inline struct offset_datetime from_local(const struct tm& t) + { + return from_zoned(t); + } + + static inline struct offset_datetime from_utc(const struct tm& t) + { + offset_datetime dt; + dt.year = t.tm_year + 1900; + dt.month = t.tm_mon + 1; + dt.day = t.tm_mday; + dt.hour = t.tm_hour; + dt.minute = t.tm_min; + dt.second = t.tm_sec; + return dt; + } +}; + +CPPTOML_DEPRECATED("datetime has been renamed to offset_datetime") +typedef offset_datetime datetime; + +class fill_guard +{ + public: + fill_guard(std::ostream& os) : os_(os), fill_{os.fill()} + { + // nothing + } + + ~fill_guard() + { + os_.fill(fill_); + } + + private: + std::ostream& os_; + std::ostream::char_type fill_; +}; + +inline std::ostream& operator<<(std::ostream& os, const local_date& dt) +{ + fill_guard g{os}; + os.fill('0'); + + using std::setw; + os << setw(4) << dt.year << "-" << setw(2) << dt.month << "-" << setw(2) + << dt.day; + + return os; +} + +inline std::ostream& operator<<(std::ostream& os, const local_time& ltime) +{ + fill_guard g{os}; + os.fill('0'); + + using std::setw; + os << setw(2) << ltime.hour << ":" << setw(2) << ltime.minute << ":" + << setw(2) << ltime.second; + + if (ltime.microsecond > 0) + { + os << "."; + int power = 100000; + for (int curr_us = ltime.microsecond; curr_us; power /= 10) + { + auto num = curr_us / power; + os << num; + curr_us -= num * power; + } + } + + return os; +} + +inline std::ostream& operator<<(std::ostream& os, const zone_offset& zo) +{ + fill_guard g{os}; + os.fill('0'); + + using std::setw; + + if (zo.hour_offset != 0 || zo.minute_offset != 0) + { + if (zo.hour_offset > 0) + { + os << "+"; + } + else + { + os << "-"; + } + os << setw(2) << std::abs(zo.hour_offset) << ":" << setw(2) + << std::abs(zo.minute_offset); + } + else + { + os << "Z"; + } + + return os; +} + +inline std::ostream& operator<<(std::ostream& os, const local_datetime& dt) +{ + return os << static_cast(dt) << "T" + << static_cast(dt); +} + +inline std::ostream& operator<<(std::ostream& os, const offset_datetime& dt) +{ + return os << static_cast(dt) + << static_cast(dt); +} + +template +struct is_one_of; + +template +struct is_one_of : std::is_same +{ +}; + +template +struct is_one_of +{ + const static bool value + = std::is_same::value || is_one_of::value; +}; + +template +class value; + +template +struct valid_value + : is_one_of +{ +}; + +template +struct value_traits; + +template +struct valid_value_or_string_convertible +{ + + const static bool value = valid_value::type>::value + || std::is_convertible::value; +}; + +template +struct value_traits::value>::type> +{ + using value_type = typename std::conditional< + valid_value::type>::value, + typename std::decay::type, std::string>::type; + + using type = value; + + static value_type construct(T&& val) + { + return value_type(val); + } +}; + +template +struct value_traits< + T, + typename std::enable_if< + !valid_value_or_string_convertible::value + && std::is_floating_point::type>::value>::type> +{ + using value_type = typename std::decay::type; + + using type = value; + + static value_type construct(T&& val) + { + return value_type(val); + } +}; + +template +struct value_traits< + T, typename std::enable_if< + !valid_value_or_string_convertible::value + && !std::is_floating_point::type>::value + && std::is_signed::type>::value>::type> +{ + using value_type = int64_t; + + using type = value; + + static value_type construct(T&& val) + { + if (val < (std::numeric_limits::min)()) + throw std::underflow_error{"constructed value cannot be " + "represented by a 64-bit signed " + "integer"}; + + if (val > (std::numeric_limits::max)()) + throw std::overflow_error{"constructed value cannot be represented " + "by a 64-bit signed integer"}; + + return static_cast(val); + } +}; + +template +struct value_traits< + T, typename std::enable_if< + !valid_value_or_string_convertible::value + && std::is_unsigned::type>::value>::type> +{ + using value_type = int64_t; + + using type = value; + + static value_type construct(T&& val) + { + if (val > static_cast((std::numeric_limits::max)())) + throw std::overflow_error{"constructed value cannot be represented " + "by a 64-bit signed integer"}; + + return static_cast(val); + } +}; + +class array; +class table; +class table_array; + +template +struct array_of_trait +{ + using return_type = option>; +}; + +template <> +struct array_of_trait +{ + using return_type = option>>; +}; + +template +inline std::shared_ptr::type> make_value(T&& val); +inline std::shared_ptr make_array(); + +namespace detail +{ +template +inline std::shared_ptr make_element(); +} + +inline std::shared_ptr make_table(); +inline std::shared_ptr make_table_array(bool is_inline = false); + +#if defined(CPPTOML_NO_RTTI) +/// Base type used to store underlying data type explicitly if RTTI is disabled +enum class base_type +{ + NONE, + STRING, + LOCAL_TIME, + LOCAL_DATE, + LOCAL_DATETIME, + OFFSET_DATETIME, + INT, + FLOAT, + BOOL, + TABLE, + ARRAY, + TABLE_ARRAY +}; + +/// Type traits class to convert C++ types to enum member +template +struct base_type_traits; + +template <> +struct base_type_traits +{ + static const base_type type = base_type::STRING; +}; + +template <> +struct base_type_traits +{ + static const base_type type = base_type::LOCAL_TIME; +}; + +template <> +struct base_type_traits +{ + static const base_type type = base_type::LOCAL_DATE; +}; + +template <> +struct base_type_traits +{ + static const base_type type = base_type::LOCAL_DATETIME; +}; + +template <> +struct base_type_traits +{ + static const base_type type = base_type::OFFSET_DATETIME; +}; + +template <> +struct base_type_traits +{ + static const base_type type = base_type::INT; +}; + +template <> +struct base_type_traits +{ + static const base_type type = base_type::FLOAT; +}; + +template <> +struct base_type_traits +{ + static const base_type type = base_type::BOOL; +}; + +template <> +struct base_type_traits
+{ + static const base_type type = base_type::TABLE; +}; + +template <> +struct base_type_traits +{ + static const base_type type = base_type::ARRAY; +}; + +template <> +struct base_type_traits +{ + static const base_type type = base_type::TABLE_ARRAY; +}; +#endif + +/** + * A generic base TOML value used for type erasure. + */ +class base : public std::enable_shared_from_this +{ + public: + virtual ~base() = default; + + virtual std::shared_ptr clone() const = 0; + + /** + * Determines if the given TOML element is a value. + */ + virtual bool is_value() const + { + return false; + } + + /** + * Determines if the given TOML element is a table. + */ + virtual bool is_table() const + { + return false; + } + + /** + * Converts the TOML element into a table. + */ + std::shared_ptr
as_table() + { + if (is_table()) + return std::static_pointer_cast
(shared_from_this()); + return nullptr; + } + /** + * Determines if the TOML element is an array of "leaf" elements. + */ + virtual bool is_array() const + { + return false; + } + + /** + * Converts the TOML element to an array. + */ + std::shared_ptr as_array() + { + if (is_array()) + return std::static_pointer_cast(shared_from_this()); + return nullptr; + } + + /** + * Determines if the given TOML element is an array of tables. + */ + virtual bool is_table_array() const + { + return false; + } + + /** + * Converts the TOML element into a table array. + */ + std::shared_ptr as_table_array() + { + if (is_table_array()) + return std::static_pointer_cast(shared_from_this()); + return nullptr; + } + + /** + * Attempts to coerce the TOML element into a concrete TOML value + * of type T. + */ + template + std::shared_ptr> as(); + + template + std::shared_ptr> as() const; + + template + void accept(Visitor&& visitor, Args&&... args) const; + +#if defined(CPPTOML_NO_RTTI) + base_type type() const + { + return type_; + } + + protected: + base(const base_type t) : type_(t) + { + // nothing + } + + private: + const base_type type_ = base_type::NONE; + +#else + protected: + base() + { + // nothing + } +#endif +}; + +/** + * A concrete TOML value representing the "leaves" of the "tree". + */ +template +class value : public base +{ + struct make_shared_enabler + { + // nothing; this is a private key accessible only to friends + }; + + template + friend std::shared_ptr::type> + cpptoml::make_value(U&& val); + + public: + static_assert(valid_value::value, "invalid value type"); + + std::shared_ptr clone() const override; + + value(const make_shared_enabler&, const T& val) : value(val) + { + // nothing; note that users cannot actually invoke this function + // because they lack access to the make_shared_enabler. + } + + bool is_value() const override + { + return true; + } + + /** + * Gets the data associated with this value. + */ + T& get() + { + return data_; + } + + /** + * Gets the data associated with this value. Const version. + */ + const T& get() const + { + return data_; + } + + private: + T data_; + + /** + * Constructs a value from the given data. + */ +#if defined(CPPTOML_NO_RTTI) + value(const T& val) : base(base_type_traits::type), data_(val) + { + } +#else + value(const T& val) : data_(val) + { + } +#endif + + value(const value& val) = delete; + value& operator=(const value& val) = delete; +}; + +template +std::shared_ptr::type> make_value(T&& val) +{ + using value_type = typename value_traits::type; + using enabler = typename value_type::make_shared_enabler; + return std::make_shared( + enabler{}, value_traits::construct(std::forward(val))); +} + +template +inline std::shared_ptr> base::as() +{ +#if defined(CPPTOML_NO_RTTI) + if (type() == base_type_traits::type) + return std::static_pointer_cast>(shared_from_this()); + else + return nullptr; +#else + return std::dynamic_pointer_cast>(shared_from_this()); +#endif +} + +// special case value to allow getting an integer parameter as a +// double value +template <> +inline std::shared_ptr> base::as() +{ +#if defined(CPPTOML_NO_RTTI) + if (type() == base_type::FLOAT) + return std::static_pointer_cast>(shared_from_this()); + + if (type() == base_type::INT) + { + auto v = std::static_pointer_cast>(shared_from_this()); + return make_value(static_cast(v->get())); + } +#else + if (auto v = std::dynamic_pointer_cast>(shared_from_this())) + return v; + + if (auto v = std::dynamic_pointer_cast>(shared_from_this())) + return make_value(static_cast(v->get())); +#endif + + return nullptr; +} + +template +inline std::shared_ptr> base::as() const +{ +#if defined(CPPTOML_NO_RTTI) + if (type() == base_type_traits::type) + return std::static_pointer_cast>(shared_from_this()); + else + return nullptr; +#else + return std::dynamic_pointer_cast>(shared_from_this()); +#endif +} + +// special case value to allow getting an integer parameter as a +// double value +template <> +inline std::shared_ptr> base::as() const +{ +#if defined(CPPTOML_NO_RTTI) + if (type() == base_type::FLOAT) + return std::static_pointer_cast>( + shared_from_this()); + + if (type() == base_type::INT) + { + auto v = as(); + // the below has to be a non-const value due to a bug in + // libc++: https://llvm.org/bugs/show_bug.cgi?id=18843 + return make_value(static_cast(v->get())); + } +#else + if (auto v + = std::dynamic_pointer_cast>(shared_from_this())) + return v; + + if (auto v = as()) + { + // the below has to be a non-const value due to a bug in + // libc++: https://llvm.org/bugs/show_bug.cgi?id=18843 + return make_value(static_cast(v->get())); + } +#endif + + return nullptr; +} + +/** + * Exception class for array insertion errors. + */ +class array_exception : public std::runtime_error +{ + public: + array_exception(const std::string& err) : std::runtime_error{err} + { + } +}; + +class array : public base +{ + public: + friend std::shared_ptr make_array(); + + std::shared_ptr clone() const override; + + virtual bool is_array() const override + { + return true; + } + + using size_type = std::size_t; + + /** + * arrays can be iterated over + */ + using iterator = std::vector>::iterator; + + /** + * arrays can be iterated over. Const version. + */ + using const_iterator = std::vector>::const_iterator; + + iterator begin() + { + return values_.begin(); + } + + const_iterator begin() const + { + return values_.begin(); + } + + iterator end() + { + return values_.end(); + } + + const_iterator end() const + { + return values_.end(); + } + + /** + * Obtains the array (vector) of base values. + */ + std::vector>& get() + { + return values_; + } + + /** + * Obtains the array (vector) of base values. Const version. + */ + const std::vector>& get() const + { + return values_; + } + + std::shared_ptr at(size_t idx) const + { + return values_.at(idx); + } + + /** + * Obtains an array of values. Note that elements may be + * nullptr if they cannot be converted to a value. + */ + template + std::vector>> array_of() const + { + std::vector>> result(values_.size()); + + std::transform(values_.begin(), values_.end(), result.begin(), + [&](std::shared_ptr v) { return v->as(); }); + + return result; + } + + /** + * Obtains a option>. The option will be empty if the array + * contains values that are not of type T. + */ + template + inline typename array_of_trait::return_type get_array_of() const + { + std::vector result; + result.reserve(values_.size()); + + for (const auto& val : values_) + { + if (auto v = val->as()) + result.push_back(v->get()); + else + return {}; + } + + return {std::move(result)}; + } + + /** + * Obtains an array of arrays. Note that elements may be nullptr + * if they cannot be converted to a array. + */ + std::vector> nested_array() const + { + std::vector> result(values_.size()); + + std::transform(values_.begin(), values_.end(), result.begin(), + [&](std::shared_ptr v) -> std::shared_ptr { + if (v->is_array()) + return std::static_pointer_cast(v); + return std::shared_ptr{}; + }); + + return result; + } + + /** + * Add a value to the end of the array + */ + template + void push_back(const std::shared_ptr>& val) + { + if (values_.empty() || values_[0]->as()) + { + values_.push_back(val); + } + else + { + throw array_exception{"Arrays must be homogenous."}; + } + } + + /** + * Add an array to the end of the array + */ + void push_back(const std::shared_ptr& val) + { + if (values_.empty() || values_[0]->is_array()) + { + values_.push_back(val); + } + else + { + throw array_exception{"Arrays must be homogenous."}; + } + } + + /** + * Convenience function for adding a simple element to the end + * of the array. + */ + template + void push_back(T&& val, typename value_traits::type* = 0) + { + push_back(make_value(std::forward(val))); + } + + /** + * Insert a value into the array + */ + template + iterator insert(iterator position, const std::shared_ptr>& value) + { + if (values_.empty() || values_[0]->as()) + { + return values_.insert(position, value); + } + else + { + throw array_exception{"Arrays must be homogenous."}; + } + } + + /** + * Insert an array into the array + */ + iterator insert(iterator position, const std::shared_ptr& value) + { + if (values_.empty() || values_[0]->is_array()) + { + return values_.insert(position, value); + } + else + { + throw array_exception{"Arrays must be homogenous."}; + } + } + + /** + * Convenience function for inserting a simple element in the array + */ + template + iterator insert(iterator position, T&& val, + typename value_traits::type* = 0) + { + return insert(position, make_value(std::forward(val))); + } + + /** + * Erase an element from the array + */ + iterator erase(iterator position) + { + return values_.erase(position); + } + + /** + * Clear the array + */ + void clear() + { + values_.clear(); + } + + /** + * Reserve space for n values. + */ + void reserve(size_type n) + { + values_.reserve(n); + } + + private: +#if defined(CPPTOML_NO_RTTI) + array() : base(base_type::ARRAY) + { + // empty + } +#else + array() = default; +#endif + + template + array(InputIterator begin, InputIterator end) : values_{begin, end} + { + // nothing + } + + array(const array& obj) = delete; + array& operator=(const array& obj) = delete; + + std::vector> values_; +}; + +inline std::shared_ptr make_array() +{ + struct make_shared_enabler : public array + { + make_shared_enabler() + { + // nothing + } + }; + + return std::make_shared(); +} + +namespace detail +{ +template <> +inline std::shared_ptr make_element() +{ + return make_array(); +} +} // namespace detail + +/** + * Obtains a option>. The option will be empty if the array + * contains values that are not of type T. + */ +template <> +inline typename array_of_trait::return_type +array::get_array_of() const +{ + std::vector> result; + result.reserve(values_.size()); + + for (const auto& val : values_) + { + if (auto v = val->as_array()) + result.push_back(v); + else + return {}; + } + + return {std::move(result)}; +} + +class table; + +class table_array : public base +{ + friend class table; + friend std::shared_ptr make_table_array(bool); + + public: + std::shared_ptr clone() const override; + + using size_type = std::size_t; + + /** + * arrays can be iterated over + */ + using iterator = std::vector>::iterator; + + /** + * arrays can be iterated over. Const version. + */ + using const_iterator = std::vector>::const_iterator; + + iterator begin() + { + return array_.begin(); + } + + const_iterator begin() const + { + return array_.begin(); + } + + iterator end() + { + return array_.end(); + } + + const_iterator end() const + { + return array_.end(); + } + + virtual bool is_table_array() const override + { + return true; + } + + std::vector>& get() + { + return array_; + } + + const std::vector>& get() const + { + return array_; + } + + /** + * Add a table to the end of the array + */ + void push_back(const std::shared_ptr
& val) + { + array_.push_back(val); + } + + /** + * Insert a table into the array + */ + iterator insert(iterator position, const std::shared_ptr
& value) + { + return array_.insert(position, value); + } + + /** + * Erase an element from the array + */ + iterator erase(iterator position) + { + return array_.erase(position); + } + + /** + * Clear the array + */ + void clear() + { + array_.clear(); + } + + /** + * Reserve space for n tables. + */ + void reserve(size_type n) + { + array_.reserve(n); + } + + /** + * Whether or not the table array is declared inline. This mostly + * matters for parsing, where statically defined arrays cannot be + * appended to using the array-of-table syntax. + */ + bool is_inline() const + { + return is_inline_; + } + + private: +#if defined(CPPTOML_NO_RTTI) + table_array(bool is_inline = false) + : base(base_type::TABLE_ARRAY), is_inline_(is_inline) + { + // nothing + } +#else + table_array(bool is_inline = false) : is_inline_(is_inline) + { + // nothing + } +#endif + + table_array(const table_array& obj) = delete; + table_array& operator=(const table_array& rhs) = delete; + + std::vector> array_; + const bool is_inline_ = false; +}; + +inline std::shared_ptr make_table_array(bool is_inline) +{ + struct make_shared_enabler : public table_array + { + make_shared_enabler(bool mse_is_inline) : table_array(mse_is_inline) + { + // nothing + } + }; + + return std::make_shared(is_inline); +} + +namespace detail +{ +template <> +inline std::shared_ptr make_element() +{ + return make_table_array(true); +} +} // namespace detail + +// The below are overloads for fetching specific value types out of a value +// where special casting behavior (like bounds checking) is desired + +template +typename std::enable_if::value + && std::is_signed::value, + option>::type +get_impl(const std::shared_ptr& elem) +{ + if (auto v = elem->as()) + { + if (v->get() < (std::numeric_limits::min)()) + throw std::underflow_error{ + "T cannot represent the value requested in get"}; + + if (v->get() > (std::numeric_limits::max)()) + throw std::overflow_error{ + "T cannot represent the value requested in get"}; + + return {static_cast(v->get())}; + } + else + { + return {}; + } +} + +template +typename std::enable_if::value + && std::is_unsigned::value, + option>::type +get_impl(const std::shared_ptr& elem) +{ + if (auto v = elem->as()) + { + if (v->get() < 0) + throw std::underflow_error{"T cannot store negative value in get"}; + + if (static_cast(v->get()) > (std::numeric_limits::max)()) + throw std::overflow_error{ + "T cannot represent the value requested in get"}; + + return {static_cast(v->get())}; + } + else + { + return {}; + } +} + +template +typename std::enable_if::value + || std::is_same::value, + option>::type +get_impl(const std::shared_ptr& elem) +{ + if (auto v = elem->as()) + { + return {v->get()}; + } + else + { + return {}; + } +} + +/** + * Represents a TOML keytable. + */ +class table : public base +{ + public: + friend class table_array; + friend std::shared_ptr
make_table(); + + std::shared_ptr clone() const override; + + /** + * tables can be iterated over. + */ + using iterator = string_to_base_map::iterator; + + /** + * tables can be iterated over. Const version. + */ + using const_iterator = string_to_base_map::const_iterator; + + iterator begin() + { + return map_.begin(); + } + + const_iterator begin() const + { + return map_.begin(); + } + + iterator end() + { + return map_.end(); + } + + const_iterator end() const + { + return map_.end(); + } + + bool is_table() const override + { + return true; + } + + bool empty() const + { + return map_.empty(); + } + + /** + * Determines if this key table contains the given key. + */ + bool contains(const std::string& key) const + { + return map_.find(key) != map_.end(); + } + + /** + * Determines if this key table contains the given key. Will + * resolve "qualified keys". Qualified keys are the full access + * path separated with dots like "grandparent.parent.child". + */ + bool contains_qualified(const std::string& key) const + { + return resolve_qualified(key); + } + + /** + * Obtains the base for a given key. + * @throw std::out_of_range if the key does not exist + */ + std::shared_ptr get(const std::string& key) const + { + return map_.at(key); + } + + /** + * Obtains the base for a given key. Will resolve "qualified + * keys". Qualified keys are the full access path separated with + * dots like "grandparent.parent.child". + * + * @throw std::out_of_range if the key does not exist + */ + std::shared_ptr get_qualified(const std::string& key) const + { + std::shared_ptr p; + resolve_qualified(key, &p); + return p; + } + + /** + * Obtains a table for a given key, if possible. + */ + std::shared_ptr
get_table(const std::string& key) const + { + if (contains(key) && get(key)->is_table()) + return std::static_pointer_cast
(get(key)); + return nullptr; + } + + /** + * Obtains a table for a given key, if possible. Will resolve + * "qualified keys". + */ + std::shared_ptr
get_table_qualified(const std::string& key) const + { + if (contains_qualified(key) && get_qualified(key)->is_table()) + return std::static_pointer_cast
(get_qualified(key)); + return nullptr; + } + + /** + * Obtains an array for a given key. + */ + std::shared_ptr get_array(const std::string& key) const + { + if (!contains(key)) + return nullptr; + return get(key)->as_array(); + } + + /** + * Obtains an array for a given key. Will resolve "qualified keys". + */ + std::shared_ptr get_array_qualified(const std::string& key) const + { + if (!contains_qualified(key)) + return nullptr; + return get_qualified(key)->as_array(); + } + + /** + * Obtains a table_array for a given key, if possible. + */ + std::shared_ptr get_table_array(const std::string& key) const + { + if (!contains(key)) + return nullptr; + return get(key)->as_table_array(); + } + + /** + * Obtains a table_array for a given key, if possible. Will resolve + * "qualified keys". + */ + std::shared_ptr + get_table_array_qualified(const std::string& key) const + { + if (!contains_qualified(key)) + return nullptr; + return get_qualified(key)->as_table_array(); + } + + /** + * Helper function that attempts to get a value corresponding + * to the template parameter from a given key. + */ + template + option get_as(const std::string& key) const + { + try + { + return get_impl(get(key)); + } + catch (const std::out_of_range&) + { + return {}; + } + } + + /** + * Helper function that attempts to get a value corresponding + * to the template parameter from a given key. Will resolve "qualified + * keys". + */ + template + option get_qualified_as(const std::string& key) const + { + try + { + return get_impl(get_qualified(key)); + } + catch (const std::out_of_range&) + { + return {}; + } + } + + /** + * Helper function that attempts to get an array of values of a given + * type corresponding to the template parameter for a given key. + * + * If the key doesn't exist, doesn't exist as an array type, or one or + * more keys inside the array type are not of type T, an empty option + * is returned. Otherwise, an option containing a vector of the values + * is returned. + */ + template + inline typename array_of_trait::return_type + get_array_of(const std::string& key) const + { + if (auto v = get_array(key)) + { + std::vector result; + result.reserve(v->get().size()); + + for (const auto& b : v->get()) + { + if (auto val = b->as()) + result.push_back(val->get()); + else + return {}; + } + return {std::move(result)}; + } + + return {}; + } + + /** + * Helper function that attempts to get an array of values of a given + * type corresponding to the template parameter for a given key. Will + * resolve "qualified keys". + * + * If the key doesn't exist, doesn't exist as an array type, or one or + * more keys inside the array type are not of type T, an empty option + * is returned. Otherwise, an option containing a vector of the values + * is returned. + */ + template + inline typename array_of_trait::return_type + get_qualified_array_of(const std::string& key) const + { + if (auto v = get_array_qualified(key)) + { + std::vector result; + result.reserve(v->get().size()); + + for (const auto& b : v->get()) + { + if (auto val = b->as()) + result.push_back(val->get()); + else + return {}; + } + return {std::move(result)}; + } + + return {}; + } + + /** + * Adds an element to the keytable. + */ + void insert(const std::string& key, const std::shared_ptr& value) + { + map_[key] = value; + } + + /** + * Convenience shorthand for adding a simple element to the + * keytable. + */ + template + void insert(const std::string& key, T&& val, + typename value_traits::type* = 0) + { + insert(key, make_value(std::forward(val))); + } + + /** + * Removes an element from the table. + */ + void erase(const std::string& key) + { + map_.erase(key); + } + + private: +#if defined(CPPTOML_NO_RTTI) + table() : base(base_type::TABLE) + { + // nothing + } +#else + table() + { + // nothing + } +#endif + + table(const table& obj) = delete; + table& operator=(const table& rhs) = delete; + + std::vector split(const std::string& value, + char separator) const + { + std::vector result; + std::string::size_type p = 0; + std::string::size_type q; + while ((q = value.find(separator, p)) != std::string::npos) + { + result.emplace_back(value, p, q - p); + p = q + 1; + } + result.emplace_back(value, p); + return result; + } + + // If output parameter p is specified, fill it with the pointer to the + // specified entry and throw std::out_of_range if it couldn't be found. + // + // Otherwise, just return true if the entry could be found or false + // otherwise and do not throw. + bool resolve_qualified(const std::string& key, + std::shared_ptr* p = nullptr) const + { + auto parts = split(key, '.'); + auto last_key = parts.back(); + parts.pop_back(); + + auto cur_table = this; + for (const auto& part : parts) + { + cur_table = cur_table->get_table(part).get(); + if (!cur_table) + { + if (!p) + return false; + + throw std::out_of_range{key + " is not a valid key"}; + } + } + + if (!p) + return cur_table->map_.count(last_key) != 0; + + *p = cur_table->map_.at(last_key); + return true; + } + + string_to_base_map map_; +}; + +/** + * Helper function that attempts to get an array of arrays for a given + * key. + * + * If the key doesn't exist, doesn't exist as an array type, or one or + * more keys inside the array type are not of type T, an empty option + * is returned. Otherwise, an option containing a vector of the values + * is returned. + */ +template <> +inline typename array_of_trait::return_type +table::get_array_of(const std::string& key) const +{ + if (auto v = get_array(key)) + { + std::vector> result; + result.reserve(v->get().size()); + + for (const auto& b : v->get()) + { + if (auto val = b->as_array()) + result.push_back(val); + else + return {}; + } + + return {std::move(result)}; + } + + return {}; +} + +/** + * Helper function that attempts to get an array of arrays for a given + * key. Will resolve "qualified keys". + * + * If the key doesn't exist, doesn't exist as an array type, or one or + * more keys inside the array type are not of type T, an empty option + * is returned. Otherwise, an option containing a vector of the values + * is returned. + */ +template <> +inline typename array_of_trait::return_type +table::get_qualified_array_of(const std::string& key) const +{ + if (auto v = get_array_qualified(key)) + { + std::vector> result; + result.reserve(v->get().size()); + + for (const auto& b : v->get()) + { + if (auto val = b->as_array()) + result.push_back(val); + else + return {}; + } + + return {std::move(result)}; + } + + return {}; +} + +std::shared_ptr
make_table() +{ + struct make_shared_enabler : public table + { + make_shared_enabler() + { + // nothing + } + }; + + return std::make_shared(); +} + +namespace detail +{ +template <> +inline std::shared_ptr
make_element
() +{ + return make_table(); +} +} // namespace detail + +template +std::shared_ptr value::clone() const +{ + return make_value(data_); +} + +inline std::shared_ptr array::clone() const +{ + auto result = make_array(); + result->reserve(values_.size()); + for (const auto& ptr : values_) + result->values_.push_back(ptr->clone()); + return result; +} + +inline std::shared_ptr table_array::clone() const +{ + auto result = make_table_array(is_inline()); + result->reserve(array_.size()); + for (const auto& ptr : array_) + result->array_.push_back(ptr->clone()->as_table()); + return result; +} + +inline std::shared_ptr table::clone() const +{ + auto result = make_table(); + for (const auto& pr : map_) + result->insert(pr.first, pr.second->clone()); + return result; +} + +/** + * Exception class for all TOML parsing errors. + */ +class parse_exception : public std::runtime_error +{ + public: + parse_exception(const std::string& err) : std::runtime_error{err} + { + } + + parse_exception(const std::string& err, std::size_t line_number) + : std::runtime_error{err + " at line " + std::to_string(line_number)} + { + } +}; + +inline bool is_number(char c) +{ + return c >= '0' && c <= '9'; +} + +inline bool is_hex(char c) +{ + return is_number(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); +} + +/** + * Helper object for consuming expected characters. + */ +template +class consumer +{ + public: + consumer(std::string::iterator& it, const std::string::iterator& end, + OnError&& on_error) + : it_(it), end_(end), on_error_(std::forward(on_error)) + { + // nothing + } + + void operator()(char c) + { + if (it_ == end_ || *it_ != c) + on_error_(); + ++it_; + } + + template + void operator()(const char (&str)[N]) + { + std::for_each(std::begin(str), std::end(str) - 1, + [&](char c) { (*this)(c); }); + } + + void eat_or(char a, char b) + { + if (it_ == end_ || (*it_ != a && *it_ != b)) + on_error_(); + ++it_; + } + + int eat_digits(int len) + { + int val = 0; + for (int i = 0; i < len; ++i) + { + if (!is_number(*it_) || it_ == end_) + on_error_(); + val = 10 * val + (*it_++ - '0'); + } + return val; + } + + void error() + { + on_error_(); + } + + private: + std::string::iterator& it_; + const std::string::iterator& end_; + OnError on_error_; +}; + +template +consumer make_consumer(std::string::iterator& it, + const std::string::iterator& end, + OnError&& on_error) +{ + return consumer(it, end, std::forward(on_error)); +} + +// replacement for std::getline to handle incorrectly line-ended files +// https://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +namespace detail +{ +inline std::istream& getline(std::istream& input, std::string& line) +{ + line.clear(); + + std::istream::sentry sentry{input, true}; + auto sb = input.rdbuf(); + + while (true) + { + auto c = sb->sbumpc(); + if (c == '\r') + { + if (sb->sgetc() == '\n') + c = sb->sbumpc(); + } + + if (c == '\n') + return input; + + if (c == std::istream::traits_type::eof()) + { + if (line.empty()) + input.setstate(std::ios::eofbit); + return input; + } + + line.push_back(static_cast(c)); + } +} +} // namespace detail + +/** + * The parser class. + */ +class parser +{ + public: + /** + * Parsers are constructed from streams. + */ + parser(std::istream& stream) : input_(stream) + { + // nothing + } + + parser& operator=(const parser& parser) = delete; + + /** + * Parses the stream this parser was created on until EOF. + * @throw parse_exception if there are errors in parsing + */ + std::shared_ptr
parse() + { + std::shared_ptr
root = make_table(); + + table* curr_table = root.get(); + + while (detail::getline(input_, line_)) + { + line_number_++; + auto it = line_.begin(); + auto end = line_.end(); + consume_whitespace(it, end); + if (it == end || *it == '#') + continue; + if (*it == '[') + { + curr_table = root.get(); + parse_table(it, end, curr_table); + } + else + { + parse_key_value(it, end, curr_table); + consume_whitespace(it, end); + eol_or_comment(it, end); + } + } + return root; + } + + private: +#if defined _MSC_VER + __declspec(noreturn) +#elif defined __GNUC__ + __attribute__((noreturn)) +#endif + void throw_parse_exception(const std::string& err) + { + throw parse_exception{err, line_number_}; + } + + void parse_table(std::string::iterator& it, + const std::string::iterator& end, table*& curr_table) + { + // remove the beginning keytable marker + ++it; + if (it == end) + throw_parse_exception("Unexpected end of table"); + if (*it == '[') + parse_table_array(it, end, curr_table); + else + parse_single_table(it, end, curr_table); + } + + void parse_single_table(std::string::iterator& it, + const std::string::iterator& end, + table*& curr_table) + { + if (it == end || *it == ']') + throw_parse_exception("Table name cannot be empty"); + + std::string full_table_name; + bool inserted = false; + + auto key_end = [](char c) { return c == ']'; }; + + auto key_part_handler = [&](const std::string& part) { + if (part.empty()) + throw_parse_exception("Empty component of table name"); + + if (!full_table_name.empty()) + full_table_name += '.'; + full_table_name += part; + + if (curr_table->contains(part)) + { +#if !defined(__PGI) + auto b = curr_table->get(part); +#else + // Workaround for PGI compiler + std::shared_ptr b = curr_table->get(part); +#endif + if (b->is_table()) + curr_table = static_cast(b.get()); + else if (b->is_table_array()) + curr_table = std::static_pointer_cast(b) + ->get() + .back() + .get(); + else + throw_parse_exception("Key " + full_table_name + + "already exists as a value"); + } + else + { + inserted = true; + curr_table->insert(part, make_table()); + curr_table = static_cast(curr_table->get(part).get()); + } + }; + + key_part_handler(parse_key(it, end, key_end, key_part_handler)); + + if (it == end) + throw_parse_exception( + "Unterminated table declaration; did you forget a ']'?"); + + if (*it != ']') + { + std::string errmsg{"Unexpected character in table definition: "}; + errmsg += '"'; + errmsg += *it; + errmsg += '"'; + throw_parse_exception(errmsg); + } + + // table already existed + if (!inserted) + { + auto is_value + = [](const std::pair&>& p) { + return p.second->is_value(); + }; + + // if there are any values, we can't add values to this table + // since it has already been defined. If there aren't any + // values, then it was implicitly created by something like + // [a.b] + if (curr_table->empty() + || std::any_of(curr_table->begin(), curr_table->end(), + is_value)) + { + throw_parse_exception("Redefinition of table " + + full_table_name); + } + } + + ++it; + consume_whitespace(it, end); + eol_or_comment(it, end); + } + + void parse_table_array(std::string::iterator& it, + const std::string::iterator& end, table*& curr_table) + { + ++it; + if (it == end || *it == ']') + throw_parse_exception("Table array name cannot be empty"); + + auto key_end = [](char c) { return c == ']'; }; + + std::string full_ta_name; + auto key_part_handler = [&](const std::string& part) { + if (part.empty()) + throw_parse_exception("Empty component of table array name"); + + if (!full_ta_name.empty()) + full_ta_name += '.'; + full_ta_name += part; + + if (curr_table->contains(part)) + { +#if !defined(__PGI) + auto b = curr_table->get(part); +#else + // Workaround for PGI compiler + std::shared_ptr b = curr_table->get(part); +#endif + + // if this is the end of the table array name, add an + // element to the table array that we just looked up, + // provided it was not declared inline + if (it != end && *it == ']') + { + if (!b->is_table_array()) + { + throw_parse_exception("Key " + full_ta_name + + " is not a table array"); + } + + auto v = b->as_table_array(); + + if (v->is_inline()) + { + throw_parse_exception("Static array " + full_ta_name + + " cannot be appended to"); + } + + v->get().push_back(make_table()); + curr_table = v->get().back().get(); + } + // otherwise, just keep traversing down the key name + else + { + if (b->is_table()) + curr_table = static_cast(b.get()); + else if (b->is_table_array()) + curr_table = std::static_pointer_cast(b) + ->get() + .back() + .get(); + else + throw_parse_exception("Key " + full_ta_name + + " already exists as a value"); + } + } + else + { + // if this is the end of the table array name, add a new + // table array and a new table inside that array for us to + // add keys to next + if (it != end && *it == ']') + { + curr_table->insert(part, make_table_array()); + auto arr = std::static_pointer_cast( + curr_table->get(part)); + arr->get().push_back(make_table()); + curr_table = arr->get().back().get(); + } + // otherwise, create the implicitly defined table and move + // down to it + else + { + curr_table->insert(part, make_table()); + curr_table + = static_cast(curr_table->get(part).get()); + } + } + }; + + key_part_handler(parse_key(it, end, key_end, key_part_handler)); + + // consume the last "]]" + auto eat = make_consumer(it, end, [this]() { + throw_parse_exception("Unterminated table array name"); + }); + eat(']'); + eat(']'); + + consume_whitespace(it, end); + eol_or_comment(it, end); + } + + void parse_key_value(std::string::iterator& it, std::string::iterator& end, + table* curr_table) + { + auto key_end = [](char c) { return c == '='; }; + + auto key_part_handler = [&](const std::string& part) { + // two cases: this key part exists already, in which case it must + // be a table, or it doesn't exist in which case we must create + // an implicitly defined table + if (curr_table->contains(part)) + { + auto val = curr_table->get(part); + if (val->is_table()) + { + curr_table = static_cast(val.get()); + } + else + { + throw_parse_exception("Key " + part + + " already exists as a value"); + } + } + else + { + auto newtable = make_table(); + curr_table->insert(part, newtable); + curr_table = newtable.get(); + } + }; + + auto key = parse_key(it, end, key_end, key_part_handler); + + if (curr_table->contains(key)) + throw_parse_exception("Key " + key + " already present"); + if (it == end || *it != '=') + throw_parse_exception("Value must follow after a '='"); + ++it; + consume_whitespace(it, end); + curr_table->insert(key, parse_value(it, end)); + consume_whitespace(it, end); + } + + template + std::string + parse_key(std::string::iterator& it, const std::string::iterator& end, + KeyEndFinder&& key_end, KeyPartHandler&& key_part_handler) + { + // parse the key as a series of one or more simple-keys joined with '.' + while (it != end && !key_end(*it)) + { + auto part = parse_simple_key(it, end); + consume_whitespace(it, end); + + if (it == end || key_end(*it)) + { + return part; + } + + if (*it != '.') + { + std::string errmsg{"Unexpected character in key: "}; + errmsg += '"'; + errmsg += *it; + errmsg += '"'; + throw_parse_exception(errmsg); + } + + key_part_handler(part); + + // consume the dot + ++it; + } + + throw_parse_exception("Unexpected end of key"); + } + + std::string parse_simple_key(std::string::iterator& it, + const std::string::iterator& end) + { + consume_whitespace(it, end); + + if (it == end) + throw_parse_exception("Unexpected end of key (blank key?)"); + + if (*it == '"' || *it == '\'') + { + return string_literal(it, end, *it); + } + else + { + auto bke = std::find_if(it, end, [](char c) { + return c == '.' || c == '=' || c == ']'; + }); + return parse_bare_key(it, bke); + } + } + + std::string parse_bare_key(std::string::iterator& it, + const std::string::iterator& end) + { + if (it == end) + { + throw_parse_exception("Bare key missing name"); + } + + auto key_end = end; + --key_end; + consume_backwards_whitespace(key_end, it); + ++key_end; + std::string key{it, key_end}; + + if (std::find(it, key_end, '#') != key_end) + { + throw_parse_exception("Bare key " + key + " cannot contain #"); + } + + if (std::find_if(it, key_end, + [](char c) { return c == ' ' || c == '\t'; }) + != key_end) + { + throw_parse_exception("Bare key " + key + + " cannot contain whitespace"); + } + + if (std::find_if(it, key_end, + [](char c) { return c == '[' || c == ']'; }) + != key_end) + { + throw_parse_exception("Bare key " + key + + " cannot contain '[' or ']'"); + } + + it = end; + return key; + } + + enum class parse_type + { + STRING = 1, + LOCAL_TIME, + LOCAL_DATE, + LOCAL_DATETIME, + OFFSET_DATETIME, + INT, + FLOAT, + BOOL, + ARRAY, + INLINE_TABLE + }; + + std::shared_ptr parse_value(std::string::iterator& it, + std::string::iterator& end) + { + parse_type type = determine_value_type(it, end); + switch (type) + { + case parse_type::STRING: + return parse_string(it, end); + case parse_type::LOCAL_TIME: + return parse_time(it, end); + case parse_type::LOCAL_DATE: + case parse_type::LOCAL_DATETIME: + case parse_type::OFFSET_DATETIME: + return parse_date(it, end); + case parse_type::INT: + case parse_type::FLOAT: + return parse_number(it, end); + case parse_type::BOOL: + return parse_bool(it, end); + case parse_type::ARRAY: + return parse_array(it, end); + case parse_type::INLINE_TABLE: + return parse_inline_table(it, end); + default: + throw_parse_exception("Failed to parse value"); + } + } + + parse_type determine_value_type(const std::string::iterator& it, + const std::string::iterator& end) + { + if (it == end) + { + throw_parse_exception("Failed to parse value type"); + } + if (*it == '"' || *it == '\'') + { + return parse_type::STRING; + } + else if (is_time(it, end)) + { + return parse_type::LOCAL_TIME; + } + else if (auto dtype = date_type(it, end)) + { + return *dtype; + } + else if (is_number(*it) || *it == '-' || *it == '+' + || (*it == 'i' && it + 1 != end && it[1] == 'n' + && it + 2 != end && it[2] == 'f') + || (*it == 'n' && it + 1 != end && it[1] == 'a' + && it + 2 != end && it[2] == 'n')) + { + return determine_number_type(it, end); + } + else if (*it == 't' || *it == 'f') + { + return parse_type::BOOL; + } + else if (*it == '[') + { + return parse_type::ARRAY; + } + else if (*it == '{') + { + return parse_type::INLINE_TABLE; + } + throw_parse_exception("Failed to parse value type"); + } + + parse_type determine_number_type(const std::string::iterator& it, + const std::string::iterator& end) + { + // determine if we are an integer or a float + auto check_it = it; + if (*check_it == '-' || *check_it == '+') + ++check_it; + + if (check_it == end) + throw_parse_exception("Malformed number"); + + if (*check_it == 'i' || *check_it == 'n') + return parse_type::FLOAT; + + while (check_it != end && is_number(*check_it)) + ++check_it; + if (check_it != end && *check_it == '.') + { + ++check_it; + while (check_it != end && is_number(*check_it)) + ++check_it; + return parse_type::FLOAT; + } + else + { + return parse_type::INT; + } + } + + std::shared_ptr> parse_string(std::string::iterator& it, + std::string::iterator& end) + { + auto delim = *it; + assert(delim == '"' || delim == '\''); + + // end is non-const here because we have to be able to potentially + // parse multiple lines in a string, not just one + auto check_it = it; + ++check_it; + if (check_it != end && *check_it == delim) + { + ++check_it; + if (check_it != end && *check_it == delim) + { + it = ++check_it; + return parse_multiline_string(it, end, delim); + } + } + return make_value(string_literal(it, end, delim)); + } + + std::shared_ptr> + parse_multiline_string(std::string::iterator& it, + std::string::iterator& end, char delim) + { + std::stringstream ss; + + auto is_ws = [](char c) { return c == ' ' || c == '\t'; }; + + bool consuming = false; + std::shared_ptr> ret; + + auto handle_line = [&](std::string::iterator& local_it, + std::string::iterator& local_end) { + if (consuming) + { + local_it = std::find_if_not(local_it, local_end, is_ws); + + // whole line is whitespace + if (local_it == local_end) + return; + } + + consuming = false; + + while (local_it != local_end) + { + // handle escaped characters + if (delim == '"' && *local_it == '\\') + { + auto check = local_it; + // check if this is an actual escape sequence or a + // whitespace escaping backslash + ++check; + consume_whitespace(check, local_end); + if (check == local_end) + { + consuming = true; + break; + } + + ss << parse_escape_code(local_it, local_end); + continue; + } + + // if we can end the string + if (std::distance(local_it, local_end) >= 3) + { + auto check = local_it; + // check for """ + if (*check++ == delim && *check++ == delim + && *check++ == delim) + { + local_it = check; + ret = make_value(ss.str()); + break; + } + } + + ss << *local_it++; + } + }; + + // handle the remainder of the current line + handle_line(it, end); + if (ret) + return ret; + + // start eating lines + while (detail::getline(input_, line_)) + { + ++line_number_; + + it = line_.begin(); + end = line_.end(); + + handle_line(it, end); + + if (ret) + return ret; + + if (!consuming) + ss << std::endl; + } + + throw_parse_exception("Unterminated multi-line basic string"); + } + + std::string string_literal(std::string::iterator& it, + const std::string::iterator& end, char delim) + { + ++it; + std::string val; + while (it != end) + { + // handle escaped characters + if (delim == '"' && *it == '\\') + { + val += parse_escape_code(it, end); + } + else if (*it == delim) + { + ++it; + consume_whitespace(it, end); + return val; + } + else + { + val += *it++; + } + } + throw_parse_exception("Unterminated string literal"); + } + + std::string parse_escape_code(std::string::iterator& it, + const std::string::iterator& end) + { + ++it; + if (it == end) + throw_parse_exception("Invalid escape sequence"); + char value; + if (*it == 'b') + { + value = '\b'; + } + else if (*it == 't') + { + value = '\t'; + } + else if (*it == 'n') + { + value = '\n'; + } + else if (*it == 'f') + { + value = '\f'; + } + else if (*it == 'r') + { + value = '\r'; + } + else if (*it == '"') + { + value = '"'; + } + else if (*it == '\\') + { + value = '\\'; + } + else if (*it == 'u' || *it == 'U') + { + return parse_unicode(it, end); + } + else + { + throw_parse_exception("Invalid escape sequence"); + } + ++it; + return std::string(1, value); + } + + std::string parse_unicode(std::string::iterator& it, + const std::string::iterator& end) + { + bool large = *it++ == 'U'; + auto codepoint = parse_hex(it, end, large ? 0x10000000 : 0x1000); + + if ((codepoint > 0xd7ff && codepoint < 0xe000) || codepoint > 0x10ffff) + { + throw_parse_exception( + "Unicode escape sequence is not a Unicode scalar value"); + } + + std::string result; + // See Table 3-6 of the Unicode standard + if (codepoint <= 0x7f) + { + // 1-byte codepoints: 00000000 0xxxxxxx + // repr: 0xxxxxxx + result += static_cast(codepoint & 0x7f); + } + else if (codepoint <= 0x7ff) + { + // 2-byte codepoints: 00000yyy yyxxxxxx + // repr: 110yyyyy 10xxxxxx + // + // 0x1f = 00011111 + // 0xc0 = 11000000 + // + result += static_cast(0xc0 | ((codepoint >> 6) & 0x1f)); + // + // 0x80 = 10000000 + // 0x3f = 00111111 + // + result += static_cast(0x80 | (codepoint & 0x3f)); + } + else if (codepoint <= 0xffff) + { + // 3-byte codepoints: zzzzyyyy yyxxxxxx + // repr: 1110zzzz 10yyyyyy 10xxxxxx + // + // 0xe0 = 11100000 + // 0x0f = 00001111 + // + result += static_cast(0xe0 | ((codepoint >> 12) & 0x0f)); + result += static_cast(0x80 | ((codepoint >> 6) & 0x1f)); + result += static_cast(0x80 | (codepoint & 0x3f)); + } + else + { + // 4-byte codepoints: 000uuuuu zzzzyyyy yyxxxxxx + // repr: 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx + // + // 0xf0 = 11110000 + // 0x07 = 00000111 + // + result += static_cast(0xf0 | ((codepoint >> 18) & 0x07)); + result += static_cast(0x80 | ((codepoint >> 12) & 0x3f)); + result += static_cast(0x80 | ((codepoint >> 6) & 0x3f)); + result += static_cast(0x80 | (codepoint & 0x3f)); + } + return result; + } + + uint32_t parse_hex(std::string::iterator& it, + const std::string::iterator& end, uint32_t place) + { + uint32_t value = 0; + while (place > 0) + { + if (it == end) + throw_parse_exception("Unexpected end of unicode sequence"); + + if (!is_hex(*it)) + throw_parse_exception("Invalid unicode escape sequence"); + + value += place * hex_to_digit(*it++); + place /= 16; + } + return value; + } + + uint32_t hex_to_digit(char c) + { + if (is_number(c)) + return static_cast(c - '0'); + return 10 + + static_cast(c + - ((c >= 'a' && c <= 'f') ? 'a' : 'A')); + } + + std::shared_ptr parse_number(std::string::iterator& it, + const std::string::iterator& end) + { + auto check_it = it; + auto check_end = find_end_of_number(it, end); + + auto eat_sign = [&]() { + if (check_it != end && (*check_it == '-' || *check_it == '+')) + ++check_it; + }; + + auto check_no_leading_zero = [&]() { + if (check_it != end && *check_it == '0' && check_it + 1 != check_end + && check_it[1] != '.') + { + throw_parse_exception("Numbers may not have leading zeros"); + } + }; + + auto eat_digits = [&](bool (*check_char)(char)) { + auto beg = check_it; + while (check_it != end && check_char(*check_it)) + { + ++check_it; + if (check_it != end && *check_it == '_') + { + ++check_it; + if (check_it == end || !check_char(*check_it)) + throw_parse_exception("Malformed number"); + } + } + + if (check_it == beg) + throw_parse_exception("Malformed number"); + }; + + auto eat_hex = [&]() { eat_digits(&is_hex); }; + + auto eat_numbers = [&]() { eat_digits(&is_number); }; + + if (check_it != end && *check_it == '0' && check_it + 1 != check_end + && (check_it[1] == 'x' || check_it[1] == 'o' || check_it[1] == 'b')) + { + ++check_it; + char base = *check_it; + ++check_it; + if (base == 'x') + { + eat_hex(); + return parse_int(it, check_it, 16); + } + else if (base == 'o') + { + auto start = check_it; + eat_numbers(); + auto val = parse_int(start, check_it, 8, "0"); + it = start; + return val; + } + else // if (base == 'b') + { + auto start = check_it; + eat_numbers(); + auto val = parse_int(start, check_it, 2); + it = start; + return val; + } + } + + eat_sign(); + check_no_leading_zero(); + + if (check_it != end && check_it + 1 != end && check_it + 2 != end) + { + if (check_it[0] == 'i' && check_it[1] == 'n' && check_it[2] == 'f') + { + auto val = std::numeric_limits::infinity(); + if (*it == '-') + val = -val; + it = check_it + 3; + return make_value(val); + } + else if (check_it[0] == 'n' && check_it[1] == 'a' + && check_it[2] == 'n') + { + auto val = std::numeric_limits::quiet_NaN(); + if (*it == '-') + val = -val; + it = check_it + 3; + return make_value(val); + } + } + + eat_numbers(); + + if (check_it != end + && (*check_it == '.' || *check_it == 'e' || *check_it == 'E')) + { + bool is_exp = *check_it == 'e' || *check_it == 'E'; + + ++check_it; + if (check_it == end) + throw_parse_exception("Floats must have trailing digits"); + + auto eat_exp = [&]() { + eat_sign(); + check_no_leading_zero(); + eat_numbers(); + }; + + if (is_exp) + eat_exp(); + else + eat_numbers(); + + if (!is_exp && check_it != end + && (*check_it == 'e' || *check_it == 'E')) + { + ++check_it; + eat_exp(); + } + + return parse_float(it, check_it); + } + else + { + return parse_int(it, check_it); + } + } + + std::shared_ptr> parse_int(std::string::iterator& it, + const std::string::iterator& end, + int base = 10, + const char* prefix = "") + { + std::string v{it, end}; + v = prefix + v; + v.erase(std::remove(v.begin(), v.end(), '_'), v.end()); + it = end; + try + { + return make_value(std::stoll(v, nullptr, base)); + } + catch (const std::invalid_argument& ex) + { + throw_parse_exception("Malformed number (invalid argument: " + + std::string{ex.what()} + ")"); + } + catch (const std::out_of_range& ex) + { + throw_parse_exception("Malformed number (out of range: " + + std::string{ex.what()} + ")"); + } + } + + std::shared_ptr> parse_float(std::string::iterator& it, + const std::string::iterator& end) + { + std::string v{it, end}; + v.erase(std::remove(v.begin(), v.end(), '_'), v.end()); + it = end; + char decimal_point = std::localeconv()->decimal_point[0]; + std::replace(v.begin(), v.end(), '.', decimal_point); + try + { + return make_value(std::stod(v)); + } + catch (const std::invalid_argument& ex) + { + throw_parse_exception("Malformed number (invalid argument: " + + std::string{ex.what()} + ")"); + } + catch (const std::out_of_range& ex) + { + throw_parse_exception("Malformed number (out of range: " + + std::string{ex.what()} + ")"); + } + } + + std::shared_ptr> parse_bool(std::string::iterator& it, + const std::string::iterator& end) + { + auto eat = make_consumer(it, end, [this]() { + throw_parse_exception("Attempted to parse invalid boolean value"); + }); + + if (*it == 't') + { + eat("true"); + return make_value(true); + } + else if (*it == 'f') + { + eat("false"); + return make_value(false); + } + + eat.error(); + return nullptr; + } + + std::string::iterator find_end_of_number(std::string::iterator it, + std::string::iterator end) + { + auto ret = std::find_if(it, end, [](char c) { + return !is_number(c) && c != '_' && c != '.' && c != 'e' && c != 'E' + && c != '-' && c != '+' && c != 'x' && c != 'o' && c != 'b'; + }); + if (ret != end && ret + 1 != end && ret + 2 != end) + { + if ((ret[0] == 'i' && ret[1] == 'n' && ret[2] == 'f') + || (ret[0] == 'n' && ret[1] == 'a' && ret[2] == 'n')) + { + ret = ret + 3; + } + } + return ret; + } + + std::string::iterator find_end_of_date(std::string::iterator it, + std::string::iterator end) + { + auto end_of_date = std::find_if(it, end, [](char c) { + return !is_number(c) && c != '-'; + }); + if (end_of_date != end && *end_of_date == ' ' && end_of_date + 1 != end + && is_number(end_of_date[1])) + end_of_date++; + return std::find_if(end_of_date, end, [](char c) { + return !is_number(c) && c != 'T' && c != 'Z' && c != ':' + && c != '-' && c != '+' && c != '.'; + }); + } + + std::string::iterator find_end_of_time(std::string::iterator it, + std::string::iterator end) + { + return std::find_if(it, end, [](char c) { + return !is_number(c) && c != ':' && c != '.'; + }); + } + + local_time read_time(std::string::iterator& it, + const std::string::iterator& end) + { + auto time_end = find_end_of_time(it, end); + + auto eat = make_consumer( + it, time_end, [&]() { throw_parse_exception("Malformed time"); }); + + local_time ltime; + + ltime.hour = eat.eat_digits(2); + eat(':'); + ltime.minute = eat.eat_digits(2); + eat(':'); + ltime.second = eat.eat_digits(2); + + int power = 100000; + if (it != time_end && *it == '.') + { + ++it; + while (it != time_end && is_number(*it)) + { + ltime.microsecond += power * (*it++ - '0'); + power /= 10; + } + } + + if (it != time_end) + throw_parse_exception("Malformed time"); + + return ltime; + } + + std::shared_ptr> + parse_time(std::string::iterator& it, const std::string::iterator& end) + { + return make_value(read_time(it, end)); + } + + std::shared_ptr parse_date(std::string::iterator& it, + const std::string::iterator& end) + { + auto date_end = find_end_of_date(it, end); + + auto eat = make_consumer( + it, date_end, [&]() { throw_parse_exception("Malformed date"); }); + + local_date ldate; + ldate.year = eat.eat_digits(4); + eat('-'); + ldate.month = eat.eat_digits(2); + eat('-'); + ldate.day = eat.eat_digits(2); + + if (it == date_end) + return make_value(ldate); + + eat.eat_or('T', ' '); + + local_datetime ldt; + static_cast(ldt) = ldate; + static_cast(ldt) = read_time(it, date_end); + + if (it == date_end) + return make_value(ldt); + + offset_datetime dt; + static_cast(dt) = ldt; + + int hoff = 0; + int moff = 0; + if (*it == '+' || *it == '-') + { + auto plus = *it == '+'; + ++it; + + hoff = eat.eat_digits(2); + dt.hour_offset = (plus) ? hoff : -hoff; + eat(':'); + moff = eat.eat_digits(2); + dt.minute_offset = (plus) ? moff : -moff; + } + else if (*it == 'Z') + { + ++it; + } + + if (it != date_end) + throw_parse_exception("Malformed date"); + + return make_value(dt); + } + + std::shared_ptr parse_array(std::string::iterator& it, + std::string::iterator& end) + { + // this gets ugly because of the "homogeneity" restriction: + // arrays can either be of only one type, or contain arrays + // (each of those arrays could be of different types, though) + // + // because of the latter portion, we don't really have a choice + // but to represent them as arrays of base values... + ++it; + + // ugh---have to read the first value to determine array type... + skip_whitespace_and_comments(it, end); + + // edge case---empty array + if (*it == ']') + { + ++it; + return make_array(); + } + + auto val_end = std::find_if( + it, end, [](char c) { return c == ',' || c == ']' || c == '#'; }); + parse_type type = determine_value_type(it, val_end); + switch (type) + { + case parse_type::STRING: + return parse_value_array(it, end); + case parse_type::LOCAL_TIME: + return parse_value_array(it, end); + case parse_type::LOCAL_DATE: + return parse_value_array(it, end); + case parse_type::LOCAL_DATETIME: + return parse_value_array(it, end); + case parse_type::OFFSET_DATETIME: + return parse_value_array(it, end); + case parse_type::INT: + return parse_value_array(it, end); + case parse_type::FLOAT: + return parse_value_array(it, end); + case parse_type::BOOL: + return parse_value_array(it, end); + case parse_type::ARRAY: + return parse_object_array(&parser::parse_array, '[', it, + end); + case parse_type::INLINE_TABLE: + return parse_object_array( + &parser::parse_inline_table, '{', it, end); + default: + throw_parse_exception("Unable to parse array"); + } + } + + template + std::shared_ptr parse_value_array(std::string::iterator& it, + std::string::iterator& end) + { + auto arr = make_array(); + while (it != end && *it != ']') + { + auto val = parse_value(it, end); + if (auto v = val->as()) + arr->get().push_back(val); + else + throw_parse_exception("Arrays must be homogeneous"); + skip_whitespace_and_comments(it, end); + if (*it != ',') + break; + ++it; + skip_whitespace_and_comments(it, end); + } + if (it != end) + ++it; + return arr; + } + + template + std::shared_ptr parse_object_array(Function&& fun, char delim, + std::string::iterator& it, + std::string::iterator& end) + { + auto arr = detail::make_element(); + + while (it != end && *it != ']') + { + if (*it != delim) + throw_parse_exception("Unexpected character in array"); + + arr->get().push_back(((*this).*fun)(it, end)); + skip_whitespace_and_comments(it, end); + + if (it == end || *it != ',') + break; + + ++it; + skip_whitespace_and_comments(it, end); + } + + if (it == end || *it != ']') + throw_parse_exception("Unterminated array"); + + ++it; + return arr; + } + + std::shared_ptr
parse_inline_table(std::string::iterator& it, + std::string::iterator& end) + { + auto tbl = make_table(); + do + { + ++it; + if (it == end) + throw_parse_exception("Unterminated inline table"); + + consume_whitespace(it, end); + if (it != end && *it != '}') + { + parse_key_value(it, end, tbl.get()); + consume_whitespace(it, end); + } + } while (*it == ','); + + if (it == end || *it != '}') + throw_parse_exception("Unterminated inline table"); + + ++it; + consume_whitespace(it, end); + + return tbl; + } + + void skip_whitespace_and_comments(std::string::iterator& start, + std::string::iterator& end) + { + consume_whitespace(start, end); + while (start == end || *start == '#') + { + if (!detail::getline(input_, line_)) + throw_parse_exception("Unclosed array"); + line_number_++; + start = line_.begin(); + end = line_.end(); + consume_whitespace(start, end); + } + } + + void consume_whitespace(std::string::iterator& it, + const std::string::iterator& end) + { + while (it != end && (*it == ' ' || *it == '\t')) + ++it; + } + + void consume_backwards_whitespace(std::string::iterator& back, + const std::string::iterator& front) + { + while (back != front && (*back == ' ' || *back == '\t')) + --back; + } + + void eol_or_comment(const std::string::iterator& it, + const std::string::iterator& end) + { + if (it != end && *it != '#') + throw_parse_exception("Unidentified trailing character '" + + std::string{*it} + + "'---did you forget a '#'?"); + } + + bool is_time(const std::string::iterator& it, + const std::string::iterator& end) + { + auto time_end = find_end_of_time(it, end); + auto len = std::distance(it, time_end); + + if (len < 8) + return false; + + if (it[2] != ':' || it[5] != ':') + return false; + + if (len > 8) + return it[8] == '.' && len > 9; + + return true; + } + + option date_type(const std::string::iterator& it, + const std::string::iterator& end) + { + auto date_end = find_end_of_date(it, end); + auto len = std::distance(it, date_end); + + if (len < 10) + return {}; + + if (it[4] != '-' || it[7] != '-') + return {}; + + if (len >= 19 && (it[10] == 'T' || it[10] == ' ') + && is_time(it + 11, date_end)) + { + // datetime type + auto time_end = find_end_of_time(it + 11, date_end); + if (time_end == date_end) + return {parse_type::LOCAL_DATETIME}; + else + return {parse_type::OFFSET_DATETIME}; + } + else if (len == 10) + { + // just a regular date + return {parse_type::LOCAL_DATE}; + } + + return {}; + } + + std::istream& input_; + std::string line_; + std::size_t line_number_ = 0; +}; + +/** + * Utility function to parse a file as a TOML file. Returns the root table. + * Throws a parse_exception if the file cannot be opened. + */ +inline std::shared_ptr
parse_file(const std::string& filename) +{ +#if defined(BOOST_NOWIDE_FSTREAM_INCLUDED_HPP) + boost::nowide::ifstream file{filename.c_str()}; +#elif defined(NOWIDE_FSTREAM_INCLUDED_HPP) + nowide::ifstream file{filename.c_str()}; +#else + std::ifstream file{filename}; +#endif + if (!file.is_open()) + throw parse_exception{filename + " could not be opened for parsing"}; + parser p{file}; + return p.parse(); +} + +template +struct value_accept; + +template <> +struct value_accept<> +{ + template + static void accept(const base&, Visitor&&, Args&&...) + { + // nothing + } +}; + +template +struct value_accept +{ + template + static void accept(const base& b, Visitor&& visitor, Args&&... args) + { + if (auto v = b.as()) + { + visitor.visit(*v, std::forward(args)...); + } + else + { + value_accept::accept(b, std::forward(visitor), + std::forward(args)...); + } + } +}; + +/** + * base implementation of accept() that calls visitor.visit() on the concrete + * class. + */ +template +void base::accept(Visitor&& visitor, Args&&... args) const +{ + if (is_value()) + { + using value_acceptor + = value_accept; + value_acceptor::accept(*this, std::forward(visitor), + std::forward(args)...); + } + else if (is_table()) + { + visitor.visit(static_cast(*this), + std::forward(args)...); + } + else if (is_array()) + { + visitor.visit(static_cast(*this), + std::forward(args)...); + } + else if (is_table_array()) + { + visitor.visit(static_cast(*this), + std::forward(args)...); + } +} + +/** + * Writer that can be passed to accept() functions of cpptoml objects and + * will output valid TOML to a stream. + */ +class toml_writer +{ + public: + /** + * Construct a toml_writer that will write to the given stream + */ + toml_writer(std::ostream& s, const std::string& indent_space = "\t") + : stream_(s), indent_(indent_space), has_naked_endline_(false) + { + // nothing + } + + public: + /** + * Output a base value of the TOML tree. + */ + template + void visit(const value& v, bool = false) + { + write(v); + } + + /** + * Output a table element of the TOML tree + */ + void visit(const table& t, bool in_array = false) + { + write_table_header(in_array); + std::vector values; + std::vector tables; + + for (const auto& i : t) + { + if (i.second->is_table() || i.second->is_table_array()) + { + tables.push_back(i.first); + } + else + { + values.push_back(i.first); + } + } + + for (unsigned int i = 0; i < values.size(); ++i) + { + path_.push_back(values[i]); + + if (i > 0) + endline(); + + write_table_item_header(*t.get(values[i])); + t.get(values[i])->accept(*this, false); + path_.pop_back(); + } + + for (unsigned int i = 0; i < tables.size(); ++i) + { + path_.push_back(tables[i]); + + if (values.size() > 0 || i > 0) + endline(); + + write_table_item_header(*t.get(tables[i])); + t.get(tables[i])->accept(*this, false); + path_.pop_back(); + } + + endline(); + } + + /** + * Output an array element of the TOML tree + */ + void visit(const array& a, bool = false) + { + write("["); + + for (unsigned int i = 0; i < a.get().size(); ++i) + { + if (i > 0) + write(", "); + + if (a.get()[i]->is_array()) + { + a.get()[i]->as_array()->accept(*this, true); + } + else + { + a.get()[i]->accept(*this, true); + } + } + + write("]"); + } + + /** + * Output a table_array element of the TOML tree + */ + void visit(const table_array& t, bool = false) + { + for (unsigned int j = 0; j < t.get().size(); ++j) + { + if (j > 0) + endline(); + + t.get()[j]->accept(*this, true); + } + + endline(); + } + + /** + * Escape a string for output. + */ + static std::string escape_string(const std::string& str) + { + std::string res; + for (auto it = str.begin(); it != str.end(); ++it) + { + if (*it == '\b') + { + res += "\\b"; + } + else if (*it == '\t') + { + res += "\\t"; + } + else if (*it == '\n') + { + res += "\\n"; + } + else if (*it == '\f') + { + res += "\\f"; + } + else if (*it == '\r') + { + res += "\\r"; + } + else if (*it == '"') + { + res += "\\\""; + } + else if (*it == '\\') + { + res += "\\\\"; + } + else if (static_cast(*it) <= UINT32_C(0x001f)) + { + res += "\\u"; + std::stringstream ss; + ss << std::hex << static_cast(*it); + res += ss.str(); + } + else + { + res += *it; + } + } + return res; + } + + protected: + /** + * Write out a string. + */ + void write(const value& v) + { + write("\""); + write(escape_string(v.get())); + write("\""); + } + + /** + * Write out a double. + */ + void write(const value& v) + { + std::stringstream ss; + ss << std::showpoint + << std::setprecision(std::numeric_limits::max_digits10) + << v.get(); + + auto double_str = ss.str(); + auto pos = double_str.find("e0"); + if (pos != std::string::npos) + double_str.replace(pos, 2, "e"); + pos = double_str.find("e-0"); + if (pos != std::string::npos) + double_str.replace(pos, 3, "e-"); + + stream_ << double_str; + has_naked_endline_ = false; + } + + /** + * Write out an integer, local_date, local_time, local_datetime, or + * offset_datetime. + */ + template + typename std::enable_if< + is_one_of::value>::type + write(const value& v) + { + write(v.get()); + } + + /** + * Write out a boolean. + */ + void write(const value& v) + { + write((v.get() ? "true" : "false")); + } + + /** + * Write out the header of a table. + */ + void write_table_header(bool in_array = false) + { + if (!path_.empty()) + { + indent(); + + write("["); + + if (in_array) + { + write("["); + } + + for (unsigned int i = 0; i < path_.size(); ++i) + { + if (i > 0) + { + write("."); + } + + if (path_[i].find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" + "fghijklmnopqrstuvwxyz0123456789" + "_-") + == std::string::npos) + { + write(path_[i]); + } + else + { + write("\""); + write(escape_string(path_[i])); + write("\""); + } + } + + if (in_array) + { + write("]"); + } + + write("]"); + endline(); + } + } + + /** + * Write out the identifier for an item in a table. + */ + void write_table_item_header(const base& b) + { + if (!b.is_table() && !b.is_table_array()) + { + indent(); + + if (path_.back().find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" + "fghijklmnopqrstuvwxyz0123456789" + "_-") + == std::string::npos) + { + write(path_.back()); + } + else + { + write("\""); + write(escape_string(path_.back())); + write("\""); + } + + write(" = "); + } + } + + private: + /** + * Indent the proper number of tabs given the size of + * the path. + */ + void indent() + { + for (std::size_t i = 1; i < path_.size(); ++i) + write(indent_); + } + + /** + * Write a value out to the stream. + */ + template + void write(const T& v) + { + stream_ << v; + has_naked_endline_ = false; + } + + /** + * Write an endline out to the stream + */ + void endline() + { + if (!has_naked_endline_) + { + stream_ << "\n"; + has_naked_endline_ = true; + } + } + + private: + std::ostream& stream_; + const std::string indent_; + std::vector path_; + bool has_naked_endline_; +}; + +inline std::ostream& operator<<(std::ostream& stream, const base& b) +{ + toml_writer writer{stream}; + b.accept(writer); + return stream; +} + +template +std::ostream& operator<<(std::ostream& stream, const value& v) +{ + toml_writer writer{stream}; + v.accept(writer); + return stream; +} + +inline std::ostream& operator<<(std::ostream& stream, const table& t) +{ + toml_writer writer{stream}; + t.accept(writer); + return stream; +} + +inline std::ostream& operator<<(std::ostream& stream, const table_array& t) +{ + toml_writer writer{stream}; + t.accept(writer); + return stream; +} + +inline std::ostream& operator<<(std::ostream& stream, const array& a) +{ + toml_writer writer{stream}; + a.accept(writer); + return stream; +} +} // namespace cpptoml +#endif // CPPTOML_H From 04439123c2d14d747237fe2ed1ab1cb83a7e152b Mon Sep 17 00:00:00 2001 From: Julian Hinxlage Date: Wed, 27 Nov 2019 13:08:32 +0100 Subject: [PATCH 34/49] ~ changed shared memory size --- main/main.cpp | 1 - src/SharedMemory.h | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/main/main.cpp b/main/main.cpp index 752fcef..9a8548f 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -18,7 +18,6 @@ int main(int argc, char** argv) { std::atexit(deleteSharedMemory); std::string eingabe; - while(eingabe != "exit") { std::cout << "cmd# "; std::cin >> eingabe; diff --git a/src/SharedMemory.h b/src/SharedMemory.h index 26a4d1d..fb7c68b 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -6,9 +6,8 @@ //ID-Speicherbereich //Größe des Speicherbereichs hier 8MB (8000) -#define shmMaxSize 8000 //Shared-Memory-Segment erstellen oder öffnen – shmget() -#define Max_Memory_Size 8000 +#define Max_Memory_Size 8000 * 1024 void deleteSharedMemory(int s); void deleteSharedMemory(void); void initSharedMemory(void); From 897f60407d0ea7eb11834b38c12f834050878eb4 Mon Sep 17 00:00:00 2001 From: "@Nurullah.Damla" Date: Thu, 28 Nov 2019 12:23:45 +0100 Subject: [PATCH 35/49] Bugfix --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aee2325..0ac7937 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,8 +11,8 @@ set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "bin" "doc" " #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") #set(CMAKE_CXX_COMPILER "clang++") -#set(CMAKE_C_COMPILER "/usr/bin/clang") -#set(CMAKE_CXX_COMPILER "/usr/bin/clang++") +set(CMAKE_C_COMPILER "clang") +set(CMAKE_CXX_COMPILER "clang++") project(Shared_Memory) set(CMAKE_CXX_STANDARD 14) From 3c8c08faefd29168b4b514e2ce9420c0a4fe99a4 Mon Sep 17 00:00:00 2001 From: cigerxwinchaker Date: Wed, 4 Dec 2019 13:26:49 +0100 Subject: [PATCH 36/49] =?UTF-8?q?=C3=A4nderungen=20wegen=20problemen=20bei?= =?UTF-8?q?=20mac=20default=20werte=20f=C3=BCr=20max=20shared=20memory=20> eingabe; diff --git a/res/config.toml b/res/config.toml index e91e65f..e90cdab 100644 --- a/res/config.toml +++ b/res/config.toml @@ -1,5 +1,5 @@ #defaultKey = 12345 -newKey = 0 +#newKey = 0 layoutVersion = 0 width = 0 height = 0 diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index 2619e92..374d980 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -8,10 +8,11 @@ + key_t changedKey() { std::ofstream keyFile; - keyFile.open("key.log", std::ofstream::out | std::ofstream::trunc); + keyFile.open("/tmp/vkvmKey.log", std::ofstream::out | std::ofstream::trunc); keyFile.clear(); int newKey; std::cout << "Type in a new Key for the Shared Memory Segment" << std::endl; @@ -21,9 +22,6 @@ key_t changedKey() keyFile << newKey; keyFile.close(); - auto config = cpptoml::parse_file(configFile); - newKey = config->get_as("newKey").value_or(0); //toml - return key_t(newKey); } @@ -52,7 +50,7 @@ void initSharedMemory(void) { if(answer.compare("y") == 0) { vkvm::impl.sharedMemoryKey = changedKey(); - std::cout << "new Try with Key:c " << vkvm::impl.sharedMemoryKey << std::endl; + std::cout << "new Try with Key: " << vkvm::impl.sharedMemoryKey << std::endl; initSharedMemory(); } else if(answer.compare("n") == 0) { std::cout << "This will end shared memory" < Date: Thu, 5 Dec 2019 07:47:41 +0000 Subject: [PATCH 37/49] ~ update ci to latest version --- .ci/clang-tidy.sh | 2 +- .clang-tidy | 2 +- .gitlab-ci.yml | 13 +++++++++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.ci/clang-tidy.sh b/.ci/clang-tidy.sh index 1c3d7b3..13b2ac7 100644 --- a/.ci/clang-tidy.sh +++ b/.ci/clang-tidy.sh @@ -5,7 +5,7 @@ bool=false # explicitly set IFS to contain only a line feed IFS=' ' -filelist="$(find . -not \( -path './*build*' -prune \) -type f ! -name "$(printf "*\n*")")" +filelist="$(find . -not \( -path './*build*' -prune \) -not \( -path './include' -prune \) -not \( -path './lib' -prune \) -type f ! -name "$(printf "*\n*")")" for file in $filelist; do if echo "$file" | grep -q -E ".*(\.cpp|\.h|\.hpp)$" ; then #Extra check missing dependencies due to clang-tidy doesn't toggle exit code. diff --git a/.clang-tidy b/.clang-tidy index b0965ca..6e8db98 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,2 +1,2 @@ -Checks: '*,-llvm-header-guard,-fuchsia*,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-hicpp-signed-bitwise,-bugprone-exception-escape,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-cstyle-cast,-hicpp-member-init,-google-readability-namespace-comments,-llvm-namespace-comment,-cppcoreguidelines-pro-type-vararg,-hicpp-vararg,-modernize-use-trailing-return-type' +Checks: '*,-llvm-header-guard,-fuchsia*,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-hicpp-signed-bitwise,-bugprone-exception-escape,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-cstyle-cast,-hicpp-member-init,-google-readability-namespace-comments,-llvm-namespace-comment,-cppcoreguidelines-pro-type-vararg,-hicpp-vararg,-modernize-use-trailing-return-type,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers' WarningsAsErrors: 'true' diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 522f05f..6492961 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,7 +14,16 @@ clang_tidy: tags: - docker-ci script: - - sh .ci/clang-tidy.sh; + - mkdir current + - ls -d .[!.]* | grep -v current | xargs mv -t current + - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.repo.digitech.hs-emden-leer.de/link/projekte/ws19/vkvm-new/library.git + - mkdir library/build + - cd library/build + - cmake .. + - make + - cd ../../current/.ci + - sh clang-tidy.sh + make_test: stage: test @@ -65,4 +74,4 @@ cmake_build: - mkdir build - cd build - cmake .. - - make \ No newline at end of file + - make From 7d11cc1730e75c63073f58b02939103ee0e10d33 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Thu, 5 Dec 2019 09:36:57 +0100 Subject: [PATCH 38/49] ~ fix unit tests not building --- CMakeLists.txt | 1 + test/test_demo.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ac7937..9dcc313 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ enable_testing() find_package(Catch2 REQUIRED) add_executable(UnitTests ${SOURCES} ${HEADERS} ${TESTS}) target_link_libraries(UnitTests Catch2::Catch2) +target_link_libraries(UnitTests ${LIB_PATH}/lib/liblibrary.a) include(CTest) include(Catch) diff --git a/test/test_demo.cpp b/test/test_demo.cpp index fde1445..ddbefb7 100644 --- a/test/test_demo.cpp +++ b/test/test_demo.cpp @@ -2,6 +2,6 @@ #include "../src/SharedMemory.h" TEST_CASE("Demo test") { - //REQUIRE(test() == 42); + REQUIRE(42 == 42); } From 2334b55dd4b2f0e97f3ac819ceafd29893e159ac Mon Sep 17 00:00:00 2001 From: "@Nurullah.Damla" Date: Thu, 12 Dec 2019 11:45:51 +0100 Subject: [PATCH 39/49] Beheben von einige "warnings" --- .ci/clang-tidy.sh | 0 main/main.cpp | 9 +++++---- test/test_demo.cpp | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) mode change 100644 => 100755 .ci/clang-tidy.sh diff --git a/.ci/clang-tidy.sh b/.ci/clang-tidy.sh old mode 100644 new mode 100755 diff --git a/main/main.cpp b/main/main.cpp index ef3064a..6b53efe 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,12 +1,13 @@ #include -#include -#include "../src/SharedMemory.h" -#include #include +#include +#include + +#include "../src/SharedMemory.h" #include "vkvm.hpp" -int main(int argc, char** argv) { +int main() { vkvm::initialize(0); initSharedMemory(); struct sigaction sigIntHandler; diff --git a/test/test_demo.cpp b/test/test_demo.cpp index ddbefb7..b86e002 100644 --- a/test/test_demo.cpp +++ b/test/test_demo.cpp @@ -1,5 +1,5 @@ -#include #include "../src/SharedMemory.h" +#include TEST_CASE("Demo test") { REQUIRE(42 == 42); From 46b3c0adf70540b155967718485b759e0016d302 Mon Sep 17 00:00:00 2001 From: cigerxwinchaker Date: Wed, 18 Dec 2019 10:57:04 +0100 Subject: [PATCH 40/49] =?UTF-8?q?=20Bitte=20geben=20Sie=20eine=20Commit-Be?= =?UTF-8?q?schreibung=20f=C3=BCr=20Ihre=20=C3=84nderungen=20ein.=20Zeilen,?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/main.cpp | 10 ++----- src/SharedMemory.cpp | 70 ++++++++++++++++---------------------------- src/SharedMemory.h | 10 +++---- test/test_demo.cpp | 1 - test/test_main.cpp | 2 -- 5 files changed, 32 insertions(+), 61 deletions(-) diff --git a/main/main.cpp b/main/main.cpp index 6b53efe..141faa2 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,20 +1,14 @@ +#include "../src/SharedMemory.h" +#include "vkvm.hpp" #include #include #include -#include -#include "../src/SharedMemory.h" -#include "vkvm.hpp" int main() { vkvm::initialize(0); initSharedMemory(); - struct sigaction sigIntHandler; - sigIntHandler.sa_handler = deleteSharedMemory; - sigemptyset(&sigIntHandler.sa_mask); - sigIntHandler.sa_flags = 0; - sigaction(SIGINT, &sigIntHandler, nullptr); vkvm::setDefaultValues(); std::atexit(deleteSharedMemory); std::string eingabe; diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index 374d980..5da689f 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -1,16 +1,11 @@ -#include #include "SharedMemory.h" -#include -#include #include +#include +#include +#include #include - - - - -key_t changedKey() -{ +key_t changedKey() { std::ofstream keyFile; keyFile.open("/tmp/vkvmKey.log", std::ofstream::out | std::ofstream::trunc); keyFile.clear(); @@ -18,44 +13,40 @@ key_t changedKey() std::cout << "Type in a new Key for the Shared Memory Segment" << std::endl; std::cout << "new Key#"; std::cin >> newKey; - std::cout <<"New Key is -> " << newKey << std::endl; + std::cout << "New Key is -> " << newKey << std::endl; keyFile << newKey; keyFile.close(); return key_t(newKey); } -std::string getAnswerFromUser() -{ - std::cout <<"answer# "; +std::string getAnswerFromUser() { + std::cout << "answer# "; std::string answer; std::cin >> answer; - if(answer.compare("y") == 0 || answer.compare("n") == 0|| answer.compare("override") == 0) { + if (answer == "y" || answer == "n" || answer == "override") { return answer; - } else { - std::cout << "wrong input: pls answer with (y) for yes, (n) for no, or (override)\n"; - getAnswerFromUser(); } + std::cout << "wrong input: pls answer with (y) for yes, (n) for no, or (override)\n"; + getAnswerFromUser(); return "-0"; } -void initSharedMemory(void) { - if(vkvm::impl.sharedMemoryKey != key_t(0)) { - if (shmget(vkvm::impl.sharedMemoryKey, Max_Memory_Size, IPC_CREAT | IPC_EXCL | 0666) < 0) - { +void initSharedMemory() { + if (vkvm::impl.sharedMemoryKey != key_t(0)) { + if (shmget(vkvm::impl.sharedMemoryKey, Max_Memory_Size, IPC_CREAT | IPC_EXCL | 0666) < 0) { std::cout << "Shared Memory with Key: " << vkvm::impl.sharedMemoryKey << " is already in use\n" - <<"You can change the Key( type -> y or n ), or you can override the shared memory Segment(type -> override)\n"; + << "You can change the Key( type -> y or n ), or you can override the shared memory Segment(type -> override)\n"; std::string answer = getAnswerFromUser(); - if(answer.compare("y") == 0) - { + if (answer == "y") { vkvm::impl.sharedMemoryKey = changedKey(); std::cout << "new Try with Key: " << vkvm::impl.sharedMemoryKey << std::endl; initSharedMemory(); - } else if(answer.compare("n") == 0) { - std::cout << "This will end shared memory" < " << vkvm::impl.sharedMemoryKey << " is not allowed here " << std::endl; + std::cerr << "key -> " << vkvm::impl.sharedMemoryKey << " is not allowed here " << std::endl; vkvm::impl.sharedMemoryKey = changedKey(); initSharedMemory(); } } -void deleteSharedMemory(int s) -{ - std::cerr << "programm ended with Code: " << s << std::endl; - if (shmctl(shmget(vkvm::impl.sharedMemoryKey, 0, 0), IPC_RMID, 0) < 0 ) - { - std::cerr << "Failed to remove shared Memory, maybe not existing: try cmd: ipcs, then delete with ipcrm -m $memID " << std::endl; - } else { - std::cout << "shared Memory deleted" << std::endl; - } -} - -void deleteSharedMemory(void) -{ - if (shmctl(shmget(vkvm::impl.sharedMemoryKey, 0, 0), IPC_RMID, 0) < 0 ) - { +void deleteSharedMemory() { + int id = shmctl(shmget(vkvm::impl.sharedMemoryKey, 0, 0), IPC_RMID, 0); + if (id < 0) { std::cerr << "Failed to remove shared Memory, maybe not existing: try cmd: ipcs " << std::endl; } else { + int x =0; std::cout << "shared Memory deleted" << std::endl; } } -void getConfig(){ +void getConfig() { auto config = cpptoml::parse_file(configFile); int layoutVersion = config->get_as("layoutVersion").value_or(0); @@ -123,7 +103,7 @@ void getConfig(){ vkvm::setForegroundColor(vkvm::Color(foregroundColor)); vkvm::setCharactersPerRow(charactersPerRow); vkvm::setCharactersPerColumn(charactersPerColumn); - vkvm::setFont(vkvm::FontType(font,"",0,0)); + vkvm::setFont(vkvm::FontType(font, "", 0, 0)); vkvm::setMousePosition(mousePositionX, mousePositionY); } diff --git a/src/SharedMemory.h b/src/SharedMemory.h index fb91dad..c15fef4 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -1,16 +1,16 @@ #ifndef SHARED_MEMORY_H #define SHARED_MEMORY_H + +#include "internal.hpp" //NOLINT #include -#include -#include "internal.hpp" //ID-Speicherbereich //Größe des Speicherbereichs hier 8MB (8000) //Shared-Memory-Segment erstellen oder öffnen – shmget() -#define Max_Memory_Size 8000 * 512 +constexpr int Max_Memory_Size (8000 * 512); void deleteSharedMemory(int s); -void deleteSharedMemory(void); -void initSharedMemory(void); +void deleteSharedMemory(); +void initSharedMemory(); void getConfig(); key_t changedKey(); std::string getAnswerFromUser(); diff --git a/test/test_demo.cpp b/test/test_demo.cpp index b86e002..25b878f 100644 --- a/test/test_demo.cpp +++ b/test/test_demo.cpp @@ -1,5 +1,4 @@ #include "../src/SharedMemory.h" -#include TEST_CASE("Demo test") { REQUIRE(42 == 42); diff --git a/test/test_main.cpp b/test/test_main.cpp index 6372e38..7096005 100644 --- a/test/test_main.cpp +++ b/test/test_main.cpp @@ -1,6 +1,4 @@ #define CATCH_CONFIG_MAIN -#include - //Dont touch this file. // add your own tests in this directory according to https://github.com/catchorg/Catch2/blob/master/docs/tutorial.md From a1e4d042e154f3ed64192fc3f2d5b2563528a654 Mon Sep 17 00:00:00 2001 From: cigerxwinchaker Date: Wed, 18 Dec 2019 11:51:28 +0100 Subject: [PATCH 41/49] warning toml weg --- src/SharedMemory.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/SharedMemory.h b/src/SharedMemory.h index c15fef4..4d45ccd 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -2,12 +2,14 @@ #define SHARED_MEMORY_H #include "internal.hpp" //NOLINT +#include #include //ID-Speicherbereich //Größe des Speicherbereichs hier 8MB (8000) //Shared-Memory-Segment erstellen oder öffnen – shmget() constexpr int Max_Memory_Size (8000 * 512); +const std::string configFile ("../res/config.toml"); void deleteSharedMemory(int s); void deleteSharedMemory(); void initSharedMemory(); @@ -15,5 +17,5 @@ void getConfig(); key_t changedKey(); std::string getAnswerFromUser(); //Config File -#define configFile "../res/config.toml" + #endif //SHARED_MEMORY_H From 09de960071a0961d990f4e1d0bf6ec726f729684 Mon Sep 17 00:00:00 2001 From: Julian Hinxlage Date: Wed, 18 Dec 2019 12:07:25 +0100 Subject: [PATCH 42/49] ~fixed font type error --- src/SharedMemory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index 5da689f..253c060 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -103,7 +103,7 @@ void getConfig() { vkvm::setForegroundColor(vkvm::Color(foregroundColor)); vkvm::setCharactersPerRow(charactersPerRow); vkvm::setCharactersPerColumn(charactersPerColumn); - vkvm::setFont(vkvm::FontType(font, "", 0, 0)); + vkvm::setFont(vkvm::FontType::ProFontIIX); vkvm::setMousePosition(mousePositionX, mousePositionY); } From eaf2c77dda656b28442e6faf93c4cc2b3d998a0a Mon Sep 17 00:00:00 2001 From: Julian Hinxlage Date: Tue, 7 Jan 2020 15:22:17 +0100 Subject: [PATCH 43/49] fixed default values --- res/config.toml | 18 +++++++++--------- src/SharedMemory.cpp | 4 +++- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/res/config.toml b/res/config.toml index e90cdab..82e77c9 100644 --- a/res/config.toml +++ b/res/config.toml @@ -1,15 +1,15 @@ #defaultKey = 12345 #newKey = 0 layoutVersion = 0 -width = 0 -height = 0 -mode = 0 -redrawInterval = 0 -timerInterruptInterval = 0 +width = 800 +height = 600 +mode = 4 +redrawInterval = 500 +timerInterruptInterval = 1000 backgroundColor = 0 -foregroundColor = 0 -charactersPerRow = 0 -charactersPerColumn = 0 -font = 0 +foregroundColor = 0xffffff +charactersPerRow = 60 +charactersPerColumn = 20 +font = 4 mousePositionX = 0 mousePositionY = 0 \ No newline at end of file diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index 253c060..dc303b8 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -78,6 +78,7 @@ void getConfig() { int height = config->get_as("height").value_or(0); int mode = config->get_as("mode").value_or(0); int timerInterruptInterval = config->get_as("timerInterruptInterval").value_or(0); + int redrawInterval = config->get_as("redrawInterval").value_or(0); int backgroundColor = config->get_as("backgroundColor").value_or(0); int foregroundColor = config->get_as("foregroundColor").value_or(0); int charactersPerRow = config->get_as("charactersPerRow").value_or(0); @@ -99,11 +100,12 @@ void getConfig() { vkvm::setHeight(height); vkvm::setMode((vkvm::GraphicMode) mode); vkvm::setTimerInterruptInterval(timerInterruptInterval); + vkvm::setRedrawInterval(redrawInterval); vkvm::setBackgroundColor(vkvm::Color(backgroundColor)); vkvm::setForegroundColor(vkvm::Color(foregroundColor)); vkvm::setCharactersPerRow(charactersPerRow); vkvm::setCharactersPerColumn(charactersPerColumn); - vkvm::setFont(vkvm::FontType::ProFontIIX); + vkvm::setFont(static_cast(font)); vkvm::setMousePosition(mousePositionX, mousePositionY); } From 63ce362b7a301e3589e0bf30ec8f2b41f6640251 Mon Sep 17 00:00:00 2001 From: cigerxwinchaker Date: Wed, 8 Jan 2020 11:58:15 +0100 Subject: [PATCH 44/49] override getConfig fix --- src/SharedMemory.cpp | 1 + test/test_demo.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index dc303b8..ef2aa0e 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -49,6 +49,7 @@ void initSharedMemory() { } else if (answer == "override") { deleteSharedMemory(); initSharedMemory(); + getConfig(); } } else { std::cout << "Shared Memory is (Re-) allocated with Key: " << vkvm::impl.sharedMemoryKey << std::endl; diff --git a/test/test_demo.cpp b/test/test_demo.cpp index 25b878f..972f344 100644 --- a/test/test_demo.cpp +++ b/test/test_demo.cpp @@ -1,6 +1,6 @@ #include "../src/SharedMemory.h" -TEST_CASE("Demo test") { +TEST_CASE("Demo test"){ REQUIRE(42 == 42); } From abcc6f1c9705b32b34f72dbe745b2f5d65ed3c82 Mon Sep 17 00:00:00 2001 From: Julian Hinxlage Date: Wed, 8 Jan 2020 12:12:32 +0100 Subject: [PATCH 45/49] fixed default values if shared memory is override --- src/SharedMemory.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index ef2aa0e..7ac359e 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -49,6 +49,7 @@ void initSharedMemory() { } else if (answer == "override") { deleteSharedMemory(); initSharedMemory(); + vkvm::reset(); getConfig(); } } else { From 7b1029a0801206bc642f885be838d4917cdb042b Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Wed, 8 Jan 2020 16:34:05 +0000 Subject: [PATCH 46/49] use clang instead of g++ --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6492961..8ef29d7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -31,7 +31,7 @@ make_test: - docker-ci script: - apt-get update - - apt-get install -y g++ make cmake clang-tidy + - apt-get install -y clang make cmake clang-tidy - mkdir current - ls | grep -v current | xargs mv -t current - git clone https://github.com/catchorg/Catch2.git @@ -57,7 +57,7 @@ cmake_build: - docker-ci script: - apt-get update - - apt-get install -y g++ make cmake clang-tidy + - apt-get install -y clang make cmake clang-tidy - mkdir current - ls | grep -v current | xargs mv -t current - git clone https://github.com/catchorg/Catch2.git From 951b15f2fc7229a1d9027ed47fceb5380d9b4be5 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Wed, 8 Jan 2020 19:12:50 +0100 Subject: [PATCH 47/49] ~ add catch2 include back --- test/test_demo.cpp | 1 + test/test_main.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/test/test_demo.cpp b/test/test_demo.cpp index 972f344..2e37823 100644 --- a/test/test_demo.cpp +++ b/test/test_demo.cpp @@ -1,3 +1,4 @@ +#include #include "../src/SharedMemory.h" TEST_CASE("Demo test"){ diff --git a/test/test_main.cpp b/test/test_main.cpp index 7096005..af3d9bb 100644 --- a/test/test_main.cpp +++ b/test/test_main.cpp @@ -1,3 +1,5 @@ +#include + #define CATCH_CONFIG_MAIN //Dont touch this file. From 82f1445612934cd18f0de9d5ddfb8e52a6c5ffed Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Wed, 8 Jan 2020 20:17:38 +0100 Subject: [PATCH 48/49] ~ changing include type --- src/SharedMemory.cpp | 4 ++-- src/SharedMemory.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SharedMemory.cpp b/src/SharedMemory.cpp index 7ac359e..2650caa 100644 --- a/src/SharedMemory.cpp +++ b/src/SharedMemory.cpp @@ -1,9 +1,9 @@ #include "SharedMemory.h" -#include +#include "../lib/toml/cpptoml.h" +#include "vkvm.hpp" #include #include #include -#include key_t changedKey() { std::ofstream keyFile; diff --git a/src/SharedMemory.h b/src/SharedMemory.h index 4d45ccd..9612b5a 100644 --- a/src/SharedMemory.h +++ b/src/SharedMemory.h @@ -1,7 +1,7 @@ #ifndef SHARED_MEMORY_H #define SHARED_MEMORY_H -#include "internal.hpp" //NOLINT +#include "internal.hpp" #include #include From e6cbdef218fb6511da6ab0802c5697101d132478 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Wed, 8 Jan 2020 21:00:37 +0100 Subject: [PATCH 49/49] ~ put define to top --- test/test_main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_main.cpp b/test/test_main.cpp index af3d9bb..6372e38 100644 --- a/test/test_main.cpp +++ b/test/test_main.cpp @@ -1,6 +1,6 @@ -#include - #define CATCH_CONFIG_MAIN +#include + //Dont touch this file. // add your own tests in this directory according to https://github.com/catchorg/Catch2/blob/master/docs/tutorial.md