stamenStatic Menu Generator | 
          
| git clone git://git.dimitrijedobrota.com/stamen.git | 
| Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | 
| commit | 45ebb3b798a9cf306ccfce512db8755e22cc472e | 
| parent | cd594065e953fe49c1ba109a1ceaf360f759a290 | 
| author | Dimitrije Dobrota < mail@dimitrijedobrota.com > | 
| date | Thu, 13 Jun 2024 19:43:46 +0200 | 
Improve C++ interface with namespace
* Distintion between C and C++ interfaces
* Extract C++ interface from stamen.h into stamen.hpp
* Fix generation to reflect changes
| M | CMakeLists.txt | | | + - | 
| M | demo/CMakeLists.txt | | | ++++ ------------ | 
| M | demo/dynamic.cpp | | | ++++ -- | 
| M | demo/main.cpp | | | ++ -- | 
| M | include/menu.h | | | + - | 
| M | include/stamen.h | | | ++++++++++++ ------------------- | 
| A | include/stamen.hpp | | | +++++++++++++++++++++ | 
| M | src/CMakeLists.txt | | | ++++++++ ----- | 
| A | src/c_bindings.cpp | | | +++++++++++++++++++ | 
| M | src/generate.cpp | | | +++++++++++++++++++++++++ -------------- | 
| M | src/menu.cpp | | | - | 
| M | src/stamen.cpp | | | ++++++++ ------- | 
12 files changed, 105 insertions(+), 64 deletions(-)
diff --git a/ CMakeLists.txt b/ CMakeLists.txt
          @@ -3,7 +3,7 @@ 
          set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
        
        
          project(
              Stamen
              VERSION 1.0.0
              VERSION 1.0.1
              DESCRIPTION "Static menu generator"
              LANGUAGES C CXX
          )
        
        diff --git a/ demo/CMakeLists.txt b/ demo/CMakeLists.txt
          @@ -9,12 +9,9 @@ 
          add_custom_command(
        
        
              COMMENT "Generating menu files"
          )
          add_executable(demo
              main.cpp
              ${GENERATE_OUT}/demo_menu.cpp
          )
          add_executable(demo main.cpp ${GENERATE_OUT}/demo_menu.cpp)
          target_link_libraries(demo stamen)
          set_target_properties(demo PROPERTIES LINKER_LANGUAGE CXX)
          target_include_directories(demo PRIVATE ${GENERATE_OUT} ${CMAKE_CURRENT_SOURCE_DIR})
          set_target_properties(demo PROPERTIES
        
        
          @@ -23,8 +20,6 @@ 
          set_target_properties(demo PROPERTIES
        
        
              RUNTIME_OUTPUT_DIRECTORY "${GENERATE_OUT}"
          )
          add_custom_command(
              OUTPUT ${GENERATE_OUT}/demo_menu.h ${GENERATE_OUT}/demo_menu.c
              COMMAND ${GENERATE_OUT}/stamen-generate ${GENERATE_OUT}/demo_menu.conf c
        
        
          @@ -32,12 +27,9 @@ 
          add_custom_command(
        
        
              COMMENT "Generating cmenu files"
          )
          add_executable(cdemo
              main.c
              ${GENERATE_OUT}/demo_menu.c
          )
          add_executable(cdemo main.c ${GENERATE_OUT}/demo_menu.c)
          target_link_libraries(cdemo stamen)
          set_target_properties(cdemo PROPERTIES LINKER_LANGUAGE C)
          target_include_directories(cdemo PRIVATE ${GENERATE_OUT} ${CMAKE_CURRENT_SOURCE_DIR})
          set_target_properties(cdemo PROPERTIES
        
        diff --git a/ demo/dynamic.cpp b/ demo/dynamic.cpp
@@ -1,7 +1,9 @@
#include "stamen.hpp"
          #include <iostream>
          #include <stamen.h>
          const stamen::display_f stamen_display = stamen::builtin_display;
          // need to link against stamen library
          // in order to use stamen::builtin_display
          const stamen::display_f &stamen::display = stamen::builtin_display;
          int finish(int) { exit(1); }
          diff --git a/ demo/main.cpp b/ demo/main.cpp
@@ -4,8 +4,8 @@
#include <iostream>
          // need to link against stamen library
          // in order to use stamen_builtin_display
          const stamen::display_f stamen_display = stamen::builtin_display;
          // in order to use stamen::builtin_display
          const stamen::display_f &stamen::display = stamen::builtin_display;
          int operation1(int) {
            std::cout << "operation 1" << std::endl;
        
        diff --git a/ include/menu.h b/ include/menu.h
@@ -1,7 +1,7 @@
#ifndef STAMEN_MENU_H
          #define STAMEN_MENU_H
          #include "stamen.h"
          #include "stamen.hpp"
          #include <cstring>
          #include <iostream>
        
        diff --git a/ include/stamen.h b/ include/stamen.h
@@ -2,9 +2,8 @@
#define STAMEN_STAMEN_H
          #ifdef __cplusplus
          #define EXTERNC extern "C"
          #else
          #define EXTERNC extern
          extern "C" {
          namespace stamen {
          #endif
          typedef int (*stamen_callback_f)(int);
        
        
          @@ -18,25 +17,19 @@ 
          struct stamen_item_t {
        
        
          typedef int (*stamen_display_f)(const char *, const stamen_item_t[], int);
          extern const stamen_display_f stamen_display;
          EXTERNC int stamen_dynamic(const char *code);
          EXTERNC void stamen_read(const char *filename);
          EXTERNC void stamen_insert(const char *code, stamen_callback_f callback);
          EXTERNC int stamen_builtin_display(const char *title,
                                             const stamen_item_t itemv[], int size);
          #ifdef __cplusplus
          namespace stamen {
          #if !defined __cplusplus || defined WITH_C_BINDINGS
          using callback_f = stamen_callback_f;
          using display_f = stamen_display_f;
          using item_t = stamen_item_t;
          int stamen_dynamic(const char *code);
          void stamen_read(const char *filename);
          void stamen_insert(const char *code, stamen_callback_f callback);
          int stamen_builtin_display(const char *title, const stamen_item_t itemv[],
                                     int size);
          const auto dynamic = stamen_dynamic;
          const auto read = stamen_read;
          const auto insert = stamen_insert;
          const auto builtin_display = stamen_builtin_display;
          #endif
          #ifdef __cplusplus
          } // namespace stamen
          } // extern "C"
          #endif
          #endif
          #endif // STAMEN_STAMEN_H
        
        diff --git a/ include/stamen.hpp b/ include/stamen.hpp
@@ -0,0 +1,21 @@
#ifndef STAMEN_STAMEN_HPP
          #define STAMEN_STAMEN_HPP
          #include "stamen.h"
          namespace stamen {
          using callback_f = stamen_callback_f;
          using display_f = stamen_display_f;
          using item_t = stamen_item_t;
          extern const display_f &display;
          int dynamic(const char *code);
          void read(const char *filename);
          void insert(const char *code, callback_f callback);
          int builtin_display(const char *title, const item_t itemv[], int size);
          } // namespace stamen
          #endif
        
        diff --git a/ src/CMakeLists.txt b/ src/CMakeLists.txt
@@ -1,12 +1,15 @@
add_library(stamen-include INTERFACE)
          target_include_directories(stamen-include INTERFACE ../include)
          add_library(stamen STATIC stamen.cpp menu.cpp c_bindings.cpp)
          target_include_directories(stamen PUBLIC ../include)
          target_compile_definitions(stamen PRIVATE WITH_C_BINDINGS)
          set_target_properties(stamen PROPERTIES LINKER_LANGUAGE CXX)
          add_library(stamen stamen.cpp menu.cpp)
          target_link_libraries(stamen PUBLIC stamen-include)
          set_target_properties(stamen PROPERTIES
              VERSION ${PROJECT_VERSION}
              SOVERSION ${PROJECT_VERSION_MAJOR}
              PUBLIC_HEADER ../include/stamen.h
              DEBUG_POSTFIX "d"
              PUBLIC_HEADER "../include/stamen.h;../include/stamen.hpp"
              MACOSX_RPATH ON
              WINDOWS_EXPORT_ALL_SYMBOLS ON
          )
          install(TARGETS stamen
        
        diff --git a/ src/c_bindings.cpp b/ src/c_bindings.cpp
@@ -0,0 +1,19 @@
#include "stamen.h"
          #include "stamen.hpp"
          namespace stamen {
          int stamen_dynamic(const char *code) { return dynamic(code); }
          void stamen_read(const char *filename) { return read(filename); }
          void stamen_insert(const char *code, stamen_callback_f callback) {
            return insert(code, callback);
          }
          int stamen_builtin_display(const char *title, const stamen_item_t itemv[],
                                     int size) {
            return builtin_display(title, itemv, size);
          }
          } // namespace stamen
        
        diff --git a/ src/generate.cpp b/ src/generate.cpp
          @@ -10,33 +10,44 @@ 
          namespace stamen {
        
        
          class Generator {
          public:
            static void generateInclude(std::ostream &os) {
            static void generateInclude(std::ostream &os, bool cpp) {
              os << "#ifndef STAMEN_MENU_H\n";
              os << "#define STAMEN_MENU_H\n\n";
              os << "#include <stamen.h>\n\n";
              if (cpp) os << "#include \"stamen.hpp\"\n\n";
              else os << "#include \"stamen.h\"\n\n";
              for (const auto &[code, menu] : Menu::menu_lookup) {
                os << std::format("int {}(int);\n", menu.getCode());
              }
              os << "\n#endif\n";
            }
            static void generateSource(std::ostream &os) {
              os << "#include <stamen.h>\n";
            static void generateSource(std::ostream &os, bool cpp) {
              if (cpp) os << "#include \"stamen.hpp\"\n\n";
              else os << "#include \"stamen.h\"\n\n";
              os << "#include \"shared.h\"\n\n";
              for (const auto &[code, menu] : Menu::menu_lookup) {
                os << std::format("int {}(int) {{\n", menu.getCode());
                os << std::format("\tstatic const stamen_item_t items[] = {{\n");
                if (cpp) os << "\tstatic const stamen::item_t items[] = ";
                else os << "\tstatic const stamen_item_t items[] = ";
                os << "{\n";
                for (int i = 0; i < menu.getSize(); i++) {
                  os << std::format("\t\t{{ {}, \"{}\" }},\n", menu.getCode(i),
                                    menu.getPrompt(i));
                  os << "\t\t{ " << menu.getCode(i);
                  os << ", \"" << menu.getPrompt(i) << "\" },\n";
                }
                os << std::format("\t}};\n");
                os << "\t};\n";
                if (cpp) os << "\treturn stamen::display";
                else os << "\treturn stamen_display";
                os << std::format("\treturn stamen_display(\"{}\", items, "
                                  "sizeof(items) / sizeof(items[0]));\n",
                                  menu.getTitle());
                os << std::format("}}\n\n");
                os << std::format("(\"{}\"", menu.getTitle());
                os << ", items, sizeof(items) / sizeof(items[0]));\n";
                os << "}\n\n";
              }
            }
          };
        
        
          @@ -63,8 +74,8 @@ 
          int main(const int argc, const char *argv[]) {
        
        
            std::string ext = cpp ? "pp" : "";
            std::ofstream source(base + ".c" + ext), include(base + ".h" + ext);
            Generator::generateSource(source);
            Generator::generateInclude(include);
            Generator::generateSource(source, cpp);
            Generator::generateInclude(include, cpp);
            return 0;
          }
        
        diff --git a/ src/menu.cpp b/ src/menu.cpp
@@ -1,5 +1,4 @@
#include "menu.h"
          #include "stamen.h"
          #include <deque>
          #include <format>
        
        diff --git a/ src/stamen.cpp b/ src/stamen.cpp
@@ -1,4 +1,4 @@
#include "stamen.h"
          #include "stamen.hpp"
          #include "menu.h"
          #include <cmath>
        
        @@ -7,16 +7,15 @@
#include <ostream>
          #include <variant>
          using namespace stamen;
          namespace stamen {
          int stamen_dynamic(const char *code) { return Menu::dynamic(code); }
          void stamen_read(const char *filename) { Menu::read(filename); }
          void stamen_insert(const char *code, stamen_callback_f callback) {
          int dynamic(const char *code) { return Menu::dynamic(code); }
          void read(const char *filename) { Menu::read(filename); }
          void insert(const char *code, callback_f callback) {
            Menu::insert(code, callback);
          }
          int stamen_builtin_display(const char *title, const stamen_item_t itemv[],
                                     int size) {
          int builtin_display(const char *title, const item_t itemv[], int size) {
            const size_t digits = size_t(std::log10(size)) + 1;
            const auto items = std::span(itemv, size_t(size));
            int choice = 0;
        
        
          @@ -56,3 +55,5 @@ 
          int stamen_builtin_display(const char *title, const stamen_item_t itemv[],
        
        
            return 1;
          }
          } // namespace stamen