OSDN Git Service

Initial commit
authorcaprice <gikomona.2chbrowser@gmail.com>
Sun, 16 Jun 2013 13:56:15 +0000 (22:56 +0900)
committercaprice <gikomona.2chbrowser@gmail.com>
Sun, 16 Jun 2013 13:56:15 +0000 (22:56 +0900)
13 files changed:
.gitignore [new file with mode: 0644]
core/doc/README.txt [new file with mode: 0644]
core/include/GikoMona.hpp [new file with mode: 0644]
core/include/config.hpp [new file with mode: 0644]
core/include/database.hpp [new file with mode: 0644]
core/include/model.hpp [new file with mode: 0644]
core/include/query.hpp [new file with mode: 0644]
core/src/GikoMona.cpp [new file with mode: 0644]
core/src/model.cpp [new file with mode: 0644]
gikomona/.gitkeep [new file with mode: 0644]
pnuts/build/build-pnuts.sh [new file with mode: 0644]
pnuts/include/pnuts.hpp [new file with mode: 0644]
pnuts/src/pnuts.cpp [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..c225b50
--- /dev/null
@@ -0,0 +1,65 @@
+.*
+!.gitignore
+!.gitkeep
+
+*~
+
+# IDE settings
+*.xcodeproj    # Xcode
+*.cbp          # code::blocks
+*.vcproj       # Visual C++
+*.vcxproj      # Visual C++
+
+# emacs
+\#*\#
+/.emacs.desktop
+/.emacs.desktop.lock
+.elc
+auto-save-list
+tramp
+.\#*
+
+# Org-mode
+.org-id-locations
+*_archive
+
+# vim
+.*.s[a-w][a-z]
+*.un~
+Session.vim
+.netrwhist
+
+# build dir
+bin/debug
+bin/release
+
+# OS X hidden/temp files
+.DS_Store
+.AppleDouble
+.LSOverride
+Icon
+
+# OS X Thumbnails
+._*
+
+# files that might appear on external disk (OS X)
+.Spotlight-V100
+.Trashes
+
+# User-specific project settings
+*.mode1v3
+*.mode2v3
+
+# Windows image thumbnail file
+Thumbs.db
+ehthumbs.db
+
+# Windows folder config file
+Desktop.ini
+
+# recycle Bin used on file shares (Windows)
+$RECYCLE.BIN/
+
+*.swp
+*~.nib
+
diff --git a/core/doc/README.txt b/core/doc/README.txt
new file mode 100644 (file)
index 0000000..18e957b
--- /dev/null
@@ -0,0 +1,46 @@
+*ビルド方法
+libcore単体でビルドする場合は、ターミナル上で、
+    cd $(LIBCORE_ROOT)
+    make standalone
+    
+pnuts/gikomonaとともにビルドする場合は、
+$(GIKOMONA_ROOT)/build/HOW-TO-BUILD.txt を参照してください。
+
+*テスト方法
+libcore単体でテストするときは、ターミナル上で、
+    cd $(LIBCORE_ROOT)
+    make test
+
+pnuts/gikomonaとともにテストする際には、自動でlibcoreのテストも行われるので、
+いちいち指定してテストする必要はありません。
+
+*ビルド後の pnuts/gikomona のフォルダの構造
+
+$(GIKOMONA_ROOT)/
+    resource/
+        icon/
+            ...
+==== pnuts のみ ====
+        pnuts.xrc
+
+==== gikomona のみ ====
+        gikomona.xrc
+
+    doc/
+        README.txt
+        LICENSE.txt
+
+    thread/
+    board-list/
+
+    history.db
+    config.xml
+    favorite.xml
+
+==== pnuts のみ ====
+    pnuts(.exe)
+    
+==== gikomona のみ ====
+    twitter/
+    gikomona(.exe)
+
diff --git a/core/include/GikoMona.hpp b/core/include/GikoMona.hpp
new file mode 100644 (file)
index 0000000..3b5ee32
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef GIKOMONA_CORE_GIKOMONA_HPP
+#define GIKOMONA_CORE_GIKOMONA_HPP
+
+#include <string>
+
+#include <boost/utility/string_ref.hpp>
+
+namespace monazilla { namespace GikoMona {
+
+typedef char u8_char;
+typedef std::basic_string<u8_char> u8_string;
+
+typedef u8_string mona_string;
+typedef boost::basic_string_ref<u8_char, std::char_traits<u8_char>> mona_string_ref;
+
+typedef std::basic_string<char> sjis_string;
+
+namespace core {
+
+bool init_core();
+void done_core() noexcept ;
+
+}
+
+} }
+
+/// @breif libbbs で string に関わる typedef を抑制する。@link libbbs/settings.hpp @endlink を見よ。
+#define LIBBBS_PRAGMA_USED_BY_GIKOMONA
+
+#define PROJECT_NAME "GikoMona project, powered by monazilla.org."
+#define PROJECT_URL "http://sourceforge.jp/projects/gikomona/"
+
+#endif
diff --git a/core/include/config.hpp b/core/include/config.hpp
new file mode 100644 (file)
index 0000000..c56adb1
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef GIKOMONA_CORE_CONFIG_HPP
+#define GIKOMONA_CORE_CONFIG_HPP
+
+#include <tuple>
+
+#include <boost/mpl/bool.hpp>
+
+#include "GikoMona.hpp"
+#include "query.hpp"
+
+namespace monazilla { namespace GikoMona { namespace core {
+
+
+class config final {
+public:
+    typedef config self_type;
+
+    config() noexcept {}
+    ~config() {}
+    
+    template <typename ...T>
+    std::tuple<T...> post_query(const mona_string_ref src) {
+        query conf_query(src);
+        return post_query(conf_query);
+    }
+    
+    template <typename ...T>
+    std::tuple<T...> post_query(const query& query) {
+        switch(query.type) {
+            case query_type::IN:
+                config_table[query.var] = query.value;
+                return std::tuple<T...>();
+
+            case query_type::OUT:
+               // = config_table[query.var];
+                
+        }
+    }
+};
+
+template <>
+struct is_responsible_to_query<config> : public boost::mpl::true_ {};
+
+} } }
+
+#endif
diff --git a/core/include/database.hpp b/core/include/database.hpp
new file mode 100644 (file)
index 0000000..8465d66
--- /dev/null
@@ -0,0 +1,116 @@
+#ifndef GIKOMONA_CORE_DATABASE_HPP
+#define GIKOMONA_CORE_DATABASE_HPP
+
+#include <memory>
+
+#include <sqlite3.h>
+
+#include <boost/filesystem.hpp>
+
+#include "GikoMona.hpp"
+#include "query.hpp"
+
+namespace monazilla { namespace GikoMona { namespace core {
+
+class database final {
+public:
+    template <typename T>
+    class sql_executer final {
+        friend database;
+        
+        sql_executer(const mona_string& sql) {}
+        ~sql_executer() {}
+        
+    public:
+        void operator()() {}
+    };
+
+public:
+    typedef ::sqlite3 *db_object_type;
+    typedef database self_type;
+
+    database() : database("") {}
+    
+    /// @breif すでに存在するデータベースファイルを開く。まだファイルが存在しない場合は、新たに作成する。
+    database(const boost::filesystem::path& db_path) {
+        if(db_path.empty()) {
+            is_opened_db = false;
+        } else {
+            if(!boost::filesystem::exists(db_path)) {
+                create(db_path);
+            } else {
+                open(db_path);
+            }
+        }
+    }
+    
+    database(const self_type& other) = delete;
+    
+    ~database() { close(); }
+    
+    /// @breif 受け取った SQL を実行する。ただし、実行できる文は返り値の無いものに限られる。
+    /**
+     * @return SQL が正常に実行された場合は true、それ以外の場合は false を返す。
+     * @note この関数は SQL の実行結果を返さない。したがって、実行結果が必要な場合は、
+     *       compile_sql() を用いるべきである。
+     */
+    bool run_sql(const mona_string& sql) {
+        return (::sqlite3_exec(db, sql.c_str(), NULL, NULL, NULL) != SQLITE_OK)
+            ? false : true;
+    }
+    
+    /// @breif 受け取った SQL を sql_executer へと変換して返す。
+    /**
+     * @note 返された sql_executer を実行することで、ここで渡した SQL の実行結果を得ることができる。
+     *       実行した SQL の実行結果が不要である (あるいはそもそも実行結果が無い) 場合は、
+     *       run_sql() を用いるべきである。
+     */
+    template <typename T>
+    sql_executer<T> compile_sql(const mona_string& sql) {
+        return sql_executer<T>(sql);
+    }
+    
+    /// @brief すでに存在するデータベースファイルを開く。
+    bool open(const boost::filesystem::path& db_path) {
+        if (is_opened_db) {
+            close();
+        }
+        
+        is_opened_db =
+            (::sqlite3_open(db_path.c_str(), &db) != SQLITE_OK)
+                ? false : true;
+        
+        return is_opened_db;
+    }
+    
+    /// @breif まだ存在しないデータベースファイルを新たに作成する。
+    /**
+     * @return true: ファイルが存在せず、かつ新たにデータベースファイルを作成することに成功した
+     *         false: ファイルが存在する、あるいは存在しないが新規データベースファイルの作成に失敗した
+     */
+    bool create(const boost::filesystem::path& db_path) {
+        if(boost::filesystem::exists(db_path)) {
+            return false;
+        }
+        
+        return open(db_path);
+    }
+    
+    void close() noexcept {
+        ::sqlite3_close(db);
+    }
+
+private:
+    db_object_type db;
+    bool is_opened_db;
+    
+    void begin_sql_statement() { run_sql("begin;"); }
+    void end_sql_statement() { run_sql("end"); }
+};
+
+template <>
+struct is_responsible_to_query<database> : public boost::mpl::true_ {};
+
+} } }
+
+#endif
diff --git a/core/include/model.hpp b/core/include/model.hpp
new file mode 100644 (file)
index 0000000..ed2f747
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef GIKOMONA_CORE_MODEL_HPP
+#define GIKOMONA_CORE_MODEL_HPP
+
+#include <unistd.h>
+
+#include <boost/lockfree/queue.hpp>
+#include <boost/filesystem/path.hpp>
+
+#include "GikoMona.hpp"
+#include "query.hpp"
+#include "database.hpp"
+#include "config.hpp"
+
+namespace monazilla { namespace GikoMona { namespace core {
+    
+class model {
+public:
+    typedef model self_type;
+    
+    model() noexcept {
+        instance = this;
+    }
+    
+    ~model() {}
+    
+    static
+    model *get_instance() {
+        return instance;
+    }
+    
+    bool push_query_in_queue(const query& src) {
+        return query_queue.push(src);
+    }
+    
+    template <typename ResultType>
+    ResultType pop_query() {
+        exec_all_query();
+    }
+    
+    bool load_file(const boost::filesystem::path& file_path);
+
+private:
+    static self_type *instance;
+    database db;
+    config app_config;
+    boost::lockfree::queue<query> query_queue;
+
+    void exec_all_query() {
+        query val("");
+        while(!query_queue.empty()) {
+            if(!query_queue.pop(val)) { continue; }
+            // valの処理
+        }
+    }
+};
+
+void post_query_to_model(const query& src) {
+    model *obj = model::get_instance();
+    while(!obj->push_query_in_queue(src)) {
+        ::sleep(10);
+    }
+}
+
+} } }
+
+#endif 
diff --git a/core/include/query.hpp b/core/include/query.hpp
new file mode 100644 (file)
index 0000000..211d521
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef GIKOMONA_CORE_QUERY_HPP_INCLUDED
+#define GIKOMONA_CORE_QUERY_HPP_INCLUDED
+
+#include <vector>
+
+#include <boost/mpl/bool.hpp>
+
+#include "GikoMona.hpp"
+
+namespace monazilla { namespace GikoMona { namespace core {
+
+/**
+ * @note このクラスは boost::lockfree::queue<> の制約から
+ *       trivially copyable の要件を満たす必要がある。
+ *       (参考:http://d.hatena.ne.jp/faith_and_brave/20130213/1360737911 )
+ */
+
+template <typename ValueType>
+class query final {
+public:
+    // query order
+    class select_ {
+    public:
+        struct select_all_column {} all_column;
+    
+        select_& distinct() {}
+        select_& group_by() {}
+        select_& where() {}
+        select_& having() {}
+    };
+
+public:
+    typedef std::vector<mona_string> column_name_list;
+    
+    query(mona_string) {}
+    ~query() = default;
+    
+    query& define() { return (*this); }
+    select_& select(const column_name_list& columnes,
+                    const mona_string& from) {
+        return (*this);
+    }
+    select_& select(select_::select_all_column /* dummy */,
+                    const mona_string& from) {
+        return (*this);
+    }
+    query& insert(const mona_string& into) {}
+};
+
+template <typename T>
+struct is_responsible_to_query : public boost::mpl::false_ {};
+
+} } }
+
+#endif
\ No newline at end of file
diff --git a/core/src/GikoMona.cpp b/core/src/GikoMona.cpp
new file mode 100644 (file)
index 0000000..9a80b05
--- /dev/null
@@ -0,0 +1,32 @@
+#include <wx/xrc/xmlres.h>
+
+#include "GikoMona.hpp"
+#include "database.hpp"
+#include "model.hpp"
+
+namespace monazilla { namespace GikoMona { namespace core {
+
+namespace {
+
+model *app_model;
+
+}
+
+bool init_core() {
+    wxXmlResource::Get()->InitAllHandlers();
+    wxXmlResource::Get()->LoadAllFiles(wxT(""));
+    
+    database db;
+    db.run_sql("");
+    
+    app_model = new model;
+    app_model->load_file("./config.xml");
+    app_model->load_file("./history.db");
+    app_model->load_file("./saved-tab-session.xml");
+}
+
+void done_core() noexcept {
+    delete app_model;
+}
+
+} } }
diff --git a/core/src/model.cpp b/core/src/model.cpp
new file mode 100644 (file)
index 0000000..576cc7d
--- /dev/null
@@ -0,0 +1,13 @@
+
+#include "model.hpp"
+
+namespace monazilla { namespace GikoMona { namespace core {
+
+bool model::load_file(const boost::filesystem::path& file_path) {
+    if(boost::filesystem::exists(file_path)) {
+        return false;
+    }
+    return true;
+}
+
+} } }
diff --git a/gikomona/.gitkeep b/gikomona/.gitkeep
new file mode 100644 (file)
index 0000000..139597f
--- /dev/null
@@ -0,0 +1,2 @@
+
+
diff --git a/pnuts/build/build-pnuts.sh b/pnuts/build/build-pnuts.sh
new file mode 100644 (file)
index 0000000..dc07fe9
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+# bootstrap
+
+echo "now loading..."
+
+BUILD_DIR=`pwd`
+ROOT=${BUILD_DIR}/../
+LIB_DIR=${ROOT}/lib
+
+function check_dir() {
+    if [ -d $1 ] ; then
+        echo "\$1 does not find."
+        exit 1
+    fi
+}
+
+check_dir ${LIB_DIR}/core
+check_dir ${LIB_DIR}/libbbs
+check_dir ${LIB_DIR}/lua
+check_dir ${LIB_DIR}/sqlite3
+
+LIBCORE_DIR=${LIB_DIR}/core
+LIBBBS_DIR=${LIB_DIR}/libbbs
+LIBLUA_DIR=${LIB_DIR}/lua
+LIBSQLITE3_DIR=${LIB_DIR}/sqlite3
+
+cd LIBLUA_DIR
+if [ ! -f LIBLUA_DIR/bin/lua ] ; then
+    if [ ! -f LIBLUA_DIR/bin/lua.exe ] ; then
+        make
+    fi
+fi
+
+LUA=LIBLUA_DIR/bin/lua
+
+echo "bootstrap stage finished."
+
+cd BUILD_DIR
+
+LUA ./lake.lua lake-build
diff --git a/pnuts/include/pnuts.hpp b/pnuts/include/pnuts.hpp
new file mode 100644 (file)
index 0000000..cb0a268
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef GIKOMONA_PNUTS_HPP
+#define GIKOMONA_PNUTS_HPP
+
+#include <wx/xrc.h>
+
+#include "core/GikoMona.hpp"
+
+namespace GikoMona {
+namespace pnuts {}
+}
+
+#define PNUTS_VERSION_MAJOR 1
+#define PNUTS_VERSION_MINOR 0
+#define PNUTS_VERSION_STATE 0
+
+#define PNUTS_VERSION   PNUTS_VERSION_MAJOR . \
+                        PNUTS_VERSION_MINOR . \
+                        PNUTS_VERSION_STATE
+
+#define PNUTS_VERSION_STR BOOST_STRINGNIZE(PNUTS_VERSION)
+
+// wxrc generate.
+extern void InitXmlResource();
+
+namespace GikoMona {
+namespace pnuts {
+
+class application : public wxApp {
+    bool OnInit();
+    int OnExit();
+};
+
+}
+}
+
+#endif
diff --git a/pnuts/src/pnuts.cpp b/pnuts/src/pnuts.cpp
new file mode 100644 (file)
index 0000000..7f58289
--- /dev/null
@@ -0,0 +1,59 @@
+
+#include "pnuts.hpp"
+
+namespace GikoMona {
+namespace pnuts {
+
+bool application::OnInit() {
+    wxXmlResource::Get()->InitAllHandlers();
+    // init embedded resources.
+    InitXmlResources();
+    // init changeable resources.
+    wxXmlResource::Get()->LoadAllFiles("resource");
+    
+    config = new config;
+#ifdef ENABLE_TWITTER
+    auto res = config.post_query<bool>("?:twitter/service=enable");
+    if(res) {
+        auto id_password
+            = config.post_query<mona_string, mona_string>(
+                ">:twitter/user/{id & password}"
+            );
+        twitter::login(id_password<0>, id_password<1>);
+    }
+#endif
+    
+    controller = new controller;
+    model = new model;
+    main_window = new main_window;
+    model.main_window = main_window;
+    main_window->PushEventHandler(controller);
+    
+    auto is_first_executation
+        = config.post_query<bool>(
+            "?:app/last-executation-time=inavailable"
+        );
+    
+    if(is_first_executation) {
+        show_welcome();
+        main_window->Show();
+        return true;
+    } else {
+        thread_window = new threaad_window;
+        model.thread_window = thread_window;
+        thread_window->PushEventHandler(controller);
+        
+        thread_window->Show();
+        return true;
+    }
+}
+
+int application::OnExit() {
+    config.post_query<void>(
+        "<:app/last-executation-time", "$:NOW"
+    );
+    return 0;
+}
+
+}
+}