OSDN Git Service

大量変更… (こういう風に書くのは好ましくない〜) master
authorcaprice <caprice@users.sourceforge.jp>
Mon, 30 Dec 2013 09:50:35 +0000 (18:50 +0900)
committercaprice <caprice@users.sourceforge.jp>
Mon, 30 Dec 2013 09:50:35 +0000 (18:50 +0900)
core/doc/README.txt
core/include/GikoMona.hpp
core/include/config.hpp
core/include/database.hpp
core/include/extension.hpp
core/include/model.hpp
core/include/query.hpp
core/include/string.hpp
core/src/GikoMona.cpp
core/src/model.cpp
core/test/query.cpp

index 18e957b..928b8f5 100644 (file)
@@ -5,6 +5,8 @@ libcore単体でビルドする場合は、ターミナル上で、
     
 pnuts/gikomonaとともにビルドする場合は、
 $(GIKOMONA_ROOT)/build/HOW-TO-BUILD.txt を参照してください。
+なお、このビルドによって生成されるライブラリは必ず静的ライブラリ (*.a, *.lib) になります。
+動的ライブラリ (*.so, *.dylib, *.dll) の生成法は用意されていません。
 
 *テスト方法
 libcore単体でテストするときは、ターミナル上で、
@@ -16,19 +18,21 @@ pnuts/gikomonaとともにテストする際には、自動でlibcoreのテス
 
 *ビルド後の pnuts/gikomona のフォルダの構造
 
+@ Windows {
 $(GIKOMONA_ROOT)/
     resource/
         icon/
             ...
-==== pnuts のみ ====
-        pnuts.xrc
-
-==== gikomona のみ ====
-        gikomona.xrc
+        pnuts.xrc   (pnuts only)
+        gikomona.xrc(gikomona only)
 
     doc/
-        README.txt
-        LICENSE.txt
+        README.html
+        LICENSE.html
+
+    pnuts.exe       (pnuts only)
+    gikomona.exe    (gikomona only)
+    update-utility.exe
 
     thread/
     board-list/
@@ -36,11 +40,25 @@ $(GIKOMONA_ROOT)/
     history.db
     config.xml
     favorite.xml
+}
 
-==== pnuts のみ ====
-    pnuts(.exe)
+@ Linux {
+$(GIKOMONA_ROOT)/
+    resource/
+    doc/
     
-==== gikomona のみ ====
-    twitter/
-    gikomona(.exe)
+}
 
+@ Mac OS X {
+$(GIKOMONA_ROOT)/
+    Contents/
+        Frameworks/
+        Resources/
+        MacOS/
+            pnuts
+            gikomona
+            update-utility
+        Info.plist
+        version.plist
+        PkgInfo
+}
index 31a075d..377c047 100644 (file)
@@ -23,6 +23,7 @@ extern void *enabler;
 
 /// @breif libbbs で string に関わる typedef を抑制する。@link libbbs/settings.hpp @endlink を見よ。
 #define LIBBBS_PRAGMA_USED_BY_GIKOMONA
+#define LIBSQLITEXX_PRAGMA_USED_BY_GIKOMONA
 
 #define PROJECT_NAME "GikoMona project, powered by monazilla.org."
 #define PROJECT_URL "http://sourceforge.jp/projects/gikomona/"
index 2aa315a..efe9338 100644 (file)
@@ -1,9 +1,9 @@
 #ifndef GIKOMONA_CORE_CONFIG_HPP
 #define GIKOMONA_CORE_CONFIG_HPP
 
-#include <tuple>
 #include <unordered_map>
 
+#include <boost/fusion/include/vector.hpp>
 #include <boost/mpl/bool.hpp>
 #include <boost/any.hpp>
 
 
 namespace monazilla { namespace GikoMona { namespace core {
 
-class config final {
+class config final : public query {
 public:
     typedef config self_type;
+    typedef query base_type;
 
     config() noexcept {}
     ~config() {}
 
-    template <typename ...ValueType>
-    void insert(const mona_string& into,
-                const std::tuple<ValueType...>& value) {}
-
+    /**
+     *  @breif query_concept を満たすクラスはこの関数と同じ型、名前を持つ関数を持っていなければならない。
+     *  @retval true insert 操作が成功した
+     *          false insert 操作に失敗した
+     *  @param[in] into どのテーブルのどの要素に対し insertion query を実行するかを記述する。
+     *                  記述の仕方は次の通り:(テーブル名)/[(サブテーブル名)/]*(要素名)
+     *  @param[in] value テーブルに対して代入する値を記述する。
+     *  @note さらに、最大限 multi-threading な環境を考慮しなければならない。
+     */
+    template <typename T, typename U, typename ...ValueType>
+    bool insert(const mona_string& into,
+                const boost::fusion::vector<T, U, ValueType...>& value) {}
+    
+    template <typename T>
+    bool insert(const mona_string& into,
+                const boost::fusion::vector<T>& value) {}
+    
+    template <typename T>
+    bool insert(const mona_string& into,
+                const boost::any& value,
+                base_type::enable_if_T_is_U<T, boost::any>*& = enabler) {}
+    
+    /**
+     *  @brief query_concept を満たすクラスはこの関数と同じ型、名前を持つ関数を持っていなければならない。
+     *  @return 引数で指定したテーブルの要素から、テンプレートで指定した方に変換された値が返される。
+     */
     template <typename T>
     T select(const mona_string& column,
              const mona_string& from) const noexcept {}
     
+    template <typename T>
+    boost::any select(const mona_string& column,
+                      const mona_string& from,
+                      base_type::enable_if_T_is_U<T, boost::any>*& = enabler) const noexcept {}
+    
     template <typename ...ValueType>
-    std::tuple<ValueType...>
+    boost::fusion::vector<ValueType...>
     select_all(const mona_string& from) const noexcept {}
-
 private:
     std::unordered_map<mona_string, boost::any> map;
 };
index e2cac3d..161cd5a 100644 (file)
@@ -5,29 +5,44 @@
 
 #include <sqlite3.h>
 
+#include <boost/system/system_error.hpp>
 #include <boost/filesystem.hpp>
+#include <boost/fusion/include/vector.hpp>
 
 #include "GikoMona.hpp"
 #include "query.hpp"
 
 namespace monazilla { namespace GikoMona { namespace core {
 
-class database final {
-public:
-    template <typename T, typename ...U>
-    class sql_executer final {
-        friend database;
+class database;
+
+template <typename ReturnTypeList, typename ArgTypeList>
+class sql_executer final {
+    friend database;
+    
+    typedef ReturnTypeList result_type;
+    typedef ArgTypeList arg_type;
+    typedef ::sqlite3 *db_object_type;
+    typedef ::sqlite3_stmt *sql_stmt_type;
+
+    const ::sqlite3_stmt *stmt;
         
-        sql_executer(const mona_string& sql) {}
-        ~sql_executer() {}
+    sql_executer(db_object_type db,
+                 const sql_stmt_type stmt,
+                 boost::system::error_code& ec) noexcept {}
+    ~sql_executer() {}
         
-    public:
-        void operator()() {}
-    };
+public:
+    typename <typename T>
+    void bind(const mona_string& param_name, const T& val) {}
+    result_type operator()() {}
+};
 
+class database final : public query {
 public:
     typedef ::sqlite3 *db_object_type;
     typedef database self_type;
+    typedef query base_type;
 
     database() : database("") {}
     
@@ -48,7 +63,7 @@ public:
     
     ~database() { close(); }
     
-    /// @brief 受け取った SQL を実行する。ただし、実行できる文は返り値の無いものに限られる。
+    /// @brief 受け取った SQL を実行する。ただし、実行できる文は引数と返り値が共に無いものに限られる。
     /**
      * @return SQL が正常に実行された場合は true、それ以外の場合は false を返す。
      * @note この関数は SQL の実行結果を返さない。したがって、実行結果が必要な場合は、
@@ -64,23 +79,69 @@ public:
      *       実行した SQL の実行結果が不要である (あるいはそもそも実行結果が無い) 場合は、
      *       run_sql() を用いるべきである。
      */
-    template <typename T, typename ...U>
-    sql_executer<T, U...> compile_sql(const mona_string& sql) {
-        return sql_executer<T>(sql);
+    template <typename ...T>
+    sql_executer<T...> compile_sql(const mona_string& sql) {
+        /**
+         *  @note sqlite3_prepare(db,zSql,nByte,ppStmtpzTail) で nByte に "sql.length() + 1" を
+         *        渡すのはなぜか?詳しくは次を参照 : http://www.sqlite.org/c3ref/prepare.html
+         *        ページ中程、"If the nByte argument is less than zero, ~" の先、関係あるところを
+         *        かいつまんで訳すと「もしも関数を呼び出した側が、zSql が NULL-terminated な文字列
+         *        (\0、\u0 が終端であるような文字列) であることを知っている場合、nByte に文字列のバイト長
+         *        (ただしここで言うバイト長には終端文字である\0または\u0も「含んだ」ものである) を渡すことで、
+         *        若干パフォーマンスが上がる」という記述がある。C++のstd::string::length()/size()は文字列の
+         *        終端文字を除いた長さを返すので、わざわざ1を加えている。
+         */
+        int result = ::sqlite3_prepare_v2(db.get_sqlite3_obj(),
+                                          sql.c_str(),
+                                          sql.length() + 1,
+                                          &stmt,
+                                          NULL);
+        if (result != ::SQLITE_OK && !stmt) {
+            
+        } else {
+            return sql_executer<T...>(sql);
+        }
     }
     
-    template <typename ...ValueType>
-    void insert(const mona_string& into,
-                const std::tuple<ValueType...>& value) {}
+    /**
+     *  @brief
+     *  @retval true insert 操作が成功した
+     *          false insert 操作に失敗した
+     *  @param[in] into どのテーブルのどの要素に対し insertion query を実行するかを記述する。
+     *                  記述の仕方は次の通り:(テーブル名)/[(サブテーブル名)/]*(要素名)
+     *  @param[in] value テーブルに対して代入する値を記述する。
+     *  @note さらに、最大限 multi-threading な環境を考慮しなければならない。
+     */
+    template <typename T, typename U, typename ...ValueType>
+    bool insert(const mona_string& into,
+                const boost::fusion::vector<T, U, ValueType...>& value) {}
+    
+    template <typename T>
+    bool insert(const mona_string& into,
+                const boost::fusion::vector<T>& value) {}
     
     template <typename T>
+    bool insert(const mona_string& into,
+                const boost::any& value,
+                base_type::enable_if_T_is_U<T, boost::any>*& = enabler) {}
+    
+    /**
+     *  @brief query_concept を満たすクラスはこの関数と同じ型、名前を持つ関数を持っていなければならない。
+     *  @return 引数で指定したテーブルの要素から、テンプレートで指定した方に変換された値が返される。
+     */
+    template <typename T>
     T select(const mona_string& column,
              const mona_string& from) const noexcept {}
     
+    template <typename T>
+    boost::any select(const mona_string& column,
+                      const mona_string& from,
+                      base_type::enable_if_T_is_U<T, boost::any>*& = enabler) const noexcept {}
+    
     template <typename ...ValueType>
-    std::tuple<ValueType...>
+    boost::fusion::vector<ValueType...>
     select_all(const mona_string& from) const noexcept {}
-    
+
     /// @brief データベースの最適化を行う。
     /**
      * @note 内部では以下のコマンドが実行され、データベースの不要データの圧縮と再構築が行われる。
index ec45233..b5443d1 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef core_extension_hpp
-#define core_extension_hpp
+#ifndef GIKOMONA_CORE_EXTENSION_HPP
+#define GIKOMONA_CORE_EXTENSION_HPP
 
 #include <unordered_map>
 #include <functional>
index 647d54c..432c6d2 100644 (file)
@@ -3,8 +3,8 @@
 
 #include <unistd.h>
 #include <memory>
-#include <tuple>
 
+#include <boost/fusion/include/vector.hpp>
 #include <boost/any.hpp>
 #include <boost/lockfree/queue.hpp>
 #include <boost/filesystem/path.hpp>
 
 namespace monazilla { namespace GikoMona { namespace core {
 
-class model {
+class model : public query {
 public:
     typedef model self_type;
-    typedef std::tuple<mona_string, boost::any> inserted_query_type;
-    typedef inserted_query_type *inserted_query_triv_copyable_type;
+    typedef query base_type;
+    typedef boost::fusion::vector<mona_string, boost::any> inserted_value_type;
+    typedef inserted_value_type *inserted_value_triv_copyable_type;
     
     model() noexcept;
     ~model();
@@ -29,25 +30,47 @@ public:
     model *get_instance() {
         return instance;
     }
+
+    /**
+     *  @breif query_concept を満たすクラスはこの関数と同じ型、名前を持つ関数を持っていなければならない。
+     *  @retval true insert 操作が成功した
+     *          false insert 操作に失敗した
+     *  @param[in] into どのテーブルのどの要素に対し insertion query を実行するかを記述する。
+     *                  記述の仕方は次の通り:(テーブル名)/[(サブテーブル名)/]*(要素名)
+     *  @param[in] value テーブルに対して代入する値を記述する。
+     *  @note さらに、最大限 multi-threading な環境を考慮しなければならない。
+     */
+    template <typename T, typename U, typename ...ValueType>
+    bool insert(const mona_string& into,
+                const boost::fusion::vector<T, U, ValueType...>& value) {}
     
-    template <typename ...ValueType>
+    template <typename T>
     bool insert(const mona_string& into,
-                const std::tuple<ValueType...>& values) {
-        /*
-        auto any_value = boost::any(values);
-        auto obj = std::make_tuple(into, any_value);
-        return inserted_query_queue.push();
-        */
-    }
+                const boost::fusion::vector<T>& value) {}
     
     template <typename T>
+    virtual
+    bool insert(const mona_string& into,
+                const boost::any& value,
+                base_type::enable_if_T_is_U<T, boost::any>*& = enabler) {}
+    
+    /**
+     *  @brief query_concept を満たすクラスはこの関数と同じ型、名前を持つ関数を持っていなければならない。
+     *  @return 引数で指定したテーブルの要素から、テンプレートで指定した方に変換された値が返される。
+     */
+    template <typename T>
     T select(const mona_string& column,
              const mona_string& from) const noexcept {}
     
+    template <typename T>
+    boost::any select(const mona_string& column,
+                      const mona_string& from,
+                      base_type::enable_if_T_is_U<T, boost::any>*& = enabler) const noexcept {}
+    
     template <typename ...ValueType>
-    std::tuple<ValueType...>
+    boost::fusion::vector<ValueType...>
     select_all(const mona_string& from) const noexcept {}
-    
+
     void exec_inserted_query();
     bool load_file(const boost::filesystem::path& file_path,
                    const mona_string& loaded_table_name);
@@ -55,11 +78,15 @@ public:
                       const mona_string& saved_table_name);
 
 private:
+    void get_object_expressing_into_path_in_query(const mona_string& src,
+                                                  const boost::any& value);
+    void analyze_into_path_in_query(const mona_string& into_path_in_query);
+    
     static self_type *instance;
     struct model_pimpl;
     
     std::shared_ptr<model_pimpl> pimpl;
-    boost::lockfree::queue<inserted_query_triv_copyable_type> inserted_query_queue;
+    boost::lockfree::queue<inserted_value_triv_copyable_type> query_queue;
 };
 
 template <>
index a28f09e..b2762e4 100644 (file)
@@ -1,9 +1,7 @@
 #ifndef GIKOMONA_CORE_QUERY_HPP_INCLUDED
 #define GIKOMONA_CORE_QUERY_HPP_INCLUDED
 
-#include <tuple>
-#include <vector>
-
+#include <boost/fusion/include/vector.hpp>
 #include <boost/mpl/bool.hpp>
 
 #include "GikoMona.hpp"
@@ -14,20 +12,20 @@ template <typename T>
 struct is_satisfied_with_query_concept : public boost::mpl::false_ {};
 
 /**
- *  @brief ã\81\93ã\81®ã\82¯ã\83©ã\82¹ã\81§ã\81¯ query_concept ã\81\8cæº\80ã\81\9fã\81\99ã\81¹ã\81\8dç\94¨ä»¶ã\81\8cè¨\98è¿°ã\81\95ã\82\8cã\81¦ã\81\84ã\82\8b
+ *  @brief ã\81\93ã\81®ã\82¯ã\83©ã\82¹ã\81¯ query_concept ã\82\92æº\80ã\81\9fã\81\99å\85¨ã\81¦ã\81®ã\82¯ã\83©ã\82¹ã\81\8cç¶\99æ\89¿ã\81\97ã\81ªã\81\91ã\82\8cã\81°ã\81ªã\82\89ã\81ªã\81\84
  */
-class query_concept final {
+class query {
 public:
     /// query_concept を満たすクラスは自分自身の型を self_type として表明しなければならない。
-    typedef query_concept self_type;
+    typedef query self_type;
     
     template <typename T, typename U>
     using enable_if_T_is_U = typename std::enable_if<std::is_same<T, U>::value>::type;
     
     /// query_concept を満たすクラスは外部から構築可能でなければならない。
-    query_concept() {}
+    query() {}
     /// query_concept を満たすクラスは外部から解体可能でなければならない。
-    ~query_concept() {}
+    ~query() {}
     
     /**
      *  @breif query_concept を満たすクラスはこの関数と同じ型、名前を持つ関数を持っていなければならない。
@@ -39,38 +37,42 @@ public:
      *  @note さらに、最大限 multi-threading な環境を考慮しなければならない。
      */
     template <typename T, typename U, typename ...ValueType>
+    virtual
     bool insert(const mona_string& into,
-                const std::tuple<T, U, ValueType...>& value) {}
+                const boost::fusion::vector<T, U, ValueType...>& value) override {}
     
     template <typename T>
+    virtual
     bool insert(const mona_string& into,
-                const std::tuple<T>& value) {}
+                const boost::fusion::vector<T>& value) override {}
     
     template <typename T>
+    virtual
     bool insert(const mona_string& into,
                 const boost::any& value,
-                enable_if_T_is_U<T, boost::any>*& = enabler) {}
+                enable_if_T_is_U<T, boost::any>*& = enabler) override {}
     
     /**
      *  @brief query_concept を満たすクラスはこの関数と同じ型、名前を持つ関数を持っていなければならない。
      *  @return 引数で指定したテーブルの要素から、テンプレートで指定した方に変換された値が返される。
      */
     template <typename T>
+    virtual
     T select(const mona_string& column,
-             const mona_string& from) const noexcept {}
+             const mona_string& from) const noexcept override {}
     
     template <typename T>
+    virtual
     boost::any select(const mona_string& column,
                       const mona_string& from,
-                      enable_if_T_is_U<T, boost::any>*& = enabler) {}
+                      enable_if_T_is_U<T, boost::any>*& = enabler) const noexcept override {}
     
     template <typename ...ValueType>
-    std::tuple<ValueType...>
-    select_all(const mona_string& from) const noexcept {}
+    virtual
+    boost::fusion::vector<ValueType...>
+    select_all(const mona_string& from) const noexcept override {}
 };
 
-template <>
-
 } } }
 
 #endif
\ No newline at end of file
index 738409c..d76fb56 100644 (file)
@@ -5,8 +5,8 @@
 //  Created by caprice on 2013/08/05.
 //
 
-#ifndef core_string_hpp
-#define core_string_hpp
+#ifndef GIKOMONA_CORE_STRING_HPP
+#define GIKOMONA_CORE_STRING_HPP
 
 #include <string>
 
 
 // このコンパイラの char16_t、char32_t を UTF-16/32 を表現するか?
 #if !(__STDC_UTF_16__)
-    #error "sorry, this compiler does not support utf-16."
+    #error "[GikoMona.libcore @pp-time] : sorry, this compiler does not support utf-16."
 #endif
 
 #if !(__STDC_UTF_32__)
-    #error "sorry, this compiler does not support utf-32."
+    #error "[GikoMona.libcore @pp-time] : sorry, this compiler does not support utf-32."
 #endif
 
 namespace monazilla { namespace GikoMona {
index 9b0b5c2..74d450c 100644 (file)
@@ -1,4 +1,8 @@
 #include <wx/xrc/xmlres.h>
+#include <exception>
+
+#include <boost/filesystem.hpp>
+
 #include <wx/msgdlg.h>
 
 #include "GikoMona.hpp"
@@ -20,8 +24,16 @@ bool init_core() {
     wxXmlResource::Get()->InitAllHandlers();
     wxXmlResource::Get()->LoadAllFiles(wxT("resouce"));
     
+    boost::system::error_code reason;
+    if(!boost::filesystem::create_directory(".tmp", reason) || reason) {
+        // log
+        std::terminate();
+    }
+    
     app_model = new model;
     app_extension = new extension;
+    
+    return true;
 }
 
 void done_core() noexcept {
@@ -33,6 +45,11 @@ void done_core() noexcept {
 
 void optimize_database(const boost::filesystem::path& db_path) {
     database db(db_path);
+    /*
+    auto value = db.compile(u8"SELECT * FROM file-information;");
+    value.execute();
+    value.get_result<int>();
+    */
     if(db.select<int>("count-of-deleting-values", "file-infomation") >= 1000) {
         db.optimize();
     }
index e72d6e7..de24846 100644 (file)
@@ -1,3 +1,4 @@
+#include <boost/filesystem/path.hpp>
 
 #include "model.hpp"
 
@@ -5,10 +6,13 @@ namespace monazilla { namespace GikoMona { namespace core {
 
 struct model::model_pimpl {
     // session/tab-window
+    /* 構造
+     * bbs-name(TEXT)|board-name(TEXT)|thread-id(TEXT)|thread-name(TEXT)|is_fixed(INTEGAR)
+     */
     database tab_db;
     // session/history
     /* 構造
-     *  date()|bbs-name()|board-name()|thread-id()|thread-name()
+     * date(TEXT)|bbs-name(TEXT)|board-name(TEXT)|thread-id(TEXT)|thread-name(TEXT)
      */
     database history_db;
     // application
@@ -18,6 +22,10 @@ struct model::model_pimpl {
 model::model() noexcept {
     instance = this;
     pimpl = std::make_shared<model_pimpl>();
+    
+    auto config_path = pimpl->app_config.select<boost::filesystem::path>("config", "file-path");
+    
+    pimpl->tab_db.create(config_path);
 }
 
 model::~model() {}
@@ -32,23 +40,25 @@ bool model::load_file(const boost::filesystem::path& file_path,
 }
 
 void model::exec_inserted_query()  {
-    inserted_query_triv_copyable_type q;
-    if(inserted_query_queue.empty()) {
+    inserted_value_triv_copyable_type q;
+    if(query_queue.empty()) {
         return;
     } else {
-        inserted_query_queue.pop(q);
+        query_queue.pop(q);
     }
     
     mona_string into;
-    boost::any tup;
-    std::tie(*q, into, tup);
+    boost::any value;
+    std::tie(*q, into, value);
+    
+    analyze_into_path_in_query(into);
 
     if(into.find_first_of("application", 0, into.length()) != mona_string::npos) {
         // application/*
     } else if (into.find_first_of("session", 0, into.length()) != mona_string::npos) {
         // session/*
         if(into.find("history", 0, into.length()) != mona_string::npos) {
-            pimpl->history_db.insert(into, tup);
+            ;
         } else if(into.find("tab-window") != mona_string::npos != mona_string::npos) {
             pimpl->tab_db.insert(into, tup);
         }
index 5928d7a..d0a8acb 100644 (file)
@@ -12,27 +12,6 @@ BOOST_AUTO_TEST_SUITE(query)
 
 namespace gm_core = monazilla::GikoMona::core;
 
-BOOST_AUTO_TEST_CASE(type_concept) {
-    BOOST_REQUIRE_EQUAL(std::is_trivially_copyable<gm_core::query>::value, true);
-}
-/*
-BOOST_AUTO_TEST_CASE(selecting) {
-    BOOST_CHECK_MESSAGE(
-        false,
-        gm_core::query().define()
-            .select(gm_core::all_columnes, "test")
-            .dump()
-    );
-    BOOST_CHECK_MESSAGE(
-        false,
-        gm_core::query().define()
-            .select({"name", "birthday", "mail"}, "test")
-            .dump()
-    );
-}
-*/
-
-
 BOOST_AUTO_TEST_SUITE_END // query
 BOOST_AUTO_TEST_SUITE_END // CORE