<commit_before>// Copyright (c) 2014 Baidu, Inc.G
//
// 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.
//
// Authors: Lei He (helei@qiyi.com)

#include <cmath>
#include <gflags/gflags.h>
#include "brpc/errno.pb.h"
#include "brpc/policy/auto_concurrency_limiter.h"

namespace brpc {
namespace policy {

DEFINE_int32(auto_cl_sample_window_size_ms, 1000, "Duration of the sampling window.");
DEFINE_int32(auto_cl_min_sample_count, 100,
             "During the duration of the sampling window, if the number of "
             "requests collected is less than this value, the sampling window "
             "will be discarded.");
DEFINE_int32(auto_cl_max_sample_count, 500,
             "During the duration of the sampling window, once the number of "
             "requests collected is greater than this value, even if the "
             "duration of the window has not ended, the max_concurrency will "
             "be updated and a new sampling window will be started.");
DEFINE_double(auto_cl_sampling_interval_ms, 0.1,
             "Interval for sampling request in auto concurrency limiter");
DEFINE_int32(auto_cl_initial_max_concurrency, 40,
             "Initial max concurrency for grandient concurrency limiter");
DEFINE_int32(auto_cl_noload_latency_remeasure_interval_ms, 50000,
             "Interval for remeasurement of noload_latency. In the period of "
             "remeasurement of noload_latency will halve max_concurrency.");
DEFINE_double(auto_cl_alpha_factor_for_ema, 0.1,
              "The smoothing coefficient used in the calculation of ema, "
              "the value range is 0-1. The smaller the value, the smaller "
              "the effect of a single sample_window on max_concurrency.");
DEFINE_double(auto_cl_overload_threshold, 0.3,
              "Expected ratio of latency fluctuations");
DEFINE_bool(auto_cl_enable_error_punish, true,
            "Whether to consider failed requests when calculating maximum concurrency");
DEFINE_double(auto_cl_fail_punish_ratio, 1.0,
              "Use the failed requests to punish normal requests. The larger "
              "the configuration item, the more aggressive the penalty strategy.");

static int32_t cast_max_concurrency(void* arg) {
    return *(int32_t*) arg;
}

AutoConcurrencyLimiter::AutoConcurrencyLimiter()
    : _remeasure_start_us(NextResetTime(butil::gettimeofday_us()))
    , _reset_latency_us(0)
    , _min_latency_us(-1)
    , _ema_peak_qps(-1)
    , _ema_factor(FLAGS_auto_cl_alpha_factor_for_ema)
    , _overload_threshold(FLAGS_auto_cl_overload_threshold)
    , _max_concurrency_bvar(cast_max_concurrency, &_max_concurrency)
    , _last_sampling_time_us(0)
    , _total_succ_req(0)
    , _current_concurrency(0) {
    _max_concurrency = FLAGS_auto_cl_initial_max_concurrency;
}

int AutoConcurrencyLimiter::Expose(const butil::StringPiece& prefix) {
    if (_max_concurrency_bvar.expose_as(prefix, "auto_cl_max_concurrency") != 0) {
        return -1;
    }
    return 0;
}

AutoConcurrencyLimiter* AutoConcurrencyLimiter::New() const {
    return new (std::nothrow) AutoConcurrencyLimiter;
}

void AutoConcurrencyLimiter::Destroy() {
    delete this;
}

bool AutoConcurrencyLimiter::OnRequested() {
    const int32_t current_concurrency =
        _current_concurrency.fetch_add(1, butil::memory_order_relaxed);
    if (current_concurrency >= _max_concurrency) {
        return false;
    }
    return true;
}

void AutoConcurrencyLimiter::OnResponded(int error_code, int64_t latency_us) {
    _current_concurrency.fetch_sub(1, butil::memory_order_relaxed);
    if (0 == error_code) {
        _total_succ_req.fetch_add(1, butil::memory_order_relaxed);
    } else if (ELIMIT == error_code) {
        return;
    }

    int64_t now_time_us = butil::gettimeofday_us();
    int64_t last_sampling_time_us =
        _last_sampling_time_us.load(butil::memory_order_relaxed);

    if (last_sampling_time_us == 0 ||
        now_time_us - last_sampling_time_us >=
            FLAGS_auto_cl_sampling_interval_ms * 1000) {
        bool sample_this_call = _last_sampling_time_us.compare_exchange_strong(
            last_sampling_time_us, now_time_us, butil::memory_order_relaxed);
        if (sample_this_call) {
            int32_t max_concurrency = AddSample(error_code, latency_us, now_time_us);
            if (max_concurrency != 0) {
                LOG_EVERY_N(INFO, 60)
                    << "MaxConcurrency updated by auto limiter,"
                    << "current_max_concurrency:" << max_concurrency << " " << _min_latency_us;
            }
        }
    }
}

int64_t AutoConcurrencyLimiter::NextResetTime(int64_t sampling_time_us) {
    int64_t reset_start_us = sampling_time_us +
        (FLAGS_auto_cl_noload_latency_remeasure_interval_ms / 2 +
        butil::fast_rand_less_than(FLAGS_auto_cl_noload_latency_remeasure_interval_ms / 2)) * 1000;
    return reset_start_us;
}

int32_t AutoConcurrencyLimiter::AddSample(int error_code,
                                          int64_t latency_us,
                                          int64_t sampling_time_us) {
    std::unique_lock<butil::Mutex> lock_guard(_sw_mutex);
    // Waiting for the current concurrent decline
    if (_reset_latency_us > sampling_time_us) {
        return 0;
    }

    // Remeasure min_latency when concurrency has dropped to low load
    if (_reset_latency_us > 0) {
        _min_latency_us = -1;
        _reset_latency_us = 0;
        _remeasure_start_us = NextResetTime(sampling_time_us);
        ResetSampleWindow(sampling_time_us);
    }

    if (_sw.start_time_us == 0) {
        _sw.start_time_us = sampling_time_us;
    }

    if (error_code != 0 && FLAGS_auto_cl_enable_error_punish) {
        ++_sw.failed_count;
        _sw.total_failed_us += latency_us;
    } else if (error_code == 0) {
        ++_sw.succ_count;
        _sw.total_succ_us += latency_us;
    }

    if (_sw.succ_count + _sw.failed_count < FLAGS_auto_cl_min_sample_count) {
        if (sampling_time_us - _sw.start_time_us >=
            FLAGS_auto_cl_sample_window_size_ms * 1000) {
            // If the sample size is insufficient at the end of the sampling
            // window, discard the entire sampling window
            ResetSampleWindow(sampling_time_us);
        }
        return 0;
    }
    if (sampling_time_us - _sw.start_time_us <
        FLAGS_auto_cl_sample_window_size_ms * 1000 &&
        _sw.succ_count + _sw.failed_count < FLAGS_auto_cl_max_sample_count) {
        return 0;
    }

    if(_sw.succ_count > 0) {
        int max_concurrency = UpdateMaxConcurrency(sampling_time_us);
        ResetSampleWindow(sampling_time_us);
        return max_concurrency;
    } else {
        // All request failed
        _max_concurrency /= 2;
        ResetSampleWindow(sampling_time_us);
        return 0;
    }
}

void AutoConcurrencyLimiter::ResetSampleWindow(int64_t sampling_time_us) {
    _sw.start_time_us = sampling_time_us;
    _sw.succ_count = 0;
    _sw.failed_count = 0;
    _sw.total_failed_us = 0;
    _sw.total_succ_us = 0;
}

void AutoConcurrencyLimiter::UpdateMinLatency(int64_t latency_us) {
    if (_min_latency_us <= 0) {
        _min_latency_us = latency_us;
    } else if (latency_us < _min_latency_us) {
        _min_latency_us = latency_us * _ema_factor + _min_latency_us * (1 - _ema_factor);
    }
}

void AutoConcurrencyLimiter::UpdateQps(int32_t succ_count,
                                       int64_t sampling_time_us) {
    double qps = 1000000.0 * succ_count / (sampling_time_us - _sw.start_time_us);

    if (qps >= _ema_peak_qps) {
        _ema_peak_qps = qps;
    } else {
        _ema_peak_qps =
            qps * (_ema_factor / 10) + _ema_peak_qps * (1 - _ema_factor / 10);
    }
}

int32_t AutoConcurrencyLimiter::UpdateMaxConcurrency(int64_t sampling_time_us) {
    int32_t total_succ_req =
        _total_succ_req.exchange(0, butil::memory_order_relaxed);
    double failed_punish =
        _sw.total_failed_us * FLAGS_auto_cl_fail_punish_ratio;
    int64_t avg_latency =
        std::ceil((failed_punish + _sw.total_succ_us) / _sw.succ_count);
    UpdateMinLatency(avg_latency);
    UpdateQps(total_succ_req, sampling_time_us);

    int next_max_concurrency = 0;
    // Remeasure min_latency at regular intervals
    if (_remeasure_start_us <= sampling_time_us) {
        _reset_latency_us = sampling_time_us + avg_latency * 2;
        next_max_concurrency = _max_concurrency * 0.75;
    } else {
        int32_t noload_concurrency =
            std::ceil(_min_latency_us * _ema_peak_qps / 1000000);
        if (avg_latency < (1.0 + _overload_threshold) * _min_latency_us) {
            next_max_concurrency = std::ceil(noload_concurrency *
                (2.0 + _overload_threshold - double(avg_latency) / _min_latency_us));
        } else {
            next_max_concurrency = noload_concurrency;
        }
    }

    if (next_max_concurrency != _max_concurrency) {
        _max_concurrency = next_max_concurrency;
    }
    return next_max_concurrency;
}

}  // namespace policy
}  // namespace brpc
<commit_msg>Modify the default value of auto_cl_max_sample_count<commit_after>// Copyright (c) 2014 Baidu, Inc.G
//
// 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.
//
// Authors: Lei He (helei@qiyi.com)

#include <cmath>
#include <gflags/gflags.h>
#include "brpc/errno.pb.h"
#include "brpc/policy/auto_concurrency_limiter.h"

namespace brpc {
namespace policy {

DEFINE_int32(auto_cl_sample_window_size_ms, 1000, "Duration of the sampling window.");
DEFINE_int32(auto_cl_min_sample_count, 100,
             "During the duration of the sampling window, if the number of "
             "requests collected is less than this value, the sampling window "
             "will be discarded.");
DEFINE_int32(auto_cl_max_sample_count, 200,
             "During the duration of the sampling window, once the number of "
             "requests collected is greater than this value, even if the "
             "duration of the window has not ended, the max_concurrency will "
             "be updated and a new sampling window will be started.");
DEFINE_double(auto_cl_sampling_interval_ms, 0.1,
             "Interval for sampling request in auto concurrency limiter");
DEFINE_int32(auto_cl_initial_max_concurrency, 40,
             "Initial max concurrency for grandient concurrency limiter");
DEFINE_int32(auto_cl_noload_latency_remeasure_interval_ms, 50000,
             "Interval for remeasurement of noload_latency. In the period of "
             "remeasurement of noload_latency will halve max_concurrency.");
DEFINE_double(auto_cl_alpha_factor_for_ema, 0.1,
              "The smoothing coefficient used in the calculation of ema, "
              "the value range is 0-1. The smaller the value, the smaller "
              "the effect of a single sample_window on max_concurrency.");
DEFINE_double(auto_cl_overload_threshold, 0.3,
              "Expected ratio of latency fluctuations");
DEFINE_bool(auto_cl_enable_error_punish, true,
            "Whether to consider failed requests when calculating maximum concurrency");
DEFINE_double(auto_cl_fail_punish_ratio, 1.0,
              "Use the failed requests to punish normal requests. The larger "
              "the configuration item, the more aggressive the penalty strategy.");

static int32_t cast_max_concurrency(void* arg) {
    return *(int32_t*) arg;
}

AutoConcurrencyLimiter::AutoConcurrencyLimiter()
    : _remeasure_start_us(NextResetTime(butil::gettimeofday_us()))
    , _reset_latency_us(0)
    , _min_latency_us(-1)
    , _ema_peak_qps(-1)
    , _ema_factor(FLAGS_auto_cl_alpha_factor_for_ema)
    , _overload_threshold(FLAGS_auto_cl_overload_threshold)
    , _max_concurrency_bvar(cast_max_concurrency, &_max_concurrency)
    , _last_sampling_time_us(0)
    , _total_succ_req(0)
    , _current_concurrency(0) {
    _max_concurrency = FLAGS_auto_cl_initial_max_concurrency;
}

int AutoConcurrencyLimiter::Expose(const butil::StringPiece& prefix) {
    if (_max_concurrency_bvar.expose_as(prefix, "auto_cl_max_concurrency") != 0) {
        return -1;
    }
    return 0;
}

AutoConcurrencyLimiter* AutoConcurrencyLimiter::New() const {
    return new (std::nothrow) AutoConcurrencyLimiter;
}

void AutoConcurrencyLimiter::Destroy() {
    delete this;
}

bool AutoConcurrencyLimiter::OnRequested() {
    const int32_t current_concurrency =
        _current_concurrency.fetch_add(1, butil::memory_order_relaxed);
    if (current_concurrency >= _max_concurrency) {
        return false;
    }
    return true;
}

void AutoConcurrencyLimiter::OnResponded(int error_code, int64_t latency_us) {
    _current_concurrency.fetch_sub(1, butil::memory_order_relaxed);
    if (0 == error_code) {
        _total_succ_req.fetch_add(1, butil::memory_order_relaxed);
    } else if (ELIMIT == error_code) {
        return;
    }

    int64_t now_time_us = butil::gettimeofday_us();
    int64_t last_sampling_time_us =
        _last_sampling_time_us.load(butil::memory_order_relaxed);

    if (last_sampling_time_us == 0 ||
        now_time_us - last_sampling_time_us >=
            FLAGS_auto_cl_sampling_interval_ms * 1000) {
        bool sample_this_call = _last_sampling_time_us.compare_exchange_strong(
            last_sampling_time_us, now_time_us, butil::memory_order_relaxed);
        if (sample_this_call) {
            int32_t max_concurrency = AddSample(error_code, latency_us, now_time_us);
            if (max_concurrency != 0) {
                LOG_EVERY_N(INFO, 60)
                    << "MaxConcurrency updated by auto limiter,"
                    << "current_max_concurrency:" << max_concurrency
                    << ", min_latency_us: " << _min_latency_us;
            }
        }
    }
}

int64_t AutoConcurrencyLimiter::NextResetTime(int64_t sampling_time_us) {
    int64_t reset_start_us = sampling_time_us +
        (FLAGS_auto_cl_noload_latency_remeasure_interval_ms / 2 +
        butil::fast_rand_less_than(FLAGS_auto_cl_noload_latency_remeasure_interval_ms / 2)) * 1000;
    return reset_start_us;
}

int32_t AutoConcurrencyLimiter::AddSample(int error_code,
                                          int64_t latency_us,
                                          int64_t sampling_time_us) {
    std::unique_lock<butil::Mutex> lock_guard(_sw_mutex);
    // Waiting for the current concurrent decline
    if (_reset_latency_us > sampling_time_us) {
        return 0;
    }

    // Remeasure min_latency when concurrency has dropped to low load
    if (_reset_latency_us > 0) {
        _min_latency_us = -1;
        _reset_latency_us = 0;
        _remeasure_start_us = NextResetTime(sampling_time_us);
        ResetSampleWindow(sampling_time_us);
    }

    if (_sw.start_time_us == 0) {
        _sw.start_time_us = sampling_time_us;
    }

    if (error_code != 0 && FLAGS_auto_cl_enable_error_punish) {
        ++_sw.failed_count;
        _sw.total_failed_us += latency_us;
    } else if (error_code == 0) {
        ++_sw.succ_count;
        _sw.total_succ_us += latency_us;
    }

    if (_sw.succ_count + _sw.failed_count < FLAGS_auto_cl_min_sample_count) {
        if (sampling_time_us - _sw.start_time_us >=
            FLAGS_auto_cl_sample_window_size_ms * 1000) {
            // If the sample size is insufficient at the end of the sampling
            // window, discard the entire sampling window
            ResetSampleWindow(sampling_time_us);
        }
        return 0;
    }
    if (sampling_time_us - _sw.start_time_us <
        FLAGS_auto_cl_sample_window_size_ms * 1000 &&
        _sw.succ_count + _sw.failed_count < FLAGS_auto_cl_max_sample_count) {
        return 0;
    }

    if(_sw.succ_count > 0) {
        int max_concurrency = UpdateMaxConcurrency(sampling_time_us);
        ResetSampleWindow(sampling_time_us);
        return max_concurrency;
    } else {
        // All request failed
        _max_concurrency /= 2;
        ResetSampleWindow(sampling_time_us);
        return 0;
    }
}

void AutoConcurrencyLimiter::ResetSampleWindow(int64_t sampling_time_us) {
    _sw.start_time_us = sampling_time_us;
    _sw.succ_count = 0;
    _sw.failed_count = 0;
    _sw.total_failed_us = 0;
    _sw.total_succ_us = 0;
}

void AutoConcurrencyLimiter::UpdateMinLatency(int64_t latency_us) {
    if (_min_latency_us <= 0) {
        _min_latency_us = latency_us;
    } else if (latency_us < _min_latency_us) {
        _min_latency_us = latency_us * _ema_factor + _min_latency_us * (1 - _ema_factor);
    }
}

void AutoConcurrencyLimiter::UpdateQps(int32_t succ_count,
                                       int64_t sampling_time_us) {
    double qps = 1000000.0 * succ_count / (sampling_time_us - _sw.start_time_us);

    if (qps >= _ema_peak_qps) {
        _ema_peak_qps = qps;
    } else {
        _ema_peak_qps =
            qps * (_ema_factor / 10) + _ema_peak_qps * (1 - _ema_factor / 10);
    }
}

int32_t AutoConcurrencyLimiter::UpdateMaxConcurrency(int64_t sampling_time_us) {
    int32_t total_succ_req =
        _total_succ_req.exchange(0, butil::memory_order_relaxed);
    double failed_punish =
        _sw.total_failed_us * FLAGS_auto_cl_fail_punish_ratio;
    int64_t avg_latency =
        std::ceil((failed_punish + _sw.total_succ_us) / _sw.succ_count);
    UpdateMinLatency(avg_latency);
    UpdateQps(total_succ_req, sampling_time_us);

    int next_max_concurrency = 0;
    // Remeasure min_latency at regular intervals
    if (_remeasure_start_us <= sampling_time_us) {
        _reset_latency_us = sampling_time_us + avg_latency * 2;
        next_max_concurrency = _max_concurrency * 0.75;
    } else {
        int32_t noload_concurrency =
            std::ceil(_min_latency_us * _ema_peak_qps / 1000000);
        if (avg_latency < (1.0 + _overload_threshold) * _min_latency_us) {
            next_max_concurrency = std::ceil(noload_concurrency *
                (2.0 + _overload_threshold - double(avg_latency) / _min_latency_us));
        } else {
            next_max_concurrency = noload_concurrency;
        }
    }

    if (next_max_concurrency != _max_concurrency) {
        _max_concurrency = next_max_concurrency;
    }
    return next_max_concurrency;
}

}  // namespace policy
}  // namespace brpc
<|endoftext|>


<commit_before>/*
   This file is part of the clazy static checker.

  Copyright (C) 2016 Sergio Martins <smartins@kde.org>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 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
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "function-args-by-value.h"
#include "Utils.h"
#include "checkmanager.h"
#include "StringUtils.h"
#include "TypeUtils.h"
#include "FixItUtils.h"

#include <clang/AST/AST.h>
#include <clang/Lex/Lexer.h>

using namespace clang;
using namespace std;

enum Fixit {
    FixitNone = 0,
    FixitAll = 0x1 // More granularity isn't needed I guess
};

// TODO, go over all these
static bool shouldIgnoreClass(CXXRecordDecl *record)
{
    if (!record)
        return false;

    if (Utils::isSharedPointer(record))
        return true;

    static const vector<string> ignoreList = {"QDebug", // Too many warnings
                                              "QGenericReturnArgument",
                                              "QColor", // TODO: Remove in Qt6
                                              "QStringRef", // TODO: Remove in Qt6
                                              "QList::const_iterator", // TODO: Remove in Qt6
                                              "QJsonArray::const_iterator", // TODO: Remove in Qt6
                                              "QList<QString>::const_iterator",  // TODO: Remove in Qt6
                                              "QtMetaTypePrivate::QSequentialIterableImpl",
                                              "QtMetaTypePrivate::QAssociativeIterableImpl",
                                              "QVariantComparisonHelper",
                                              "QHashDummyValue", "QCharRef", "QString::Null"
                                             };
    return clazy_std::contains(ignoreList, record->getQualifiedNameAsString());
}

static bool shouldIgnoreFunction(clang::FunctionDecl *function)
{
    // Too many warnings in operator<<
    static const vector<string> ignoreList = {"operator<<"};
    static const vector<string> qualifiedIgnoreList = {"QDBusMessage::createErrorReply", // Fixed in Qt6
                                                       "QMenu::exec", // Fixed in Qt6
                                                       "QTextFrame::iterator", // Fixed in Qt6
                                                       "QGraphicsWidget::addActions", // Fixed in Qt6
                                                       "QListWidget::mimeData", // Fixed in Qt6
                                                       "QTableWidget::mimeData", // Fixed in Qt6
                                                       "QTreeWidget::mimeData", // Fixed in Qt6
                                                       "QWidget::addActions", // Fixed in Qt6
                                                       "QSslCertificate::verify", // Fixed in Qt6
                                                       "QSslConfiguration::setAllowedNextProtocols" // Fixed in Qt6
                                                      };
    if (clazy_std::contains(ignoreList, function->getNameAsString()))
        return true;

    return clazy_std::contains(qualifiedIgnoreList, function->getQualifiedNameAsString());
}

FunctionArgsByValue::FunctionArgsByValue(const std::string &name, ClazyContext *context)
    : CheckBase(name, context)
{
    m_filesToIgnore = {"/c++/",
                       "qimage.cpp", // TODO: Uncomment in Qt6
                       "qimage.h",    // TODO: Uncomment in Qt6
                       "qevent.h", // TODO: Uncomment in Qt6
                       "avxintrin.h",
                       "avx2intrin.h",
                       "qnoncontiguousbytedevice.cpp",
                       "qlocale_unix.cpp",
                       "/clang/",
                       "qmetatype.h", // TODO: fix in Qt
                       "qbytearray.h" // TODO: fix in Qt
                      };
}

void FunctionArgsByValue::VisitDecl(Decl *decl)
{
    processFunction(dyn_cast<FunctionDecl>(decl));
}

void FunctionArgsByValue::VisitStmt(Stmt *stmt)
{
    if (LambdaExpr *lambda = dyn_cast<LambdaExpr>(stmt)) {
        if (!shouldIgnoreFile(stmt->getLocStart()))
            processFunction(lambda->getCallOperator());
    }
}

void FunctionArgsByValue::processFunction(FunctionDecl *func)
{
    if (!func || shouldIgnoreFunction(func) ||
        !func->isThisDeclarationADefinition() || func->isDeleted())
        return;

    if (shouldIgnoreFile(func->getLocStart()))
        return;

    Stmt *body = func->getBody();

    int i = -1;
    for (auto param : Utils::functionParameters(func)) {
        i++;
        QualType paramQt = TypeUtils::unrefQualType(param->getType());
        const Type *paramType = paramQt.getTypePtrOrNull();
        if (!paramType || paramType->isIncompleteType() || paramType->isDependentType())
            continue;

        if (shouldIgnoreClass(paramType->getAsCXXRecordDecl()))
            continue;

        TypeUtils::QualTypeClassification classif;
        bool success = TypeUtils::classifyQualType(&m_astContext, param, classif, body);
        if (!success)
            continue;

        if (classif.passSmallTrivialByValue) {
            std::vector<FixItHint> fixits;
            if (isFixitEnabled(FixitAll)) {
                for (auto redecl : func->redecls()) { // Fix in both header and .cpp
                    FunctionDecl *fdecl = dyn_cast<FunctionDecl>(redecl);
                    const ParmVarDecl *param = fdecl->getParamDecl(i);
                    fixits.push_back(fixit(fdecl, param, classif));
                }
            }

            const string paramStr = param->getType().getAsString();
            string error = "Pass small and trivially-copyable type by value (" + paramStr + ')';
            emitWarning(param->getLocStart(), error.c_str(), fixits);
        }
    }
}

FixItHint FunctionArgsByValue::fixit(FunctionDecl *func, const ParmVarDecl *param,
                                     TypeUtils::QualTypeClassification)
{
    QualType qt = TypeUtils::unrefQualType(param->getType());
    qt.removeLocalConst();
    const string typeName = qt.getAsString(PrintingPolicy(lo()));
    string replacement = typeName + ' ' + string(param->getName());
    SourceLocation startLoc = param->getLocStart();
    SourceLocation endLoc = param->getLocEnd();

    const int numRedeclarations = std::distance(func->redecls_begin(), func->redecls_end());
    const bool definitionIsAlsoDeclaration = numRedeclarations == 1;
    const bool isDeclarationButNotDefinition = !func->doesThisDeclarationHaveABody();

    if (param->hasDefaultArg() && (isDeclarationButNotDefinition || definitionIsAlsoDeclaration)) {
        endLoc = param->getDefaultArg()->getLocStart().getLocWithOffset(-1);
        replacement += " =";
    }

    if (!startLoc.isValid() || !endLoc.isValid()) {
        llvm::errs() << "Internal error could not apply fixit " << startLoc.printToString(sm())
                     << ';' << endLoc.printToString(sm()) << "\n";
        return {};
    }

    return FixItUtils::createReplacement({ startLoc, endLoc }, replacement);
}

REGISTER_CHECK("function-args-by-value", FunctionArgsByValue, CheckLevel2)
<commit_msg>function-args-by-value: Don't warn in copy-ctors<commit_after>/*
   This file is part of the clazy static checker.

  Copyright (C) 2016-2017 Sergio Martins <smartins@kde.org>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 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
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "function-args-by-value.h"
#include "Utils.h"
#include "checkmanager.h"
#include "StringUtils.h"
#include "TypeUtils.h"
#include "FixItUtils.h"

#include <clang/AST/AST.h>
#include <clang/Lex/Lexer.h>

using namespace clang;
using namespace std;

enum Fixit {
    FixitNone = 0,
    FixitAll = 0x1 // More granularity isn't needed I guess
};

// TODO, go over all these
static bool shouldIgnoreClass(CXXRecordDecl *record)
{
    if (!record)
        return false;

    if (Utils::isSharedPointer(record))
        return true;

    static const vector<string> ignoreList = {"QDebug", // Too many warnings
                                              "QGenericReturnArgument",
                                              "QColor", // TODO: Remove in Qt6
                                              "QStringRef", // TODO: Remove in Qt6
                                              "QList::const_iterator", // TODO: Remove in Qt6
                                              "QJsonArray::const_iterator", // TODO: Remove in Qt6
                                              "QList<QString>::const_iterator",  // TODO: Remove in Qt6
                                              "QtMetaTypePrivate::QSequentialIterableImpl",
                                              "QtMetaTypePrivate::QAssociativeIterableImpl",
                                              "QVariantComparisonHelper",
                                              "QHashDummyValue", "QCharRef", "QString::Null"
                                             };
    return clazy_std::contains(ignoreList, record->getQualifiedNameAsString());
}

static bool shouldIgnoreFunction(clang::FunctionDecl *function)
{
    // Too many warnings in operator<<
    static const vector<string> ignoreList = {"operator<<"};
    static const vector<string> qualifiedIgnoreList = {"QDBusMessage::createErrorReply", // Fixed in Qt6
                                                       "QMenu::exec", // Fixed in Qt6
                                                       "QTextFrame::iterator", // Fixed in Qt6
                                                       "QGraphicsWidget::addActions", // Fixed in Qt6
                                                       "QListWidget::mimeData", // Fixed in Qt6
                                                       "QTableWidget::mimeData", // Fixed in Qt6
                                                       "QTreeWidget::mimeData", // Fixed in Qt6
                                                       "QWidget::addActions", // Fixed in Qt6
                                                       "QSslCertificate::verify", // Fixed in Qt6
                                                       "QSslConfiguration::setAllowedNextProtocols" // Fixed in Qt6
                                                      };
    if (clazy_std::contains(ignoreList, function->getNameAsString()))
        return true;

    return clazy_std::contains(qualifiedIgnoreList, function->getQualifiedNameAsString());
}

FunctionArgsByValue::FunctionArgsByValue(const std::string &name, ClazyContext *context)
    : CheckBase(name, context)
{
    m_filesToIgnore = {"/c++/",
                       "qimage.cpp", // TODO: Uncomment in Qt6
                       "qimage.h",    // TODO: Uncomment in Qt6
                       "qevent.h", // TODO: Uncomment in Qt6
                       "avxintrin.h",
                       "avx2intrin.h",
                       "qnoncontiguousbytedevice.cpp",
                       "qlocale_unix.cpp",
                       "/clang/",
                       "qmetatype.h", // TODO: fix in Qt
                       "qbytearray.h" // TODO: fix in Qt
                      };
}

void FunctionArgsByValue::VisitDecl(Decl *decl)
{
    processFunction(dyn_cast<FunctionDecl>(decl));
}

void FunctionArgsByValue::VisitStmt(Stmt *stmt)
{
    if (LambdaExpr *lambda = dyn_cast<LambdaExpr>(stmt)) {
        if (!shouldIgnoreFile(stmt->getLocStart()))
            processFunction(lambda->getCallOperator());
    }
}

void FunctionArgsByValue::processFunction(FunctionDecl *func)
{
    if (!func || shouldIgnoreFunction(func) ||
        !func->isThisDeclarationADefinition() || func->isDeleted())
        return;

    if (shouldIgnoreFile(func->getLocStart()))
        return;

    if (auto ctor = dyn_cast<CXXConstructorDecl>(func)) {
        if (ctor->isCopyConstructor())
            return; // copy-ctor must take by ref
    }

    Stmt *body = func->getBody();

    int i = -1;
    for (auto param : Utils::functionParameters(func)) {
        i++;
        QualType paramQt = TypeUtils::unrefQualType(param->getType());
        const Type *paramType = paramQt.getTypePtrOrNull();
        if (!paramType || paramType->isIncompleteType() || paramType->isDependentType())
            continue;

        if (shouldIgnoreClass(paramType->getAsCXXRecordDecl()))
            continue;

        TypeUtils::QualTypeClassification classif;
        bool success = TypeUtils::classifyQualType(&m_astContext, param, classif, body);
        if (!success)
            continue;

        if (classif.passSmallTrivialByValue) {
            std::vector<FixItHint> fixits;
            if (isFixitEnabled(FixitAll)) {
                for (auto redecl : func->redecls()) { // Fix in both header and .cpp
                    FunctionDecl *fdecl = dyn_cast<FunctionDecl>(redecl);
                    const ParmVarDecl *param = fdecl->getParamDecl(i);
                    fixits.push_back(fixit(fdecl, param, classif));
                }
            }

            const string paramStr = param->getType().getAsString();
            string error = "Pass small and trivially-copyable type by value (" + paramStr + ')';
            emitWarning(param->getLocStart(), error.c_str(), fixits);
        }
    }
}

FixItHint FunctionArgsByValue::fixit(FunctionDecl *func, const ParmVarDecl *param,
                                     TypeUtils::QualTypeClassification)
{
    QualType qt = TypeUtils::unrefQualType(param->getType());
    qt.removeLocalConst();
    const string typeName = qt.getAsString(PrintingPolicy(lo()));
    string replacement = typeName + ' ' + string(param->getName());
    SourceLocation startLoc = param->getLocStart();
    SourceLocation endLoc = param->getLocEnd();

    const int numRedeclarations = std::distance(func->redecls_begin(), func->redecls_end());
    const bool definitionIsAlsoDeclaration = numRedeclarations == 1;
    const bool isDeclarationButNotDefinition = !func->doesThisDeclarationHaveABody();

    if (param->hasDefaultArg() && (isDeclarationButNotDefinition || definitionIsAlsoDeclaration)) {
        endLoc = param->getDefaultArg()->getLocStart().getLocWithOffset(-1);
        replacement += " =";
    }

    if (!startLoc.isValid() || !endLoc.isValid()) {
        llvm::errs() << "Internal error could not apply fixit " << startLoc.printToString(sm())
                     << ';' << endLoc.printToString(sm()) << "\n";
        return {};
    }

    return FixItUtils::createReplacement({ startLoc, endLoc }, replacement);
}

REGISTER_CHECK("function-args-by-value", FunctionArgsByValue, CheckLevel2)
<|endoftext|>


<commit_before>#include <getopt.h>
#include <string>
#include <math.h>

#include <boost/lexical_cast.hpp>

#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include <libwatcher/client.h>
#include <libwatcher/gpsMessage.h>
#include <libwatcher/labelMessage.h>
#include <libwatcher/edgeMessage.h>
#include <libwatcher/watcherColors.h>
#include "logger.h"
#include "sendMessageHandler.h"

using namespace std;
using namespace watcher;
using namespace watcher::event;
using namespace boost;

#define PI (3.141592653589793) // Isn't this #DEFINEd somewhere?

void usage(const char *progName)
{
    fprintf(stderr, "Usage: %s [args]\n", basename(progName));
    fprintf(stderr, "Args:\n");
    fprintf(stderr, "   -s, --server=address        The addres of the node running watcherd\n");
    fprintf(stderr, "\n");
    fprintf(stderr, "Optional args:\n");
    fprintf(stderr, "   -p, --logProps              log.properties file, which controls logging for this program\n");
    fprintf(stderr, "   -r, --radius                The radius of the circle in some unknown unit\n");
    fprintf(stderr, "\n");
    fprintf(stderr, "   -h, --help                  Show this message\n");

    exit(1);
}

int main(int argc, char **argv)
{
    TRACE_ENTER();

    int c;
    string server;
    string logProps(string(basename(argv[0]))+string(".log.properties"));
    double radius=50.0;

    while (true)
    {
        int option_index = 0;
        static struct option long_options[] = {
            {"server", required_argument, 0, 's'},
            {"logProps", required_argument, 0, 'p'},
            {"radius", required_argument, 0, 'r'},
            {"help", no_argument, 0, 'h'},
            {0, 0, 0, 0}
        };

        c = getopt_long(argc, argv, "r:s:p:hH?", long_options, &option_index);

        if (c == -1)
            break;

        switch(c)
        {
            case 's':
                server=optarg;
                break;
            case 'p':
                logProps=optarg;
                break;
            case 'r':
                radius=lexical_cast<double>(optarg);
                break;
            case 'h':
            case 'H':
            case '?':
            default:
                usage(argv[0]);
                break;
        }
    }

    if (server=="")
    {
        usage(argv[0]);
        exit(1);
    }

    //
    // Now do some actual work.
    //
    LOAD_LOG_PROPS(logProps);

    Client client(server);
    LOG_INFO("Connecting to " << server << " and sending message.");
    // Do not add empty handler - default Client handler does not close connection.
    // client.addMessageHandler(SendMessageHandler::create());

    unsigned int loopTime=1;
    // Create hour, min, sec, and center nodes.
    NodeIdentifier centerId=NodeIdentifier::from_string("192.168.1.100");
    NodeIdentifier hourId=NodeIdentifier::from_string("192.168.1.101");
    NodeIdentifier minId=NodeIdentifier::from_string("192.168.1.102");
    NodeIdentifier secId=NodeIdentifier::from_string("192.168.1.103");

    const GUILayer layer("Clock");
    const double step=(2*PI)/60;
    struct
    {
        double theta;
        NodeIdentifier *id;
        const char *label;
        Color color;
    } nodeData[]=
    {
        { 0,   &hourId, "hour", Color::red },
        { 0,    &minId,  "min", Color::blue },
        { 0,    &secId,  "sec", Color::green },
    };
    while (true)  // draw everything all the time as we don't know when watcher will start
    {
        // Draw center node
        GPSMessagePtr gpsMess(new GPSMessage(radius, radius, 0));
        gpsMess->layer=layer;
        gpsMess->fromNodeID=centerId;
        if(!client.sendMessage(gpsMess))
        {
            LOG_ERROR("Error sending gps message: " << *gpsMess);
            TRACE_EXIT_RET(EXIT_FAILURE);
            return EXIT_FAILURE;
        }
        // draw hour, min, and second nodes, connecting them to center.
        for (unsigned int i=0; i<sizeof(nodeData)/sizeof(nodeData[0]); i++)
        {
            // update location offsets by current time.
            time_t nowInSecs=time(NULL);
            struct tm *now=localtime(&nowInSecs);
            if (*nodeData[i].id==hourId)
                nodeData[i].theta=step*((now->tm_hour*(60/12))+(now->tm_min/12));
            else if(*nodeData[i].id==minId)
                nodeData[i].theta=step*now->tm_min;
            else if(*nodeData[i].id==secId)
                nodeData[i].theta=step*now->tm_sec;

            // Move hour. min, and sec nodes to appropriate locations.
            GPSMessagePtr gpsMess(new GPSMessage((sin(nodeData[i].theta)*radius)+radius, (cos(nodeData[i].theta)*radius)+radius, 0.0));
            gpsMess->layer=layer;
            gpsMess->fromNodeID=*nodeData[i].id;
            if(!client.sendMessage(gpsMess))
            {
                LOG_ERROR("Error sending gps message: " << *gpsMess);
                TRACE_EXIT_RET(EXIT_FAILURE);
                return EXIT_FAILURE;
            }

            LabelMessagePtr labMess(new LabelMessage(nodeData[i].label));
            labMess->layer=layer;
            labMess->expiration=loopTime*2000;  // 2000 to stop blinking
            EdgeMessagePtr edgeMess(new EdgeMessage(centerId, *nodeData[i].id, layer, nodeData[i].color, 2));
            edgeMess->middleLabel=labMess;
            if(!client.sendMessage(edgeMess))
            {
                LOG_ERROR("Error sending edge message: " << *edgeMess);
                TRACE_EXIT_RET(EXIT_FAILURE);
                return EXIT_FAILURE;
            }
        }

        // add nodes at clock face number locations.
        double theta=(2*PI)/12;
        for (unsigned int i=0; i<12; i++, theta+=(2*PI)/12)
        {
            NodeIdentifier thisId=NodeIdentifier::from_string("192.168.2." + lexical_cast<string>(i+1));
            double faceRad=radius*1.15;
            GPSMessagePtr gpsMess(new GPSMessage((sin(theta)*faceRad)+radius, (cos(theta)*faceRad)+radius, 0.0));
            gpsMess->layer=layer;
            gpsMess->fromNodeID=thisId;
            if(!client.sendMessage(gpsMess))
            {
                LOG_ERROR("Error sending gps message: " << *gpsMess);
                TRACE_EXIT_RET(EXIT_FAILURE);
                return EXIT_FAILURE;
            }
        }

        // add nodes at clock face second locations.
        theta=(2*PI)/60;
        for (unsigned int i=0; i<60; i++, theta+=(2*PI)/60)
        {
            NodeIdentifier thisId=NodeIdentifier::from_string("192.168.3." + lexical_cast<string>(i+1));
            double faceRad=radius*1.35;
            GPSMessagePtr gpsMess(new GPSMessage((sin(theta)*faceRad)+radius, (cos(theta)*faceRad)+radius, 0.0));
            gpsMess->layer=layer;
            gpsMess->fromNodeID=thisId;
            if(!client.sendMessage(gpsMess))
            {
                LOG_ERROR("Error sending gps message: " << *gpsMess);
                TRACE_EXIT_RET(EXIT_FAILURE);
                return EXIT_FAILURE;
            }
        }
        sleep(loopTime);
    }

    client.wait();

    TRACE_EXIT_RET(EXIT_SUCCESS);
    return EXIT_SUCCESS;
}

<commit_msg>stagger "hands" slightly on the z axis, so the colors blend when they are on top of each other.<commit_after>#include <getopt.h>
#include <string>
#include <math.h>

#include <boost/lexical_cast.hpp>

#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include <libwatcher/client.h>
#include <libwatcher/gpsMessage.h>
#include <libwatcher/labelMessage.h>
#include <libwatcher/edgeMessage.h>
#include <libwatcher/watcherColors.h>
#include "logger.h"
#include "sendMessageHandler.h"

using namespace std;
using namespace watcher;
using namespace watcher::event;
using namespace boost;

#define PI (3.141592653589793) // Isn't this #DEFINEd somewhere?

void usage(const char *progName)
{
    fprintf(stderr, "Usage: %s [args]\n", basename(progName));
    fprintf(stderr, "Args:\n");
    fprintf(stderr, "   -s, --server=address        The addres of the node running watcherd\n");
    fprintf(stderr, "\n");
    fprintf(stderr, "Optional args:\n");
    fprintf(stderr, "   -p, --logProps              log.properties file, which controls logging for this program\n");
    fprintf(stderr, "   -r, --radius                The radius of the circle in some unknown unit\n");
    fprintf(stderr, "\n");
    fprintf(stderr, "   -h, --help                  Show this message\n");

    exit(1);
}

int main(int argc, char **argv)
{
    TRACE_ENTER();

    int c;
    string server;
    string logProps(string(basename(argv[0]))+string(".log.properties"));
    double radius=50.0;

    while (true)
    {
        int option_index = 0;
        static struct option long_options[] = {
            {"server", required_argument, 0, 's'},
            {"logProps", required_argument, 0, 'p'},
            {"radius", required_argument, 0, 'r'},
            {"help", no_argument, 0, 'h'},
            {0, 0, 0, 0}
        };

        c = getopt_long(argc, argv, "r:s:p:hH?", long_options, &option_index);

        if (c == -1)
            break;

        switch(c)
        {
            case 's':
                server=optarg;
                break;
            case 'p':
                logProps=optarg;
                break;
            case 'r':
                radius=lexical_cast<double>(optarg);
                break;
            case 'h':
            case 'H':
            case '?':
            default:
                usage(argv[0]);
                break;
        }
    }

    if (server=="")
    {
        usage(argv[0]);
        exit(1);
    }

    //
    // Now do some actual work.
    //
    LOAD_LOG_PROPS(logProps);

    Client client(server);
    LOG_INFO("Connecting to " << server << " and sending message.");
    // Do not add empty handler - default Client handler does not close connection.
    // client.addMessageHandler(SendMessageHandler::create());

    unsigned int loopTime=1;
    // Create hour, min, sec, and center nodes.
    NodeIdentifier centerId=NodeIdentifier::from_string("192.168.1.100");
    NodeIdentifier hourId=NodeIdentifier::from_string("192.168.1.101");
    NodeIdentifier minId=NodeIdentifier::from_string("192.168.1.102");
    NodeIdentifier secId=NodeIdentifier::from_string("192.168.1.103");

    const GUILayer layer("Clock");
    const double step=(2*PI)/60;
    struct
    {
        double theta;
        NodeIdentifier *id;
        const char *label;
        Color color;
    } nodeData[]=
    {
        { 0,   &hourId, "hour", Color::red },
        { 0,    &minId,  "min", Color::blue },
        { 0,    &secId,  "sec", Color::green },
    };
    while (true)  // draw everything all the time as we don't know when watcher will start
    {
        // Draw center node
        GPSMessagePtr gpsMess(new GPSMessage(radius, radius, 0));
        gpsMess->layer=layer;
        gpsMess->fromNodeID=centerId;
        if(!client.sendMessage(gpsMess))
        {
            LOG_ERROR("Error sending gps message: " << *gpsMess);
            TRACE_EXIT_RET(EXIT_FAILURE);
            return EXIT_FAILURE;
        }
        // draw hour, min, and second nodes, connecting them to center.
        for (unsigned int i=0; i<sizeof(nodeData)/sizeof(nodeData[0]); i++)
        {
            // update location offsets by current time.
            time_t nowInSecs=time(NULL);
            struct tm *now=localtime(&nowInSecs);
            if (*nodeData[i].id==hourId)
                nodeData[i].theta=step*((now->tm_hour*(60/12))+(now->tm_min/12));
            else if(*nodeData[i].id==minId)
                nodeData[i].theta=step*now->tm_min;
            else if(*nodeData[i].id==secId)
                nodeData[i].theta=step*now->tm_sec;

            // Move hour. min, and sec nodes to appropriate locations.
            GPSMessagePtr gpsMess(new GPSMessage((sin(nodeData[i].theta)*radius)+radius, (cos(nodeData[i].theta)*radius)+radius, (double)i));
            gpsMess->layer=layer;
            gpsMess->fromNodeID=*nodeData[i].id;
            if(!client.sendMessage(gpsMess))
            {
                LOG_ERROR("Error sending gps message: " << *gpsMess);
                TRACE_EXIT_RET(EXIT_FAILURE);
                return EXIT_FAILURE;
            }

            LabelMessagePtr labMess(new LabelMessage(nodeData[i].label));
            labMess->layer=layer;
            labMess->expiration=loopTime*2000;  // 2000 to stop blinking
            EdgeMessagePtr edgeMess(new EdgeMessage(centerId, *nodeData[i].id, layer, nodeData[i].color, 2));
            edgeMess->middleLabel=labMess;
            if(!client.sendMessage(edgeMess))
            {
                LOG_ERROR("Error sending edge message: " << *edgeMess);
                TRACE_EXIT_RET(EXIT_FAILURE);
                return EXIT_FAILURE;
            }
        }

        // add nodes at clock face number locations.
        double theta=(2*PI)/12;
        for (unsigned int i=0; i<12; i++, theta+=(2*PI)/12)
        {
            NodeIdentifier thisId=NodeIdentifier::from_string("192.168.2." + lexical_cast<string>(i+1));
            double faceRad=radius*1.15;
            GPSMessagePtr gpsMess(new GPSMessage((sin(theta)*faceRad)+radius, (cos(theta)*faceRad)+radius, 0.0));
            gpsMess->layer=layer;
            gpsMess->fromNodeID=thisId;
            if(!client.sendMessage(gpsMess))
            {
                LOG_ERROR("Error sending gps message: " << *gpsMess);
                TRACE_EXIT_RET(EXIT_FAILURE);
                return EXIT_FAILURE;
            }
        }

        // add nodes at clock face second locations.
        theta=(2*PI)/60;
        for (unsigned int i=0; i<60; i++, theta+=(2*PI)/60)
        {
            NodeIdentifier thisId=NodeIdentifier::from_string("192.168.3." + lexical_cast<string>(i+1));
            double faceRad=radius*1.35;
            GPSMessagePtr gpsMess(new GPSMessage((sin(theta)*faceRad)+radius, (cos(theta)*faceRad)+radius, 0.0));
            gpsMess->layer=layer;
            gpsMess->fromNodeID=thisId;
            if(!client.sendMessage(gpsMess))
            {
                LOG_ERROR("Error sending gps message: " << *gpsMess);
                TRACE_EXIT_RET(EXIT_FAILURE);
                return EXIT_FAILURE;
            }
        }
        sleep(loopTime);
    }

    client.wait();

    TRACE_EXIT_RET(EXIT_SUCCESS);
    return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>/**
 * \file SimpleActiveSocketState.cpp
 * \date Apr 6, 2010
 * \author samael
 */

#include <cstdio>
#include <cstring>
#include <errno.h>
#include <arpa/inet.h>
#include "SimpleActiveSocketState.h"
#include "ClosedSocketState.h"
#include "ConnectedSocketState.h"
#include "BoundSocketState.h"
#include "TCPSocket.h"
#include "UDPSocket.h"
#include "SingletonAutoDestructor.h"

namespace cml
{

SINGLETON_REGISTRATION(SimpleActiveSocketState);
SINGLETON_REGISTRATION_END();

bool SimpleActiveSocketState::activeOpen(AbstractSocket *sock,
		const HostAddress &addr, uint16_t port)
{
	// Clear and set address/port.
	sockaddr_in inaddr;
	memset(&inaddr, 0, sizeof(inaddr));
	inaddr.sin_family = AF_INET;
	inaddr.sin_addr.s_addr = addr.toInetAddr();
	inaddr.sin_port = htons(port);

	// Perform connection.
	PINF_3("Connecting to a remote host.");
	if (connect(sock->sockfd(), (struct sockaddr *)&inaddr, sizeof(inaddr)) != 0) {
		perror("Error: SimpleActiveSocketState::activeOpen()");
		return false;
	}

	sock->changeState(ConnectedSocketState::instance());
	return true;
}

bool SimpleActiveSocketState::passiveOpen(AbstractSocket *sock,
		uint16_t port, int qlen)
{
	// Clear and set inet address/port.
	sockaddr_in inaddr;
	memset(&inaddr, 0, sizeof(inaddr));
	inaddr.sin_family = AF_INET;
	inaddr.sin_addr.s_addr = INADDR_ANY;
	inaddr.sin_port = htons(port);

	// Perform binding.
	PINF_3("Binding a port.");
	if (bind(sock->sockfd(), (struct sockaddr *)&inaddr, sizeof(inaddr)) != 0) {
		perror("Error: SimpleActiveSocketState::passiveOpen()");
		return false;
	}

	// Perform listen if it's a TCP socket.
	if ((dynamic_cast<TCPSocket *>(sock))) {
		PINF_3("Listening for connections.");
		if (listen(sock->sockfd(), qlen) < 0) {
			perror("Error: SimpleActiveSocketState::passiveOpen()");
			return false;
		}
	}

	sock->changeState(BoundSocketState::instance());
	return true;
}

bool SimpleActiveSocketState::close(AbstractSocket *sock)
{
	PINF_3("Closing the socket.");
	if (::close(sock->sockfd()) != 0) {
		perror("Error: ConnectedSocketState::close(): close");
		return false;
	}

	sock->changeState(ClosedSocketState::instance());
	return true;
}

ssize_t SimpleActiveSocketState::recvfrom(AbstractSocket *sock, char *buf,
		size_t size, HostAddress *addr, uint16_t *port)
{
	if (!(dynamic_cast<UDPSocket *>(sock))) {
		PERR("recvfrom is only suitable for UDP sockets.");
		return -1;
	}

	ssize_t result;
	struct sockaddr_in inaddr;
	socklen_t alen = sizeof(inaddr);

	PINF_3("Receiving an incoming message.");
	if ((result = ::recvfrom(sock->sockfd(), buf, size, 0,
			(struct sockaddr *)&inaddr, &alen)) < 0) {
		perror("Error: SimpleActiveSocketState::recvfrom()");
	}
	PINF_3(result << " bytes received.");

	addr->setAddr(inaddr.sin_addr.s_addr);
	*port = ntohs(inaddr.sin_port);

	return result;
}

ssize_t SimpleActiveSocketState::sendto(AbstractSocket *sock, const char *buf,
		size_t size, const HostAddress &addr, uint16_t port)
{
	if (!(dynamic_cast<UDPSocket *>(sock))) {
		PERR("sendto is only suitable for UDP sockets.");
		return -1;
	}

	ssize_t result;
	sockaddr_in inaddr;

	// Clear and set address/port.
	memset(&inaddr, 0, sizeof(inaddr));
	inaddr.sin_family = AF_INET;
	inaddr.sin_addr.s_addr = addr.toInetAddr();
	inaddr.sin_port = htons(port);

	PINF_3("Sending an outgoing message.");
	if ((result = ::sendto(sock->sockfd(), buf, size, 0,
			(struct sockaddr *)&inaddr,	sizeof(inaddr))) < 0) {
		perror("Error: SimpleActiveSocketState::sendto()");
	}
	PINF_3(result << " bytes sent.");

	return result;
}

}
<commit_msg><commit_after>/**
 * \file SimpleActiveSocketState.cpp
 * \date Apr 6, 2010
 * \author samael
 */

#include <cstdio>
#include <cstring>
#include <errno.h>
#include <arpa/inet.h>
#include "SimpleActiveSocketState.h"
#include "ClosedSocketState.h"
#include "ConnectedSocketState.h"
#include "BoundSocketState.h"
#include "TCPSocket.h"
#include "UDPSocket.h"
#include "SingletonAutoDestructor.h"

namespace cml
{

SINGLETON_REGISTRATION(SimpleActiveSocketState);
SINGLETON_REGISTRATION_END();

bool SimpleActiveSocketState::activeOpen(AbstractSocket *sock,
		const HostAddress &addr, uint16_t port)
{
	// Clear and set address/port.
	sockaddr_in inaddr;
	memset(&inaddr, 0, sizeof(inaddr));
	inaddr.sin_family = AF_INET;
	inaddr.sin_addr.s_addr = addr.toInetAddr();
	inaddr.sin_port = htons(port);

	// Perform connection.
	PINF_3("Connecting to a remote host.");
	if (connect(sock->sockfd(), (struct sockaddr *)&inaddr, sizeof(inaddr)) != 0) {
		perror("Error: SimpleActiveSocketState::activeOpen()");
		return false;
	}

	sock->changeState(ConnectedSocketState::instance());
	return true;
}

bool SimpleActiveSocketState::passiveOpen(AbstractSocket *sock,
		uint16_t port, int qlen)
{
	// Clear and set inet address/port.
	sockaddr_in inaddr;
	memset(&inaddr, 0, sizeof(inaddr));
	inaddr.sin_family = AF_INET;
	inaddr.sin_addr.s_addr = INADDR_ANY;
	inaddr.sin_port = htons(port);

	// Reuse port.
    socklen_t reuseaddr_len;
	setsockopt(sock->sockfd(), SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
			reuseaddr_len);

	// Perform binding.
	int reuseaddr = 1;
	PINF_3("Binding a port.");
	if (bind(sock->sockfd(), (struct sockaddr *)&inaddr, sizeof(inaddr)) != 0) {
		perror("Error: SimpleActiveSocketState::passiveOpen()");
		return false;
	}

	// Perform listen if it's a TCP socket.
	if ((dynamic_cast<TCPSocket *>(sock))) {
		PINF_3("Listening for connections.");
		if (listen(sock->sockfd(), qlen) < 0) {
			perror("Error: SimpleActiveSocketState::passiveOpen()");
			return false;
		}
	}

	sock->changeState(BoundSocketState::instance());
	return true;
}

bool SimpleActiveSocketState::close(AbstractSocket *sock)
{
	PINF_3("Closing the socket.");
	if (::close(sock->sockfd()) != 0) {
		perror("Error: ConnectedSocketState::close(): close");
		return false;
	}

	sock->changeState(ClosedSocketState::instance());
	return true;
}

ssize_t SimpleActiveSocketState::recvfrom(AbstractSocket *sock, char *buf,
		size_t size, HostAddress *addr, uint16_t *port)
{
	if (!(dynamic_cast<UDPSocket *>(sock))) {
		PERR("recvfrom is only suitable for UDP sockets.");
		return -1;
	}

	ssize_t result;
	struct sockaddr_in inaddr;
	socklen_t alen = sizeof(inaddr);

	PINF_3("Receiving an incoming message.");
	if ((result = ::recvfrom(sock->sockfd(), buf, size, 0,
			(struct sockaddr *)&inaddr, &alen)) < 0) {
		perror("Error: SimpleActiveSocketState::recvfrom()");
	}
	PINF_3(result << " bytes received.");

	addr->setAddr(inaddr.sin_addr.s_addr);
	*port = ntohs(inaddr.sin_port);

	return result;
}

ssize_t SimpleActiveSocketState::sendto(AbstractSocket *sock, const char *buf,
		size_t size, const HostAddress &addr, uint16_t port)
{
	if (!(dynamic_cast<UDPSocket *>(sock))) {
		PERR("sendto is only suitable for UDP sockets.");
		return -1;
	}

	ssize_t result;
	sockaddr_in inaddr;

	// Clear and set address/port.
	memset(&inaddr, 0, sizeof(inaddr));
	inaddr.sin_family = AF_INET;
	inaddr.sin_addr.s_addr = addr.toInetAddr();
	inaddr.sin_port = htons(port);

	PINF_3("Sending an outgoing message.");
	if ((result = ::sendto(sock->sockfd(), buf, size, 0,
			(struct sockaddr *)&inaddr,	sizeof(inaddr))) < 0) {
		perror("Error: SimpleActiveSocketState::sendto()");
	}
	PINF_3(result << " bytes sent.");

	return result;
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

#include "port/port_posix.h"

#include <cstdlib>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "util/logging.h"

namespace leveldb {
namespace port {

static void PthreadCall(const char* label, int result) {
  if (result != 0) {
    fprintf(stderr, "pthread %s: %s\n", label, strerror(result));
    abort();
  }
}

Mutex::Mutex(bool recursive) {
  if (recursive) {
    pthread_mutexattr_t attr;

    PthreadCall("init mutex attr", pthread_mutexattr_init(&attr));
    PthreadCall("set mutex recursive", pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE));
    PthreadCall("init recursive mutex", pthread_mutex_init(&mu_, &attr));
    PthreadCall("destroy mutex attr", pthread_mutexattr_destroy(&attr));
  }
  else {
    PthreadCall("init mutex", pthread_mutex_init(&mu_, NULL));
  }
}

Mutex::~Mutex() { PthreadCall("destroy mutex", pthread_mutex_destroy(&mu_)); }

void Mutex::Lock() { PthreadCall("lock", pthread_mutex_lock(&mu_)); }

void Mutex::Unlock() { PthreadCall("unlock", pthread_mutex_unlock(&mu_)); }

#if defined(_POSIX_SPIN_LOCKS) && 0<_POSIX_SPIN_LOCKS
Spin::Spin() { PthreadCall("init spinlock", pthread_spin_init(&sp_, PTHREAD_PROCESS_PRIVATE)); }

Spin::~Spin() { PthreadCall("destroy spinlock", pthread_spin_destroy(&sp_)); }

void Spin::Lock() { PthreadCall("lock spin", pthread_spin_lock(&sp_)); }

void Spin::Unlock() { PthreadCall("unlock spin", pthread_spin_unlock(&sp_)); }
#endif

CondVar::CondVar(Mutex* mu)
    : mu_(mu) {
    PthreadCall("init cv", pthread_cond_init(&cv_, NULL));
}

CondVar::~CondVar() { PthreadCall("destroy cv", pthread_cond_destroy(&cv_)); }

void CondVar::Wait() {
  PthreadCall("wait", pthread_cond_wait(&cv_, &mu_->mu_));
}

bool CondVar::Wait(struct timespec* pTimespec) {
  bool signaled = true;
  int result = pthread_cond_timedwait(&cv_, &mu_->mu_, pTimespec);
  if (0 != result) {
    signaled = false;

    // the only expected errno is ETIMEDOUT; anything else is a real error
    if (ETIMEDOUT != result) {
      PthreadCall("timed wait", result);
    }
  }
  return signaled;
}

void CondVar::Signal() {
  PthreadCall("signal", pthread_cond_signal(&cv_));
}

void CondVar::SignalAll() {
  PthreadCall("broadcast", pthread_cond_broadcast(&cv_));
}

void InitOnce(OnceType* once, void (*initializer)()) {
  PthreadCall("once", pthread_once(once, initializer));
}

RWMutex::RWMutex() { PthreadCall("init mutex", pthread_rwlock_init(&mu_, NULL)); }

RWMutex::~RWMutex() { PthreadCall("destroy mutex", pthread_rwlock_destroy(&mu_)); }

void RWMutex::ReadLock() { PthreadCall("read lock", pthread_rwlock_rdlock(&mu_)); }

void RWMutex::WriteLock() { PthreadCall("write lock", pthread_rwlock_wrlock(&mu_)); }

void RWMutex::Unlock() { PthreadCall("unlock", pthread_rwlock_unlock(&mu_)); }

}  // namespace port
}  // namespace leveldb
<commit_msg>have pthread functions use default leveldb LOG(NULL ...) construct that push messages to syslog.<commit_after>// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

#include "port/port_posix.h"

#include <cstdlib>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "leveldb/env.h"
#include "util/logging.h"

namespace leveldb {
namespace port {

static void PthreadCall(const char* label, int result) {
  if (result != 0) {
    fprintf(stderr, "pthread %s: %s\n", label, strerror(result));
    Log(NULL, "pthread %s: %s\n", label, strerror(result));
    abort();
  }
}

Mutex::Mutex(bool recursive) {
  if (recursive) {
    pthread_mutexattr_t attr;

    PthreadCall("init mutex attr", pthread_mutexattr_init(&attr));
    PthreadCall("set mutex recursive", pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE));
    PthreadCall("init recursive mutex", pthread_mutex_init(&mu_, &attr));
    PthreadCall("destroy mutex attr", pthread_mutexattr_destroy(&attr));
  }
  else {
    PthreadCall("init mutex", pthread_mutex_init(&mu_, NULL));
  }
}

Mutex::~Mutex() { PthreadCall("destroy mutex", pthread_mutex_destroy(&mu_)); }

void Mutex::Lock() { PthreadCall("lock", pthread_mutex_lock(&mu_)); }

void Mutex::Unlock() { PthreadCall("unlock", pthread_mutex_unlock(&mu_)); }

#if defined(_POSIX_SPIN_LOCKS) && 0<_POSIX_SPIN_LOCKS
Spin::Spin() { PthreadCall("init spinlock", pthread_spin_init(&sp_, PTHREAD_PROCESS_PRIVATE)); }

Spin::~Spin() { PthreadCall("destroy spinlock", pthread_spin_destroy(&sp_)); }

void Spin::Lock() { PthreadCall("lock spin", pthread_spin_lock(&sp_)); }

void Spin::Unlock() { PthreadCall("unlock spin", pthread_spin_unlock(&sp_)); }
#endif

CondVar::CondVar(Mutex* mu)
    : mu_(mu) {
    PthreadCall("init cv", pthread_cond_init(&cv_, NULL));
}

CondVar::~CondVar() { PthreadCall("destroy cv", pthread_cond_destroy(&cv_)); }

void CondVar::Wait() {
  PthreadCall("wait", pthread_cond_wait(&cv_, &mu_->mu_));
}

bool CondVar::Wait(struct timespec* pTimespec) {
  bool signaled = true;
  int result = pthread_cond_timedwait(&cv_, &mu_->mu_, pTimespec);
  if (0 != result) {
    signaled = false;

    // the only expected errno is ETIMEDOUT; anything else is a real error
    if (ETIMEDOUT != result) {
      PthreadCall("timed wait", result);
    }
  }
  return signaled;
}

void CondVar::Signal() {
  PthreadCall("signal", pthread_cond_signal(&cv_));
}

void CondVar::SignalAll() {
  PthreadCall("broadcast", pthread_cond_broadcast(&cv_));
}

void InitOnce(OnceType* once, void (*initializer)()) {
  PthreadCall("once", pthread_once(once, initializer));
}

RWMutex::RWMutex() { PthreadCall("init mutex", pthread_rwlock_init(&mu_, NULL)); }

RWMutex::~RWMutex() { PthreadCall("destroy mutex", pthread_rwlock_destroy(&mu_)); }

void RWMutex::ReadLock() { PthreadCall("read lock", pthread_rwlock_rdlock(&mu_)); }

void RWMutex::WriteLock() { PthreadCall("write lock", pthread_rwlock_wrlock(&mu_)); }

void RWMutex::Unlock() { PthreadCall("unlock", pthread_rwlock_unlock(&mu_)); }

}  // namespace port
}  // namespace leveldb
<|endoftext|>


<commit_before>#pragma once
// pow.hpp: pow functions for posits
//
// Copyright (C) 2017-2018 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.

namespace sw {
	namespace unum {

		// the current shims are NON-COMPLIANT with the posit standard, which says that every function must be
		// correctly rounded for every input value. Anything less sacrifices bitwise reproducibility of results.

		template<size_t nbits, size_t es>
		posit<nbits,es> pow(posit<nbits,es> x, posit<nbits, es> y) {
			return posit<nbits,es>(std::pow(double(x), double(y)));
		}

		template<size_t nbits, size_t es>
		posit<nbits,es> pow(posit<nbits,es> x, int y) {
			return posit<nbits,es>(std::pow(double(x), double(y)));
		}

	}  // namespace unum

}  // namespace sw
<commit_msg>WIP: additional mathematical function shims<commit_after>#pragma once
// pow.hpp: pow functions for posits
//
// Copyright (C) 2017-2018 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.

namespace sw {
	namespace unum {

		// the current shims are NON-COMPLIANT with the posit standard, which says that every function must be
		// correctly rounded for every input value. Anything less sacrifices bitwise reproducibility of results.

		template<size_t nbits, size_t es>
		posit<nbits,es> pow(posit<nbits,es> x, posit<nbits, es> y) {
			return posit<nbits,es>(std::pow(double(x), double(y)));
		}

		template<size_t nbits, size_t es>
		posit<nbits,es> pow(posit<nbits,es> x, int y) {
			return posit<nbits,es>(std::pow(double(x), double(y)));
		}

		template<size_t nbits, size_t es>
		posit<nbits,es> pow(posit<nbits,es> x, double y) {
			return posit<nbits,es>(std::pow(double(x), y));
		}

	}  // namespace unum

}  // namespace sw
<|endoftext|>


<commit_before>//
//  main.cpp
//  prel
//
//  Created by George Oblapenko on 11/11/14.
//  Copyright (c) 2014 George Oblapenko. All rights reserved.
//

#include <iostream>
#include <kineticlib.h>

int main(int argc, const char * argv[]) {
	double start_T = 2000.; // the start temperature
	double end_T = 10000.0; // the end temperature
	double p = 100000.0; // atmospheric pressure
	double xN = 0.5; // the relative numeric density of atomic nitrogen
	double xN2 = 1. - xN;

	std::string cs_model = "VSS";  // the dissociation cross-section model
	bool vl_dependent = false;  // whether the dissociation cross-section is dependent on the vibrational level of the dissociating molecule

	int points_amt = 50; // the amount of points
	arma::vec T_array = arma::linspace<arma::vec>(start_T, end_T, points_amt); // start value of T, end value of T, amount of steps
	arma::vec prel = arma::zeros(50); // array of relaxation pressure values

	klib::MoleculeOneT N2 = klib::MoleculeOneT("N2");
	klib::Atom N = klib::Atom("N");
	arma::vec idata_N2N2 = klib::load_elastic_parameters(N2, N2); // N2 + N2 elastic interaction data
	arma::vec idata_N2N = klib::load_elastic_parameters(N2, N); // N2 + N elastic interaction data
	arma::vec ddata_N2N2 = klib::load_dissociation_parameters(N2, N2); // N2 + N2 dissociation data
	arma::vec ddata_N2N = klib::load_dissociation_parameters(N2, N); // N2 + N dissociation data
	arma::mat33 beta_matrix; // the matrix of beta integral brackets
	arma::vec3 right_parts; // the right-hand side of the system
	arma::vec3 results; // the values of the expansion coefficients g_{c,pq} - the order is g_{N2,10}, g_{N2,01}, g_{N,10}

	double R_react_N2, R_react_N; // relaxation terms
	double T, n, rho, omega11_N2N, tau_rot_N2N, tau_rot_N2N2, eta_zeta_N2N2, eta_zeta_N2N, cV, SJsl, PJsl, SJslN2, PJslN2; // the numeric density of the mixture, the density of the mixture, Omega^{(1,1)}_{N2,N}, rotational relaxation times for N2+N and N2+N2, the quantity 4T \pi / (\eta_{cd} * \xi_{cd}), the quantity dE/dT
	double tmp_int00 = 0.0;
	beta_matrix.at(0, 0) = 1.5 * (1. - xN);
	beta_matrix.at(0, 2) = 1.5 * xN; // these appear due to the constraint conditions and are independent of temperature
	beta_matrix.zeros();
	right_parts[0] = 0.;
	for (int i = 0; i < points_amt; i++) {
		T = T_array[i];
		n = p / (KLIB_CONST_K * T);
		N2.renorm(T, xN2 * n);
		rho = xN2 * n * N2.mass + xN * n * N.mass;
		omega11_N2N = klib::omega(T, 1, 1, idata_N2N, "ESA", true, true); // we set nokt to true so that the result is of order 10e-07 instead of 10e-16
		tau_rot_N2N = klib::rot_rel_time_vss(T, idata_N2N, N2, n);
		tau_rot_N2N2 = klib::rot_rel_time_vss(T, idata_N2N2, N2, n);
		eta_zeta_N2N2 = 1. / (n * KLIB_CONST_K * tau_rot_N2N2);
		eta_zeta_N2N = 1. / (n * KLIB_CONST_K * tau_rot_N2N);
		cV = 1.5 * KLIB_CONST_K * n / rho + xN2 * (N2.mass * n / rho) * (N2.crot + N2.E_vibr_dT(T));
		beta_matrix.at(0, 1) = xN2 * klib::wt_poly_norm(T, N2);

		beta_matrix.at(1, 0) = -xN2 * N2.mass * N2.crot * (xN * (0.33333) * eta_zeta_N2N + xN2 * eta_zeta_N2N2); // does vibrational relaxation time play any significant role?
		beta_matrix.at(1, 1) = xN2 * N2.mass * N2.crot * (xN * eta_zeta_N2N + xN2 * eta_zeta_N2N2);
		beta_matrix.at(2, 0) = (2. / 9.) * xN2 * xN * (-16 * omega11_N2N + sqrt(1. / (KLIB_CONST_K * T)) * N2.mass * N2.crot * eta_zeta_N2N);
		beta_matrix.at(2, 2) = (2. / 9.) * xN2 * xN * (16 * omega11_N2N + sqrt(1. / (KLIB_CONST_K * T)) * N2.mass * N2.crot * eta_zeta_N2N);

		beta_matrix.at(1, 0) /= sqrt(KLIB_CONST_K * T);
		beta_matrix.at(1, 1) /= sqrt(KLIB_CONST_K * T);
		R_react_N2 = -klib::diss_rate_treanor_marrone(T, ddata_N2N, N2) * (xN * n) * (xN2 * n);

		R_react_N2 /= sqrt(KLIB_CONST_K * T);
		R_react_N = -2 * R_react_N2; // this is a binary mixture and the relaxation terms are related in a simple way

		SJsl = 0.0;
		PJsl = 0.0;
		SJslN2 = 0.0;
		PJslN2 = 0.0;

		for (int vl = 0; vl <= N2.num_vibr; vl++) {
			tmp_int00 = klib::diss_integral(T, 0, idata_N2N, N2, vl, true, vl_dependent, cs_model, true);
			SJsl += (1. / 3.) * (12 * tmp_int00  - klib::diss_integral(T, 1, idata_N2N, N2, vl, true, true, cs_model, true)) * N2.vibr_exp(T, vl) / N2.Z_vibr(T);
			PJsl += (N2.avg_vibr_energy(T, false) - N2.vibr[vl] / (KLIB_CONST_K * T)) * 8 * tmp_int00 * N2.vibr_exp(T, vl) / N2.Z_vibr(T);

			tmp_int00 = klib::diss_integral(T, 0, idata_N2N2, N2, vl, true, vl_dependent, cs_model, true);
			SJslN2 += (1. / 2.) * (12 * tmp_int00 - 8 * klib::diss_integral(T, 1, idata_N2N2, N2, vl, true, vl_dependent, cs_model, true)) * N2.vibr_exp(T, vl) / N2.Z_vibr(T);
			PJslN2 += (N2.avg_vibr_energy(T, false) - N2.vibr[vl] / (KLIB_CONST_K * T)) * 8 * tmp_int00 * N2.vibr_exp(T, vl) / N2.Z_vibr(T);
		}

		right_parts[1] = xN2 * (R_react_N2 * (1.5 * KLIB_CONST_K * T + N2.avg_full_energy(T) + N2.form)
			+ R_react_N * (1.5 * KLIB_CONST_K * T + N.form)) * klib::wt_poly_norm(T, N2) / (rho * T * cV) + PJsl * (xN * xN2) * n;
		right_parts[2] = xN * (R_react_N2 * (1.5 * KLIB_CONST_K * T + N2.avg_full_energy(T) + N2.form)
			+ R_react_N * (1.5 * KLIB_CONST_K * T + N.form)) * 1.5 / (rho * T * cV) - 2 * 1.5 * SJsl * (xN * xN2) * n;
		results = arma::solve(beta_matrix, right_parts);
		std::cout << "\nprel_{N2+N}=" << -KLIB_CONST_K * T * (xN2 * results[0] + xN * results[2]) * klib::Gamma_diss(T, N2, N, N, xN2 * n, xN * n, xN * n);

		R_react_N2 = klib::diss_rate_treanor_marrone(T, ddata_N2N2, N2) * (xN2 * n) * (xN2 * n);
		R_react_N2 /= sqrt(KLIB_CONST_K * T);
		R_react_N = -2 * R_react_N2;
		right_parts[1] = xN2 * (R_react_N2 * (1.5 * KLIB_CONST_K * T + N2.avg_full_energy(T) + N2.form)
			+ R_react_N * (1.5 * KLIB_CONST_K * T + N.form)) * klib::wt_poly_norm(T, N2) / (rho * T * cV) + PJslN2 * (xN2 * xN2) * n;
		right_parts[2] = xN * (R_react_N2 * (1.5 * KLIB_CONST_K * T + N2.avg_full_energy(T) + N2.form)
			+ R_react_N * (1.5 * KLIB_CONST_K * T + N.form)) * 1.5 / (rho * T * cV) - 2 * 1.5 * SJslN2 * (xN2 * xN2) * n;
		results = arma::solve(beta_matrix, right_parts);
		std::cout << "; prel_{N2+N2}=" << -KLIB_CONST_K * T * (xN2 * results[0] + xN * results[2]) * klib::Gamma_diss(T, N2, N, N, xN2 * n, xN * n, xN * n);
	}
}
<commit_msg>fixed N2+N2 reaction<commit_after>//
//  main.cpp
//  prel
//
//  Created by George Oblapenko on 11/11/14.
//  Copyright (c) 2014 George Oblapenko. All rights reserved.
//

#include <iostream>
#include <kineticlib.h>

int main(int argc, const char * argv[]) {
	double start_T = 2000.; // the start temperature
	double end_T = 10000.0; // the end temperature
	double p = 100000.0; // atmospheric pressure
	double xN = 0.5; // the relative numeric density of atomic nitrogen
	double xN2 = 1. - xN;

	std::string cs_model = "VSS";  // the dissociation cross-section model
	bool vl_dependent = false;  // whether the dissociation cross-section is dependent on the vibrational level of the dissociating molecule

	int points_amt = 50; // the amount of points
	arma::vec T_array = arma::linspace<arma::vec>(start_T, end_T, points_amt); // start value of T, end value of T, amount of steps
	arma::vec prel = arma::zeros(50); // array of relaxation pressure values

	klib::MoleculeOneT N2 = klib::MoleculeOneT("N2");
	klib::Atom N = klib::Atom("N");
	arma::vec idata_N2N2 = klib::load_elastic_parameters(N2, N2); // N2 + N2 elastic interaction data
	arma::vec idata_N2N = klib::load_elastic_parameters(N2, N); // N2 + N elastic interaction data
	arma::vec ddata_N2N2 = klib::load_dissociation_parameters(N2, N2); // N2 + N2 dissociation data
	arma::vec ddata_N2N = klib::load_dissociation_parameters(N2, N); // N2 + N dissociation data
	arma::mat33 beta_matrix; // the matrix of beta integral brackets
	arma::vec3 right_parts; // the right-hand side of the system
	arma::vec3 results; // the values of the expansion coefficients g_{c,pq} - the order is g_{N2,10}, g_{N2,01}, g_{N,10}

	double R_react_N2, R_react_N; // relaxation terms
	double T, n, rho, omega11_N2N, tau_rot_N2N, tau_rot_N2N2, eta_zeta_N2N2, eta_zeta_N2N, cV, SJsl, PJsl, SJslN2, PJslN2; // the numeric density of the mixture, the density of the mixture, Omega^{(1,1)}_{N2,N}, rotational relaxation times for N2+N and N2+N2, the quantity 4T \pi / (\eta_{cd} * \xi_{cd}), the quantity dE/dT
	double tmp_int00 = 0.0;
	beta_matrix.at(0, 0) = 1.5 * (1. - xN);
	beta_matrix.at(0, 2) = 1.5 * xN; // these appear due to the constraint conditions and are independent of temperature
	beta_matrix.zeros();
	right_parts[0] = 0.;
	for (int i = 0; i < points_amt; i++) {
		T = T_array[i];
		n = p / (KLIB_CONST_K * T);
		N2.renorm(T, xN2 * n);
		rho = xN2 * n * N2.mass + xN * n * N.mass;
		omega11_N2N = klib::omega(T, 1, 1, idata_N2N, "ESA", true, true); // we set nokt to true so that the result is of order 10e-07 instead of 10e-16
		tau_rot_N2N = klib::rot_rel_time_vss(T, idata_N2N, N2, n);
		tau_rot_N2N2 = klib::rot_rel_time_vss(T, idata_N2N2, N2, n);
		eta_zeta_N2N2 = 1. / (n * KLIB_CONST_K * tau_rot_N2N2);
		eta_zeta_N2N = 1. / (n * KLIB_CONST_K * tau_rot_N2N);
		cV = 1.5 * KLIB_CONST_K * n / rho + xN2 * (N2.mass * n / rho) * (N2.crot + N2.E_vibr_dT(T));
		beta_matrix.at(0, 1) = xN2 * klib::wt_poly_norm(T, N2);

		beta_matrix.at(1, 0) = -xN2 * N2.mass * N2.crot * (xN * (0.33333) * eta_zeta_N2N + xN2 * eta_zeta_N2N2); // does vibrational relaxation time play any significant role?
		beta_matrix.at(1, 1) = xN2 * N2.mass * N2.crot * (xN * eta_zeta_N2N + xN2 * eta_zeta_N2N2);
		beta_matrix.at(2, 0) = (2. / 9.) * xN2 * xN * (-16 * omega11_N2N + sqrt(1. / (KLIB_CONST_K * T)) * N2.mass * N2.crot * eta_zeta_N2N);
		beta_matrix.at(2, 2) = (2. / 9.) * xN2 * xN * (16 * omega11_N2N + sqrt(1. / (KLIB_CONST_K * T)) * N2.mass * N2.crot * eta_zeta_N2N);

		beta_matrix.at(1, 0) /= sqrt(KLIB_CONST_K * T);
		beta_matrix.at(1, 1) /= sqrt(KLIB_CONST_K * T);
		R_react_N2 = -klib::diss_rate_treanor_marrone(T, ddata_N2N, N2) * (xN * n) * (xN2 * n);

		R_react_N2 /= sqrt(KLIB_CONST_K * T);
		R_react_N = -2 * R_react_N2; // this is a binary mixture and the relaxation terms are related in a simple way

		SJsl = 0.0;
		PJsl = 0.0;
		SJslN2 = 0.0;
		PJslN2 = 0.0;

		for (int vl = 0; vl <= N2.num_vibr; vl++) {
			tmp_int00 = klib::diss_integral(T, 0, idata_N2N, N2, vl, true, vl_dependent, cs_model, true);
			SJsl += (1. / 3.) * (12 * tmp_int00  - klib::diss_integral(T, 1, idata_N2N, N2, vl, true, true, cs_model, true)) * N2.vibr_exp(T, vl) / N2.Z_vibr(T);
			PJsl += (N2.avg_vibr_energy(T, false) - N2.vibr[vl] / (KLIB_CONST_K * T)) * 8 * tmp_int00 * N2.vibr_exp(T, vl) / N2.Z_vibr(T);

			tmp_int00 = klib::diss_integral(T, 0, idata_N2N2, N2, vl, true, vl_dependent, cs_model, true);
			SJslN2 += (1. / 2.) * (12 * tmp_int00 - 8 * klib::diss_integral(T, 1, idata_N2N2, N2, vl, true, vl_dependent, cs_model, true)) * N2.vibr_exp(T, vl) / N2.Z_vibr(T);
			PJslN2 += (N2.avg_vibr_energy(T, false) - N2.vibr[vl] / (KLIB_CONST_K * T)) * 8 * tmp_int00 * N2.vibr_exp(T, vl) / N2.Z_vibr(T);
		}

		right_parts[1] = xN2 * (R_react_N2 * (1.5 * KLIB_CONST_K * T + N2.avg_full_energy(T) + N2.form)
			+ R_react_N * (1.5 * KLIB_CONST_K * T + N.form)) * klib::wt_poly_norm(T, N2) / (rho * T * cV) + PJsl * (xN * xN2) * n;
		right_parts[2] = xN * (R_react_N2 * (1.5 * KLIB_CONST_K * T + N2.avg_full_energy(T) + N2.form)
			+ R_react_N * (1.5 * KLIB_CONST_K * T + N.form)) * 1.5 / (rho * T * cV) - 2 * 1.5 * SJsl * (xN * xN2) * n;
		results = arma::solve(beta_matrix, right_parts);
		std::cout << "\nprel_{N2+N}=" << -KLIB_CONST_K * T * (xN2 * results[0] + xN * results[2]) * klib::Gamma_diss(T, N2, N, N, xN2 * n, xN * n, xN * n);

		R_react_N2 = klib::diss_rate_treanor_marrone(T, ddata_N2N2, N2) * (xN2 * n) * (xN2 * n);
		R_react_N2 /= sqrt(KLIB_CONST_K * T);
		R_react_N = -2 * R_react_N2;
		right_parts[1] = xN2 * (R_react_N2 * (1.5 * KLIB_CONST_K * T + N2.avg_full_energy(T) + N2.form)
			+ R_react_N * (1.5 * KLIB_CONST_K * T + N.form)) * klib::wt_poly_norm(T, N2) / (rho * T * cV) + PJslN2 * (xN2 * xN2) * n;
		right_parts[2] = xN * (R_react_N2 * (1.5 * KLIB_CONST_K * T + N2.avg_full_energy(T) + N2.form)
			+ R_react_N * (1.5 * KLIB_CONST_K * T + N.form)) * 1.5 / (rho * T * cV);
		results = arma::solve(beta_matrix, right_parts);
		std::cout << "; prel_{N2+N2}=" << -KLIB_CONST_K * T * (xN2 * results[0] + xN * results[2]) * klib::Gamma_diss(T, N2, N, N, xN2 * n, xN * n, xN * n);
	}
}
<|endoftext|>


<commit_before>#ifndef assembler_class_hpp
#define assembler_class_hpp

#include "misc_includes.hpp"

#include "symbol_table_class.hpp"

namespace flare32
{

class Assembler
{
private:		// classes

private:		// variables
	SymbolTable __builtin_sym_tbl, __user_sym_tbl;
	InstructionTable __instr_tbl;

	// Where are we in the file?
	size_t __addr = 0;
	size_t __line_num = 1;

	int __next_char = ' ';
	PTok __next_tok = nullptr;
	std::string __next_sym_str;
	s64 __next_num = -1;

	//bool __changed = false;
	s32 __pass = 0;

	char* __input_filename = nullptr;
	std::FILE* __infile = nullptr;

public:		// functions
	Assembler(char* s_input_filename);

	int operator () ();

private:		// functions
	gen_getter_by_ref(builtin_sym_tbl)
	gen_getter_by_ref(user_sym_tbl)
	gen_getter_by_ref(instr_tbl)

	gen_getter_and_setter_by_val(addr)
	gen_getter_and_setter_by_val(line_num)
	gen_getter_and_setter_by_val(next_char)
	gen_getter_and_setter_by_val(next_tok)
	gen_getter_and_setter_by_con_ref(next_sym_str)
	gen_getter_and_setter_by_val(next_num)
	//gen_getter_and_setter_by_val(changed)
	gen_getter_and_setter_by_val(pass)
	gen_getter_and_setter_by_val(input_filename)
	gen_getter_and_setter_by_val(infile)

	void reinit();
	void fill_builtin_sym_tbl();

	template<typename... ArgTypes>
	void err_suffix(ArgTypes&&... args) const
	{
		printerr(", On line ", line_num(), ":  ", args..., "\n");
		exit(1);
	}
	template<typename... ArgTypes>
	void err(ArgTypes&&... args) const
	{
		printerr("Error");
		err_suffix(args...);
	}

	template<typename... ArgTypes>
	void expected(ArgTypes&&... args) const
	{
		err("Expected ", args...);
	}

	void __expected_tokens_innards() const
	{
	}
	template<typename... RemArgTypes>
	void __expected_tokens_innards(PTok tok, RemArgTypes&&... rem_args)
		const
	{
		printerr("\"", tok->str(), "\"");

		if (sizeof...(rem_args) > 0)
		{
			printerr(" or ");
			__expected_tokens_innards(rem_args...);
		}
	}

	template<typename... ArgTypes>
	void expected_tokens(ArgTypes&&... args) const
	{
		printerr("Expected token of type ");
		__expected_tokens_innards(args...);
		printerr("!\n");
		exit(1);
	}

	void need(PTok tok);

	void advance();
	void lex();

	void line();

	s64 handle_term();
	s64 handle_factor();
	s64 handle_expr();

	bool tok_is_punct(PTok some_tok) const;
	bool tok_is_ident_ish(PTok some_tok) const;

	inline bool next_tok_is_punct() const
	{
		return tok_is_punct(next_tok());
	}
	inline bool next_tok_is_ident_ish() const
	{
		return tok_is_ident_ish(next_tok());
	}

};

}

#endif		// assembler_class_hpp
<commit_msg>More stuffs<commit_after>#ifndef assembler_class_hpp
#define assembler_class_hpp

#include "misc_includes.hpp"

#include "symbol_table_class.hpp"

namespace flare32
{

class Assembler
{
private:		// classes
	class ParseNode
	{
	public:		// variables
		PTok next_tok = nullptr;
		std::string next_sym_str;
		s64 next_num = -1;

	public:		// functions
		inline ParseNode()
		{
		}

		inline ParseNode(PTok s_next_tok,
			const std::string& s_next_sym_str, s64 s_next_num)
			: next_tok(s_next_tok), next_sym_str(s_next_sym_str),
			next_num(s_next_num)
		{
		}

		inline ParseNode(const ParseNode& to_copy) = default;
		inline ParseNode(ParseNode&& to_move) = default;
		inline ParseNode& operator = (const ParseNode& to_copy) = default;
		inline ParseNode& operator = (ParseNode&& to_move) = default;
	};

private:		// variables
	SymbolTable __builtin_sym_tbl, __user_sym_tbl;
	InstructionTable __instr_tbl;

	// Where are we in the file?
	size_t __addr = 0;
	size_t __line_num = 1;

	int __next_char = ' ';
	PTok __next_tok = nullptr;
	std::string __next_sym_str;
	s64 __next_num = -1;

	//bool __changed = false;
	s32 __pass = 0;

	char* __input_filename = nullptr;
	std::FILE* __infile = nullptr;

public:		// functions
	Assembler(char* s_input_filename);

	int operator () ();

private:		// functions
	gen_getter_by_ref(builtin_sym_tbl)
	gen_getter_by_ref(user_sym_tbl)
	gen_getter_by_ref(instr_tbl)

	gen_getter_and_setter_by_val(addr)
	gen_getter_and_setter_by_val(line_num)
	gen_getter_and_setter_by_val(next_char)
	gen_getter_and_setter_by_val(next_tok)
	gen_getter_and_setter_by_con_ref(next_sym_str)
	gen_getter_and_setter_by_val(next_num)
	//gen_getter_and_setter_by_val(changed)
	gen_getter_and_setter_by_val(pass)
	gen_getter_and_setter_by_val(input_filename)
	gen_getter_and_setter_by_val(infile)

	void reinit();
	void fill_builtin_sym_tbl();

	template<typename... ArgTypes>
	void err_suffix(ArgTypes&&... args) const
	{
		printerr(", On line ", line_num(), ":  ", args..., "\n");
		exit(1);
	}
	template<typename... ArgTypes>
	void err(ArgTypes&&... args) const
	{
		printerr("Error");
		err_suffix(args...);
	}

	template<typename... ArgTypes>
	void expected(ArgTypes&&... args) const
	{
		err("Expected ", args...);
	}

	void __expected_tokens_innards() const
	{
	}
	template<typename... RemArgTypes>
	void __expected_tokens_innards(PTok tok, RemArgTypes&&... rem_args)
		const
	{
		printerr("\"", tok->str(), "\"");

		if (sizeof...(rem_args) > 0)
		{
			printerr(" or ");
			__expected_tokens_innards(rem_args...);
		}
	}

	template<typename... ArgTypes>
	void expected_tokens(ArgTypes&&... args) const
	{
		printerr("Expected token of type ");
		__expected_tokens_innards(args...);
		printerr("!\n");
		exit(1);
	}

	void need(PTok tok);

	void advance();
	void lex();

	void line();

	s64 handle_term();
	s64 handle_factor();
	s64 handle_expr();

	bool tok_is_punct(PTok some_tok) const;
	bool tok_is_ident_ish(PTok some_tok) const;

	inline bool next_tok_is_punct() const
	{
		return tok_is_punct(next_tok());
	}
	inline bool next_tok_is_ident_ish() const
	{
		return tok_is_ident_ish(next_tok());
	}

};

}

#endif		// assembler_class_hpp
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015-2016 Nagisa Sekiguchi
 *
 * 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.
 */

#include <iostream>

#include "node_dumper.h"
#include "node.h"

namespace ydsh {
namespace ast {

void NodeDumper::dump(const char *fieldName, const char *value) {
    std::string str(value);
    this->dump(fieldName, str);
}

void NodeDumper::dump(const char *fieldName, const std::string &value) {
    this->writeName(fieldName);

    this->stream << '"';
    for(char ch : value) {
        bool escape = true;
        switch(ch) {
        case '\t':
            ch = 't';
            break;
        case '\r':
            ch = 'r';
            break;
        case '\n':
            ch = 'n';
            break;
        case '"':
            ch = '"';
            break;
        case '\\':
            ch = '\\';
            break;
        default:
            escape = false;
            break;
        }
        if(escape) {
            this->stream << '\\';
        }
        this->stream << ch;
    }
    this->stream << '"' << std::endl;
}

void NodeDumper::dump(const char *fieldName, const std::vector<Node *> &nodes) {
    this->writeName(fieldName);
    this->stream << std::endl;

    this->enterIndent();
    for(Node *node : nodes) {
        this->indent();
        this->stream << "- ";
        this->dumpNodeHeader(*node, true);
        this->enterIndent();
        node->dump(*this);
        this->leaveIndent();
    }
    this->leaveIndent();
}

void NodeDumper::dump(const char *fieldName, const std::list<Node *> &nodes) {
    this->writeName(fieldName);
    this->stream << std::endl;

    this->enterIndent();
    for(Node *node : nodes) {
        this->indent();
        this->stream << "- ";
        this->dumpNodeHeader(*node, true);
        this->enterIndent();
        node->dump(*this);
        this->leaveIndent();
    }
    this->leaveIndent();
}

void NodeDumper::dump(const char *fieldName, const Node &node) {
    // write field name
    this->writeName(fieldName);

    // write node body
    this->stream << std::endl;
    this->enterIndent();
    this->dump(node);
    this->leaveIndent();
}

void NodeDumper::dump(const char *fieldName, const DSType &type) {
    this->writeName(fieldName);
    this->stream << this->pool.getTypeName(type) << std::endl;
}

void NodeDumper::dumpNull(const char *fieldName) {
    this->writeName(fieldName);
    this->stream << std::endl;
}

void NodeDumper::dump(const Node &node) {
    this->indent();
    this->dumpNodeHeader(node);
    node.dump(*this);
}

void NodeDumper::enterIndent() {
    this->indentLevel++;
}

void NodeDumper::leaveIndent() {
    this->indentLevel--;
}

void NodeDumper::indent() {
    for(unsigned int i = 0; i < this->indentLevel; i++) {
        this->stream << "  ";
    }
}

void NodeDumper::dumpNodeHeader(const Node &node, bool inArray) {
    std::string className = misc::Demangle()(typeid(node));

    this->stream << "__Node: " << std::endl;
    this->enterIndent();
    if(inArray) {
        this->enterIndent();
    }

    this->indent(); this->stream << "__typeid: " << className << std::endl;
    this->indent(); this->stream << "pos: " << node.getStartPos() << std::endl;
    this->indent(); this->stream << "size: " << node.getSize() << std::endl;
    this->indent(); this->stream << "type: " <<
            (!node.isUntyped() ? this->pool.getTypeName(node.getType()) : "") << std::endl;

    this->leaveIndent();
    if(inArray) {
        this->leaveIndent();
    }
}

void NodeDumper::writeName(const char *fieldName) {
    this->indent(); this->stream << fieldName << ": ";
}

void NodeDumper::operator()(const RootNode &rootNode) {
    this->dump(rootNode);
}

void NodeDumper::dump(std::ostream &out, TypePool &pool, const RootNode &rootNode) {
    NodeDumper writer(out, pool);
    writer(rootNode);
}

} // namespace ast
} // namespace ydsh<commit_msg>fix ast dump format<commit_after>/*
 * Copyright (C) 2015-2016 Nagisa Sekiguchi
 *
 * 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.
 */

#include <iostream>

#include "node_dumper.h"
#include "node.h"

namespace ydsh {
namespace ast {

void NodeDumper::dump(const char *fieldName, const char *value) {
    std::string str(value);
    this->dump(fieldName, str);
}

void NodeDumper::dump(const char *fieldName, const std::string &value) {
    this->writeName(fieldName);

    this->stream << '"';
    for(char ch : value) {
        bool escape = true;
        switch(ch) {
        case '\t':
            ch = 't';
            break;
        case '\r':
            ch = 'r';
            break;
        case '\n':
            ch = 'n';
            break;
        case '"':
            ch = '"';
            break;
        case '\\':
            ch = '\\';
            break;
        default:
            escape = false;
            break;
        }
        if(escape) {
            this->stream << '\\';
        }
        this->stream << ch;
    }
    this->stream << '"' << std::endl;
}

void NodeDumper::dump(const char *fieldName, const std::vector<Node *> &nodes) {
    this->writeName(fieldName);
    this->stream << std::endl;

    this->enterIndent();
    for(Node *node : nodes) {
        this->indent();
        this->stream << "- ";
        this->dumpNodeHeader(*node, true);
        this->enterIndent();
        node->dump(*this);
        this->leaveIndent();
    }
    this->leaveIndent();
}

void NodeDumper::dump(const char *fieldName, const std::list<Node *> &nodes) {
    this->writeName(fieldName);
    this->stream << std::endl;

    this->enterIndent();
    for(Node *node : nodes) {
        this->indent();
        this->stream << "- ";
        this->dumpNodeHeader(*node, true);
        this->enterIndent();
        node->dump(*this);
        this->leaveIndent();
    }
    this->leaveIndent();
}

void NodeDumper::dump(const char *fieldName, const Node &node) {
    // write field name
    this->writeName(fieldName);

    // write node body
    this->stream << std::endl;
    this->enterIndent();
    this->dump(node);
    this->leaveIndent();
}

void NodeDumper::dump(const char *fieldName, const DSType &type) {
    this->writeName(fieldName);
    this->stream << this->pool.getTypeName(type) << std::endl;
}

void NodeDumper::dumpNull(const char *fieldName) {
    this->writeName(fieldName);
    this->stream << std::endl;
}

void NodeDumper::dump(const Node &node) {
    this->indent();
    this->dumpNodeHeader(node);
    node.dump(*this);
}

void NodeDumper::enterIndent() {
    this->indentLevel++;
}

void NodeDumper::leaveIndent() {
    this->indentLevel--;
}

void NodeDumper::indent() {
    for(unsigned int i = 0; i < this->indentLevel; i++) {
        this->stream << "  ";
    }
}

void NodeDumper::dumpNodeHeader(const Node &node, bool inArray) {
    std::string className = misc::Demangle()(typeid(node));

    this->stream << "__Node: " << std::endl;
    this->enterIndent();
    if(inArray) {
        this->enterIndent();
    }

    this->indent(); this->stream << "__typeid: " << strrchr(className.c_str(), ':') + 1 << std::endl;
    this->indent(); this->stream << "pos: " << node.getStartPos() << std::endl;
    this->indent(); this->stream << "size: " << node.getSize() << std::endl;
    this->indent(); this->stream << "type: " <<
            (!node.isUntyped() ? this->pool.getTypeName(node.getType()) : "") << std::endl;

    this->leaveIndent();
    if(inArray) {
        this->leaveIndent();
    }
}

void NodeDumper::writeName(const char *fieldName) {
    this->indent(); this->stream << fieldName << ": ";
}

void NodeDumper::operator()(const RootNode &rootNode) {
    this->dump(rootNode);
}

void NodeDumper::dump(std::ostream &out, TypePool &pool, const RootNode &rootNode) {
    NodeDumper writer(out, pool);
    writer(rootNode);
}

} // namespace ast
} // namespace ydsh<|endoftext|>


<commit_before>#pragma once

#include "utility/memory_cast.hpp"

#include "sha3.h"

#include <assert.h>
#include <array>
#include <stdint.h>

template <size_t NBits>
class Sha3_Hasher {
public:
	Sha3_Hasher() noexcept
	{
		if constexpr (NBits == 256)
			sha3_Init256(&_c);
		else if constexpr (NBits == 384)
			sha3_Init384(&_c);
		else if constexpr (NBits == 256)
			sha3_Init512(&_c);
		else
			static_assert(NBits == 256, "The following SHA3 width is supported: 256, 384, 512 bits");
	}

	void update(const void * const bufIn, const size_t len) noexcept
	{
		assert(!_finalized);
		if (len > 0) // it's unclear whether sha3_Update support 0 length. In fact, it seems to underflow it and enter an [almost] infinite loop.
			sha3_Update(&_c, bufIn, len);
		else
			assert(len > 0);
	}

	void update(const std::string& str) noexcept
	{
		this->update(str.data(), str.size());
	}

	template <typename T, typename = std::enable_if_t<is_trivially_serializable_v<std::remove_reference_t<T>>>>
	void update(T&& value) noexcept
	{
		static_assert(is_trivially_serializable_v<std::remove_reference_t<T>>);
		this->update(std::addressof(value), sizeof(value));
	}

	std::array<uint8_t, NBits / 8> getHash() noexcept
	{
		assert(!_finalized);

		const void* const hashData = sha3_Finalize(&_c);
		std::array<uint8_t, NBits / 8> hashDataArray;
		::memcpy(hashDataArray.data(), hashData, hashDataArray.size());
		_finalized = true;
		return hashDataArray;
	}

	uint64_t get64BitHash() noexcept
	{
		const auto fullHash = getHash();

		uint64_t hash64 = 0;
		for (size_t offset = 0; offset < fullHash.size(); offset += sizeof(uint64_t))
		{
			const auto eightBytes = memory_cast<uint64_t>(fullHash.data() + offset);
			hash64 ^= eightBytes;
		}

		return hash64;
	}

private:
	sha3_context _c;
	bool _finalized = false;
};

inline uint64_t sha3_64bit(const void * const bufIn, const size_t len) noexcept
{
	Sha3_Hasher<256> hasher;
	hasher.update(bufIn, len);
	return hasher.get64BitHash();
}
<commit_msg>Sha3_Hasher<512> bug fixed<commit_after>#pragma once

#include "utility/memory_cast.hpp"

#include "sha3.h"

#include <assert.h>
#include <array>
#include <stdint.h>

template <size_t NBits>
class Sha3_Hasher {
public:
	Sha3_Hasher() noexcept
	{
		if constexpr (NBits == 256)
			sha3_Init256(&_c);
		else if constexpr (NBits == 384)
			sha3_Init384(&_c);
		else if constexpr (NBits == 512)
			sha3_Init512(&_c);
		else
			static_assert(NBits == 256, "The following SHA3 width is supported: 256, 384, 512 bits");
	}

	void update(const void * const bufIn, const size_t len) noexcept
	{
		assert(!_finalized);
		if (len > 0) // it's unclear whether sha3_Update support 0 length. In fact, it seems to underflow it and enter an [almost] infinite loop.
			sha3_Update(&_c, bufIn, len);
		else
			assert(len > 0);
	}

	void update(const std::string& str) noexcept
	{
		this->update(str.data(), str.size());
	}

	template <typename T, typename = std::enable_if_t<is_trivially_serializable_v<std::remove_reference_t<T>>>>
	void update(T&& value) noexcept
	{
		static_assert(is_trivially_serializable_v<std::remove_reference_t<T>>);
		this->update(std::addressof(value), sizeof(value));
	}

	std::array<uint8_t, NBits / 8> getHash() noexcept
	{
		assert(!_finalized);

		const void* const hashData = sha3_Finalize(&_c);
		std::array<uint8_t, NBits / 8> hashDataArray;
		::memcpy(hashDataArray.data(), hashData, hashDataArray.size());
		_finalized = true;
		return hashDataArray;
	}

	uint64_t get64BitHash() noexcept
	{
		const auto fullHash = getHash();

		uint64_t hash64 = 0;
		for (size_t offset = 0; offset < fullHash.size(); offset += sizeof(uint64_t))
		{
			const auto eightBytes = memory_cast<uint64_t>(fullHash.data() + offset);
			hash64 ^= eightBytes;
		}

		return hash64;
	}

private:
	sha3_context _c;
	bool _finalized = false;
};

inline uint64_t sha3_64bit(const void * const bufIn, const size_t len) noexcept
{
	Sha3_Hasher<256> hasher;
	hasher.update(bufIn, len);
	return hasher.get64BitHash();
}
<|endoftext|>