<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 <signal.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <string.h>
#include <unistd.h>

#include <mesos/mesos.hpp>

#include <process/pid.hpp>
#include <process/defer.hpp>
#include <process/delay.hpp>
#include <process/future.hpp>
#include <process/io.hpp>
#include <process/process.hpp>
#include <process/protobuf.hpp>
#include <process/subprocess.hpp>

#include <stout/duration.hpp>
#include <stout/os.hpp>
#include <stout/option.hpp>
#include <stout/flags.hpp>
#include <stout/protobuf.hpp>
#include <stout/json.hpp>

#include "common/status_utils.hpp"

#include "messages/messages.hpp"

using namespace mesos;

using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::map;

using process::UPID;

namespace mesos {
namespace internal {

using namespace process;

using namespace mesos::internal::status;

class HealthCheckerProcess : public ProtobufProcess<HealthCheckerProcess>
{
public:
  HealthCheckerProcess(
    const HealthCheck& _check,
    const UPID& _executor,
    const TaskID& _taskID)
    : check(_check),
      initializing(true),
      executor(_executor),
      taskID(_taskID),
      consecutiveFailures(0) {}

  virtual ~HealthCheckerProcess() {}

  Future<Nothing> healthCheck()
  {
    VLOG(2) << "Health checks starting in "
      << Seconds(check.delay_seconds()) << ", grace period "
      << Seconds(check.grace_period_seconds());

    startTime = Clock::now();

    delay(Seconds(check.delay_seconds()), self(), &Self::_healthCheck);
    return promise.future();
  }

private:
  void failure(const string& message)
  {
    if (check.grace_period_seconds() > 0 &&
        (Clock::now() - startTime).secs() <= check.grace_period_seconds()) {
      LOG(INFO) << "Ignoring failure as health check still in grace period";
      reschedule();
      return;
    }

    consecutiveFailures++;
    VLOG(1) << "#" << consecutiveFailures << " check failed: " << message;

    bool killTask = consecutiveFailures >= check.consecutive_failures();

    TaskHealthStatus taskHealthStatus;
    taskHealthStatus.set_healthy(false);
    taskHealthStatus.set_consecutive_failures(consecutiveFailures);
    taskHealthStatus.set_kill_task(killTask);
    taskHealthStatus.mutable_task_id()->CopyFrom(taskID);
    send(executor, taskHealthStatus);

    if (killTask) {
      promise.fail(message);
    } else {
      reschedule();
    }
  }

  void success()
  {
    VLOG(1) << "Check passed";
    if (initializing) {
      TaskHealthStatus taskHealthStatus;
      taskHealthStatus.set_healthy(true);
      taskHealthStatus.mutable_task_id()->CopyFrom(taskID);
      send(executor, taskHealthStatus);
      initializing = false;
    }
    consecutiveFailures = 0;
    reschedule();
  }

  void _healthCheck()
  {
    if (check.has_http()) {
      promise.fail("HTTP health check is not supported");
    } else if (check.has_command()) {
      const CommandInfo& command = check.command();

      map<string, string> environment;

      foreach (const Environment_Variable& variable,
               command.environment().variables()) {
        environment[variable.name()] = variable.value();
      }

      VLOG(2) << "Launching health command: " << command.value();

      Try<Subprocess> external =
        process::subprocess(
          command.value(),
          Subprocess::PIPE(),
          Subprocess::FD(STDERR_FILENO),
          Subprocess::FD(STDERR_FILENO),
          environment);

      if (external.isError()) {
        promise.fail("Error creating subprocess for healthcheck");
      } else {
        Future<Option<int> > status = external.get().status();
        status.await(Seconds(check.timeout_seconds()));

        if (status.isFailed()) {
          promise.fail("Shell command check failed with status: " +
                        status.failure());
          return;
        }

        int statusCode = status.get().get();
        if (statusCode != 0) {
          string message = "Health command check " + WSTRINGIFY(statusCode);
          failure(message);
        } else {
          success();
        }
      }
    } else {
      promise.fail("No check found in health check");
    }
  }

  void reschedule()
  {
    VLOG(1) << "Rescheduling health check in "
      << Seconds(check.interval_seconds());

    delay(Seconds(check.interval_seconds()), self(), &Self::_healthCheck);
  }

  Promise<Nothing> promise;
  HealthCheck check;
  bool initializing;
  UPID executor;
  TaskID taskID;
  uint32_t consecutiveFailures;
  process::Time startTime;
};

} // namespace internal {
} // namespace mesos {

class Flags : public virtual flags::FlagsBase
{
public:
  Flags()
  {
    add(&Flags::health_check_json,
        "health_check_json",
        "JSON describing health check to perform");

    add(&Flags::executor,
        "executor",
        "Executor UPID to send health check messages to");

    add(&Flags::task_id,
        "task_id",
        "Task ID that this health check process is checking");
  }

  Option<std::string> health_check_json;
  Option<UPID> executor;
  Option<std::string> task_id;
};

void usage(const char* argv0, const flags::FlagsBase& flags)
{
  cerr << "Usage: " << os::basename(argv0).get() << " [...]" << endl
       << endl
       << "Supported options:" << endl
       << flags.usage();
}

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

  Flags flags;

  bool help;
  flags.add(&help,
            "help",
            "Prints this help message",
            false);

  Try<Nothing> load = flags.load(None(), argc, argv);

  if (load.isError()) {
    LOG(WARNING) << load.error();
    usage(argv[0], flags);
    return -1;
  }

  if (help) {
    usage(argv[0], flags);
    return 0;
  }

  if (flags.health_check_json.isNone()) {
    LOG(WARNING) << "Expected JSON with health check description";
    usage(argv[0], flags);
    return 0;
  }

  Try<JSON::Object> parse =
    JSON::parse<JSON::Object>(flags.health_check_json.get());
  if (parse.isError()) {
    LOG(WARNING) << "JSON parse error: " << parse.error();
    usage(argv[0], flags);
    return 0;
  }

  if (flags.executor.isNone()) {
    LOG(WARNING) << "Expected UPID for health check";
    usage(argv[0], flags);
    return 0;
  }

  Try<HealthCheck> check = protobuf::parse<HealthCheck>(parse.get());
  if (check.isError()) {
    LOG(WARNING) << "JSON error: " << check.error();
    usage(argv[0], flags);
    return 0;
  }

  if (check.get().has_http() && check.get().has_command()) {
    LOG(WARNING) << "Both HTTP and Command check passed in";
    return -1;
  }

  if (!check.get().has_http() && !check.get().has_command()) {
    LOG(WARNING) << "No health check found";
    return -1;
  }

  if (flags.task_id.isNone()) {
    LOG(WARNING) << "TaskID error: " << check.error();
    usage(argv[0], flags);
    return 0;
  }

  TaskID taskID;
  taskID.set_value(flags.task_id.get());

  internal::HealthCheckerProcess process(
    check.get(),
    flags.executor.get(),
    taskID);

  process::spawn(&process);

  process::Future<Nothing> checking =
    process::dispatch(
      process, &internal::HealthCheckerProcess::healthCheck);

  checking.await();

  process::terminate(process);
  process::wait(process);

  if (checking.isFailed()) {
    LOG(WARNING) << "Health check failed " << checking.failure();
    return 1;
  }

  return 0;
}
<commit_msg>Fixed health check command subprocess handling.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 <signal.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <string.h>
#include <unistd.h>

#include <mesos/mesos.hpp>

#include <process/pid.hpp>
#include <process/defer.hpp>
#include <process/delay.hpp>
#include <process/future.hpp>
#include <process/io.hpp>
#include <process/process.hpp>
#include <process/protobuf.hpp>
#include <process/subprocess.hpp>

#include <stout/duration.hpp>
#include <stout/os.hpp>
#include <stout/option.hpp>
#include <stout/flags.hpp>
#include <stout/protobuf.hpp>
#include <stout/json.hpp>

#include "common/status_utils.hpp"

#include "messages/messages.hpp"

using namespace mesos;

using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::map;

using process::UPID;

namespace mesos {
namespace internal {

using namespace process;

using namespace mesos::internal::status;

class HealthCheckerProcess : public ProtobufProcess<HealthCheckerProcess>
{
public:
  HealthCheckerProcess(
    const HealthCheck& _check,
    const UPID& _executor,
    const TaskID& _taskID)
    : check(_check),
      initializing(true),
      executor(_executor),
      taskID(_taskID),
      consecutiveFailures(0) {}

  virtual ~HealthCheckerProcess() {}

  Future<Nothing> healthCheck()
  {
    VLOG(2) << "Health checks starting in "
      << Seconds(check.delay_seconds()) << ", grace period "
      << Seconds(check.grace_period_seconds());

    startTime = Clock::now();

    delay(Seconds(check.delay_seconds()), self(), &Self::_healthCheck);
    return promise.future();
  }

private:
  void failure(const string& message)
  {
    if (check.grace_period_seconds() > 0 &&
        (Clock::now() - startTime).secs() <= check.grace_period_seconds()) {
      LOG(INFO) << "Ignoring failure as health check still in grace period";
      reschedule();
      return;
    }

    consecutiveFailures++;
    VLOG(1) << "#" << consecutiveFailures << " check failed: " << message;

    bool killTask = consecutiveFailures >= check.consecutive_failures();

    TaskHealthStatus taskHealthStatus;
    taskHealthStatus.set_healthy(false);
    taskHealthStatus.set_consecutive_failures(consecutiveFailures);
    taskHealthStatus.set_kill_task(killTask);
    taskHealthStatus.mutable_task_id()->CopyFrom(taskID);
    send(executor, taskHealthStatus);

    if (killTask) {
      promise.fail(message);
    } else {
      reschedule();
    }
  }

  void success()
  {
    VLOG(1) << "Check passed";
    if (initializing) {
      TaskHealthStatus taskHealthStatus;
      taskHealthStatus.set_healthy(true);
      taskHealthStatus.mutable_task_id()->CopyFrom(taskID);
      send(executor, taskHealthStatus);
      initializing = false;
    }
    consecutiveFailures = 0;
    reschedule();
  }

  void _healthCheck()
  {
    if (check.has_http()) {
      promise.fail("HTTP health check is not supported");
    } else if (check.has_command()) {
      const CommandInfo& command = check.command();

      map<string, string> environment;

      foreach (const Environment_Variable& variable,
               command.environment().variables()) {
        environment[variable.name()] = variable.value();
      }

      VLOG(2) << "Launching health command: " << command.value();

      Try<Subprocess> external =
        process::subprocess(
          command.value(),
          // Reading from STDIN instead of PIPE because scripts
          // seeing an open STDIN pipe might behave differently
          // and we do not expect to pass any value from STDIN
          // or PIPE.
          Subprocess::FD(STDIN_FILENO),
          Subprocess::FD(STDERR_FILENO),
          Subprocess::FD(STDERR_FILENO),
          environment);

      if (external.isError()) {
        promise.fail("Error creating subprocess for healthcheck");
      } else {
        Future<Option<int> > status = external.get().status();
        status.await(Seconds(check.timeout_seconds()));

        if (!status.isReady()) {
          string msg = "Shell command check failed with reason: ";
          if (status.isFailed()) {
            msg += "failed with error: " + status.failure();
          } else if (status.isDiscarded()) {
            msg += "status future discarded";
          } else {
            msg += "status still pending after timeout " +
                   stringify(Seconds(check.timeout_seconds()));
          }

          promise.fail(msg);
          return;
        }

        int statusCode = status.get().get();
        if (statusCode != 0) {
          string message = "Health command check " + WSTRINGIFY(statusCode);
          failure(message);
        } else {
          success();
        }
      }
    } else {
      promise.fail("No check found in health check");
    }
  }

  void reschedule()
  {
    VLOG(1) << "Rescheduling health check in "
      << Seconds(check.interval_seconds());

    delay(Seconds(check.interval_seconds()), self(), &Self::_healthCheck);
  }

  Promise<Nothing> promise;
  HealthCheck check;
  bool initializing;
  UPID executor;
  TaskID taskID;
  uint32_t consecutiveFailures;
  process::Time startTime;
};

} // namespace internal {
} // namespace mesos {

class Flags : public virtual flags::FlagsBase
{
public:
  Flags()
  {
    add(&Flags::health_check_json,
        "health_check_json",
        "JSON describing health check to perform");

    add(&Flags::executor,
        "executor",
        "Executor UPID to send health check messages to");

    add(&Flags::task_id,
        "task_id",
        "Task ID that this health check process is checking");
  }

  Option<std::string> health_check_json;
  Option<UPID> executor;
  Option<std::string> task_id;
};

void usage(const char* argv0, const flags::FlagsBase& flags)
{
  cerr << "Usage: " << os::basename(argv0).get() << " [...]" << endl
       << endl
       << "Supported options:" << endl
       << flags.usage();
}

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

  Flags flags;

  bool help;
  flags.add(&help,
            "help",
            "Prints this help message",
            false);

  Try<Nothing> load = flags.load(None(), argc, argv);

  if (load.isError()) {
    LOG(WARNING) << load.error();
    usage(argv[0], flags);
    return -1;
  }

  if (help) {
    usage(argv[0], flags);
    return 0;
  }

  if (flags.health_check_json.isNone()) {
    LOG(WARNING) << "Expected JSON with health check description";
    usage(argv[0], flags);
    return 0;
  }

  Try<JSON::Object> parse =
    JSON::parse<JSON::Object>(flags.health_check_json.get());
  if (parse.isError()) {
    LOG(WARNING) << "JSON parse error: " << parse.error();
    usage(argv[0], flags);
    return 0;
  }

  if (flags.executor.isNone()) {
    LOG(WARNING) << "Expected UPID for health check";
    usage(argv[0], flags);
    return 0;
  }

  Try<HealthCheck> check = protobuf::parse<HealthCheck>(parse.get());
  if (check.isError()) {
    LOG(WARNING) << "JSON error: " << check.error();
    usage(argv[0], flags);
    return 0;
  }

  if (check.get().has_http() && check.get().has_command()) {
    LOG(WARNING) << "Both HTTP and Command check passed in";
    return -1;
  }

  if (!check.get().has_http() && !check.get().has_command()) {
    LOG(WARNING) << "No health check found";
    return -1;
  }

  if (flags.task_id.isNone()) {
    LOG(WARNING) << "TaskID error: " << check.error();
    usage(argv[0], flags);
    return 0;
  }

  TaskID taskID;
  taskID.set_value(flags.task_id.get());

  internal::HealthCheckerProcess process(
    check.get(),
    flags.executor.get(),
    taskID);

  process::spawn(&process);

  process::Future<Nothing> checking =
    process::dispatch(
      process, &internal::HealthCheckerProcess::healthCheck);

  checking.await();

  process::terminate(process);
  process::wait(process);

  if (checking.isFailed()) {
    LOG(WARNING) << "Health check failed " << checking.failure();
    return 1;
  }

  return 0;
}
<|endoftext|>


<commit_before><commit_msg>coverity#1266494 Untrusted value as argument<commit_after><|endoftext|>


<commit_before>#include "training-data-manager.h"

#include <sstream>

const char kDefaultTrainingDataName[] = "Default";

// Useful macros that simplifies the coding.
// Always check label first!
#define CHECK_LABEL(label)                          \
    assert((label) > 0 && label <= num_classes_ &&  \
           "Label should be [1, num_classes_]");

#define CHECK_INDEX(label, index)                       \
    assert((index) < num_samples_per_label_[(label)] && \
           "Index exceeds the available samples");

TrainingDataManager::TrainingDataManager(uint32_t num_classes)
        : num_classes_(num_classes) {
    training_sample_names_.resize(num_classes + 1);
    training_sample_scores_.resize(num_classes + 1);
    training_sample_class_likelihoods_.resize(num_classes + 1);
    num_samples_per_label_.resize(num_classes + 1, 0);

    for (uint32_t i = 0; i <= num_classes; i++) {
        default_label_names_.push_back(
            std::string("Label ") + std::to_string(i));
    }

    data_.setDatasetName(kDefaultTrainingDataName);
}

bool TrainingDataManager::setNumDimensions(uint32_t dim) {
    return data_.setNumDimensions(dim);
}

bool TrainingDataManager::setDatasetName(const std::string name) {
    return data_.setDatasetName(name);
}

bool TrainingDataManager::setDatasetName(const char* const name) {
    if ((name != NULL) && (name[0] == '\0')) {
        return data_.setDatasetName(std::string(name));
    }
    return false;
}

std::string TrainingDataManager::getSampleName(uint32_t label, uint32_t index) {
    CHECK_LABEL(label);
    CHECK_INDEX(label, index);

    const auto& name = training_sample_names_[label][index];
    if (name.first) {
        return name.second;
    } else {
        return default_label_names_[label] + " [" + std::to_string(index) + "]";
    }
}

bool TrainingDataManager::setSampleName(
    uint32_t label, uint32_t index, const std::string new_name) {
    CHECK_LABEL(label);

    auto& name = training_sample_names_[label][index];
    name.first = true;
    name.second = new_name;
    return true;
}

bool TrainingDataManager::addSample(
    uint32_t label, const GRT::MatrixDouble& sample) {
    CHECK_LABEL(label);

    // By default, set the name be <false, ""> so we will use the default name.
    training_sample_names_[label].push_back(
        std::make_pair(false, std::string()));
    training_sample_scores_[label].push_back(std::make_pair(false, 0.0));
    training_sample_class_likelihoods_[label].push_back(std::make_pair(false, std::vector<double>()));
    data_.addSample(label, sample);
    num_samples_per_label_[label]++;

    return true;
}

std::string TrainingDataManager::getLabelName(uint32_t label) {
    CHECK_LABEL(label);
    return default_label_names_[label];
}

bool TrainingDataManager::setNameForLabel(const std::string name, uint32_t label) {
    CHECK_LABEL(label);
    default_label_names_[label] = name;
    return true;
}

GRT::MatrixDouble TrainingDataManager::getSample(uint32_t label, uint32_t index) {
    CHECK_LABEL(label);
    CHECK_INDEX(label, index);
    return data_.getClassData(label)[index].getData();
}

uint32_t TrainingDataManager::getNumSampleForLabel(uint32_t label) {
    CHECK_LABEL(label);
    assert(num_samples_per_label_[label] ==
           data_.getClassData(label).getNumSamples());
    return num_samples_per_label_[label];
}

bool TrainingDataManager::deleteSample(uint32_t label, uint32_t index) {
    CHECK_LABEL(label);
    CHECK_INDEX(label, index);

    // The implementation first remove all data and then add them back. This is
    // a temporary solution because GRT::TimeSeriesClassificationData doesn't
    // allow per-sample operation.
    GRT::TimeSeriesClassificationData data = data_.getClassData(label);
    data_.eraseAllSamplesWithClassLabel(label);

    for (uint32_t i = 0; i < data.getNumSamples(); i++) {
        if (i != index) {
            data_.addSample(label, data[i].getData());
        }
    }

    auto& names = training_sample_names_[label];
    names.erase(names.begin() + index);

    auto& scores = training_sample_scores_[label];
    scores.erase(scores.begin() + index);

    auto& likelihoods = training_sample_class_likelihoods_[label];
    likelihoods.erase(likelihoods.begin() + index);

    num_samples_per_label_[label]--;

    return true;
}

bool TrainingDataManager::deleteAllSamples() {
    for (uint32_t i = 0; i < num_classes_; i++) {
        data_.eraseAllSamplesWithClassLabel(i + 1);
        num_samples_per_label_[i + 1] = 0;
        auto& scores = training_sample_scores_[i + 1];
        scores.erase(scores.begin(), scores.end());
        auto& likelihoods = training_sample_class_likelihoods_[i + 1];
        likelihoods.erase(likelihoods.begin(), likelihoods.end());
    }
    return true;
}

bool TrainingDataManager::deleteAllSamplesWithLabel(uint32_t label) {
    CHECK_LABEL(label);
    data_.eraseAllSamplesWithClassLabel(label);
    num_samples_per_label_[label] = 0;
    auto& scores = training_sample_scores_[label];
    scores.erase(scores.begin(), scores.end());
    auto& likelihoods = training_sample_class_likelihoods_[label];
    likelihoods.erase(likelihoods.begin(), likelihoods.end());
    return true;
}

bool TrainingDataManager::relabelSample(
    uint32_t label, uint32_t index, uint32_t new_label) {
    CHECK_LABEL(label);
    CHECK_LABEL(new_label);
    CHECK_INDEX(label, index);

    GRT::MatrixDouble data = getSample(label, index);
    deleteSample(label, index);
    addSample(new_label, data);

    return true;
}

bool TrainingDataManager::trimSample(
    uint32_t label, uint32_t index, uint32_t start, uint32_t end) {
    CHECK_LABEL(label);
    CHECK_INDEX(label, index);

    GRT::TimeSeriesClassificationData data = data_.getClassData(label);
    data_.eraseAllSamplesWithClassLabel(label);

    for (uint32_t i = 0; i < data.getNumSamples(); i++) {
        if (i == index) {
            GRT::MatrixDouble sample = data[i].getData();
            GRT::MatrixDouble new_sample;

            for (uint32_t row = start; row <= end; row++) {
                new_sample.push_back(sample.getRowVector(row));
            }
            data_.addSample(label, new_sample);
        } else {
            data_.addSample(label, data[i].getData());
        }
    }
    return true;
}

bool TrainingDataManager::hasSampleScore(uint32_t label, uint32_t index) {
    if (!(label > 0 && label <= num_classes_)) return false;
    if (!(index < num_samples_per_label_[label])) return false;

    const auto& score = training_sample_scores_[label][index];
    return score.first;
}

double TrainingDataManager::getSampleScore(uint32_t label, uint32_t index) {
    CHECK_LABEL(label);
    CHECK_INDEX(label, index);

    const auto& score = training_sample_scores_[label][index];
    if (score.first) {
        return score.second;
    } else {
        return 0.0; // is there something better we can do here?
    }
}

bool TrainingDataManager::setSampleScore(
    uint32_t label, uint32_t index, double new_score) {
    CHECK_LABEL(label);

    auto& score = training_sample_scores_[label][index];
    score.first = true;
    score.second = new_score;
    return true;
}

bool TrainingDataManager::hasSampleClassLikelihoods(uint32_t label, uint32_t index) {
    if (!(label > 0 && label <= num_classes_)) return false;
    if (!(index < num_samples_per_label_[label])) return false;

    const auto& likelihood = training_sample_class_likelihoods_[label][index];
    return likelihood.first;
}

std::vector<double> TrainingDataManager::getSampleClassLikelihoods(uint32_t label, uint32_t index) {
    CHECK_LABEL(label);
    CHECK_INDEX(label, index);

    const auto& likelihood = training_sample_class_likelihoods_[label][index];
    if (likelihood.first) {
        return likelihood.second;
    } else {
        return std::vector<double>(); // is there something better we can do here?
    }
}

bool TrainingDataManager::setSampleClassLikelihoods(
    uint32_t label, uint32_t index, vector<double> new_likelihoods) {
    CHECK_LABEL(label);

    auto& likelihood = training_sample_class_likelihoods_[label][index];
    likelihood.first = true;
    likelihood.second = new_likelihoods;
    return true;
}

bool TrainingDataManager::load(const std::string& filename) {
    if (!data_.load(filename)) {
        return false;
    }

    // Use the larger of the current value of num_classes_ and
    // data_.getNumClasses(). See discussion at
    // https://github.com/damellis/ESP/issues/252.
    num_classes_ = std::max(data_.getNumClasses(), num_classes_);

    // Populate the internals of the manager from data_. Most importantly, need
    // to resize all vectors to hold the data.
    training_sample_names_.resize(num_classes_ + 1);
    default_label_names_.resize(num_classes_ + 1);
    num_samples_per_label_.resize(num_classes_ + 1);
    training_sample_scores_.resize(num_classes_ + 1);
    training_sample_class_likelihoods_.resize(num_classes_ + 1);

    for (uint32_t i = 1; i <= num_classes_; i++) {
        const string class_name = data_.getClassNameForCorrespondingClassLabel(i);
        if (class_name == "NOT_SET" || class_name == "CLASS_LABEL_NOT_FOUND") {
            default_label_names_[i] = std::string("Label ") + std::to_string(i);
        } else {
            default_label_names_[i] = class_name;
        }

        uint32_t num_samples = data_.getClassData(i).getNumSamples();
        num_samples_per_label_[i] = num_samples;

        training_sample_names_[i].clear();
        training_sample_scores_[i].clear();
        training_sample_class_likelihoods_[i].clear();
        for (uint32_t j = 0; j < num_samples; j++) {
            // Since we don't yet have per-sample name saved, we will use
            // default names (marking the pair as <false, "">).
            training_sample_names_[i].push_back(
                std::make_pair(false, std::string()));
            training_sample_scores_[i].push_back(std::make_pair(false, 0.0));
            training_sample_class_likelihoods_[i].push_back(
                std::make_pair(false, vector<double>()));
        }
    }

    return true;
}
<commit_msg>Change default label from "Label N" to "N".<commit_after>#include "training-data-manager.h"

#include <sstream>

const char kDefaultTrainingDataName[] = "Default";

// Useful macros that simplifies the coding.
// Always check label first!
#define CHECK_LABEL(label)                          \
    assert((label) > 0 && label <= num_classes_ &&  \
           "Label should be [1, num_classes_]");

#define CHECK_INDEX(label, index)                       \
    assert((index) < num_samples_per_label_[(label)] && \
           "Index exceeds the available samples");

TrainingDataManager::TrainingDataManager(uint32_t num_classes)
        : num_classes_(num_classes) {
    training_sample_names_.resize(num_classes + 1);
    training_sample_scores_.resize(num_classes + 1);
    training_sample_class_likelihoods_.resize(num_classes + 1);
    num_samples_per_label_.resize(num_classes + 1, 0);

    for (uint32_t i = 0; i <= num_classes; i++) {
        default_label_names_.push_back(std::to_string(i));
    }

    data_.setDatasetName(kDefaultTrainingDataName);
}

bool TrainingDataManager::setNumDimensions(uint32_t dim) {
    return data_.setNumDimensions(dim);
}

bool TrainingDataManager::setDatasetName(const std::string name) {
    return data_.setDatasetName(name);
}

bool TrainingDataManager::setDatasetName(const char* const name) {
    if ((name != NULL) && (name[0] == '\0')) {
        return data_.setDatasetName(std::string(name));
    }
    return false;
}

std::string TrainingDataManager::getSampleName(uint32_t label, uint32_t index) {
    CHECK_LABEL(label);
    CHECK_INDEX(label, index);

    const auto& name = training_sample_names_[label][index];
    if (name.first) {
        return name.second;
    } else {
        return default_label_names_[label] + " [" + std::to_string(index) + "]";
    }
}

bool TrainingDataManager::setSampleName(
    uint32_t label, uint32_t index, const std::string new_name) {
    CHECK_LABEL(label);

    auto& name = training_sample_names_[label][index];
    name.first = true;
    name.second = new_name;
    return true;
}

bool TrainingDataManager::addSample(
    uint32_t label, const GRT::MatrixDouble& sample) {
    CHECK_LABEL(label);

    // By default, set the name be <false, ""> so we will use the default name.
    training_sample_names_[label].push_back(
        std::make_pair(false, std::string()));
    training_sample_scores_[label].push_back(std::make_pair(false, 0.0));
    training_sample_class_likelihoods_[label].push_back(std::make_pair(false, std::vector<double>()));
    data_.addSample(label, sample);
    num_samples_per_label_[label]++;

    return true;
}

std::string TrainingDataManager::getLabelName(uint32_t label) {
    CHECK_LABEL(label);
    return default_label_names_[label];
}

bool TrainingDataManager::setNameForLabel(const std::string name, uint32_t label) {
    CHECK_LABEL(label);
    default_label_names_[label] = name;
    return true;
}

GRT::MatrixDouble TrainingDataManager::getSample(uint32_t label, uint32_t index) {
    CHECK_LABEL(label);
    CHECK_INDEX(label, index);
    return data_.getClassData(label)[index].getData();
}

uint32_t TrainingDataManager::getNumSampleForLabel(uint32_t label) {
    CHECK_LABEL(label);
    assert(num_samples_per_label_[label] ==
           data_.getClassData(label).getNumSamples());
    return num_samples_per_label_[label];
}

bool TrainingDataManager::deleteSample(uint32_t label, uint32_t index) {
    CHECK_LABEL(label);
    CHECK_INDEX(label, index);

    // The implementation first remove all data and then add them back. This is
    // a temporary solution because GRT::TimeSeriesClassificationData doesn't
    // allow per-sample operation.
    GRT::TimeSeriesClassificationData data = data_.getClassData(label);
    data_.eraseAllSamplesWithClassLabel(label);

    for (uint32_t i = 0; i < data.getNumSamples(); i++) {
        if (i != index) {
            data_.addSample(label, data[i].getData());
        }
    }

    auto& names = training_sample_names_[label];
    names.erase(names.begin() + index);

    auto& scores = training_sample_scores_[label];
    scores.erase(scores.begin() + index);

    auto& likelihoods = training_sample_class_likelihoods_[label];
    likelihoods.erase(likelihoods.begin() + index);

    num_samples_per_label_[label]--;

    return true;
}

bool TrainingDataManager::deleteAllSamples() {
    for (uint32_t i = 0; i < num_classes_; i++) {
        data_.eraseAllSamplesWithClassLabel(i + 1);
        num_samples_per_label_[i + 1] = 0;
        auto& scores = training_sample_scores_[i + 1];
        scores.erase(scores.begin(), scores.end());
        auto& likelihoods = training_sample_class_likelihoods_[i + 1];
        likelihoods.erase(likelihoods.begin(), likelihoods.end());
    }
    return true;
}

bool TrainingDataManager::deleteAllSamplesWithLabel(uint32_t label) {
    CHECK_LABEL(label);
    data_.eraseAllSamplesWithClassLabel(label);
    num_samples_per_label_[label] = 0;
    auto& scores = training_sample_scores_[label];
    scores.erase(scores.begin(), scores.end());
    auto& likelihoods = training_sample_class_likelihoods_[label];
    likelihoods.erase(likelihoods.begin(), likelihoods.end());
    return true;
}

bool TrainingDataManager::relabelSample(
    uint32_t label, uint32_t index, uint32_t new_label) {
    CHECK_LABEL(label);
    CHECK_LABEL(new_label);
    CHECK_INDEX(label, index);

    GRT::MatrixDouble data = getSample(label, index);
    deleteSample(label, index);
    addSample(new_label, data);

    return true;
}

bool TrainingDataManager::trimSample(
    uint32_t label, uint32_t index, uint32_t start, uint32_t end) {
    CHECK_LABEL(label);
    CHECK_INDEX(label, index);

    GRT::TimeSeriesClassificationData data = data_.getClassData(label);
    data_.eraseAllSamplesWithClassLabel(label);

    for (uint32_t i = 0; i < data.getNumSamples(); i++) {
        if (i == index) {
            GRT::MatrixDouble sample = data[i].getData();
            GRT::MatrixDouble new_sample;

            for (uint32_t row = start; row <= end; row++) {
                new_sample.push_back(sample.getRowVector(row));
            }
            data_.addSample(label, new_sample);
        } else {
            data_.addSample(label, data[i].getData());
        }
    }
    return true;
}

bool TrainingDataManager::hasSampleScore(uint32_t label, uint32_t index) {
    if (!(label > 0 && label <= num_classes_)) return false;
    if (!(index < num_samples_per_label_[label])) return false;

    const auto& score = training_sample_scores_[label][index];
    return score.first;
}

double TrainingDataManager::getSampleScore(uint32_t label, uint32_t index) {
    CHECK_LABEL(label);
    CHECK_INDEX(label, index);

    const auto& score = training_sample_scores_[label][index];
    if (score.first) {
        return score.second;
    } else {
        return 0.0; // is there something better we can do here?
    }
}

bool TrainingDataManager::setSampleScore(
    uint32_t label, uint32_t index, double new_score) {
    CHECK_LABEL(label);

    auto& score = training_sample_scores_[label][index];
    score.first = true;
    score.second = new_score;
    return true;
}

bool TrainingDataManager::hasSampleClassLikelihoods(uint32_t label, uint32_t index) {
    if (!(label > 0 && label <= num_classes_)) return false;
    if (!(index < num_samples_per_label_[label])) return false;

    const auto& likelihood = training_sample_class_likelihoods_[label][index];
    return likelihood.first;
}

std::vector<double> TrainingDataManager::getSampleClassLikelihoods(uint32_t label, uint32_t index) {
    CHECK_LABEL(label);
    CHECK_INDEX(label, index);

    const auto& likelihood = training_sample_class_likelihoods_[label][index];
    if (likelihood.first) {
        return likelihood.second;
    } else {
        return std::vector<double>(); // is there something better we can do here?
    }
}

bool TrainingDataManager::setSampleClassLikelihoods(
    uint32_t label, uint32_t index, vector<double> new_likelihoods) {
    CHECK_LABEL(label);

    auto& likelihood = training_sample_class_likelihoods_[label][index];
    likelihood.first = true;
    likelihood.second = new_likelihoods;
    return true;
}

bool TrainingDataManager::load(const std::string& filename) {
    if (!data_.load(filename)) {
        return false;
    }

    // Use the larger of the current value of num_classes_ and
    // data_.getNumClasses(). See discussion at
    // https://github.com/damellis/ESP/issues/252.
    num_classes_ = std::max(data_.getNumClasses(), num_classes_);

    // Populate the internals of the manager from data_. Most importantly, need
    // to resize all vectors to hold the data.
    training_sample_names_.resize(num_classes_ + 1);
    default_label_names_.resize(num_classes_ + 1);
    num_samples_per_label_.resize(num_classes_ + 1);
    training_sample_scores_.resize(num_classes_ + 1);
    training_sample_class_likelihoods_.resize(num_classes_ + 1);

    for (uint32_t i = 1; i <= num_classes_; i++) {
        const string class_name = data_.getClassNameForCorrespondingClassLabel(i);
        if (class_name == "NOT_SET" || class_name == "CLASS_LABEL_NOT_FOUND") {
            default_label_names_[i] = std::to_string(i);
        } else {
            default_label_names_[i] = class_name;
        }

        uint32_t num_samples = data_.getClassData(i).getNumSamples();
        num_samples_per_label_[i] = num_samples;

        training_sample_names_[i].clear();
        training_sample_scores_[i].clear();
        training_sample_class_likelihoods_[i].clear();
        for (uint32_t j = 0; j < num_samples; j++) {
            // Since we don't yet have per-sample name saved, we will use
            // default names (marking the pair as <false, "">).
            training_sample_names_[i].push_back(
                std::make_pair(false, std::string()));
            training_sample_scores_[i].push_back(std::make_pair(false, 0.0));
            training_sample_class_likelihoods_[i].push_back(
                std::make_pair(false, vector<double>()));
        }
    }

    return true;
}
<|endoftext|>


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

#include "palette.h"
#include <algorithm>
#include <math.h>

#include <ppapi/c/ppb_image_data.h>
#include <ppapi/cpp/image_data.h>

namespace {

const uint32_t kBlack = 0xff000000;
const uint32_t kWhite = 0xffffffff;

real NonnegativeFmod(real x, real y) {
  return fmod(fmod(x, y) + y, y);
}

void Uint32ToRGB(uint32_t c, uint8_t* r, uint8_t* g, uint8_t* b) {
  *r = (c >> 16) & 0xff;
  *g = (c >> 8) & 0xff;
  *b = (c >> 0) & 0xff;
}

uint32_t RGBToUint32(uint8_t r, uint8_t g, uint8_t b) {
  static PP_ImageDataFormat format = pp::ImageData::GetNativeImageDataFormat();
  if (format == PP_IMAGEDATAFORMAT_BGRA_PREMUL) {
    return 0xff000000 | (r << 16) | (g << 8) | b;
  } else if (format == PP_IMAGEDATAFORMAT_RGBA_PREMUL) {
    return 0xff000000 | (b << 16) | (g << 8) | r;
  } else {
    assert(0);
    return 0xff000000;
  }
}

template <typename T>
T Mix(T t0, T t1, real x) {
  return static_cast<T>(t0 * (1 - x) + t1 * x);
}

uint32_t MixColor(uint32_t c0, uint32_t c1, real x) {
  uint8_t r0, g0, b0;
  uint8_t r1, g1, b1;
  Uint32ToRGB(c0, &r0, &g0, &b0);
  Uint32ToRGB(c1, &r1, &g1, &b1);
  return RGBToUint32(Mix(r0, r1, x), Mix(g0, g1, x), Mix(b0, b1, x));
}

class PaletteGenerator {
 public:
  virtual uint32_t GetColor(real value) const = 0;
};

class GradientPaletteGenerator : public PaletteGenerator {
 public:
  GradientPaletteGenerator(const ColorStops& stops, bool repeating);
  virtual uint32_t GetColor(real value) const;

 private:
  real GetMinStopPos() const;
  real GetMaxStopPos() const;

  ColorStops stops_;
  bool repeating_;
  real min_pos_;
  real max_pos_;
};

GradientPaletteGenerator::GradientPaletteGenerator(const ColorStops& stops,
                                                   bool repeating)
    : stops_(stops),
      repeating_(repeating),
      min_pos_(GetMinStopPos()),
      max_pos_(GetMaxStopPos()) {
}

uint32_t GradientPaletteGenerator::GetColor(real value) const {
  if (stops_.empty())
    return kBlack;

  if (repeating_)
    value = NonnegativeFmod(value - min_pos_, max_pos_ - min_pos_) + min_pos_;

  if (value < min_pos_)
    return stops_[0].color;

  real range_min = 0;
  for (size_t i = 0; i < stops_.size() - 1; ++i) {
    range_min = std::max(range_min, stops_[i].pos);
    real range_max = stops_[i + 1].pos;
    if (range_min >= range_max)
      continue;

    if (value < range_min || value > range_max)
      continue;

    real mix_fraction = (value - range_min) / (range_max - range_min);
    return MixColor(stops_[i].color, stops_[i + 1].color, mix_fraction);
  }

  return stops_[stops_.size() - 1].color;
}

real GradientPaletteGenerator::GetMinStopPos() const {
  return stops_.empty() ? 0 : stops_[0].pos;
}

real GradientPaletteGenerator::GetMaxStopPos() const {
  if (stops_.empty())
    return 0;

  real maxpos = stops_[0].pos;
  for (size_t i = 1; i < stops_.size(); ++i) {
    maxpos = std::max(stops_[i].pos, maxpos);
  }
  return maxpos;
}

template <size_t size>
void MakeLookupTable(const PaletteGenerator& generator,
                     uint32_t (*color_map)[size]) {
  for (size_t i = 0; i < size; ++i) {
    (*color_map)[i] = generator.GetColor(static_cast<real>(i) / size);
  }
}

}  // namespace

ColorStop::ColorStop(uint32_t color, real pos)
    : color(color),
      pos(pos) {
}

PaletteConfig::PaletteConfig()
    : repeating(false) {
}

Palette::Palette(const PaletteConfig& config) {
  SetConfig(config);
}

uint32_t Palette::GetColor(real value) const {
  size_t index = static_cast<size_t>(value * kColorMapSize);
  index = std::max<size_t>(0, std::min(kColorMapSize - 1, index));
  return value_color_map_[index];
}

void Palette::SetConfig(const PaletteConfig& config) {
  MakeLookupTable(GradientPaletteGenerator(config.stops, config.repeating),
                  &value_color_map_);
}
<commit_msg>Remove unused variable kWhite.<commit_after>// Copyright 2013 Ben Smith. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "palette.h"
#include <algorithm>
#include <math.h>

#include <ppapi/c/ppb_image_data.h>
#include <ppapi/cpp/image_data.h>

namespace {

const uint32_t kBlack = 0xff000000;

real NonnegativeFmod(real x, real y) {
  return fmod(fmod(x, y) + y, y);
}

void Uint32ToRGB(uint32_t c, uint8_t* r, uint8_t* g, uint8_t* b) {
  *r = (c >> 16) & 0xff;
  *g = (c >> 8) & 0xff;
  *b = (c >> 0) & 0xff;
}

uint32_t RGBToUint32(uint8_t r, uint8_t g, uint8_t b) {
  static PP_ImageDataFormat format = pp::ImageData::GetNativeImageDataFormat();
  if (format == PP_IMAGEDATAFORMAT_BGRA_PREMUL) {
    return 0xff000000 | (r << 16) | (g << 8) | b;
  } else if (format == PP_IMAGEDATAFORMAT_RGBA_PREMUL) {
    return 0xff000000 | (b << 16) | (g << 8) | r;
  } else {
    assert(0);
    return 0xff000000;
  }
}

template <typename T>
T Mix(T t0, T t1, real x) {
  return static_cast<T>(t0 * (1 - x) + t1 * x);
}

uint32_t MixColor(uint32_t c0, uint32_t c1, real x) {
  uint8_t r0, g0, b0;
  uint8_t r1, g1, b1;
  Uint32ToRGB(c0, &r0, &g0, &b0);
  Uint32ToRGB(c1, &r1, &g1, &b1);
  return RGBToUint32(Mix(r0, r1, x), Mix(g0, g1, x), Mix(b0, b1, x));
}

class PaletteGenerator {
 public:
  virtual uint32_t GetColor(real value) const = 0;
};

class GradientPaletteGenerator : public PaletteGenerator {
 public:
  GradientPaletteGenerator(const ColorStops& stops, bool repeating);
  virtual uint32_t GetColor(real value) const;

 private:
  real GetMinStopPos() const;
  real GetMaxStopPos() const;

  ColorStops stops_;
  bool repeating_;
  real min_pos_;
  real max_pos_;
};

GradientPaletteGenerator::GradientPaletteGenerator(const ColorStops& stops,
                                                   bool repeating)
    : stops_(stops),
      repeating_(repeating),
      min_pos_(GetMinStopPos()),
      max_pos_(GetMaxStopPos()) {
}

uint32_t GradientPaletteGenerator::GetColor(real value) const {
  if (stops_.empty())
    return kBlack;

  if (repeating_)
    value = NonnegativeFmod(value - min_pos_, max_pos_ - min_pos_) + min_pos_;

  if (value < min_pos_)
    return stops_[0].color;

  real range_min = 0;
  for (size_t i = 0; i < stops_.size() - 1; ++i) {
    range_min = std::max(range_min, stops_[i].pos);
    real range_max = stops_[i + 1].pos;
    if (range_min >= range_max)
      continue;

    if (value < range_min || value > range_max)
      continue;

    real mix_fraction = (value - range_min) / (range_max - range_min);
    return MixColor(stops_[i].color, stops_[i + 1].color, mix_fraction);
  }

  return stops_[stops_.size() - 1].color;
}

real GradientPaletteGenerator::GetMinStopPos() const {
  return stops_.empty() ? 0 : stops_[0].pos;
}

real GradientPaletteGenerator::GetMaxStopPos() const {
  if (stops_.empty())
    return 0;

  real maxpos = stops_[0].pos;
  for (size_t i = 1; i < stops_.size(); ++i) {
    maxpos = std::max(stops_[i].pos, maxpos);
  }
  return maxpos;
}

template <size_t size>
void MakeLookupTable(const PaletteGenerator& generator,
                     uint32_t (*color_map)[size]) {
  for (size_t i = 0; i < size; ++i) {
    (*color_map)[i] = generator.GetColor(static_cast<real>(i) / size);
  }
}

}  // namespace

ColorStop::ColorStop(uint32_t color, real pos)
    : color(color),
      pos(pos) {
}

PaletteConfig::PaletteConfig()
    : repeating(false) {
}

Palette::Palette(const PaletteConfig& config) {
  SetConfig(config);
}

uint32_t Palette::GetColor(real value) const {
  size_t index = static_cast<size_t>(value * kColorMapSize);
  index = std::max<size_t>(0, std::min(kColorMapSize - 1, index));
  return value_color_map_[index];
}

void Palette::SetConfig(const PaletteConfig& config) {
  MakeLookupTable(GradientPaletteGenerator(config.stops, config.repeating),
                  &value_color_map_);
}
<|endoftext|>


<commit_before>#include "scripting.h"

#include <iostream>

#include <glkernel/sequence.h>

#include <cppexpose/variant/Variant.h>
#include <cppexpose/scripting/ScriptContext.h>

void printKernel(const std::array<float, 10>& kernel) {
    for (int i = 0; i < 10; ++i)
    {
        std::cout << kernel[i] << std::endl;
    }
}

//void printKernel2(const cppexpose::Variant& variant) {
//    const auto& map = *variant.asMap();
//    const auto& kernelVariant = map.at("kernel");
//    const auto kernel = kernelVariant.value<glkernel::kernel1>();

//    std::cout << kernel.size() << std::endl;
//}

void doScripting()
{
    ScriptingObject obj;

    cppexpose::ScriptContext scriptContext;
    scriptContext.addGlobalObject(&obj);

    auto variant = scriptContext.evaluate("kernel.uniform(0.0, 1.0); kernel.print();");
}

ScriptingObject::ScriptingObject()
: Object("kernel")
{
    m_kernel = glkernel::kernel1(10, 1, 1);

    addFunction("uniform", this, &ScriptingObject::uniform);
    addFunction("print", this, &ScriptingObject::print);
}

void ScriptingObject::uniform(float range_min, float range_max)
{
    glkernel::sequence::uniform(m_kernel, range_min, range_max);
}

void ScriptingObject::print()
{
    for (const auto& val : m_kernel)
        std::cout << val << std::endl;
}
<commit_msg>Remove old code<commit_after>#include "scripting.h"

#include <iostream>

#include <glkernel/sequence.h>

#include <cppexpose/variant/Variant.h>
#include <cppexpose/scripting/ScriptContext.h>

void printKernel(const std::array<float, 10>& kernel) {
    for (int i = 0; i < 10; ++i)
    {
        std::cout << kernel[i] << std::endl;
    }
}

void doScripting()
{
    ScriptingObject obj;

    cppexpose::ScriptContext scriptContext;
    scriptContext.addGlobalObject(&obj);

    auto variant = scriptContext.evaluate("kernel.uniform(0.0, 1.0); kernel.print();");
}

ScriptingObject::ScriptingObject()
: Object("kernel")
{
    m_kernel = glkernel::kernel1(10, 1, 1);

    addFunction("uniform", this, &ScriptingObject::uniform);
    addFunction("print", this, &ScriptingObject::print);
}

void ScriptingObject::uniform(float range_min, float range_max)
{
    glkernel::sequence::uniform(m_kernel, range_min, range_max);
}

void ScriptingObject::print()
{
    for (const auto& val : m_kernel)
        std::cout << val << std::endl;
}
<|endoftext|>


<commit_before>Parcer::Parcer(std::string filename){
  Tokens = LexicalAnaltysis(filename);
};

/*  構文解析実行
    @return 成功：true 失敗：false
*/
bool Parser::doParse(){
  if(!Tokens){
    fprintf(stderr, "error at lexer\n");
    return false;
  }
  else{
    return VisitTranslationUnit();
  }
};

TranslationUnitAST &Parser::getAST(){
  if(TU){
    return *TU;
  }
  else{
    return *(new TranslationUnitAST());
  }
};

// TranslationUnit用構文解析メソッド
bool Parser::visitTranslationUnit(){
  TU = new TranslatonUnitAST();

  // ExternalDecl
  while(true){
    if(!visitExternalDeclaration(TU)){
      SAFE_DELETE(TU);
      return false;
    }
    if(Tokens->getCurType == TOK_EOF){
      break;
    }
  }
  return true;
}

// ExternalDeclaration用構文解析メソッド
bool Parser::visitExternalDeclaration(TranslationUnitAST *tunit){
  PrototypeAST *proto = visitFunctionDeclaration();
  if(proto){
    tunit->addPrototype(proto);
    return true;
  }

  FunctionAST *func_def = visitFunctionDefinition();
  if(func_def){
    tunit->addFunction(func_def);
    return true;
  }

  return false;
}

PrototypeAST *Parser::visitFunctionDeclaration(){
  int backup = Tokens->getCurIndex();
  PrototypeAST *proto = visitPrototype();
  if(!proto){
    return NULL;
  }

  // prototype
  if(Tokens->getCurString() == ";"){
    // 再定義されていないか確認
    if( PrototypeTable.find(proto->getName()) != PrototypeTable.end() ||
        (FunctionTable.find(proto->getName()) != FunctionTable.end() &&
        FunctionTable[proto->getName()] != proto->getParamNum()) ){
      fprintf(stderr, "Function : %s is redefined", proto->getName().c_str());
      SAFE_DELETE(proto);
      return NULL;
    }
    // プロトタイプ宣言テーブルに追加
    PrototypeTable[proto->getName()] = proto->getParamNum();
    Tokens->getNextToken();
    return proto;
  }
  else{
    SAFE_DELETE(proto);
    Tokens->applyTokenIndex(backup);
    return NULL;
  }
}

FunctionAST *Parser::visitFunctionDefinition(){
  int backup = Tokens->getCurIndex();

  PrototypeAST *proto = visitPrototype();
  if(!proto){
    return NULL;
  }

  // 本来であればここで再定義されていないか確認
  FunctionStmtAST *func_stmt = visitFunctionStatement(proto);
}

PrototypeAST *Parser::visitPrototype(){
  int backup = Tokens->getCurIndex();

  bool is_first_param = true;
  std::vector<std::string> param_list;
  while(true){
    if(!is_first_param && Tokens->getCurType() == TOK_SYMBOL && Tokens->getCurString() == ","){
      Tokens->getNextToken();
    }
    if(Tokens->getCurType() == TOK_INT){
      Tokens->getNextToken();
    }
    else{
      break;
    }

    if(Tokens->getCurType() == TOK_IDENTIFIRE){
      param_list.push_back(Tokens->getCurString());
      Tokens->getNextToken();
    }
    else{
      Tokens->applyTokenIndex(buckup);
      return NULL;
    }
  }
}

FunctionStmtAST *Parser::visitFunvtionStatement(PrototypeAST *proto){
  int buckup = Tokens->getCurIndex();

  if(Tokens->getCurString() == "{"){
    Tokens->getNextToken();
  }
  else{
    return NULL;
  }

  FunctionStmtAST *func_stmt = new FunctionStmtAST();

  for(int i = 0; i < proto->getparamNum(); i++){
    VariableDeclAST *vdecl = new VariableDeclAST(proto->getParamName(i));
    vdecl->setDeclType(VariableDeclAST::param);
    func_stmt->addVariableDeclaration(vdecl);
    VariableTable.push_back(vdecl->getName());
  }

  /* omit */

  else if(var_decl = visitVariableDeclaration()){
    while(var_decl){
      var_decl->setDeclType(VariableDeclAST::local);

      /* TODO : 二重宣言のチェック */

      func_stmt->addVariableDeclaration(var_decl);
      VariableTable.push_back(var_decl->getName());
      var_decl = visitVariabeDeclaration();
    }

    if(stmt = visitStatement()){
      while(stmt){
        last_stmt = stmt;
        func_stmt -> addStatement(stmt);
        stmt = visitStatement();
      }
    }
  }
  else{
    SAFE_DELETE(func_stmt);
    Tokens->applyTokenIndex(bkup);
    return NULL;
  }

  /* TODO : 戻り値の確認 */

  if(Tokens->getCurString() == "}"){
    Tokens->getNextToken();
    return func_stmt;
  }
  else{
    SAFE_DELETE(func_stmt);
    Tokens->applyTokenIndex(bkup);
    return NULL;
  }
}

BaseAST *Parser::visitAssignmentExpression(){
  int bkup = Tokens-> getCurIndex();

  BaseAST *lhs;
  if(Tokens->getCurType() == TOK_IDENTIFIRE){

    /* TODO : 変数の宣言確認 */

    lhs = new VariableAST(Tokens->getCurString());
    Tokens->getNextToken();
    BaseAST *rhs;
    if(Tokens->getCurType() == TOK_SYMBOL && Tokens->getCurString() == "="){
      Tokens->getNextToken();
      if(rhs = visit AdditiveExpression(NULL)){
        return new BinaryExprAST("=", lhs, rhs);
      }
      else{
        SAFE_DELETE(lhs);
        Tokens->applyTokenIndex(bkup);
      }
    }
    else{
      SAFE_DELETE(lhs);
      Tokens->applyTokenIndex(bkup);
    }
  }
  BaseAST *add_expr = visitAdditiveExpression(NULL);
  if(add_expr){
    return add_expr;
  }
  return NULL;
}

BaseAST *Parser::visitPrimaryExpression(){
  int bkup = Tokens->getCurIndex();

  if(Tokens->getCurType() == TOK_IDENTIFIER){
    /* TODO : 変数の宣言確認 */

    std::string var_name = Tokens->getCurString();
    Tokens->getNextToken();
    return new VariableAST(var_name);
  }
  else if(Tokens->getCurType() == TOK_DIGIT){
    int val = Tokens->getCurNumVal();
    Tokens->getNextToken();
    return new NumberAST(val);
  }
  else if(Tokens->getCurType() == TOK_SYMBOL && Tokens->getCurString == "-"){
    /* omit */
  }
  return NULL;
}

BaseAST *Parser::visitPostfixExpression(){
  int bkup = Tokens->getCurIndex();

  /* omit */

  if(Tokens->getCurType() == TOK_IDENTIFIRE){
    /* TODO : 関数の宣言確認 */

    std::string Callee = Tokens->getCurString();
    Tokens->getNextToken();

    if(Tokens->getCurType() != TOK_SYMBOL || Tokens->getCurString() != "("){
      Tokens->applyTokenIndex(bkup);
      return NULL;
    }

    Tokens->getNextToken();
    std::vector<BaseAST*> args;
    BaseAST *assign_expr = visitAssignmentExpression();
    if(assign_expr){
      args.push_back(assign_expr);
      while(Tokens->getCurType() == TOK_SYMBOL && Tokens->getCurString() == ","){
        Tokens->getNextToken();
        assign_expre = visitAssignmentExpression();
        if(assign_expre){
          args.push_back(assign_expr);
        }
        else{
          break;
        }
      }
    }

    /* TODO : 引数の数を確認 */

    if(Tokens->getCurType() == TOK_SYMBOL && Tokens->getCurString == ")"){
      Tokens->getNextToken();
      return new CallExprAST(Callee, args);
    }
    else{
      for(int i = 0; i < args.size(); i++){
        SAFE_DELETE(args[i]);
      }
      Tokens->applyTokenIndex(bkup);
      return NULL;
    }
  }
  else{
    return NULL;
  }
}

BaseAST *Parser::visitAdditiveExpression(BaseAST *lhs){
  int bkup = Tokens->getCurIndex();

  if(!lhs){
    lhs = visitMultiplicativeExpression(NULL);
  }

  if(!lhs){
    return NULL;
  }

  BaseAST *rhs;
  if(Tokens->getCurType() == TOR_SYMBOL && Tokens->getCurString() == "+"){
    Tokens->getNextToken();
    rhs = visitMultiplcativeExpression(NULL);
    if(rhs){
      return visitAdditiveExpression(new BinaryExprAST("+", lhs, rhs));
    }
    else{
      SAFE_DELETE(lhs);
      Tokens->applyTokenIndex(bkup);
      return NULL;
    }
  }
  else if(Tokens->getCurType() == TOR_SYMBOL && Tokens->getCurString() == "-"){
    Tokens->getNextToken();
    rhs = visitMultiplcativeExpression(NULL);
    if(rhs){
      return visitAdditiveExpression(new BinaryExprAST("-", lhs, rhs));
    }
    else{
      SAFE_DELETE(lhs);
      Tokens->applyTokenIndex(bkup);
      return NULL;
    }
  }

  return lhs;
}

BaseAST *Parser::visitExpressionStatement(){
  BaseAST *assign_expr;
  if(Tokens->getCurString() == ";"){
    Tokens->getNextToken();
    return new NullExprAST();
  }
  else if(assign_expr = visitAssignmentExpression()){
    if(Tokens->getCurString() == ";"){
      Tokens->getNextToken();
      return assign_expr;
    }
  }
  return NULL;
}
<commit_msg>backupのリファクタリング<commit_after>Parcer::Parcer(std::string filename){
  Tokens = LexicalAnaltysis(filename);
};

/*  構文解析実行
    @return 成功：true 失敗：false
*/
bool Parser::doParse(){
  if(!Tokens){
    fprintf(stderr, "error at lexer\n");
    return false;
  }
  else{
    return VisitTranslationUnit();
  }
};

TranslationUnitAST &Parser::getAST(){
  if(TU){
    return *TU;
  }
  else{
    return *(new TranslationUnitAST());
  }
};

// TranslationUnit用構文解析メソッド
bool Parser::visitTranslationUnit(){
  TU = new TranslatonUnitAST();

  // ExternalDecl
  while(true){
    if(!visitExternalDeclaration(TU)){
      SAFE_DELETE(TU);
      return false;
    }
    if(Tokens->getCurType == TOK_EOF){
      break;
    }
  }
  return true;
}

// ExternalDeclaration用構文解析メソッド
bool Parser::visitExternalDeclaration(TranslationUnitAST *tunit){
  PrototypeAST *proto = visitFunctionDeclaration();
  if(proto){
    tunit->addPrototype(proto);
    return true;
  }

  FunctionAST *func_def = visitFunctionDefinition();
  if(func_def){
    tunit->addFunction(func_def);
    return true;
  }

  return false;
}

PrototypeAST *Parser::visitFunctionDeclaration(){
  int bkup = Tokens->getCurIndex();
  PrototypeAST *proto = visitPrototype();
  if(!proto){
    return NULL;
  }

  // prototype
  if(Tokens->getCurString() == ";"){
    // 再定義されていないか確認
    if( PrototypeTable.find(proto->getName()) != PrototypeTable.end() ||
        (FunctionTable.find(proto->getName()) != FunctionTable.end() &&
        FunctionTable[proto->getName()] != proto->getParamNum()) ){
      fprintf(stderr, "Function : %s is redefined", proto->getName().c_str());
      SAFE_DELETE(proto);
      return NULL;
    }
    // プロトタイプ宣言テーブルに追加
    PrototypeTable[proto->getName()] = proto->getParamNum();
    Tokens->getNextToken();
    return proto;
  }
  else{
    SAFE_DELETE(proto);
    Tokens->applyTokenIndex(bkup);
    return NULL;
  }
}

FunctionAST *Parser::visitFunctionDefinition(){
  int bkup = Tokens->getCurIndex();

  PrototypeAST *proto = visitPrototype();
  if(!proto){
    return NULL;
  }

  // 本来であればここで再定義されていないか確認
  FunctionStmtAST *func_stmt = visitFunctionStatement(proto);
}

PrototypeAST *Parser::visitPrototype(){
  int bkup = Tokens->getCurIndex();

  bool is_first_param = true;
  std::vector<std::string> param_list;
  while(true){
    if(!is_first_param && Tokens->getCurType() == TOK_SYMBOL && Tokens->getCurString() == ","){
      Tokens->getNextToken();
    }
    if(Tokens->getCurType() == TOK_INT){
      Tokens->getNextToken();
    }
    else{
      break;
    }

    if(Tokens->getCurType() == TOK_IDENTIFIRE){
      param_list.push_back(Tokens->getCurString());
      Tokens->getNextToken();
    }
    else{
      Tokens->applyTokenIndex(bkup);
      return NULL;
    }
  }
}

FunctionStmtAST *Parser::visitFunvtionStatement(PrototypeAST *proto){
  int bkup = Tokens->getCurIndex();

  if(Tokens->getCurString() == "{"){
    Tokens->getNextToken();
  }
  else{
    return NULL;
  }

  FunctionStmtAST *func_stmt = new FunctionStmtAST();

  for(int i = 0; i < proto->getparamNum(); i++){
    VariableDeclAST *vdecl = new VariableDeclAST(proto->getParamName(i));
    vdecl->setDeclType(VariableDeclAST::param);
    func_stmt->addVariableDeclaration(vdecl);
    VariableTable.push_back(vdecl->getName());
  }

  /* omit */

  else if(var_decl = visitVariableDeclaration()){
    while(var_decl){
      var_decl->setDeclType(VariableDeclAST::local);

      /* TODO : 二重宣言のチェック */

      func_stmt->addVariableDeclaration(var_decl);
      VariableTable.push_back(var_decl->getName());
      var_decl = visitVariabeDeclaration();
    }

    if(stmt = visitStatement()){
      while(stmt){
        last_stmt = stmt;
        func_stmt -> addStatement(stmt);
        stmt = visitStatement();
      }
    }
  }
  else{
    SAFE_DELETE(func_stmt);
    Tokens->applyTokenIndex(bkup);
    return NULL;
  }

  /* TODO : 戻り値の確認 */

  if(Tokens->getCurString() == "}"){
    Tokens->getNextToken();
    return func_stmt;
  }
  else{
    SAFE_DELETE(func_stmt);
    Tokens->applyTokenIndex(bkup);
    return NULL;
  }
}

BaseAST *Parser::visitAssignmentExpression(){
  int bkup = Tokens-> getCurIndex();

  BaseAST *lhs;
  if(Tokens->getCurType() == TOK_IDENTIFIRE){

    /* TODO : 変数の宣言確認 */

    lhs = new VariableAST(Tokens->getCurString());
    Tokens->getNextToken();
    BaseAST *rhs;
    if(Tokens->getCurType() == TOK_SYMBOL && Tokens->getCurString() == "="){
      Tokens->getNextToken();
      if(rhs = visit AdditiveExpression(NULL)){
        return new BinaryExprAST("=", lhs, rhs);
      }
      else{
        SAFE_DELETE(lhs);
        Tokens->applyTokenIndex(bkup);
      }
    }
    else{
      SAFE_DELETE(lhs);
      Tokens->applyTokenIndex(bkup);
    }
  }
  BaseAST *add_expr = visitAdditiveExpression(NULL);
  if(add_expr){
    return add_expr;
  }
  return NULL;
}

BaseAST *Parser::visitPrimaryExpression(){
  int bkup = Tokens->getCurIndex();

  if(Tokens->getCurType() == TOK_IDENTIFIER){
    /* TODO : 変数の宣言確認 */

    std::string var_name = Tokens->getCurString();
    Tokens->getNextToken();
    return new VariableAST(var_name);
  }
  else if(Tokens->getCurType() == TOK_DIGIT){
    int val = Tokens->getCurNumVal();
    Tokens->getNextToken();
    return new NumberAST(val);
  }
  else if(Tokens->getCurType() == TOK_SYMBOL && Tokens->getCurString == "-"){
    /* omit */
  }
  return NULL;
}

BaseAST *Parser::visitPostfixExpression(){
  int bkup = Tokens->getCurIndex();

  /* omit */

  if(Tokens->getCurType() == TOK_IDENTIFIRE){
    /* TODO : 関数の宣言確認 */

    std::string Callee = Tokens->getCurString();
    Tokens->getNextToken();

    if(Tokens->getCurType() != TOK_SYMBOL || Tokens->getCurString() != "("){
      Tokens->applyTokenIndex(bkup);
      return NULL;
    }

    Tokens->getNextToken();
    std::vector<BaseAST*> args;
    BaseAST *assign_expr = visitAssignmentExpression();
    if(assign_expr){
      args.push_back(assign_expr);
      while(Tokens->getCurType() == TOK_SYMBOL && Tokens->getCurString() == ","){
        Tokens->getNextToken();
        assign_expre = visitAssignmentExpression();
        if(assign_expre){
          args.push_back(assign_expr);
        }
        else{
          break;
        }
      }
    }

    /* TODO : 引数の数を確認 */

    if(Tokens->getCurType() == TOK_SYMBOL && Tokens->getCurString == ")"){
      Tokens->getNextToken();
      return new CallExprAST(Callee, args);
    }
    else{
      for(int i = 0; i < args.size(); i++){
        SAFE_DELETE(args[i]);
      }
      Tokens->applyTokenIndex(bkup);
      return NULL;
    }
  }
  else{
    return NULL;
  }
}

BaseAST *Parser::visitAdditiveExpression(BaseAST *lhs){
  int bkup = Tokens->getCurIndex();

  if(!lhs){
    lhs = visitMultiplicativeExpression(NULL);
  }

  if(!lhs){
    return NULL;
  }

  BaseAST *rhs;
  if(Tokens->getCurType() == TOR_SYMBOL && Tokens->getCurString() == "+"){
    Tokens->getNextToken();
    rhs = visitMultiplcativeExpression(NULL);
    if(rhs){
      return visitAdditiveExpression(new BinaryExprAST("+", lhs, rhs));
    }
    else{
      SAFE_DELETE(lhs);
      Tokens->applyTokenIndex(bkup);
      return NULL;
    }
  }
  else if(Tokens->getCurType() == TOR_SYMBOL && Tokens->getCurString() == "-"){
    Tokens->getNextToken();
    rhs = visitMultiplcativeExpression(NULL);
    if(rhs){
      return visitAdditiveExpression(new BinaryExprAST("-", lhs, rhs));
    }
    else{
      SAFE_DELETE(lhs);
      Tokens->applyTokenIndex(bkup);
      return NULL;
    }
  }

  return lhs;
}

BaseAST *Parser::visitExpressionStatement(){
  BaseAST *assign_expr;
  if(Tokens->getCurString() == ";"){
    Tokens->getNextToken();
    return new NullExprAST();
  }
  else if(assign_expr = visitAssignmentExpression()){
    if(Tokens->getCurString() == ";"){
      Tokens->getNextToken();
      return assign_expr;
    }
  }
  return NULL;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fpicker.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 17:49:17 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_fpicker.hxx"

#ifndef _SAL_TYPES_H_
#include "sal/types.h"
#endif

#ifndef _RTL_USTRING_HXX_
#include "rtl/ustring.hxx"
#endif

#ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_
#include "cppuhelper/implementationentry.hxx"
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTICOMPONENTFACTORY_HPP_
#include "com/sun/star/lang/XMultiComponentFactory.hpp"
#endif

#ifndef INCLUDED_SVTOOLS_MISCOPT_HXX
#include "svtools/miscopt.hxx"
#endif

#ifndef SVTOOLS_PICKERHISTORYACCESS_HXX
#include "svtools/pickerhistoryaccess.hxx"
#endif

#ifndef _SV_APP_HXX
#include "vcl/svapp.hxx"
#endif

namespace css = com::sun::star;

using css::uno::Reference;
using css::uno::Sequence;
using rtl::OUString;

/*
 * FilePicker implementation.
 */
static OUString FilePicker_getSystemPickerServiceName()
{
    OUString aDesktopEnvironment (Application::GetDesktopEnvironment());
    if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("gnome"))
        return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.GtkFilePicker"));
    else if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("kde"))
        return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.KDEFilePicker"));
    else
        return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.SystemFilePicker"));
}

static Reference< css::uno::XInterface > FilePicker_createInstance (
    Reference< css::uno::XComponentContext > const & rxContext)
{
    Reference< css::uno::XInterface > xResult;
    if (rxContext.is())
    {
        Reference< css::lang::XMultiComponentFactory > xFactory (rxContext->getServiceManager());
        if (xFactory.is())
        {
            if (SvtMiscOptions().UseSystemFileDialog())
            {
                try
                {
                    xResult = xFactory->createInstanceWithContext (
                        FilePicker_getSystemPickerServiceName(),
                        rxContext);
                }
                catch (css::uno::Exception const &)
                {
                    // Handled below (see @ fallback).
                }
            }
            if (!xResult.is())
            {
                // Always fall back to OfficeFilePicker.
                xResult = xFactory->createInstanceWithContext (
                    OUString (RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.OfficeFilePicker")),
                    rxContext);
            }
            if (xResult.is())
            {
                // Add to FilePicker history.
                svt::addFilePicker (xResult);
            }
        }
    }
    return xResult;
}

static OUString FilePicker_getImplementationName()
{
    return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.comp.fpicker.FilePicker"));
}

static Sequence< OUString > FilePicker_getSupportedServiceNames()
{
    Sequence< OUString > aServiceNames(1);
    aServiceNames.getArray()[0] =
        OUString (RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FilePicker"));
    return aServiceNames;
}

/*
 * FolderPicker implementation.
 */
static OUString FolderPicker_getSystemPickerServiceName()
{
    OUString aDesktopEnvironment (Application::GetDesktopEnvironment());
    if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("gnome"))
        return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.GtkFolderPicker"));
    else if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("kde"))
        return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.KDEFolderPicker"));
    else
        return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.SystemFolderPicker"));
}

static Reference< css::uno::XInterface > FolderPicker_createInstance (
    Reference< css::uno::XComponentContext > const & rxContext)
{
    Reference< css::uno::XInterface > xResult;
    if (rxContext.is())
    {
        Reference< css::lang::XMultiComponentFactory > xFactory (rxContext->getServiceManager());
        if (xFactory.is())
        {
            if (SvtMiscOptions().UseSystemFileDialog())
            {
                try
                {
                    xResult = xFactory->createInstanceWithContext (
                        FolderPicker_getSystemPickerServiceName(),
                        rxContext);
                }
                catch (css::uno::Exception const &)
                {
                    // Handled below (see @ fallback).
                }
            }
            if (!xResult.is())
            {
                // Always fall back to OfficeFolderPicker.
                xResult = xFactory->createInstanceWithContext (
                    OUString (RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.OfficeFolderPicker")),
                    rxContext);
            }
            if (xResult.is())
            {
                // Add to FolderPicker history.
                svt::addFolderPicker (xResult);
            }
        }
    }
    return xResult;
}

static OUString FolderPicker_getImplementationName()
{
    return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.comp.fpicker.FolderPicker"));
}

static Sequence< OUString > FolderPicker_getSupportedServiceNames()
{
    Sequence< OUString > aServiceNames(1);
    aServiceNames.getArray()[0] =
        OUString (RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FolderPicker"));
    return aServiceNames;
}

/*
 * Implementation entries.
 */
static cppu::ImplementationEntry g_entries[] =
{
    {
        FilePicker_createInstance,
        FilePicker_getImplementationName,
        FilePicker_getSupportedServiceNames,
        cppu::createSingleComponentFactory, 0, 0
    },
    {
        FolderPicker_createInstance,
        FolderPicker_getImplementationName,
        FolderPicker_getSupportedServiceNames,
        cppu::createSingleComponentFactory, 0, 0
    },
    { 0, 0, 0, 0, 0, 0 }
};

/*
 * Public (exported) interface.
 */
extern "C"
{
SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment (
    const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */)
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo (
    void * pServiceManager, void * pRegistryKey)
{
    return cppu::component_writeInfoHelper (
        pServiceManager, pRegistryKey, g_entries);
}

SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory (
    const sal_Char * pImplementationName, void * pServiceManager, void * pRegistryKey)
{
    return cppu::component_getFactoryHelper (
        pImplementationName, pServiceManager, pRegistryKey, g_entries);
}

} // extern "C"
<commit_msg>INTEGRATION: CWS aquafilepicker01 (1.4.6); FILE MERGED 2007/06/16 11:34:19 pjanik 1.4.6.3: #i74798#: Revert back all whitespace changes, add back precompiled include. 2007/06/15 21:25:50 fheckl 1.4.6.2: cleanup changes 2006/10/06 21:18:34 fheckl 1.4.6.1: Initial version of MacOSX native file picker<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fpicker.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: ihi $ $Date: 2007-07-11 11:01:20 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_fpicker.hxx"

#ifndef _SAL_TYPES_H_
#include "sal/types.h"
#endif

#ifndef _RTL_USTRING_HXX_
#include "rtl/ustring.hxx"
#endif

#ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_
#include "cppuhelper/implementationentry.hxx"
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTICOMPONENTFACTORY_HPP_
#include "com/sun/star/lang/XMultiComponentFactory.hpp"
#endif

#ifndef INCLUDED_SVTOOLS_MISCOPT_HXX
#include "svtools/miscopt.hxx"
#endif

#ifndef SVTOOLS_PICKERHISTORYACCESS_HXX
#include "svtools/pickerhistoryaccess.hxx"
#endif

#ifndef _SV_APP_HXX
#include "vcl/svapp.hxx"
#endif

namespace css = com::sun::star;

using css::uno::Reference;
using css::uno::Sequence;
using rtl::OUString;

/*
 * FilePicker implementation.
 */
static OUString FilePicker_getSystemPickerServiceName()
{
    OUString aDesktopEnvironment (Application::GetDesktopEnvironment());
    if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("gnome"))
        return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.GtkFilePicker"));
    else if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("kde"))
        return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.KDEFilePicker"));
    else if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("macosx"))
        return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.AquaFilePicker"));
    else
        return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.SystemFilePicker"));
}

static Reference< css::uno::XInterface > FilePicker_createInstance (
    Reference< css::uno::XComponentContext > const & rxContext)
{
    Reference< css::uno::XInterface > xResult;
    if (rxContext.is())
    {
        Reference< css::lang::XMultiComponentFactory > xFactory (rxContext->getServiceManager());
        if (xFactory.is())
        {
            if (SvtMiscOptions().UseSystemFileDialog())
            {
                try
                {
                    xResult = xFactory->createInstanceWithContext (
                        FilePicker_getSystemPickerServiceName(),
                        rxContext);
                }
                catch (css::uno::Exception const &)
                {
                    // Handled below (see @ fallback).
                }
            }
            if (!xResult.is())
            {
                // Always fall back to OfficeFilePicker.
                xResult = xFactory->createInstanceWithContext (
                    OUString (RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.OfficeFilePicker")),
                    rxContext);
            }
            if (xResult.is())
            {
                // Add to FilePicker history.
                svt::addFilePicker (xResult);
            }
        }
    }
    return xResult;
}

static OUString FilePicker_getImplementationName()
{
    return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.comp.fpicker.FilePicker"));
}

static Sequence< OUString > FilePicker_getSupportedServiceNames()
{
    Sequence< OUString > aServiceNames(1);
    aServiceNames.getArray()[0] =
        OUString (RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FilePicker"));
    return aServiceNames;
}

/*
 * FolderPicker implementation.
 */
static OUString FolderPicker_getSystemPickerServiceName()
{
    OUString aDesktopEnvironment (Application::GetDesktopEnvironment());
    if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("gnome"))
        return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.GtkFolderPicker"));
    else if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("kde"))
        return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.KDEFolderPicker"));
    else if (aDesktopEnvironment.equalsIgnoreAsciiCaseAscii ("macosx"))
        return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.AquaFolderPicker"));
    else
        return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.ui.dialogs.SystemFolderPicker"));
}

static Reference< css::uno::XInterface > FolderPicker_createInstance (
    Reference< css::uno::XComponentContext > const & rxContext)
{
    Reference< css::uno::XInterface > xResult;
    if (rxContext.is())
    {
        Reference< css::lang::XMultiComponentFactory > xFactory (rxContext->getServiceManager());
        if (xFactory.is())
        {
            if (SvtMiscOptions().UseSystemFileDialog())
            {
                try
                {
                    xResult = xFactory->createInstanceWithContext (
                        FolderPicker_getSystemPickerServiceName(),
                        rxContext);
                }
                catch (css::uno::Exception const &)
                {
                    // Handled below (see @ fallback).
                }
            }
            if (!xResult.is())
            {
                // Always fall back to OfficeFolderPicker.
                xResult = xFactory->createInstanceWithContext (
                    OUString (RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.OfficeFolderPicker")),
                    rxContext);
            }
            if (xResult.is())
            {
                // Add to FolderPicker history.
                svt::addFolderPicker (xResult);
            }
        }
    }
    return xResult;
}

static OUString FolderPicker_getImplementationName()
{
    return OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.comp.fpicker.FolderPicker"));
}

static Sequence< OUString > FolderPicker_getSupportedServiceNames()
{
    Sequence< OUString > aServiceNames(1);
    aServiceNames.getArray()[0] =
        OUString (RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FolderPicker"));
    return aServiceNames;
}

/*
 * Implementation entries.
 */
static cppu::ImplementationEntry g_entries[] =
{
    {
        FilePicker_createInstance,
        FilePicker_getImplementationName,
        FilePicker_getSupportedServiceNames,
        cppu::createSingleComponentFactory, 0, 0
    },
    {
        FolderPicker_createInstance,
        FolderPicker_getImplementationName,
        FolderPicker_getSupportedServiceNames,
        cppu::createSingleComponentFactory, 0, 0
    },
    { 0, 0, 0, 0, 0, 0 }
};

/*
 * Public (exported) interface.
 */
extern "C"
{
SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment (
    const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */)
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo (
    void * pServiceManager, void * pRegistryKey)
{
    return cppu::component_writeInfoHelper (
        pServiceManager, pRegistryKey, g_entries);
}

SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory (
    const sal_Char * pImplementationName, void * pServiceManager, void * pRegistryKey)
{
    return cppu::component_getFactoryHelper (
        pImplementationName, pServiceManager, pRegistryKey, g_entries);
}

} // extern "C"
<|endoftext|>


<commit_before>// Copyright 2010, Shuo Chen.  All rights reserved.
// http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.

// Author: Shuo Chen (chenshuo at chenshuo dot com)

#include <muduo/net/TcpServer.h>

#include <muduo/base/Logging.h>
#include <muduo/net/Acceptor.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/EventLoopThreadPool.h>
#include <muduo/net/SocketsOps.h>

#include <stdio.h>  // snprintf

using namespace muduo;
using namespace muduo::net;

TcpServer::TcpServer(EventLoop* loop,
                     const InetAddress& listenAddr,
                     const string& nameArg,
                     Option option)
  : loop_(CHECK_NOTNULL(loop)),
    ipPort_(listenAddr.toIpPort()),
    name_(nameArg),
    acceptor_(new Acceptor(loop, listenAddr, option == kReusePort)),
    threadPool_(new EventLoopThreadPool(loop, name_)),
    connectionCallback_(defaultConnectionCallback),
    messageCallback_(defaultMessageCallback),
    nextConnId_(1)
{
  acceptor_->setNewConnectionCallback(
      std::bind(&TcpServer::newConnection, this, _1, _2));
}

TcpServer::~TcpServer()
{
  loop_->assertInLoopThread();
  LOG_TRACE << "TcpServer::~TcpServer [" << name_ << "] destructing";

  for (ConnectionMap::iterator it(connections_.begin());
      it != connections_.end(); ++it)
  {
    TcpConnectionPtr conn = it->second;
    it->second.reset();
    conn->getLoop()->runInLoop(
      std::bind(&TcpConnection::connectDestroyed, conn));
    conn.reset();
  }
}

void TcpServer::setThreadNum(int numThreads)
{
  assert(0 <= numThreads);
  threadPool_->setThreadNum(numThreads);
}

void TcpServer::start()
{
  if (started_.getAndSet(1) == 0)
  {
    threadPool_->start(threadInitCallback_);

    assert(!acceptor_->listenning());
    loop_->runInLoop(
        std::bind(&Acceptor::listen, get_pointer(acceptor_)));
  }
}

void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)
{
  loop_->assertInLoopThread();
  EventLoop* ioLoop = threadPool_->getNextLoop();
  char buf[64];
  snprintf(buf, sizeof buf, "-%s#%d", ipPort_.c_str(), nextConnId_);
  ++nextConnId_;
  string connName = name_ + buf;

  LOG_INFO << "TcpServer::newConnection [" << name_
           << "] - new connection [" << connName
           << "] from " << peerAddr.toIpPort();
  InetAddress localAddr(sockets::getLocalAddr(sockfd));
  // FIXME poll with zero timeout to double confirm the new connection
  // FIXME use make_shared if necessary
  TcpConnectionPtr conn(new TcpConnection(ioLoop,
                                          connName,
                                          sockfd,
                                          localAddr,
                                          peerAddr));
  connections_[connName] = conn;
  conn->setConnectionCallback(connectionCallback_);
  conn->setMessageCallback(messageCallback_);
  conn->setWriteCompleteCallback(writeCompleteCallback_);
  conn->setCloseCallback(
      std::bind(&TcpServer::removeConnection, this, _1)); // FIXME: unsafe
  ioLoop->runInLoop(std::bind(&TcpConnection::connectEstablished, conn));
}

void TcpServer::removeConnection(const TcpConnectionPtr& conn)
{
  // FIXME: unsafe
  loop_->runInLoop(std::bind(&TcpServer::removeConnectionInLoop, this, conn));
}

void TcpServer::removeConnectionInLoop(const TcpConnectionPtr& conn)
{
  loop_->assertInLoopThread();
  LOG_INFO << "TcpServer::removeConnectionInLoop [" << name_
           << "] - connection " << conn->name();
  size_t n = connections_.erase(conn->name());
  (void)n;
  assert(n == 1);
  EventLoop* ioLoop = conn->getLoop();
  ioLoop->queueInLoop(
      std::bind(&TcpConnection::connectDestroyed, conn));
}

<commit_msg>Remove conn.reset() in TcpServer::~TcpServer (#217)<commit_after>// Copyright 2010, Shuo Chen.  All rights reserved.
// http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.

// Author: Shuo Chen (chenshuo at chenshuo dot com)

#include <muduo/net/TcpServer.h>

#include <muduo/base/Logging.h>
#include <muduo/net/Acceptor.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/EventLoopThreadPool.h>
#include <muduo/net/SocketsOps.h>

#include <stdio.h>  // snprintf

using namespace muduo;
using namespace muduo::net;

TcpServer::TcpServer(EventLoop* loop,
                     const InetAddress& listenAddr,
                     const string& nameArg,
                     Option option)
  : loop_(CHECK_NOTNULL(loop)),
    ipPort_(listenAddr.toIpPort()),
    name_(nameArg),
    acceptor_(new Acceptor(loop, listenAddr, option == kReusePort)),
    threadPool_(new EventLoopThreadPool(loop, name_)),
    connectionCallback_(defaultConnectionCallback),
    messageCallback_(defaultMessageCallback),
    nextConnId_(1)
{
  acceptor_->setNewConnectionCallback(
      std::bind(&TcpServer::newConnection, this, _1, _2));
}

TcpServer::~TcpServer()
{
  loop_->assertInLoopThread();
  LOG_TRACE << "TcpServer::~TcpServer [" << name_ << "] destructing";

  for (ConnectionMap::iterator it(connections_.begin());
      it != connections_.end(); ++it)
  {
    TcpConnectionPtr conn(it->second);
    it->second.reset();
    conn->getLoop()->runInLoop(
      std::bind(&TcpConnection::connectDestroyed, conn));
  }
}

void TcpServer::setThreadNum(int numThreads)
{
  assert(0 <= numThreads);
  threadPool_->setThreadNum(numThreads);
}

void TcpServer::start()
{
  if (started_.getAndSet(1) == 0)
  {
    threadPool_->start(threadInitCallback_);

    assert(!acceptor_->listenning());
    loop_->runInLoop(
        std::bind(&Acceptor::listen, get_pointer(acceptor_)));
  }
}

void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)
{
  loop_->assertInLoopThread();
  EventLoop* ioLoop = threadPool_->getNextLoop();
  char buf[64];
  snprintf(buf, sizeof buf, "-%s#%d", ipPort_.c_str(), nextConnId_);
  ++nextConnId_;
  string connName = name_ + buf;

  LOG_INFO << "TcpServer::newConnection [" << name_
           << "] - new connection [" << connName
           << "] from " << peerAddr.toIpPort();
  InetAddress localAddr(sockets::getLocalAddr(sockfd));
  // FIXME poll with zero timeout to double confirm the new connection
  // FIXME use make_shared if necessary
  TcpConnectionPtr conn(new TcpConnection(ioLoop,
                                          connName,
                                          sockfd,
                                          localAddr,
                                          peerAddr));
  connections_[connName] = conn;
  conn->setConnectionCallback(connectionCallback_);
  conn->setMessageCallback(messageCallback_);
  conn->setWriteCompleteCallback(writeCompleteCallback_);
  conn->setCloseCallback(
      std::bind(&TcpServer::removeConnection, this, _1)); // FIXME: unsafe
  ioLoop->runInLoop(std::bind(&TcpConnection::connectEstablished, conn));
}

void TcpServer::removeConnection(const TcpConnectionPtr& conn)
{
  // FIXME: unsafe
  loop_->runInLoop(std::bind(&TcpServer::removeConnectionInLoop, this, conn));
}

void TcpServer::removeConnectionInLoop(const TcpConnectionPtr& conn)
{
  loop_->assertInLoopThread();
  LOG_INFO << "TcpServer::removeConnectionInLoop [" << name_
           << "] - connection " << conn->name();
  size_t n = connections_.erase(conn->name());
  (void)n;
  assert(n == 1);
  EventLoop* ioLoop = conn->getLoop();
  ioLoop->queueInLoop(
      std::bind(&TcpConnection::connectDestroyed, conn));
}

<|endoftext|>