<commit_before>//   Copyright 2015 Patrick Putnam
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
#ifndef CLOTHO_ROW_GROUPED_CROSSOVER_METHOD_HPP_
#define CLOTHO_ROW_GROUPED_CROSSOVER_METHOD_HPP_

#include "clotho/data_spaces/crossover/crossover_method_def.hpp"
#include "clotho/data_spaces/association_matrix/row_grouped_association_matrix.hpp"

#include "clotho/data_spaces/generators/small_crossover_event_generator.hpp"
#include "clotho/utility/bit_helper.hpp"
#include "clotho/utility/debruijn_bit_walker.hpp"

namespace clotho {
namespace genetics {

template < class RNG, class AlleleSpaceType, class BlockType >
class crossover_method< RNG, AlleleSpaceType, association_matrix< BlockType, row_grouped< 2 > > > {
public:
    typedef RNG                                                 random_engine_type;
    typedef AlleleSpaceType                                     allele_type;
    typedef association_matrix< BlockType, row_grouped< 2 > >     sequence_space_type;

    typedef typename sequence_space_type::raw_block_pointer     sequence_iterator;
    typedef typename sequence_space_type::raw_block_pointer     genome_iterator;

    typedef typename allele_type::position_type                 position_type;

    typedef crossover_event_generator< RNG, position_type >     event_generator_type;

    typedef typename sequence_space_type::block_type            block_type;
    typedef clotho::utility::debruijn_bit_walker< block_type >  bit_walker_type;
    typedef clotho::utility::BitHelper< block_type >            bit_helper_type;

    crossover_method( RNG * rng, boost::property_tree::ptree & config ) :
        m_event_gen( rng, config )
    {}

    void initAlleles( allele_type & alls ) {
        m_event_gen.update( alls.getPositions(), alls.size());
    }

    void crossover( genome_iterator start, genome_iterator end, sequence_iterator s, size_t p_step, size_t s_step ) {

        size_t N = m_event_gen.generate();

        if( N != 0 ) {
            size_t j = 0;
            while( start != end ) {
                block_type first = *start++;
                block_type second = *start++;

                block_type hets = first ^ second;
                block_type sec  = bit_helper_type::ALL_UNSET;   // mask state from second strand

                while( hets ) {
                    size_t idx = bit_walker_type::unset_next_index( hets ) + j;

                    if( m_event_gen( idx ) ) {
                        sec |= bit_helper_type::bit_offset( idx );
                    }
                }

                *s = ((first & ~sec) | (second & sec));

                j += bit_helper_type::BITS_PER_BLOCK;

                s += row_grouped< 2 >::GROUP_SIZE;
            }
        } else {
            if( m_event_gen.getBaseSequence() != 0 ) {

                ++start;
                ++end;
            }

            size_t j = 0;
            while( start != end ) {
                *s = *start;

                start += row_grouped< 2 >::GROUP_SIZE;
                s += row_grouped< 2 >::GROUP_SIZE;

                j += bit_helper_type::BITS_PER_BLOCK;
            }
        }
    }

    virtual ~crossover_method() {}

protected:
    event_generator_type m_event_gen;
};

template < class RNG, class AlleleSpaceType, class BlockType >
class crossover_method< RNG, AlleleSpaceType, association_matrix< BlockType, row_grouped< 1 > > > {
public:
    typedef RNG                                                 random_engine_type;
    typedef AlleleSpaceType                                     allele_type;
    typedef association_matrix< BlockType, row_grouped< 1 > >   sequence_space_type;

    typedef typename sequence_space_type::raw_block_pointer     sequence_iterator;
    typedef typename sequence_space_type::raw_block_pointer     genome_iterator;

    typedef typename allele_type::position_type                 position_type;

    typedef small_crossover_event_generator< RNG, position_type >     event_generator_type;

    typedef typename sequence_space_type::block_type            block_type;
    typedef clotho::utility::debruijn_bit_walker< block_type >  bit_walker_type;
    typedef clotho::utility::BitHelper< block_type >            bit_helper_type;

    crossover_method( RNG * rng, boost::property_tree::ptree & config ) :
        m_event_gen( rng, config )
    {}

    void initAlleles( allele_type & alls ) {
        m_event_gen.update( alls.getPositions(), alls.size() );
    }

    void crossover( genome_iterator start, genome_iterator end, sequence_iterator s, size_t p_step, size_t s_step ) {

        size_t N = m_event_gen.generate();

        genome_iterator sec_ptr = end;
        if( N != 0 ) {
            size_t j = 0;
            while( start != end ) {
                block_type first = *start++;
                block_type second = *sec_ptr++;

                block_type hets = first ^ second;
                block_type sec  = bit_helper_type::ALL_UNSET;   // mask state from second strand

                while( hets ) {
                    size_t idx = bit_walker_type::unset_next_index( hets ) + j;

                    if( m_event_gen( idx ) ) {
                        sec |= bit_helper_type::bit_offset( idx );
                    }
                }

                *s++ = ((first & ~sec) | (second & sec));

                j += bit_helper_type::BITS_PER_BLOCK;
            }
        } else {
            size_t N = (end - start);

            if( m_event_gen.getBaseSequence() != 0 ) {
                // use second strand
                start = end;
            }

            for( size_t i = 0; i < N; ++i )
                s[i] = start[i];
//            size_t i = 0;
//            size_t M = N % 4;
//            while( i < M ) {
//                s[i] = start[i];
//                ++i;
//            }
//
//            while( i < N ) {
//                s[ i ] = start[ i ];
//                s[ i + 1 ] = start[i + 1];
//                s[ i + 2 ] = start[i + 2 ];
//                s[ i + 3 ] = start[i + 3 ];
//                i += 4;
//            }
//
        }
    }

    virtual ~crossover_method() {}

protected:
    event_generator_type m_event_gen;
};
}   // namespace genetics
}   // namespace clotho

#endif  // CLOTHO_ROW_GROUPED_CROSSOVER_METHOD_HPP_
<commit_msg>Modified to cleanup code.<commit_after>//   Copyright 2015 Patrick Putnam
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
#ifndef CLOTHO_ROW_GROUPED_CROSSOVER_METHOD_HPP_
#define CLOTHO_ROW_GROUPED_CROSSOVER_METHOD_HPP_

#include "clotho/data_spaces/crossover/crossover_method_def.hpp"
#include "clotho/data_spaces/association_matrix/row_grouped_association_matrix.hpp"

#include "clotho/data_spaces/generators/small_crossover_event_generator.hpp"
#include "clotho/utility/bit_helper.hpp"
#include "clotho/utility/debruijn_bit_walker.hpp"

namespace clotho {
namespace genetics {

template < class RNG, class AlleleSpaceType, class BlockType >
class crossover_method< RNG, AlleleSpaceType, association_matrix< BlockType, row_grouped< 2 > > > {
public:
    typedef RNG                                                 random_engine_type;
    typedef AlleleSpaceType                                     allele_type;
    typedef association_matrix< BlockType, row_grouped< 2 > >     sequence_space_type;

    typedef typename sequence_space_type::raw_block_pointer     sequence_iterator;
    typedef typename sequence_space_type::raw_block_pointer     genome_iterator;

    typedef typename allele_type::position_type                 position_type;

    typedef crossover_event_generator< RNG, position_type >     event_generator_type;

    typedef typename sequence_space_type::block_type            block_type;
    typedef clotho::utility::debruijn_bit_walker< block_type >  bit_walker_type;
    typedef clotho::utility::BitHelper< block_type >            bit_helper_type;

    crossover_method( RNG * rng, boost::property_tree::ptree & config ) :
        m_event_gen( rng, config )
    {}

    void initAlleles( allele_type & alls ) {
        m_event_gen.update( alls.getPositions(), alls.size());
    }

    void crossover( genome_iterator start, genome_iterator end, sequence_iterator s, size_t p_step, size_t s_step ) {

        size_t N = m_event_gen.generate();

        if( N != 0 ) {
            size_t j = 0;
            while( start != end ) {
                block_type first = *start++;
                block_type second = *start++;

                block_type hets = first ^ second;
                block_type sec  = bit_helper_type::ALL_UNSET;   // mask state from second strand

                while( hets ) {
                    size_t idx = bit_walker_type::unset_next_index( hets ) + j;

                    if( m_event_gen( idx ) ) {
                        sec |= bit_helper_type::bit_offset( idx );
                    }
                }

                *s = ((first & ~sec) | (second & sec));

                j += bit_helper_type::BITS_PER_BLOCK;

                s += row_grouped< 2 >::GROUP_SIZE;
            }
        } else {
            if( m_event_gen.getBaseSequence() != 0 ) {

                ++start;
                ++end;
            }

            size_t j = 0;
            while( start != end ) {
                *s = *start;

                start += row_grouped< 2 >::GROUP_SIZE;
                s += row_grouped< 2 >::GROUP_SIZE;

                j += bit_helper_type::BITS_PER_BLOCK;
            }
        }
    }

    virtual ~crossover_method() {}

protected:
    event_generator_type m_event_gen;
};

template < class BlockType >
struct base_crossover_method {
    inline BlockType operator()( const BlockType & a, const BlockType & b, const BlockType & c) const {
        return ((a & ~c) | (b & c));
    }
};

template < class BlockType >
struct alt_crossover_method {
    inline BlockType operator()( const BlockType & a, const BlockType & b, const BlockType & c) const {
        return ((a & c) | (b & ~c));
    }
};

template < class RNG, class AlleleSpaceType, class BlockType >
class crossover_method< RNG, AlleleSpaceType, association_matrix< BlockType, row_grouped< 1 > > > {
public:
    typedef RNG                                                 random_engine_type;
    typedef AlleleSpaceType                                     allele_type;
    typedef association_matrix< BlockType, row_grouped< 1 > >   sequence_space_type;

    typedef typename sequence_space_type::raw_block_pointer     sequence_iterator;
    typedef typename sequence_space_type::raw_block_pointer     genome_iterator;

    typedef typename allele_type::position_type                 position_type;

    typedef small_crossover_event_generator< RNG, position_type >     event_generator_type;

    typedef typename sequence_space_type::block_type            block_type;
    typedef clotho::utility::debruijn_bit_walker< block_type >  bit_walker_type;
    typedef clotho::utility::BitHelper< block_type >            bit_helper_type;

    typedef base_crossover_method< block_type >                 base_method;
    typedef alt_crossover_method< block_type >                  alt_method;

    crossover_method( RNG * rng, boost::property_tree::ptree & config ) :
        m_event_gen( rng, config )
    {}

    void initAlleles( allele_type & alls ) {
        m_event_gen.update( alls.getPositions(), alls.size() );
    }

    void crossover( genome_iterator start, genome_iterator end, sequence_iterator s, size_t p_step, size_t s_step ) {

        genome_iterator sec_ptr = end;
        if( m_event_gen.generate() != 0 ) {
            if( m_event_gen.getBaseSequence() == 0 ) {
                base_method met;
                build_sequence( s, start, end, met );
            } else {
                alt_method met;
                build_sequence(s, start, end, met );
            }
        } else {
            const size_t W = (end - start);

            if( m_event_gen.getBaseSequence() != 0 ) {
                // use second strand
                copy_sequence( s, end, W );
            } else {
                copy_sequence( s, start, W );
            }
        }
    }

    virtual ~crossover_method() {}

protected:

    template < class Method >
    void build_sequence( sequence_iterator s, genome_iterator start, genome_iterator end, const Method & m ) {
        size_t j = 0;
        genome_iterator sec_ptr = end;
        while( start != end ) {
            block_type first = *start++;
            block_type second = *sec_ptr++;

            block_type hets = first ^ second;
            block_type sec  = bit_helper_type::ALL_UNSET;   // mask state from second strand

            while( hets ) {
                size_t idx = bit_walker_type::unset_next_index( hets );

                if( m_event_gen( idx + j ) ) {
                    sec |= clotho::utility::bit_masks[ idx ];
                }
            }

            *s++ = m(first, second, sec);

            j += bit_helper_type::BITS_PER_BLOCK;
        }
    }

    void copy_sequence( sequence_iterator s, genome_iterator start, const size_t W ) {
        size_t i = 0;
        switch( W % 4 ) {
            case 3:
                s[i] = start[i];
                ++i;
            case 2:
                s[i] = start[i];
                ++i;
            case 1:
                s[i] = start[i];
                ++i;
            default:
                break;
        }

        while( i < W ) {
            s[ i ] = start[i];
            s[ i + 1 ] = start[i + 1];
            s[ i + 2 ] = start[i + 2];
            s[ i + 3 ] = start[i + 3];
            i += 4;
        }
    }

    event_generator_type m_event_gen;
};
}   // namespace genetics
}   // namespace clotho

#endif  // CLOTHO_ROW_GROUPED_CROSSOVER_METHOD_HPP_
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *  Manjeet Dahiya
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "QXmppVersionManager.h"
#include "QXmppOutgoingClient.h"

QXmppVersionManager::QXmppVersionManager(QXmppOutgoingClient* stream, QObject *parent)
    : QObject(parent),
    m_stream(stream)
{
//    bool check = QObject::connect(m_stream, SIGNAL(versionIqReceived(const QXmppVersionIq&)),
//        this, SLOT(versionIqReceived(const QXmppVersionIq&)));
//    Q_ASSERT(check);
//    Q_UNUSED(check);
}

void QXmppVersionManager::versionIqReceived(const QXmppVersionIq& verIq)
{
    emit versionReceived(verIq);
}
<commit_msg>make connection<commit_after>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *  Manjeet Dahiya
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "QXmppVersionManager.h"
#include "QXmppOutgoingClient.h"

QXmppVersionManager::QXmppVersionManager(QXmppOutgoingClient* stream, QObject *parent)
    : QObject(parent),
    m_stream(stream)
{
    bool check = QObject::connect(m_stream, SIGNAL(versionIqReceived(const QXmppVersionIq&)),
        this, SLOT(versionIqReceived(const QXmppVersionIq&)));
    Q_ASSERT(check);
    Q_UNUSED(check);
}

void QXmppVersionManager::versionIqReceived(const QXmppVersionIq& verIq)
{
    emit versionReceived(verIq);
}
<|endoftext|>


<commit_before>/* JaneClone - a text board site viewer for 2ch
 * Copyright (C) 2012 Hiroyuki Nagata
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Contributor:
 *	Hiroyuki Nagata <newserver002@gmail.com>
 */

#include "SocketCommunication.h"
/**
 * 板一覧ファイルをダウンロードしてくるメソッド 引数は板一覧ファイル保存先、板一覧ファイルヘッダ保存先
 */
int SocketCommunication::DownloadBoardList(const wxString outputPath,
		const wxString headerPath) {

	// 実行コード
	int rc = 0;
	// 拡張子をgzipに変える
	wxString gzipPath = outputPath;
	gzipPath.Replace(wxT(".html"), wxT(".gzip"));
	// 一時保存用ファイルのパスを設定する
	wxString tmpPath = wxT("./dat/tmp.html");

	// 解凍された板一覧情報が存在しないor前回の通信ログが残っていないならば通常通りソケット通信を行う
	if ((!wxFileExists(outputPath)) || (!wxFileExists(headerPath))) {
		rc = DownloadBoardListNew(gzipPath, headerPath);
		// そうでなければ前回の通信の差分を取得しに行く
	} else {
		rc = DownloadBoardListMod(gzipPath, headerPath);
	}

	// gzip拡張子のファイルがあれば、ファイルの解凍・UTF化を行う
	if (wxFile::Exists(gzipPath)) {
		JaneCloneUtil::DecommpressFile(gzipPath, tmpPath);
		JaneCloneUtil::ConvertSJISToUTF8(tmpPath, (wxString&) outputPath);
	}
	// 更新が終わったらgzipファイルとSJISファイルを消しておく
	RemoveTmpFile(gzipPath);
	RemoveTmpFile(tmpPath);

	return rc;
}

/**
 * 新規に板一覧情報を取得しに行く
 */
int SocketCommunication::DownloadBoardListNew(const wxString outputPath,
		const wxString headerPath) {
	// 実行コード
	int rc = 0;

	wxHTTP http;
	http.SetHeader(_T("Accept-Encoding"), _T("gzip"));
	http.SetHeader(_T("Host"), _T("menu.2ch.net"));
	http.SetHeader(_T("Accept"), _T(""));
	http.SetHeader(_T("Referer"), _T("http://menu.2ch.net/"));
	http.SetHeader(_T("Accept-Language"), _T("ja"));
	http.SetHeader(_T("User-Agent"), _T("Mozilla/5.0"));
	http.SetTimeout(5);

	wxString server = "menu.2ch.net";
	wxString path = "/bbsmenu.html";
	wxString msg = "";

	// 保存先を決める
	wxFileOutputStream output(outputPath);
	wxDataOutputStream store(output);

	if (http.Connect(server, 80)) {
		wxInputStream *stream;
		stream = http.GetInputStream(path);

		if (stream == NULL) {
			return -1;
		} else {
			unsigned char buffer[1024];
			int byteRead;
			int totalRead;
			totalRead = 0;

			// ヘッダを読み出す
			cout << http.GetResponse() << endl;
			cout << http.GetHeader(wxT("Date")) << endl;
			cout << http.GetHeader(wxT("Server")) << endl;
			cout << http.GetHeader(wxT("Last-Modified")) << endl;
			cout << http.GetHeader(wxT("ETag")) << endl;
			cout << http.GetHeader(wxT("Accept-Ranges")) << endl;
			cout << http.GetHeader(wxT("Content-Length")) << endl;
			cout << http.GetHeader(wxT("Connection")) << endl;
			cout << http.GetContentType() << endl;

			// ストリームを受け取るループ部分
			while (!stream->Eof()) {
				stream->Read(buffer, sizeof(buffer));
				store.Write8(buffer, sizeof(buffer));
				byteRead = stream->LastRead();
				if (byteRead <= 0) {
					break;
				}
				totalRead += byteRead;
			}
			wxString stringInt = wxString::Format(wxT("%i"), totalRead);
			stringInt += wxT("バイト読み込みました。");
			msg = stringInt;
		}
	} else {
		msg = wxT("サーバーに接続できませんでした");
	}

	cout << msg << endl;

	return rc;
}
/**
 * 前回との差分を取得しに行く
 */
int SocketCommunication::DownloadBoardListMod(const wxString outputPath,
		const wxString headerPath) {
	// 実行コード
	int rc = 0;
	// 最終更新日時をヘッダ情報から取得する
	wxString lastModifiedTime = CheckLastModifiedTime(headerPath);
	// バイナリとヘッダは前回取得した名前と同じでは困るのでtmpファイルとして作成しておく
	wxString tmpOutputPath = outputPath;
	tmpOutputPath += wxT(".tmp");
	wxString tmpHeaderPath = headerPath;
	tmpHeaderPath += wxT(".tmp");

	// 304かどうか判断するためのフラグ
	bool mod_flag = false;
	// ヘッダを取り除くためのフラグ
	bool flag = false;
	// gzipのヘッダ作成
	char HEX[] = { 0x1f, 0x8b, 0x08, 0x00 };

	// gimiteによる通信開始
	gimite::startup_socket();
	{
		// menu.2ch.netのポート80(HTTP)に接続。
		gimite::socket_stream sst("menu.2ch.net", 80);
		//エラーチェック。
		if (!sst) {
			std::cerr << "Failed to connect." << std::endl;
		} else {
			//文字列を送信。
			sst << "GET /bbsmenu.html HTTP/1.1 \r\n";
			sst << "Accept-Encoding: gzip \r\n";
			sst << "Host: menu.2ch.net \r\n";
			sst << "If-Modified-Since:" << lastModifiedTime.mb_str() << "\r\n";
			sst << "Accept: */* \r\n";
			sst << "Referer: http://menu.2ch.net/ \r\n";
			sst << "Accept-Language: ja \r\n";
			sst << "User-Agent: Monazilla/1.00 (monaweb/1.00) \r\n";
			sst << "Connection: close \r\n";
			sst << "\r\n";

			// 受信用文字列
			std::string s;

			// ファイルに書き出す(バイナリ部分)
			wxCharBuffer binaryFile = tmpOutputPath.ToUTF8();
			std::ofstream ofs(binaryFile.data(),
					std::ios::binary | std::ios::trunc);
			// ファイルに書き出す(ヘッダ部分)
			wxCharBuffer headerFile = tmpHeaderPath.ToUTF8();
			std::ofstream ofsh(headerFile.data(), std::ios::trunc);

			/** 1行目に「HTTP/1.1 304 Not Modified」が含まれない場合のみ更新を行う */
			while (std::getline(sst, s)) {

				/** 更新フラグ立たず・ヘッダ部分 */
				if (!mod_flag && !flag) {
					unsigned int loc = s.find("304 Not Modified");
					// １行目の読み出しで304があればbreak
					if (loc != std::string::npos) {
						ofs.close();
						ofsh.close();
						// tmpファイルは消しておく
						RemoveTmpFile(tmpOutputPath);
						RemoveTmpFile(tmpHeaderPath);
						break;
						// そうでなければファイルストリームの準備をする
					} else {
						// 更新フラグを立てる
						mod_flag = true;
						// ヘッダーを書きだす（更新）
						ofsh << s;
					}

					/** 更新フラグ立つ・ヘッダ部分 */
				} else if (mod_flag && !flag) {
					unsigned int loc = s.find(*HEX, 0);
					if (loc != std::string::npos) {
						ofs << s << std::endl;
						flag = true;
					} else {
						// ヘッダーを書きだす（更新）
						ofsh << s;
					}
					/** 更新フラグ立つ・ボディ部分 */
				} else if (mod_flag && flag) {
					ofs << s << std::endl;
				}
			}
		}
		// gimiteによる通信終了
		gimite::cleanup_socket();

		// 更新が最後までうまく行った場合以前のファイルを削除する
		if (mod_flag && flag) {
			RemoveTmpFile(outputPath);
			RemoveTmpFile(headerPath);
			// tmpファイルを本物のファイルとする
			wxRenameFile(tmpOutputPath, outputPath);
			wxRenameFile(tmpHeaderPath, headerPath);
		}
	}

	return rc;
}

/**
 * 前回の通信ログが存在すれば、最後に取得した日時を変数に格納する
 */
wxString SocketCommunication::CheckLastModifiedTime(const wxString headerPath) {
	wxString lastGetTime = wxT("");

	// ログを読み込む
	wxTextFile file(headerPath);
	file.Open(wxConvUTF8);
	wxString line;

	if (file.IsOpened()) {
		// ログの中身を1行ずつ走査
		for (line = file.GetFirstLine(); !file.Eof();
				line = file.GetNextLine()) {
			if (line.Contains(wxT("Last-Modified:"))) {
				lastGetTime = line.Mid(14);
				break;
			}
		}
		// ファイルのクローズを行う
		file.Close();
		return lastGetTime;

	} else {
		std::cout << "ファイルのオープンに失敗しました" << std::endl;
	}
}

/**
 * スレッド一覧をダウンロードしてくるメソッド
 * @param 板名,URL,サーバー名
 * @return datファイル保存先
 */
wxString SocketCommunication::DownloadThreadList(const wxString & boardName,
		const wxString & boardURL, const wxString & boardNameAscii) {

	// 実行コード
	int rc = 0;
	// 出力するファイルの名前
	wxString outputFileName = boardNameAscii;
	outputFileName += wxT(".dat");
	// 出力先のファイルパスを設定する
	wxString outputFilePath = wxT("./dat/");
	outputFilePath += boardNameAscii;
	outputFilePath += wxT("/");

	// 保存用フォルダ存在するか確認。無ければフォルダを作成
	if (!wxFile::Exists(outputFilePath)) {
		::wxMkdir(outputFilePath);
	}
	outputFilePath += outputFileName;
	// gzip用のパスを設定する
	wxString gzipPath = outputFilePath;
	gzipPath.Replace(wxT(".dat"), wxT(".gzip"));
	// ヘッダーのパスを設定する
	wxString headerPath = outputFilePath;
	headerPath.Replace(wxT(".dat"), wxT(".header"));

	// 解凍された板一覧情報が存在しないor前回の通信ログが残っていないならば通常通りソケット通信を行う
	if ((!wxFileExists(outputFilePath)) || (!wxFileExists(headerPath))) {
		rc = DownloadThreadListNew((const wxString) gzipPath,
				(const wxString) headerPath);
		// そうでなければ前回の通信の差分を取得しに行く
	} else {
		rc = DownloadThreadListNew((const wxString) gzipPath,
				(const wxString) headerPath);
	}

	// gzip拡張子のファイルがあれば、ファイルの解凍を行う
	if (wxFile::Exists(gzipPath)) {
		JaneCloneUtil::DecommpressFile(gzipPath, outputFilePath);
	}
	// 更新が終わったらgzipファイルを消しておく
	RemoveTmpFile(gzipPath);

	return outputFileName;
}

/**
 * 新規にスレッド一覧をダウンロードしてくるメソッド
 * @param 板名,URL,サーバー名
 * @return 実行コード
 */
int SocketCommunication::DownloadThreadListNew(const wxString& gzipPath,
		const wxString& headerPath) {
	int rc = 0;

	return rc;
}

/**
 * 前回との差分のスレッド一覧をダウンロードしてくるメソッド
 * @param 板名,URL,サーバー名
 * @return 実行コード
 */
int SocketCommunication::DownloadThreadListMod(const wxString& gzipPath,
		const wxString& headerPath) {
	int rc = 0;

	return rc;
}

/**
 * 一時ファイルを消す
 */
void SocketCommunication::RemoveTmpFile(const wxString removeFile) {
	if (wxFile::Exists(removeFile)) {
		wxRemoveFile(removeFile);
	}
}

/**
 * HTTPヘッダを書きだす
 */
void SocketCommunication::WriteHeaderFile(const wxHTTP & http,
		const wxString & headerPath) {

	// ヘッダファイルの書き出し先を作る
	wxTextFile headerFile(headerPath);

	// 既にファイルが存在するならば中身を消す
	if (headerFile.Exists()) {
		headerFile.Open(wxConvUTF8);
		headerFile.Clear();
	// 存在しないなら作成する
	} else {
		headerFile.Create();
	}

	// ヘッダの内容を書きだしていく
	wxString status = wxT("HTTP1.1/ ");
	status += wxString::Format(_T("%d"), http.GetResponse());
	headerFile.AddLine(status, TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetHeader(wxT("Date")),TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetHeader(wxT("Server")),TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetHeader(wxT("Last-Modified")),TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetHeader(wxT("ETag")),TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetHeader(wxT("Accept-Ranges")),TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetHeader(wxT("Content-Length")),TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetHeader(wxT("Connection")),TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetContentType(),TEXT_ENDLINE_TYPE);

	// 書きだした内容を保存する
	headerFile.Write(wxTextFileType_None, wxConvUTF8);
	headerFIle.Close();
}

<commit_msg>板一覧情報の更新をwxのみを使って実装した<commit_after>/* JaneClone - a text board site viewer for 2ch
 * Copyright (C) 2012 Hiroyuki Nagata
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Contributor:
 *	Hiroyuki Nagata <newserver002@gmail.com>
 */

#include "SocketCommunication.h"
/**
 * 板一覧ファイルをダウンロードしてくるメソッド 引数は板一覧ファイル保存先、板一覧ファイルヘッダ保存先
 */
int SocketCommunication::DownloadBoardList(const wxString outputPath,
		const wxString headerPath) {

	// 実行コード
	int rc = 0;
	// 拡張子をgzipに変える
	wxString gzipPath = outputPath;
	gzipPath.Replace(wxT(".html"), wxT(".gzip"));
	// 一時保存用ファイルのパスを設定する
	wxString tmpPath = wxT("./dat/tmp.html");

	// 解凍された板一覧情報が存在しないor前回の通信ログが残っていないならば通常通りソケット通信を行う
	if ((!wxFileExists(outputPath)) || (!wxFileExists(headerPath))) {
		rc = DownloadBoardListNew(gzipPath, headerPath);
		// そうでなければ前回の通信の差分を取得しに行く
	} else {
		rc = DownloadBoardListMod(gzipPath, headerPath);
	}

	// gzip拡張子のファイルがあれば、ファイルの解凍・UTF化を行う
	if (wxFile::Exists(gzipPath)) {
		JaneCloneUtil::DecommpressFile(gzipPath, tmpPath);
		JaneCloneUtil::ConvertSJISToUTF8(tmpPath, (wxString&) outputPath);
	}
	// 更新が終わったらgzipファイルとSJISファイルを消しておく
	RemoveTmpFile(gzipPath);
	RemoveTmpFile(tmpPath);

	return rc;
}

/**
 * 新規に板一覧情報を取得しに行く
 */
int SocketCommunication::DownloadBoardListNew(const wxString outputPath,
		const wxString headerPath) {
	// 実行コード
	int rc = 0;

	wxHTTP http;
	http.SetHeader(_T("Accept-Encoding"), _T("gzip"));
	http.SetHeader(_T("Host"), _T("menu.2ch.net"));
	http.SetHeader(_T("Accept"), _T(""));
	http.SetHeader(_T("Referer"), _T("http://menu.2ch.net/"));
	http.SetHeader(_T("Accept-Language"), _T("ja"));
	http.SetHeader(_T("User-Agent"), _T("Mozilla/5.0"));
	http.SetTimeout(5);

	wxString server = "menu.2ch.net";
	wxString path = "/bbsmenu.html";
	wxString msg = "";

	// 保存先を決める
	wxFileOutputStream output(outputPath);
	wxDataOutputStream store(output);

	if (http.Connect(server, 80)) {
		wxInputStream *stream;
		stream = http.GetInputStream(path);

		if (stream == NULL) {
			output.Close();
			return -1;
		} else {
			unsigned char buffer[1024];
			int byteRead;
			int totalRead;
			totalRead = 0;

			// ヘッダを書きだす
			WriteHeaderFile(http, headerPath);

			// ストリームを受け取るループ部分
			while (!stream->Eof()) {
				stream->Read(buffer, sizeof(buffer));
				store.Write8(buffer, sizeof(buffer));
				byteRead = stream->LastRead();
				if (byteRead <= 0) {
					break;
				}
				totalRead += byteRead;
			}

			output.Close();
		}
	} else {
		output.Close();
		return -1;
	}

	return rc;
}
/**
 * 前回との差分を取得しに行く
 */
int SocketCommunication::DownloadBoardListMod(const wxString outputPath,
		const wxString headerPath) {
	// 実行コード
	int rc = 0;
	// 最終更新日時をヘッダ情報から取得する
	wxString lastModifiedTime = CheckLastModifiedTime(headerPath);
	// バイナリとヘッダは前回取得した名前と同じでは困るのでtmpファイルとして作成しておく
	wxString tmpOutputPath = outputPath;
	tmpOutputPath += wxT(".tmp");
	wxString tmpHeaderPath = headerPath;
	tmpHeaderPath += wxT(".tmp");

	wxHTTP http;
	http.SetHeader(_T("Accept-Encoding"), _T("gzip"));
	http.SetHeader(_T("Host"), _T("menu.2ch.net"));
	http.SetHeader(_T("If-Modified-Since"), lastModifiedTime);
	http.SetHeader(_T("Accept"), _T(""));
	http.SetHeader(_T("Referer"), _T("http://menu.2ch.net/"));
	http.SetHeader(_T("Accept-Language"), _T("ja"));
	http.SetHeader(_T("User-Agent"), _T("Mozilla/5.0"));
	http.SetTimeout(5);

	wxString server = "menu.2ch.net";
	wxString path = "/bbsmenu.html";
	wxString msg = "";

	// 保存先を決める
	wxFileOutputStream output(tmpOutputPath);
	wxDataOutputStream store(output);

	if (http.Connect(server, 80)) {
		wxInputStream *stream;
		stream = http.GetInputStream(path);

		if (stream == NULL) {
			output.Close();
			return -1;
		} else if (304 == http.GetResponse()) {
			output.Close();
			// レスポンスコードが304ならば変更なしなので正常終了
			RemoveTmpFile(tmpOutputPath);
			return 0;
		} else {
			unsigned char buffer[1024];
			int byteRead;
			int totalRead;
			totalRead = 0;

			// ヘッダを書きだす
			WriteHeaderFile(http, tmpHeaderPath);

			// ストリームを受け取るループ部分
			while (!stream->Eof()) {
				stream->Read(buffer, sizeof(buffer));
				store.Write8(buffer, sizeof(buffer));
				byteRead = stream->LastRead();
				if (byteRead <= 0) {
					break;
				}
				totalRead += byteRead;
			}

			output.Close();

			// 最後までうまく行った場合
			RemoveTmpFile(outputPath);
			RemoveTmpFile(headerPath);
			// tmpファイルを本物のファイルとする
			wxRenameFile(tmpOutputPath, outputPath);
			wxRenameFile(tmpHeaderPath, headerPath);
		}
	} else {
		output.Close();
		return -1;
	}

	return rc;
}

/**
 * 前回の通信ログが存在すれば、最後に取得した日時を変数に格納する
 */
wxString SocketCommunication::CheckLastModifiedTime(const wxString headerPath) {
	wxString lastGetTime = wxT("");

	// ログを読み込む
	wxTextFile file(headerPath);
	file.Open(wxConvUTF8);
	wxString line;

	if (file.IsOpened()) {
		// ログの中身を1行ずつ走査
		for (line = file.GetFirstLine(); !file.Eof();
				line = file.GetNextLine()) {
			if (line.Contains(wxT("Last-Modified:"))) {
				lastGetTime = line.Mid(14);
				break;
			}
		}
		// ファイルのクローズを行う
		file.Close();
		return lastGetTime;

	} else {
		std::cout << "ファイルのオープンに失敗しました" << std::endl;
	}
}

/**
 * スレッド一覧をダウンロードしてくるメソッド
 * @param 板名,URL,サーバー名
 * @return datファイル保存先
 */
wxString SocketCommunication::DownloadThreadList(const wxString & boardName,
		const wxString & boardURL, const wxString & boardNameAscii) {

	// 実行コード
	int rc = 0;
	// 出力するファイルの名前
	wxString outputFileName = boardNameAscii;
	outputFileName += wxT(".dat");
	// 出力先のファイルパスを設定する
	wxString outputFilePath = wxT("./dat/");
	outputFilePath += boardNameAscii;
	outputFilePath += wxT("/");

	// 保存用フォルダ存在するか確認。無ければフォルダを作成
	if (!wxFile::Exists(outputFilePath)) {
		::wxMkdir(outputFilePath);
	}
	outputFilePath += outputFileName;
	// gzip用のパスを設定する
	wxString gzipPath = outputFilePath;
	gzipPath.Replace(wxT(".dat"), wxT(".gzip"));
	// ヘッダーのパスを設定する
	wxString headerPath = outputFilePath;
	headerPath.Replace(wxT(".dat"), wxT(".header"));

	// 解凍された板一覧情報が存在しないor前回の通信ログが残っていないならば通常通りソケット通信を行う
	if ((!wxFileExists(outputFilePath)) || (!wxFileExists(headerPath))) {
		rc = DownloadThreadListNew((const wxString) gzipPath,
				(const wxString) headerPath);
		// そうでなければ前回の通信の差分を取得しに行く
	} else {
		rc = DownloadThreadListNew((const wxString) gzipPath,
				(const wxString) headerPath);
	}

	// gzip拡張子のファイルがあれば、ファイルの解凍を行う
	if (wxFile::Exists(gzipPath)) {
		JaneCloneUtil::DecommpressFile(gzipPath, outputFilePath);
	}
	// 更新が終わったらgzipファイルを消しておく
	RemoveTmpFile(gzipPath);

	return outputFileName;
}

/**
 * 新規にスレッド一覧をダウンロードしてくるメソッド
 * @param 板名,URL,サーバー名
 * @return 実行コード
 */
int SocketCommunication::DownloadThreadListNew(const wxString& gzipPath,
		const wxString& headerPath) {
	int rc = 0;

	return rc;
}

/**
 * 前回との差分のスレッド一覧をダウンロードしてくるメソッド
 * @param 板名,URL,サーバー名
 * @return 実行コード
 */
int SocketCommunication::DownloadThreadListMod(const wxString& gzipPath,
		const wxString& headerPath) {
	int rc = 0;

	return rc;
}

/**
 * 一時ファイルを消す
 */
void SocketCommunication::RemoveTmpFile(const wxString removeFile) {
	if (wxFile::Exists(removeFile)) {
		wxRemoveFile(removeFile);
	}
}

/**
 * HTTPヘッダを書きだす
 */
void SocketCommunication::WriteHeaderFile(const wxHTTP & http,
		const wxString & headerPath) {

	// ヘッダファイルの書き出し先を作る
	wxTextFile headerFile(headerPath);

	// 既にファイルが存在するならば中身を消す
	if (headerFile.Exists()) {
		headerFile.Open(wxConvUTF8);
		headerFile.Clear();
		// 存在しないなら作成する
	} else {
		headerFile.Create();
	}

	// ヘッダの内容を書きだしていく
	wxString status = wxT("HTTP1.1/ ");
	status += wxString::Format(_T("%d"), http.GetResponse());
	headerFile.AddLine(status, TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetHeader(wxT("Date")), TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetHeader(wxT("Server")), TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetHeader(wxT("Last-Modified")), TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetHeader(wxT("ETag")), TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetHeader(wxT("Accept-Ranges")), TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetHeader(wxT("Content-Length")),
			TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetHeader(wxT("Connection")), TEXT_ENDLINE_TYPE);
	headerFile.AddLine(http.GetContentType(), TEXT_ENDLINE_TYPE);

	// 書きだした内容を保存する
	headerFile.Write(wxTextFileType_None, wxConvUTF8);
	headerFile.Close();
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkQuadratureSchemeDefinition.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkQuadratureSchemeDefinition.h"

#include "vtkObjectFactory.h"
#include "vtkInformationQuadratureSchemeDefinitionVectorKey.h"
#include "vtkInformationStringKey.h"
#include "vtkCellType.h"
#include "vtkXMLDataElement.h"
#include "vtksys/ios/sstream"
using vtksys_ios::ostringstream;
using vtksys_ios::istringstream;
#include <string>
using std::string;

vtkStandardNewMacro(vtkQuadratureSchemeDefinition);

//-----------------------------------------------------------------------------
vtkInformationKeyMacro(
        vtkQuadratureSchemeDefinition,
        DICTIONARY,
        QuadratureSchemeDefinitionVector);

vtkInformationKeyMacro(
        vtkQuadratureSchemeDefinition,
        QUADRATURE_OFFSET_ARRAY_NAME,
        String);

//-----------------------------------------------------------------------------
vtkQuadratureSchemeDefinition::vtkQuadratureSchemeDefinition()
{
  this->ShapeFunctionWeights=0;
  this->QuadratureWeights=0;
  this->Clear();
}

//-----------------------------------------------------------------------------
vtkQuadratureSchemeDefinition::~vtkQuadratureSchemeDefinition()
{
  this->Clear();
}

//-----------------------------------------------------------------------------
int vtkQuadratureSchemeDefinition::DeepCopy(const vtkQuadratureSchemeDefinition *other)
{
  this->ShapeFunctionWeights=0;
  this->QuadratureWeights=0;
  this->Clear();
  //
  this->CellType=other->CellType;
  this->QuadratureKey=other->QuadratureKey;
  this->NumberOfNodes=other->NumberOfNodes;
  this->NumberOfQuadraturePoints=other->NumberOfQuadraturePoints;
  //
  this->SecureResources();
  //
  this->SetShapeFunctionWeights(other->GetShapeFunctionWeights());
  this->SetQuadratureWeights(other->GetQuadratureWeights());
  //
  return 1;
}

//-----------------------------------------------------------------------------
void vtkQuadratureSchemeDefinition::Clear()
{
  this->ReleaseResources();
  this->CellType=-1;
  this->QuadratureKey=-1;
  this->NumberOfNodes=0;
  this->NumberOfQuadraturePoints=0;
}

//-----------------------------------------------------------------------------
void vtkQuadratureSchemeDefinition::Initialize(
        int cellType,
        int numberOfNodes,
        int numberOfQuadraturePoints,
        double *shapeFunctionWeights)
{
  this->ReleaseResources();
  //
  this->CellType=cellType;
  this->QuadratureKey=-1;
  this->NumberOfNodes=numberOfNodes;
  this->NumberOfQuadraturePoints=numberOfQuadraturePoints;
  //
  this->SecureResources();
  //
  this->SetShapeFunctionWeights(shapeFunctionWeights);
}

//-----------------------------------------------------------------------------
void vtkQuadratureSchemeDefinition::Initialize(
        int cellType,
        int numberOfNodes,
        int numberOfQuadraturePoints,
        double *shapeFunctionWeights,
        double *quadratureWeights)
{
  this->ReleaseResources();
  //
  this->CellType=cellType;
  this->QuadratureKey=-1;
  this->NumberOfNodes=numberOfNodes;
  this->NumberOfQuadraturePoints=numberOfQuadraturePoints;
  //
  this->SecureResources();
  //
  this->SetShapeFunctionWeights(shapeFunctionWeights);
  this->SetQuadratureWeights(quadratureWeights);
}

//-----------------------------------------------------------------------------
void vtkQuadratureSchemeDefinition::ReleaseResources()
{
  delete [] this->ShapeFunctionWeights;
  this->ShapeFunctionWeights=0;

  delete [] this->QuadratureWeights;
  this->QuadratureWeights=0;
}

//-----------------------------------------------------------------------------
int vtkQuadratureSchemeDefinition::SecureResources()
{
  if ((this->NumberOfQuadraturePoints<=0)
      || (this->NumberOfNodes<=0))
    {
    vtkWarningMacro("Failed to allocate. Invalid buffer size.");
    return 0;
    }

  // Delete weights if they have been allocated
  this->ReleaseResources();

  // Shape function weights, one vector for each quad point.
  this->ShapeFunctionWeights =
    new double [this->NumberOfQuadraturePoints*this->NumberOfNodes];
  for (int i = 0;
       i < this->NumberOfQuadraturePoints*this->NumberOfNodes; i++)
    {
    this->ShapeFunctionWeights[i] = 0.0;
    }

 // Quadrature weights, one double for each quad point
  this->QuadratureWeights =
    new double [this->NumberOfQuadraturePoints];
  for (int i = 0; i < this->NumberOfQuadraturePoints; i++)
    {
    this->QuadratureWeights[i] = 0.0;
    }
  return 1;
}

//-----------------------------------------------------------------------------
void vtkQuadratureSchemeDefinition::SetShapeFunctionWeights(const double *W)
{
  if ((this->NumberOfQuadraturePoints<=0)
      || (this->NumberOfNodes<=0)
      || (this->ShapeFunctionWeights==0))
    {
    return;
    }
  // Copy
  int n=this->NumberOfQuadraturePoints*this->NumberOfNodes;
  for (int i=0; i<n; ++i)
    {
    this->ShapeFunctionWeights[i]=W[i];
    }
}

//-----------------------------------------------------------------------------
void vtkQuadratureSchemeDefinition::SetQuadratureWeights(const double *W)
{
  if ((this->NumberOfQuadraturePoints<=0)
      || (this->NumberOfNodes<=0)
      || (this->QuadratureWeights==0))
    {
    return;
    }
  // Copy
  for (int i=0; i<this->NumberOfQuadraturePoints; ++i)
    {
    this->QuadratureWeights[i]=W[i];
    }
}

//-----------------------------------------------------------------------------
void vtkQuadratureSchemeDefinition::PrintSelf(ostream &sout, vtkIndent indent)
{

  vtkObject::PrintSelf(sout,indent);

  double *pSfWt=this->ShapeFunctionWeights;

  for (int ptId=0; ptId<this->NumberOfQuadraturePoints; ++ptId)
    {
    sout << indent << "(" << pSfWt[0];
    ++pSfWt;
    for (int nodeId=1; nodeId<this->NumberOfNodes; ++nodeId)
      {
      sout << indent << ", " << pSfWt[0];
      ++pSfWt;
      }
    sout << ")" << endl;
    }
  return;
}

//NOTE: These are used by XML readers/writers.
//-----------------------------------------------------------------------------
ostream &operator<<(ostream &sout, const vtkQuadratureSchemeDefinition &def)
{
  /*
  stream will have this space delimited format:
  [cell type][number of cell nodes][number quadrature points][Qp1 ... QpN][Qwt1...QwtN]
  */

  // Size of arrays
  int nQuadPts=def.GetNumberOfQuadraturePoints();
  int nNodes=def.GetNumberOfNodes();

  // Write header
  sout << def.GetCellType()
       << " " << nNodes
       << " " << nQuadPts;

  if ((nNodes>0) && (nQuadPts>0))
    {
    sout.setf(ios::floatfield, ios::scientific);
    sout.precision(16);

    const double *pWt;
    // Write shape function weights
    pWt=def.GetShapeFunctionWeights();
    for (int ptId=0; ptId<nQuadPts; ++ptId)
      {
      for (int nodeId=0; nodeId<nNodes; ++nodeId)
        {
        sout << " " << pWt[0];
        ++pWt;
        }
      }
    // Write quadrature weights
    pWt=def.GetQuadratureWeights();
    for (int nodeId=0; nodeId<nNodes; ++nodeId)
      {
      sout << " " << pWt[0];
      ++pWt;
      }
    }
  else
    {
    vtkGenericWarningMacro("Empty definition written to stream.");
    }
  return sout;
}

//-----------------------------------------------------------------------------
istream &operator>>(istream &sin, vtkQuadratureSchemeDefinition &def)
{
  /*
  stream will have this space delimited format:
  [cell type][number of cell nodes][number quadrature points][Qp1 ... QpN][Qwt1...QwtN]
  */

  // read the header
  int cellType, nNodes, nQuadPts;
  sin >> cellType
      >> nNodes
      >> nQuadPts;

  double *SfWt=0,*QWt=0,*pWt=0;
  if ((nNodes>0) && (nQuadPts>0))
    {
    // read shape function weights
    SfWt=new double [nQuadPts*nNodes];
    pWt=SfWt;
    for (int ptId=0; ptId<nQuadPts; ++ptId)
      {
      for (int nodeId=0; nodeId<nNodes; ++nodeId)
        {
        sin >> pWt[0];
        ++pWt;
        }
      }
    // Write quadrature weights
    QWt=new double [nQuadPts];
    pWt=QWt;
    for (int nodeId=0; nodeId<nNodes; ++nodeId)
      {
      sin >> pWt[0];
      ++pWt;
      }
    }
  else
    {
    vtkGenericWarningMacro("Empty definition found in stream.");
    }

  // intialize the object
  def.Initialize(cellType,nNodes,nQuadPts,SfWt,QWt);

  // clean up
  delete [] SfWt;
  delete [] QWt;

  return sin;
}

//-----------------------------------------------------------------------------
int vtkQuadratureSchemeDefinition::SaveState(vtkXMLDataElement *root)
{
  // Quick sanity check, we're not nesting rather treating
  // this as a root, to be nested by the caller as needed.
  if (root->GetName()!=NULL
      || root->GetNumberOfNestedElements()>0)
    {
    vtkWarningMacro("Can't save state to non-empty element.");
    return 0;
    }

  root->SetName("vtkQuadratureSchemeDefinition");

  vtkXMLDataElement *e;
  e=vtkXMLDataElement::New();
  e->SetName("CellType");
  e->SetIntAttribute("value",this->CellType);
  root->AddNestedElement(e);
  e->Delete();

  e=vtkXMLDataElement::New();
  e->SetName("NumberOfNodes");
  e->SetIntAttribute("value",this->NumberOfNodes);
  root->AddNestedElement(e);
  e->Delete();

  e=vtkXMLDataElement::New();
  e->SetName("NumberOfQuadraturePoints");
  e->SetIntAttribute("value",this->NumberOfQuadraturePoints);
  root->AddNestedElement(e);
  e->Delete();

  vtkXMLDataElement *eShapeWts=vtkXMLDataElement::New();
  eShapeWts->SetName("ShapeFunctionWeights");
  eShapeWts->SetCharacterDataWidth(4);
  root->AddNestedElement(eShapeWts);
  eShapeWts->Delete();

  vtkXMLDataElement *eQuadWts=vtkXMLDataElement::New();
  eQuadWts->SetName("QuadratureWeights");
  eQuadWts->SetCharacterDataWidth(4);
  root->AddNestedElement(eQuadWts);
  eQuadWts->Delete();

  if ((this->NumberOfNodes>0)
      && (this->NumberOfQuadraturePoints>0))
    {
    // Write shape function weights
    ostringstream ssShapeWts;
    ssShapeWts.setf(ios::floatfield, ios::scientific);
    ssShapeWts.precision(16);
    ssShapeWts << this->ShapeFunctionWeights[0];
    int nIds=this->NumberOfNodes*this->NumberOfQuadraturePoints;
    for (int id=1; id<nIds; ++id)
      {
      ssShapeWts << " " << this->ShapeFunctionWeights[id];
      }
    string sShapeWts=ssShapeWts.str();
    eShapeWts->SetCharacterData(sShapeWts.c_str(),static_cast<int>(sShapeWts.size()));

    // Write quadrature weights
    ostringstream ssQuadWts;
    ssQuadWts.setf(ios::floatfield, ios::scientific);
    ssQuadWts.precision(16);
    ssQuadWts << this->QuadratureWeights[0];
    for (int id=1; id<this->NumberOfQuadraturePoints; ++id)
      {
      ssQuadWts << " " << this->QuadratureWeights[id];
      }
    string sQuadWts=ssQuadWts.str();
    eQuadWts->SetCharacterData(sQuadWts.c_str(),static_cast<int>(sQuadWts.size()));
    }
  else
    {
    vtkGenericWarningMacro("Empty definition written to stream.");
    return 0;
    }

  return 1;
}

//-----------------------------------------------------------------------------
int vtkQuadratureSchemeDefinition::RestoreState(vtkXMLDataElement *root)
{
  // A quick sanity check to be sure we have the correct tag.
  if (strcmp(root->GetName(),"vtkQuadratureSchemeDefinition")!=0)
    {
    vtkWarningMacro("Attempting to restore the state in "
                    << root->GetName() <<
                    " into vtkQuadratureSchemeDefinition.");
    return 0;
    }

  vtkXMLDataElement *e;
  const char *value;
  // Transfer state from XML hierarchy.
  e=root->FindNestedElementWithName("CellType");
  if (e==NULL)
    {
    vtkWarningMacro("Expected nested element \"CellType\" "
                    "is not present.");
    return 0;
    }
  value=e->GetAttribute("value");
  this->CellType=atoi(value);
  //
  e=root->FindNestedElementWithName("NumberOfNodes");
  if (e==NULL)
    {
    vtkWarningMacro("Expected nested element \"NumberOfNodes\" "
                    "is not present.");
    return 0;
    }
  value=e->GetAttribute("value");
  this->NumberOfNodes=atoi(value);
  //
  e=root->FindNestedElementWithName("NumberOfQuadraturePoints");
  if (e==NULL)
    {
    vtkWarningMacro("Expected nested element \"NumberOfQuadraturePoints\" "
                    "is not present.");
    return 0;
    }
  value=e->GetAttribute("value");
  this->NumberOfQuadraturePoints=atoi(value);
  // Extract the weights.
  if (this->SecureResources())
    {
    istringstream issWts;
    //
    e=root->FindNestedElementWithName("ShapeFunctionWeights");
    if (e==NULL)
      {
      vtkWarningMacro("Expected nested element \"ShapeFunctionWeights\" "
                      "is not present.");
      return 0;
      }
    value=e->GetCharacterData();
    if (value==NULL)
      {
      vtkWarningMacro("Character data in nested element"
                      " \"ShapeFunctionWeights\" is not present.");
      return 0;
      }
    issWts.str(value);
    int nWts=this->NumberOfNodes*this->NumberOfQuadraturePoints;
    for (int id=0; id<nWts; ++id)
      {
      if (!issWts.good())
        {
        vtkWarningMacro("Character data for \"ShapeFunctionWeights\" "
                        "is short.");
        return 0;
        }
      issWts >> this->ShapeFunctionWeights[id];
      }
    //
    e=root->FindNestedElementWithName("QuadratureWeights");
    if (e==NULL)
      {
      vtkWarningMacro("Expected element \"QuadratureWeights\" "
                      "is not present.");
      return 0;
      }
    value=e->GetCharacterData();
    if (value==NULL)
      {
      vtkWarningMacro("Character data in expected nested element"
                      " \"QuadratureWeights\" is not present.");
      return 0;
      }
    issWts.str(value);
    for (int id=0; id<this->NumberOfQuadraturePoints; ++id)
      {
      if (!issWts.good())
        {
        vtkWarningMacro("Character data for \"QuadratureWeights\" "
                        "is short.");
        return 0;
        }
      issWts >> this->QuadratureWeights[id];
      }
    }

  return 1;
}

<commit_msg>Silence clang static analyzer warning about possible null deref<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkQuadratureSchemeDefinition.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkQuadratureSchemeDefinition.h"

#include "vtkObjectFactory.h"
#include "vtkInformationQuadratureSchemeDefinitionVectorKey.h"
#include "vtkInformationStringKey.h"
#include "vtkCellType.h"
#include "vtkXMLDataElement.h"
#include "vtksys/ios/sstream"
using vtksys_ios::ostringstream;
using vtksys_ios::istringstream;
#include <string>
using std::string;

vtkStandardNewMacro(vtkQuadratureSchemeDefinition);

//-----------------------------------------------------------------------------
vtkInformationKeyMacro(
        vtkQuadratureSchemeDefinition,
        DICTIONARY,
        QuadratureSchemeDefinitionVector);

vtkInformationKeyMacro(
        vtkQuadratureSchemeDefinition,
        QUADRATURE_OFFSET_ARRAY_NAME,
        String);

//-----------------------------------------------------------------------------
vtkQuadratureSchemeDefinition::vtkQuadratureSchemeDefinition()
{
  this->ShapeFunctionWeights=0;
  this->QuadratureWeights=0;
  this->Clear();
}

//-----------------------------------------------------------------------------
vtkQuadratureSchemeDefinition::~vtkQuadratureSchemeDefinition()
{
  this->Clear();
}

//-----------------------------------------------------------------------------
int vtkQuadratureSchemeDefinition::DeepCopy(const vtkQuadratureSchemeDefinition *other)
{
  this->ShapeFunctionWeights=0;
  this->QuadratureWeights=0;
  this->Clear();
  //
  this->CellType=other->CellType;
  this->QuadratureKey=other->QuadratureKey;
  this->NumberOfNodes=other->NumberOfNodes;
  this->NumberOfQuadraturePoints=other->NumberOfQuadraturePoints;
  //
  this->SecureResources();
  //
  this->SetShapeFunctionWeights(other->GetShapeFunctionWeights());
  this->SetQuadratureWeights(other->GetQuadratureWeights());
  //
  return 1;
}

//-----------------------------------------------------------------------------
void vtkQuadratureSchemeDefinition::Clear()
{
  this->ReleaseResources();
  this->CellType=-1;
  this->QuadratureKey=-1;
  this->NumberOfNodes=0;
  this->NumberOfQuadraturePoints=0;
}

//-----------------------------------------------------------------------------
void vtkQuadratureSchemeDefinition::Initialize(
        int cellType,
        int numberOfNodes,
        int numberOfQuadraturePoints,
        double *shapeFunctionWeights)
{
  this->ReleaseResources();
  //
  this->CellType=cellType;
  this->QuadratureKey=-1;
  this->NumberOfNodes=numberOfNodes;
  this->NumberOfQuadraturePoints=numberOfQuadraturePoints;
  //
  this->SecureResources();
  //
  this->SetShapeFunctionWeights(shapeFunctionWeights);
}

//-----------------------------------------------------------------------------
void vtkQuadratureSchemeDefinition::Initialize(
        int cellType,
        int numberOfNodes,
        int numberOfQuadraturePoints,
        double *shapeFunctionWeights,
        double *quadratureWeights)
{
  this->ReleaseResources();
  //
  this->CellType=cellType;
  this->QuadratureKey=-1;
  this->NumberOfNodes=numberOfNodes;
  this->NumberOfQuadraturePoints=numberOfQuadraturePoints;
  //
  this->SecureResources();
  //
  this->SetShapeFunctionWeights(shapeFunctionWeights);
  this->SetQuadratureWeights(quadratureWeights);
}

//-----------------------------------------------------------------------------
void vtkQuadratureSchemeDefinition::ReleaseResources()
{
  delete [] this->ShapeFunctionWeights;
  this->ShapeFunctionWeights=0;

  delete [] this->QuadratureWeights;
  this->QuadratureWeights=0;
}

//-----------------------------------------------------------------------------
int vtkQuadratureSchemeDefinition::SecureResources()
{
  if ((this->NumberOfQuadraturePoints<=0)
      || (this->NumberOfNodes<=0))
    {
    vtkWarningMacro("Failed to allocate. Invalid buffer size.");
    return 0;
    }

  // Delete weights if they have been allocated
  this->ReleaseResources();

  // Shape function weights, one vector for each quad point.
  this->ShapeFunctionWeights =
    new double [this->NumberOfQuadraturePoints*this->NumberOfNodes];
  for (int i = 0;
       i < this->NumberOfQuadraturePoints*this->NumberOfNodes; i++)
    {
    this->ShapeFunctionWeights[i] = 0.0;
    }

 // Quadrature weights, one double for each quad point
  this->QuadratureWeights =
    new double [this->NumberOfQuadraturePoints];
  for (int i = 0; i < this->NumberOfQuadraturePoints; i++)
    {
    this->QuadratureWeights[i] = 0.0;
    }
  return 1;
}

//-----------------------------------------------------------------------------
void vtkQuadratureSchemeDefinition::SetShapeFunctionWeights(const double *W)
{
  if ((this->NumberOfQuadraturePoints<=0)
      || (this->NumberOfNodes<=0)
      || (this->ShapeFunctionWeights==0)
      || !W)
    {
    return;
    }
  // Copy
  int n=this->NumberOfQuadraturePoints*this->NumberOfNodes;
  for (int i=0; i<n; ++i)
    {
    this->ShapeFunctionWeights[i]=W[i];
    }
}

//-----------------------------------------------------------------------------
void vtkQuadratureSchemeDefinition::SetQuadratureWeights(const double *W)
{
  if ((this->NumberOfQuadraturePoints<=0)
      || (this->NumberOfNodes<=0)
      || (this->QuadratureWeights==0)
      || !W)
    {
    return;
    }
  // Copy
  for (int i=0; i<this->NumberOfQuadraturePoints; ++i)
    {
    this->QuadratureWeights[i]=W[i];
    }
}

//-----------------------------------------------------------------------------
void vtkQuadratureSchemeDefinition::PrintSelf(ostream &sout, vtkIndent indent)
{

  vtkObject::PrintSelf(sout,indent);

  double *pSfWt=this->ShapeFunctionWeights;

  for (int ptId=0; ptId<this->NumberOfQuadraturePoints; ++ptId)
    {
    sout << indent << "(" << pSfWt[0];
    ++pSfWt;
    for (int nodeId=1; nodeId<this->NumberOfNodes; ++nodeId)
      {
      sout << indent << ", " << pSfWt[0];
      ++pSfWt;
      }
    sout << ")" << endl;
    }
  return;
}

//NOTE: These are used by XML readers/writers.
//-----------------------------------------------------------------------------
ostream &operator<<(ostream &sout, const vtkQuadratureSchemeDefinition &def)
{
  /*
  stream will have this space delimited format:
  [cell type][number of cell nodes][number quadrature points][Qp1 ... QpN][Qwt1...QwtN]
  */

  // Size of arrays
  int nQuadPts=def.GetNumberOfQuadraturePoints();
  int nNodes=def.GetNumberOfNodes();

  // Write header
  sout << def.GetCellType()
       << " " << nNodes
       << " " << nQuadPts;

  if ((nNodes>0) && (nQuadPts>0))
    {
    sout.setf(ios::floatfield, ios::scientific);
    sout.precision(16);

    const double *pWt;
    // Write shape function weights
    pWt=def.GetShapeFunctionWeights();
    for (int ptId=0; ptId<nQuadPts; ++ptId)
      {
      for (int nodeId=0; nodeId<nNodes; ++nodeId)
        {
        sout << " " << pWt[0];
        ++pWt;
        }
      }
    // Write quadrature weights
    pWt=def.GetQuadratureWeights();
    for (int nodeId=0; nodeId<nNodes; ++nodeId)
      {
      sout << " " << pWt[0];
      ++pWt;
      }
    }
  else
    {
    vtkGenericWarningMacro("Empty definition written to stream.");
    }
  return sout;
}

//-----------------------------------------------------------------------------
istream &operator>>(istream &sin, vtkQuadratureSchemeDefinition &def)
{
  /*
  stream will have this space delimited format:
  [cell type][number of cell nodes][number quadrature points][Qp1 ... QpN][Qwt1...QwtN]
  */

  // read the header
  int cellType, nNodes, nQuadPts;
  sin >> cellType
      >> nNodes
      >> nQuadPts;

  double *SfWt=0,*QWt=0,*pWt=0;
  if ((nNodes>0) && (nQuadPts>0))
    {
    // read shape function weights
    SfWt=new double [nQuadPts*nNodes];
    pWt=SfWt;
    for (int ptId=0; ptId<nQuadPts; ++ptId)
      {
      for (int nodeId=0; nodeId<nNodes; ++nodeId)
        {
        sin >> pWt[0];
        ++pWt;
        }
      }
    // Write quadrature weights
    QWt=new double [nQuadPts];
    pWt=QWt;
    for (int nodeId=0; nodeId<nNodes; ++nodeId)
      {
      sin >> pWt[0];
      ++pWt;
      }
    }
  else
    {
    vtkGenericWarningMacro("Empty definition found in stream.");
    }

  // intialize the object
  def.Initialize(cellType,nNodes,nQuadPts,SfWt,QWt);

  // clean up
  delete [] SfWt;
  delete [] QWt;

  return sin;
}

//-----------------------------------------------------------------------------
int vtkQuadratureSchemeDefinition::SaveState(vtkXMLDataElement *root)
{
  // Quick sanity check, we're not nesting rather treating
  // this as a root, to be nested by the caller as needed.
  if (root->GetName()!=NULL
      || root->GetNumberOfNestedElements()>0)
    {
    vtkWarningMacro("Can't save state to non-empty element.");
    return 0;
    }

  root->SetName("vtkQuadratureSchemeDefinition");

  vtkXMLDataElement *e;
  e=vtkXMLDataElement::New();
  e->SetName("CellType");
  e->SetIntAttribute("value",this->CellType);
  root->AddNestedElement(e);
  e->Delete();

  e=vtkXMLDataElement::New();
  e->SetName("NumberOfNodes");
  e->SetIntAttribute("value",this->NumberOfNodes);
  root->AddNestedElement(e);
  e->Delete();

  e=vtkXMLDataElement::New();
  e->SetName("NumberOfQuadraturePoints");
  e->SetIntAttribute("value",this->NumberOfQuadraturePoints);
  root->AddNestedElement(e);
  e->Delete();

  vtkXMLDataElement *eShapeWts=vtkXMLDataElement::New();
  eShapeWts->SetName("ShapeFunctionWeights");
  eShapeWts->SetCharacterDataWidth(4);
  root->AddNestedElement(eShapeWts);
  eShapeWts->Delete();

  vtkXMLDataElement *eQuadWts=vtkXMLDataElement::New();
  eQuadWts->SetName("QuadratureWeights");
  eQuadWts->SetCharacterDataWidth(4);
  root->AddNestedElement(eQuadWts);
  eQuadWts->Delete();

  if ((this->NumberOfNodes>0)
      && (this->NumberOfQuadraturePoints>0))
    {
    // Write shape function weights
    ostringstream ssShapeWts;
    ssShapeWts.setf(ios::floatfield, ios::scientific);
    ssShapeWts.precision(16);
    ssShapeWts << this->ShapeFunctionWeights[0];
    int nIds=this->NumberOfNodes*this->NumberOfQuadraturePoints;
    for (int id=1; id<nIds; ++id)
      {
      ssShapeWts << " " << this->ShapeFunctionWeights[id];
      }
    string sShapeWts=ssShapeWts.str();
    eShapeWts->SetCharacterData(sShapeWts.c_str(),static_cast<int>(sShapeWts.size()));

    // Write quadrature weights
    ostringstream ssQuadWts;
    ssQuadWts.setf(ios::floatfield, ios::scientific);
    ssQuadWts.precision(16);
    ssQuadWts << this->QuadratureWeights[0];
    for (int id=1; id<this->NumberOfQuadraturePoints; ++id)
      {
      ssQuadWts << " " << this->QuadratureWeights[id];
      }
    string sQuadWts=ssQuadWts.str();
    eQuadWts->SetCharacterData(sQuadWts.c_str(),static_cast<int>(sQuadWts.size()));
    }
  else
    {
    vtkGenericWarningMacro("Empty definition written to stream.");
    return 0;
    }

  return 1;
}

//-----------------------------------------------------------------------------
int vtkQuadratureSchemeDefinition::RestoreState(vtkXMLDataElement *root)
{
  // A quick sanity check to be sure we have the correct tag.
  if (strcmp(root->GetName(),"vtkQuadratureSchemeDefinition")!=0)
    {
    vtkWarningMacro("Attempting to restore the state in "
                    << root->GetName() <<
                    " into vtkQuadratureSchemeDefinition.");
    return 0;
    }

  vtkXMLDataElement *e;
  const char *value;
  // Transfer state from XML hierarchy.
  e=root->FindNestedElementWithName("CellType");
  if (e==NULL)
    {
    vtkWarningMacro("Expected nested element \"CellType\" "
                    "is not present.");
    return 0;
    }
  value=e->GetAttribute("value");
  this->CellType=atoi(value);
  //
  e=root->FindNestedElementWithName("NumberOfNodes");
  if (e==NULL)
    {
    vtkWarningMacro("Expected nested element \"NumberOfNodes\" "
                    "is not present.");
    return 0;
    }
  value=e->GetAttribute("value");
  this->NumberOfNodes=atoi(value);
  //
  e=root->FindNestedElementWithName("NumberOfQuadraturePoints");
  if (e==NULL)
    {
    vtkWarningMacro("Expected nested element \"NumberOfQuadraturePoints\" "
                    "is not present.");
    return 0;
    }
  value=e->GetAttribute("value");
  this->NumberOfQuadraturePoints=atoi(value);
  // Extract the weights.
  if (this->SecureResources())
    {
    istringstream issWts;
    //
    e=root->FindNestedElementWithName("ShapeFunctionWeights");
    if (e==NULL)
      {
      vtkWarningMacro("Expected nested element \"ShapeFunctionWeights\" "
                      "is not present.");
      return 0;
      }
    value=e->GetCharacterData();
    if (value==NULL)
      {
      vtkWarningMacro("Character data in nested element"
                      " \"ShapeFunctionWeights\" is not present.");
      return 0;
      }
    issWts.str(value);
    int nWts=this->NumberOfNodes*this->NumberOfQuadraturePoints;
    for (int id=0; id<nWts; ++id)
      {
      if (!issWts.good())
        {
        vtkWarningMacro("Character data for \"ShapeFunctionWeights\" "
                        "is short.");
        return 0;
        }
      issWts >> this->ShapeFunctionWeights[id];
      }
    //
    e=root->FindNestedElementWithName("QuadratureWeights");
    if (e==NULL)
      {
      vtkWarningMacro("Expected element \"QuadratureWeights\" "
                      "is not present.");
      return 0;
      }
    value=e->GetCharacterData();
    if (value==NULL)
      {
      vtkWarningMacro("Character data in expected nested element"
                      " \"QuadratureWeights\" is not present.");
      return 0;
      }
    issWts.str(value);
    for (int id=0; id<this->NumberOfQuadraturePoints; ++id)
      {
      if (!issWts.good())
        {
        vtkWarningMacro("Character data for \"QuadratureWeights\" "
                        "is short.");
        return 0;
        }
      issWts >> this->QuadratureWeights[id];
      }
    }

  return 1;
}

<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License
 */
/*
 * @file        admin-api.cpp
 * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
 * @version     1.0
 * @brief       Implementation of external libcynara-admin API
 */

#include <map>
#include <new>
#include <string>
#include <vector>

#include <common.h>
#include <types/Policy.h>
#include <types/PolicyBucketId.h>
#include <types/PolicyKey.h>
#include <types/PolicyResult.h>
#include <types/PolicyType.h>

#include <cynara-admin.h>

#include <api/ApiInterface.h>
#include <logic/Logic.h>

struct cynara_admin {
    Cynara::ApiInterface *impl;

    cynara_admin(Cynara::ApiInterface *_impl) : impl(_impl) {
    }
    ~cynara_admin() {
        delete impl;
    }
};

CYNARA_API
int cynara_admin_initialize(struct cynara_admin **pp_cynara_admin) {
    if (!pp_cynara_admin)
        return CYNARA_ADMIN_API_INVALID_PARAM;

    try {
        *pp_cynara_admin = new cynara_admin(new Cynara::Logic);
    } catch (const std::bad_alloc &ex) {
        return CYNARA_ADMIN_API_OUT_OF_MEMORY;
    }

    return CYNARA_ADMIN_API_SUCCESS;
}

CYNARA_API
int cynara_admin_finish(struct cynara_admin *p_cynara_admin) {
    delete p_cynara_admin;

    return CYNARA_ADMIN_API_SUCCESS;
}

CYNARA_API
int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin,
                              const cynara_admin_policy *const *policies) {
    if (!p_cynara_admin || !p_cynara_admin->impl)
        return CYNARA_ADMIN_API_INVALID_PARAM;
    if (!policies)
        return CYNARA_ADMIN_API_INVALID_PARAM;

    std::map<Cynara::PolicyBucketId, std::vector<Cynara::Policy>> insertOrUpdate;
    std::map<Cynara::PolicyBucketId, std::vector<Cynara::PolicyKey>> remove;

    auto key = ([](const cynara_admin_policy *i)->Cynara::PolicyKey {
        std::string wildcard(CYNARA_ADMIN_WILDCARD);

        auto feature = ([&wildcard] (const char *str)->Cynara::PolicyKeyFeature {
            if (wildcard.compare(str))
                return Cynara::PolicyKeyFeature::create(str);
            else
                return Cynara::PolicyKeyFeature::createWildcard();
        });

        return Cynara::PolicyKey(feature(i->client), feature(i->user), feature(i->privilege));
    });

    try {
        for (auto i = policies[0]; i; i++) {
            if(!i->bucket || !i->client || !i->user || !i->privilege)
                return CYNARA_ADMIN_API_INVALID_PARAM;

            switch (i->result) {
                case CYNARA_ADMIN_DELETE:
                    remove[i->bucket].push_back(key(i));
                    break;
                case CYNARA_ADMIN_DENY:
                    insertOrUpdate[i->bucket].push_back(Cynara::Policy(key(i),
                                                        Cynara::PredefinedPolicyType::DENY));
                    break;
                case CYNARA_ADMIN_ALLOW:
                    insertOrUpdate[i->bucket].push_back(Cynara::Policy(key(i),
                                                        Cynara::PredefinedPolicyType::ALLOW));
                    break;
                case CYNARA_ADMIN_BUCKET:
                    insertOrUpdate[i->bucket].push_back(Cynara::Policy(key(i),
                                                        Cynara::PolicyResult(
                                                        Cynara::PredefinedPolicyType::BUCKET,
                                                        i->result_extra ? i->result_extra : "")));
                    break;
                default:
                    return CYNARA_ADMIN_API_INVALID_PARAM;
            }
        }
    } catch (std::bad_alloc ex) {
        return CYNARA_ADMIN_API_OUT_OF_MEMORY;
    }

    return p_cynara_admin->impl->setPolicies(insertOrUpdate, remove);
}

CYNARA_API
int cynara_admin_set_bucket(struct cynara_admin *p_cynara_admin, const char *bucket,
                            int operation, const char *extra) {
    if (!p_cynara_admin || !p_cynara_admin->impl)
        return CYNARA_ADMIN_API_INVALID_PARAM;
    if (!bucket)
        return CYNARA_ADMIN_API_INVALID_PARAM;

    std::string extraStr;
    try {
         extraStr = extra ? extra : "";
    } catch (std::bad_alloc ex) {
        return CYNARA_ADMIN_API_OUT_OF_MEMORY;
    }
    switch (operation) {
        case CYNARA_ADMIN_DELETE:
            return p_cynara_admin->impl->removeBucket(bucket);
        case CYNARA_ADMIN_DENY:
            return p_cynara_admin->impl->insertOrUpdateBucket(bucket,
                Cynara::PolicyResult(Cynara::PredefinedPolicyType::DENY, extraStr));
        case CYNARA_ADMIN_ALLOW:
            return p_cynara_admin->impl->insertOrUpdateBucket(bucket,
                Cynara::PolicyResult(Cynara::PredefinedPolicyType::ALLOW, extraStr));
        case CYNARA_ADMIN_BUCKET:
        default:
            return CYNARA_ADMIN_API_INVALID_PARAM;
    }
}
<commit_msg>Fix badly inceremented pointers<commit_after>/*
 *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License
 */
/*
 * @file        admin-api.cpp
 * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
 * @version     1.0
 * @brief       Implementation of external libcynara-admin API
 */

#include <map>
#include <new>
#include <string>
#include <vector>

#include <common.h>
#include <types/Policy.h>
#include <types/PolicyBucketId.h>
#include <types/PolicyKey.h>
#include <types/PolicyResult.h>
#include <types/PolicyType.h>

#include <cynara-admin.h>

#include <api/ApiInterface.h>
#include <logic/Logic.h>

struct cynara_admin {
    Cynara::ApiInterface *impl;

    cynara_admin(Cynara::ApiInterface *_impl) : impl(_impl) {
    }
    ~cynara_admin() {
        delete impl;
    }
};

CYNARA_API
int cynara_admin_initialize(struct cynara_admin **pp_cynara_admin) {
    if (!pp_cynara_admin)
        return CYNARA_ADMIN_API_INVALID_PARAM;

    try {
        *pp_cynara_admin = new cynara_admin(new Cynara::Logic);
    } catch (const std::bad_alloc &ex) {
        return CYNARA_ADMIN_API_OUT_OF_MEMORY;
    }

    return CYNARA_ADMIN_API_SUCCESS;
}

CYNARA_API
int cynara_admin_finish(struct cynara_admin *p_cynara_admin) {
    delete p_cynara_admin;

    return CYNARA_ADMIN_API_SUCCESS;
}

CYNARA_API
int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin,
                              const cynara_admin_policy *const *policies) {
    if (!p_cynara_admin || !p_cynara_admin->impl)
        return CYNARA_ADMIN_API_INVALID_PARAM;
    if (!policies)
        return CYNARA_ADMIN_API_INVALID_PARAM;

    std::map<Cynara::PolicyBucketId, std::vector<Cynara::Policy>> insertOrUpdate;
    std::map<Cynara::PolicyBucketId, std::vector<Cynara::PolicyKey>> remove;

    auto key = ([](const cynara_admin_policy *i)->Cynara::PolicyKey {
        std::string wildcard(CYNARA_ADMIN_WILDCARD);

        auto feature = ([&wildcard] (const char *str)->Cynara::PolicyKeyFeature {
            if (wildcard.compare(str))
                return Cynara::PolicyKeyFeature::create(str);
            else
                return Cynara::PolicyKeyFeature::createWildcard();
        });

        return Cynara::PolicyKey(feature(i->client), feature(i->user), feature(i->privilege));
    });

    try {
        for (auto i = policies; *i; i++) {
            if(!(*i)->bucket || !(*i)->client || !(*i)->user || !(*i)->privilege)
                return CYNARA_ADMIN_API_INVALID_PARAM;

            switch ((*i)->result) {
                case CYNARA_ADMIN_DELETE:
                    remove[(*i)->bucket].push_back(key(*i));
                    break;
                case CYNARA_ADMIN_DENY:
                    insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i),
                                                        Cynara::PredefinedPolicyType::DENY));
                    break;
                case CYNARA_ADMIN_ALLOW:
                    insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i),
                                                        Cynara::PredefinedPolicyType::ALLOW));
                    break;
                case CYNARA_ADMIN_BUCKET:
                    insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i),
                                                        Cynara::PolicyResult(
                                                        Cynara::PredefinedPolicyType::BUCKET,
                                                        (*i)->result_extra ? (*i)->result_extra
                                                        : "")));
                    break;
                default:
                    return CYNARA_ADMIN_API_INVALID_PARAM;
            }
        }
    } catch (std::bad_alloc ex) {
        return CYNARA_ADMIN_API_OUT_OF_MEMORY;
    }

    return p_cynara_admin->impl->setPolicies(insertOrUpdate, remove);
}

CYNARA_API
int cynara_admin_set_bucket(struct cynara_admin *p_cynara_admin, const char *bucket,
                            int operation, const char *extra) {
    if (!p_cynara_admin || !p_cynara_admin->impl)
        return CYNARA_ADMIN_API_INVALID_PARAM;
    if (!bucket)
        return CYNARA_ADMIN_API_INVALID_PARAM;

    std::string extraStr;
    try {
         extraStr = extra ? extra : "";
    } catch (std::bad_alloc ex) {
        return CYNARA_ADMIN_API_OUT_OF_MEMORY;
    }
    switch (operation) {
        case CYNARA_ADMIN_DELETE:
            return p_cynara_admin->impl->removeBucket(bucket);
        case CYNARA_ADMIN_DENY:
            return p_cynara_admin->impl->insertOrUpdateBucket(bucket,
                Cynara::PolicyResult(Cynara::PredefinedPolicyType::DENY, extraStr));
        case CYNARA_ADMIN_ALLOW:
            return p_cynara_admin->impl->insertOrUpdateBucket(bucket,
                Cynara::PolicyResult(Cynara::PredefinedPolicyType::ALLOW, extraStr));
        case CYNARA_ADMIN_BUCKET:
        default:
            return CYNARA_ADMIN_API_INVALID_PARAM;
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Ryan Prichard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include "DebugShowInput.h"

#include <windows.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include <string>

#include "../shared/StringBuilder.h"
#include "InputMap.h"

namespace {

struct Flag {
    DWORD value;
    const char *text;
};

static const Flag kButtonStates[] = {
    { FROM_LEFT_1ST_BUTTON_PRESSED, "1" },
    { FROM_LEFT_2ND_BUTTON_PRESSED, "2" },
    { FROM_LEFT_3RD_BUTTON_PRESSED, "3" },
    { FROM_LEFT_4TH_BUTTON_PRESSED, "4" },
    { RIGHTMOST_BUTTON_PRESSED,     "R" },
};

static const Flag kControlKeyStates[] = {
    { CAPSLOCK_ON,          "CapsLock"      },
    { ENHANCED_KEY,         "Enhanced"      },
    { LEFT_ALT_PRESSED,     "LAlt"          },
    { LEFT_CTRL_PRESSED,    "LCtrl"         },
    { NUMLOCK_ON,           "NumLock"       },
    { RIGHT_ALT_PRESSED,    "RAlt"          },
    { RIGHT_CTRL_PRESSED,   "RCtrl"         },
    { SCROLLLOCK_ON,        "ScrollLock"    },
    { SHIFT_PRESSED,        "Shift"         },
};

static const Flag kMouseEventFlags[] = {
    { DOUBLE_CLICK,         "Double"        },
    { 8/*MOUSE_HWHEELED*/,  "HWheel"        },
    { MOUSE_MOVED,          "Move"          },
    { MOUSE_WHEELED,        "Wheel"         },
};

static void writeFlags(StringBuilder &out, DWORD flags,
                       const char *remainderName,
                       const Flag *table, size_t tableSize,
                       char pre, char sep, char post) {
    DWORD remaining = flags;
    bool wroteSomething = false;
    for (size_t i = 0; i < tableSize; ++i) {
        const Flag &f = table[i];
        if ((f.value & flags) == f.value) {
            if (!wroteSomething && pre != '\0') {
                out << pre;
            } else if (wroteSomething && sep != '\0') {
                out << sep;
            }
            out << f.text;
            wroteSomething = true;
            remaining &= ~f.value;
        }
    }
    if (remaining != 0) {
        if (!wroteSomething && pre != '\0') {
            out << pre;
        } else if (wroteSomething && sep != '\0') {
            out << sep;
        }
        out << remainderName << "(0x" << hexOfInt(remaining) << ')';
        wroteSomething = true;
    }
    if (wroteSomething && post != '\0') {
        out << post;
    }
}

template <size_t n>
static void writeFlags(StringBuilder &out, DWORD flags,
                       const char *remainderName,
                       const Flag (&table)[n],
                       char pre, char sep, char post) {
    writeFlags(out, flags, remainderName, table, n, pre, sep, post);
}

} // anonymous namespace

std::string controlKeyStatePrefix(DWORD controlKeyState) {
    StringBuilder sb;
    writeFlags(sb, controlKeyState,
               "keyState", kControlKeyStates, '\0', '-', '-');
    return sb.str_moved();
}

std::string mouseEventToString(const MOUSE_EVENT_RECORD &mer) {
    const uint16_t buttons = mer.dwButtonState & 0xFFFF;
    const int16_t wheel = mer.dwButtonState >> 16;
    StringBuilder sb;
    sb << "pos=" << mer.dwMousePosition.X << ','
                 << mer.dwMousePosition.Y;
    writeFlags(sb, mer.dwControlKeyState, "keyState", kControlKeyStates, ' ', ' ', '\0');
    writeFlags(sb, mer.dwEventFlags, "flags", kMouseEventFlags, ' ', ' ', '\0');
    writeFlags(sb, buttons, "buttons", kButtonStates, ' ', ' ', '\0');
    if (wheel != 0) {
        sb << " wheel=" << wheel;
    }
    return sb.str_moved();
}

void debugShowInput(bool enableMouse, bool escapeInput) {
    HANDLE conin = GetStdHandle(STD_INPUT_HANDLE);
    DWORD origConsoleMode = 0;
    if (!GetConsoleMode(conin, &origConsoleMode)) {
        fprintf(stderr, "Error: could not read console mode -- "
                        "is STDIN a console handle?\n");
        exit(1);
    }
    DWORD restoreConsoleMode = origConsoleMode;
    if (enableMouse && !(restoreConsoleMode & ENABLE_EXTENDED_FLAGS)) {
        // We need to disable QuickEdit mode, because it blocks mouse events.
        // If ENABLE_EXTENDED_FLAGS wasn't originally in the console mode, then
        // we have no way of knowning whether QuickEdit or InsertMode are
        // currently enabled.  Enable them both (eventually), because they're
        // sensible defaults.  This case shouldn't happen typically.  See
        // misc/EnableExtendedFlags.txt.
        restoreConsoleMode |= ENABLE_EXTENDED_FLAGS;
        restoreConsoleMode |= ENABLE_QUICK_EDIT_MODE;
        restoreConsoleMode |= ENABLE_INSERT_MODE;
    }
    DWORD newConsoleMode = restoreConsoleMode;
    newConsoleMode &= ~ENABLE_PROCESSED_INPUT;
    newConsoleMode &= ~ENABLE_LINE_INPUT;
    newConsoleMode &= ~ENABLE_ECHO_INPUT;
    newConsoleMode |= ENABLE_WINDOW_INPUT;
    if (enableMouse) {
        newConsoleMode |= ENABLE_MOUSE_INPUT;
        newConsoleMode &= ~ENABLE_QUICK_EDIT_MODE;
    } else {
        newConsoleMode &= ~ENABLE_MOUSE_INPUT;
    }
    if (escapeInput) {
        // As of this writing (2016-06-05), Microsoft has shipped two preview
        // builds of Windows 10 (14316 and 14342) that include a new "Windows
        // Subsystem for Linux" that runs Ubuntu in a new subsystem.  Running
        // bash in this subsystem requires the non-legacy console mode, and the
        // console input buffer is put into a special mode where escape
        // sequences are written into the console input buffer.  This mode is
        // enabled with the 0x200 flag, which is as-yet undocumented.
        // See https://github.com/rprichard/winpty/issues/82.
        newConsoleMode |= 0x200;
    }
    if (!SetConsoleMode(conin, newConsoleMode)) {
        fprintf(stderr, "Error: could not set console mode "
            "(0x%x -> 0x%x -> 0x%x)\n",
            static_cast<unsigned int>(origConsoleMode),
            static_cast<unsigned int>(newConsoleMode),
            static_cast<unsigned int>(restoreConsoleMode));
        exit(1);
    }
    printf("\nPress any keys -- Ctrl-D exits\n\n");
    INPUT_RECORD records[32];
    DWORD actual = 0;
    bool finished = false;
    while (!finished &&
            ReadConsoleInputW(conin, records, 32, &actual) && actual >= 1) {
        StringBuilder sb;
        for (DWORD i = 0; i < actual; ++i) {
            const INPUT_RECORD &record = records[i];
            if (record.EventType == KEY_EVENT) {
                const KEY_EVENT_RECORD &ker = record.Event.KeyEvent;
                InputMap::Key key = {
                    ker.wVirtualKeyCode,
                    ker.uChar.UnicodeChar,
                    static_cast<uint16_t>(ker.dwControlKeyState),
                };
                sb << "key: " << (ker.bKeyDown ? "dn" : "up")
                   << " rpt=" << ker.wRepeatCount
                   << " scn=" << ker.wVirtualScanCode
                   << ' ' << key.toString() << '\n';
                if ((ker.dwControlKeyState & LEFT_CTRL_PRESSED) &&
                        ker.wVirtualKeyCode == 'D') {
                    finished = true;
                    break;
                }
            } else if (record.EventType == MOUSE_EVENT) {
                const MOUSE_EVENT_RECORD &mer = record.Event.MouseEvent;
                sb << "mouse: " << mouseEventToString(mer) << '\n';
            } else if (record.EventType == WINDOW_BUFFER_SIZE_EVENT) {
                const WINDOW_BUFFER_SIZE_RECORD &wbsr =
                    record.Event.WindowBufferSizeEvent;
                sb << "buffer-resized: dwSize=("
                   << wbsr.dwSize.X << ','
                   << wbsr.dwSize.Y << ")\n";
            } else if (record.EventType == MENU_EVENT) {
                const MENU_EVENT_RECORD &mer = record.Event.MenuEvent;
                sb << "menu-event: commandId=0x"
                   << hexOfInt(mer.dwCommandId) << '\n';
            } else if (record.EventType == FOCUS_EVENT) {
                const FOCUS_EVENT_RECORD &fer = record.Event.FocusEvent;
                sb << "focus: " << (fer.bSetFocus ? "gained" : "lost") << '\n';
            }
        }

        const auto str = sb.str_moved();
        fwrite(str.data(), 1, str.size(), stdout);
        fflush(stdout);
    }
    SetConsoleMode(conin, restoreConsoleMode);
}
<commit_msg>Improve Ctrl-D detection for `winpty-agent --show-input` test mode.<commit_after>// Copyright (c) 2015 Ryan Prichard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include "DebugShowInput.h"

#include <windows.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include <string>

#include "../shared/StringBuilder.h"
#include "InputMap.h"

namespace {

struct Flag {
    DWORD value;
    const char *text;
};

static const Flag kButtonStates[] = {
    { FROM_LEFT_1ST_BUTTON_PRESSED, "1" },
    { FROM_LEFT_2ND_BUTTON_PRESSED, "2" },
    { FROM_LEFT_3RD_BUTTON_PRESSED, "3" },
    { FROM_LEFT_4TH_BUTTON_PRESSED, "4" },
    { RIGHTMOST_BUTTON_PRESSED,     "R" },
};

static const Flag kControlKeyStates[] = {
    { CAPSLOCK_ON,          "CapsLock"      },
    { ENHANCED_KEY,         "Enhanced"      },
    { LEFT_ALT_PRESSED,     "LAlt"          },
    { LEFT_CTRL_PRESSED,    "LCtrl"         },
    { NUMLOCK_ON,           "NumLock"       },
    { RIGHT_ALT_PRESSED,    "RAlt"          },
    { RIGHT_CTRL_PRESSED,   "RCtrl"         },
    { SCROLLLOCK_ON,        "ScrollLock"    },
    { SHIFT_PRESSED,        "Shift"         },
};

static const Flag kMouseEventFlags[] = {
    { DOUBLE_CLICK,         "Double"        },
    { 8/*MOUSE_HWHEELED*/,  "HWheel"        },
    { MOUSE_MOVED,          "Move"          },
    { MOUSE_WHEELED,        "Wheel"         },
};

static void writeFlags(StringBuilder &out, DWORD flags,
                       const char *remainderName,
                       const Flag *table, size_t tableSize,
                       char pre, char sep, char post) {
    DWORD remaining = flags;
    bool wroteSomething = false;
    for (size_t i = 0; i < tableSize; ++i) {
        const Flag &f = table[i];
        if ((f.value & flags) == f.value) {
            if (!wroteSomething && pre != '\0') {
                out << pre;
            } else if (wroteSomething && sep != '\0') {
                out << sep;
            }
            out << f.text;
            wroteSomething = true;
            remaining &= ~f.value;
        }
    }
    if (remaining != 0) {
        if (!wroteSomething && pre != '\0') {
            out << pre;
        } else if (wroteSomething && sep != '\0') {
            out << sep;
        }
        out << remainderName << "(0x" << hexOfInt(remaining) << ')';
        wroteSomething = true;
    }
    if (wroteSomething && post != '\0') {
        out << post;
    }
}

template <size_t n>
static void writeFlags(StringBuilder &out, DWORD flags,
                       const char *remainderName,
                       const Flag (&table)[n],
                       char pre, char sep, char post) {
    writeFlags(out, flags, remainderName, table, n, pre, sep, post);
}

} // anonymous namespace

std::string controlKeyStatePrefix(DWORD controlKeyState) {
    StringBuilder sb;
    writeFlags(sb, controlKeyState,
               "keyState", kControlKeyStates, '\0', '-', '-');
    return sb.str_moved();
}

std::string mouseEventToString(const MOUSE_EVENT_RECORD &mer) {
    const uint16_t buttons = mer.dwButtonState & 0xFFFF;
    const int16_t wheel = mer.dwButtonState >> 16;
    StringBuilder sb;
    sb << "pos=" << mer.dwMousePosition.X << ','
                 << mer.dwMousePosition.Y;
    writeFlags(sb, mer.dwControlKeyState, "keyState", kControlKeyStates, ' ', ' ', '\0');
    writeFlags(sb, mer.dwEventFlags, "flags", kMouseEventFlags, ' ', ' ', '\0');
    writeFlags(sb, buttons, "buttons", kButtonStates, ' ', ' ', '\0');
    if (wheel != 0) {
        sb << " wheel=" << wheel;
    }
    return sb.str_moved();
}

void debugShowInput(bool enableMouse, bool escapeInput) {
    HANDLE conin = GetStdHandle(STD_INPUT_HANDLE);
    DWORD origConsoleMode = 0;
    if (!GetConsoleMode(conin, &origConsoleMode)) {
        fprintf(stderr, "Error: could not read console mode -- "
                        "is STDIN a console handle?\n");
        exit(1);
    }
    DWORD restoreConsoleMode = origConsoleMode;
    if (enableMouse && !(restoreConsoleMode & ENABLE_EXTENDED_FLAGS)) {
        // We need to disable QuickEdit mode, because it blocks mouse events.
        // If ENABLE_EXTENDED_FLAGS wasn't originally in the console mode, then
        // we have no way of knowning whether QuickEdit or InsertMode are
        // currently enabled.  Enable them both (eventually), because they're
        // sensible defaults.  This case shouldn't happen typically.  See
        // misc/EnableExtendedFlags.txt.
        restoreConsoleMode |= ENABLE_EXTENDED_FLAGS;
        restoreConsoleMode |= ENABLE_QUICK_EDIT_MODE;
        restoreConsoleMode |= ENABLE_INSERT_MODE;
    }
    DWORD newConsoleMode = restoreConsoleMode;
    newConsoleMode &= ~ENABLE_PROCESSED_INPUT;
    newConsoleMode &= ~ENABLE_LINE_INPUT;
    newConsoleMode &= ~ENABLE_ECHO_INPUT;
    newConsoleMode |= ENABLE_WINDOW_INPUT;
    if (enableMouse) {
        newConsoleMode |= ENABLE_MOUSE_INPUT;
        newConsoleMode &= ~ENABLE_QUICK_EDIT_MODE;
    } else {
        newConsoleMode &= ~ENABLE_MOUSE_INPUT;
    }
    if (escapeInput) {
        // As of this writing (2016-06-05), Microsoft has shipped two preview
        // builds of Windows 10 (14316 and 14342) that include a new "Windows
        // Subsystem for Linux" that runs Ubuntu in a new subsystem.  Running
        // bash in this subsystem requires the non-legacy console mode, and the
        // console input buffer is put into a special mode where escape
        // sequences are written into the console input buffer.  This mode is
        // enabled with the 0x200 flag, which is as-yet undocumented.
        // See https://github.com/rprichard/winpty/issues/82.
        newConsoleMode |= 0x200;
    }
    if (!SetConsoleMode(conin, newConsoleMode)) {
        fprintf(stderr, "Error: could not set console mode "
            "(0x%x -> 0x%x -> 0x%x)\n",
            static_cast<unsigned int>(origConsoleMode),
            static_cast<unsigned int>(newConsoleMode),
            static_cast<unsigned int>(restoreConsoleMode));
        exit(1);
    }
    printf("\nPress any keys -- Ctrl-D exits\n\n");
    INPUT_RECORD records[32];
    DWORD actual = 0;
    bool finished = false;
    while (!finished &&
            ReadConsoleInputW(conin, records, 32, &actual) && actual >= 1) {
        StringBuilder sb;
        for (DWORD i = 0; i < actual; ++i) {
            const INPUT_RECORD &record = records[i];
            if (record.EventType == KEY_EVENT) {
                const KEY_EVENT_RECORD &ker = record.Event.KeyEvent;
                InputMap::Key key = {
                    ker.wVirtualKeyCode,
                    ker.uChar.UnicodeChar,
                    static_cast<uint16_t>(ker.dwControlKeyState),
                };
                sb << "key: " << (ker.bKeyDown ? "dn" : "up")
                   << " rpt=" << ker.wRepeatCount
                   << " scn=" << ker.wVirtualScanCode
                   << ' ' << key.toString() << '\n';
                if ((ker.dwControlKeyState &
                        (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) &&
                        ker.wVirtualKeyCode == 'D') {
                    finished = true;
                    break;
                } else if (ker.wVirtualKeyCode == 0 &&
                        ker.wVirtualScanCode == 0 &&
                        ker.uChar.UnicodeChar == 4) {
                    // Also look for a zeroed-out Ctrl-D record generated for
                    // ENABLE_VIRTUAL_TERMINAL_INPUT.
                    finished = true;
                    break;
                }
            } else if (record.EventType == MOUSE_EVENT) {
                const MOUSE_EVENT_RECORD &mer = record.Event.MouseEvent;
                sb << "mouse: " << mouseEventToString(mer) << '\n';
            } else if (record.EventType == WINDOW_BUFFER_SIZE_EVENT) {
                const WINDOW_BUFFER_SIZE_RECORD &wbsr =
                    record.Event.WindowBufferSizeEvent;
                sb << "buffer-resized: dwSize=("
                   << wbsr.dwSize.X << ','
                   << wbsr.dwSize.Y << ")\n";
            } else if (record.EventType == MENU_EVENT) {
                const MENU_EVENT_RECORD &mer = record.Event.MenuEvent;
                sb << "menu-event: commandId=0x"
                   << hexOfInt(mer.dwCommandId) << '\n';
            } else if (record.EventType == FOCUS_EVENT) {
                const FOCUS_EVENT_RECORD &fer = record.Event.FocusEvent;
                sb << "focus: " << (fer.bSetFocus ? "gained" : "lost") << '\n';
            }
        }

        const auto str = sb.str_moved();
        fwrite(str.data(), 1, str.size(), stdout);
        fflush(stdout);
    }
    SetConsoleMode(conin, restoreConsoleMode);
}
<|endoftext|>