예제 #1
0
// ------------------------------------------------------------------------------------
// エラーがあった場合、例外で返される。このとき dst_wrt_WS_buf には、エラーの発生コードと、ID.End が書き込まれる。
// file_path は、"md_root/..." の形のもの
        public static void LexFile(Write_WS_Buffer dst_wrt_WS_buf, string file_path)
        {
            ReadFile_to_MD_buf(file_path);
            // この時点で、MD_buf の最後は \n\0 で終わっている。

            // ---------------------------------------------------------
            // 字句解析用のフラグを初期化
            msb_next_is_Div       = true; // ファイル先頭は、必ず Div ブロックとなる
            msb_Dtct_CodeBlk_Mark = false;

            msb_is_in_CodeBlk  = false;
            msb_is_in_QuoteBlk = false;

            // まず、Lexed_MD をエラー状態で書き込んでおく(エラーがあったときは、例外で外に飛んでいくため)
            ms_write_WS_buf = dst_wrt_WS_buf;
            ms_write_WS_buf.Wrt_ID_param(ID.Lexed_MD, Param.EN_Failed);

            ms_write_WS_buf.Clear_Txt_flags();

            // ---------------------------------------------------------
            // 1行ごとに字句解析を実行する
            fixed(byte *pstr_MD_top = ms_MD_buf)
            {
                ushort *psrc = (ushort *)(pstr_MD_top + 2);  // +2 は、utf-16le の BOM

                while (true)
                {
                    // Consume_Line() は、次の行頭を返してくる
                    psrc = Consume_Line(psrc);
                    // 行頭が \0 であるとき、ファイル読み取りが終了したと判断する
                    // エラーの場合は、例外処理で返される
                    if (*psrc == 0)
                    {
                        break;
                    }
                }
            }

            MainForm.StdOut($"変換後のサイズ : {ms_write_WS_buf.Get_idx_byte_cur().ToString("N0")}\r\n");

            // Write_WS_Buffer で THROW_ERR() がコールされた場合、ID_End が既に書き込まれている
            // ここに来た場合、Lexing に成功している
            ms_write_WS_buf.Wrt_ID_param_At(0, ID.Lexed_MD, Param.EN_Succeeded);
            ms_write_WS_buf.Wrt_ID_End();
        }
예제 #2
0
            // ------------------------------------------------------------------------------------
            // m_files_in_dir のみが Update される(m_dirs_in_dir はチェックされないため注意)
            public void Update_and_DirFileList(Write_WS_Buffer send_WS_buf, bool bNeed_DirNames)
            {
                m_SEC_Updated = (int)((DateTime.Now.Ticks - ms_base_tick) / 10_000_000);
                send_WS_buf.Wrt_Num_int(m_SEC_Updated);

                // ---------------------------------------------------------
                // ディレクトリ名の設定
                if (bNeed_DirNames == true)
                {
                    send_WS_buf.Wrt_ID_param(ID.Directory_Names, (byte)m_dirs_in_dir.Count);
                    foreach (string dname in m_dirs_in_dir)
                    {
                        send_WS_buf.Wrt_PStr(dname);
                    }
                }

                // ---------------------------------------------------------
                // ファイル名の設定
                {
                    // ID.File_Names は、ディレクトリの個数が分かってから書き込む
                    int idx_byte_AtFName = send_WS_buf.Get_idx_byte_cur();
                    send_WS_buf.Skip_Wrt_ID();

                    var files = Directory.EnumerateFiles(mc_str_path_dir);
                    int cnt   = 0;
                    m_exist_check_cnt++;              // 存在確認用のカウンタを1つ進める
                    foreach (string fpath in files)
                    {
                        // md ファイル以外であれば処理しない
                        if (IsMdFile(fpath) == false)
                        {
                            continue;
                        }

                        string fname = Get_FName(fpath, true);

                        if (m_files_in_dir.ContainsKey(fname) == true)
                        {
                            m_files_in_dir[fname] = m_exist_check_cnt;
                        }
                        else
                        {
                            m_files_in_dir.Add(fname, m_exist_check_cnt);
#if DBG_LOG_FileLister
                            MainForm.DBG_StdOut($"【DBG_LOG_FileLister】Update() でファイル追加 -> {fname}\r\n");
#endif
                        }

                        send_WS_buf.Wrt_PStr(fname);
                        cnt++;
                    }
                    if (cnt > 255)
                    {
                        throw new Exception("ファイルの個数が 255 個を超えています。");
                    }

                    // cnt == 0 であっても、ファイルの削除処理が必要である場合もあるため注意
                    send_WS_buf.Wrt_ID_param_At(idx_byte_AtFName, ID.File_Names, (byte)cnt);

                    // 存在しなくなったファイル名を削除する
                    if (m_files_in_dir.Count == 0)
                    {
                        return;
                    }                                                       // m_files_in_dir が空であるときは、何もしなくて良い

                    var it                      = m_files_in_dir.GetEnumerator();
                    int idx_of_files            = 0;
                    int rem_remove_idx_ary      = ms_remove_idx_ary_pcs;
                    int idx_next_on_rmv_idx_ary = 0;

                    // イテレータを利用している間はコンテナの削除等ができないため、削除対象の idx のみを記録していく
                    while (it.MoveNext())
                    {
                        if (it.Current.Value != m_exist_check_cnt)
                        {
                            if (rem_remove_idx_ary == 0)
                            {
                                ms_remove_idx_ary_pcs += 10;
                                Array.Resize(ref msa_remove_idx_ary, ms_remove_idx_ary_pcs);
                                rem_remove_idx_ary = 10;
                            }

                            msa_remove_idx_ary[idx_next_on_rmv_idx_ary++] = idx_of_files;
                            rem_remove_idx_ary--;

                            // リムーブ対象に登録した時点で、リムーブされることを通知する
                            // もし、Lexed されたデータが残っていたら削除すること
                            ms_INtfy_DeleteFile.Ntfy_DeleteFile(mc_str_path_dir + it.Current.Key);
                        }

                        idx_of_files++;
                    }

                    // リムーブを実行する
                    // RemoveAt は後ろ側から実行する必要がある(前の方を削除すると、インデックス値が変わるため)
                    for (int idx_on_rmv_idx_ary = idx_next_on_rmv_idx_ary; idx_on_rmv_idx_ary > 0;)
                    {
                        int idx_of_files_to_rmv = msa_remove_idx_ary[--idx_on_rmv_idx_ary];
                        m_files_in_dir.RemoveAt(idx_of_files_to_rmv);
                    }
                }
            }
예제 #3
0
// ------------------------------------------------------------------------------------
        public async Task Spawn_Context(HttpListenerContext context, uint idx_context)
        {
            // AcceptWebSocketAsync() は、キャンセルトークンをサポートしていない
            // 引数: サポートされている WebSocket サブプロトコル
            HttpListenerWebSocketContext wsc = await context.AcceptWebSocketAsync(null);

            MainForm.StdOut("--- WebSocket 接続完了\r\n");

            using (m_WS = wsc.WebSocket)
                using (WS_Buf_Pool.MemBlock mem_blk = WS_Buf_Pool.Lease_MemBlock())
                {
                    m_read_WS_buf  = new Read_WS_Buf(mem_blk.m_ary_buf);
                    m_write_WS_buf = new Write_WS_Buffer(mem_blk.m_ary_buf);

                    try
                    {
                        // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#if CREATE_TEST_LEXED_CODE
                        // Test Lexed Code を送信する
                        Write_WS_Buffer write_ws_buf = MainForm.ms_DBG_write_WS_buf;
                        await m_WS.SendAsync(
                            new ArraySegment <byte>(write_ws_buf.Get_buf(), 0, write_ws_buf.Get_idx_byte_cur())
                            , WebSocketMessageType.Binary, true, ms_cts_shutdown.Token);
#else
                        // まずはルートフォルダのファイル情報を送信しておく
                        FileLister.Set_DirFileNames(m_write_WS_buf, "./");
                        await m_write_WS_buf.SendAsync(m_WS, ms_cts_shutdown);
#endif

                        while (true)
                        {
                            WebSocketReceiveResult rslt = await m_WS.ReceiveAsync(
                                new ArraySegment <byte>(mem_blk.m_ary_buf), ms_cts_shutdown.Token);

                            if (rslt.EndOfMessage == false)
                            {
                                MainForm.StdOut("--- 不正な大きさのデータを受信しました。クライアントを切断します\r\n");
                                break;
                            }
                            if (m_WS.State == WebSocketState.CloseReceived)
                            {
                                MainForm.StdOut("--- クライアントが接続を Close しました\r\n");
                                break;
                            }

                            m_read_WS_buf.Renew(rslt.Count);
                            switch (m_read_WS_buf.Read_ID())
                            {
                            case ID.DirFileList: {
                                ID id = m_read_WS_buf.Read_ID();
                                if (id != ID.Text)
                                {
                                    throw new Exception($"不正なパラメータを受信 DirFileList / id -> {((byte)id).ToString()}");
                                }

                                FileLister.Set_DirFileNames(m_write_WS_buf, m_read_WS_buf.Get_text_cur());
                                await m_write_WS_buf.SendAsync(m_WS, ms_cts_shutdown);
                            } continue;

                            case ID.Files_inDir: {
                                ID id = m_read_WS_buf.Read_ID();
                                if (id != ID.Text)
                                {
                                    throw new Exception($"不正なパラメータを受信 Files_inDir / id -> {((byte)id).ToString()}");
                                }

                                string str_path_dir = m_read_WS_buf.Get_text_cur();

                                id = m_read_WS_buf.Read_ID();
                                if (id != ID.Num_int)
                                {
                                    throw new Exception($"不正なパラメータを受信 Files_inDir / id -> {((byte)id).ToString()}");
                                }

                                int SEC_Updated_recv = m_read_WS_buf.Get_Num_int();

                                FileLister.OnFiles_inDir(m_write_WS_buf, str_path_dir, SEC_Updated_recv);
                                await m_write_WS_buf.SendAsync(m_WS, ms_cts_shutdown);
                            } continue;

                            case ID.MD_file: {
                                var(path_md_file, SEC_Updated, idx_byte_SEC_updated) = m_read_WS_buf.Read_Req_MD();
                                MainForm.StdOut($"path_md_file : {path_md_file} / SEC_Updated : {SEC_Updated.ToString()}\r\n");

                                // ID.MD_file -> ID_Text (path_dir) -> ID_Text (file name) は Receive時の値を流用
                                m_write_WS_buf.Set_idx_byte(idx_byte_SEC_updated);
                                m_write_WS_buf.Wrt_Num_int(1000);          // 1000 は試験値

                                Lexer.LexFile(m_write_WS_buf, path_md_file);
                                MainForm.StdOut("--- Lexing 処理完了\r\n");

                                m_write_WS_buf.Simplify_Buf();
                                MainForm.StdOut("--- Simplify_Buf 処理完了\r\n");

                                await m_write_WS_buf.SendAsync(m_WS, ms_cts_shutdown);
                            } continue;
                            }



                            MainForm.StdOut($"--- ReceiveAsync() : 受信バイト数 -> {rslt.Count}\r\n");
                            MainForm.HexDump(mem_blk.m_ary_buf, 0, 20);
                            DBG_WS_Buffer.Show_WS_buf(MainForm.ms_RBox_stdout, mem_blk.m_ary_buf, rslt.Count);



                            // 今は、index.md のみを解析するようにしている
//				string ret_str = Lexer.LexFile(m_write_WS_buf, "md_root/index.md");

//				string str_recv = ms_utf16_encoding.GetString(mem_blk.m_ary_buf, 0, rslt.Count);
//				MainForm.StdOut(str_recv);
                        }

                        await m_WS.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "接続を終了します", ms_cts_shutdown.Token);
                    }
                    catch (OperationCanceledException)
                    {
                        MainForm.StdOut("--- サーバーシャットダウンのシグナルを受信しました\r\n");
                    }
                    catch (WebSocketException ex)
                    {
                        MainForm.StdOut($"!!! 例外発を補足しました WebSoketErrorCode : {ex.WebSocketErrorCode.ToString()}\r\n");
                        MainForm.StdOut($"    {ex.ToString()}\r\n");
                    }
                    catch (Exception ex)
                    {
                        MainForm.StdOut($"!!! 例外を補足しました : {ex.ToString()}\r\n");
                    }
                }

            MdSvr.Remove_task_context(idx_context);
            MainForm.StdOut("--- WebSocket 切断完了\r\n");
        }