<commit_before>// Copyright 2014 The Bazel Authors. 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 "src/main/cpp/blaze_startup_options.h"

#include <cassert>
#include <cstdio>
#include <cstdlib>

#include "src/main/cpp/blaze_util.h"
#include "src/main/cpp/blaze_util_platform.h"
#include "src/main/cpp/util/exit_code.h"
#include "src/main/cpp/util/file.h"
#include "src/main/cpp/util/numbers.h"
#include "src/main/cpp/util/strings.h"

#ifndef PRODUCT_NAME
#define PRODUCT_NAME "Bazel"
#endif

namespace blaze {

void BlazeStartupOptions::Init() {
  bool testing = getenv("TEST_TMPDIR") != NULL;
  if (testing) {
    output_root = MakeAbsolute(getenv("TEST_TMPDIR"));
  } else {
    output_root = GetOutputRoot();
  }

  product_name = PRODUCT_NAME;
  string product_name_lower = PRODUCT_NAME;
  blaze_util::ToLower(&product_name_lower);
  output_user_root = blaze_util::JoinPath(
      output_root, "_" + product_name_lower + "_" + GetUserName());
  deep_execroot = true;
  block_for_lock = true;
  host_jvm_debug = false;
  host_javabase = "";
  batch = false;
  batch_cpu_scheduling = false;
  allow_configurable_attributes = false;
  fatal_event_bus_exceptions = false;
  io_nice_level = -1;
  // 3 hours (but only 15 seconds if used within a test)
  max_idle_secs = testing ? 15 : (3 * 3600);
  oom_more_eagerly_threshold = 100;
  command_port = -1;
  oom_more_eagerly = false;
  watchfs = false;
  invocation_policy = NULL;
}

string BlazeStartupOptions::GetHostJavabase() {
  if (host_javabase.empty()) {
    host_javabase = GetDefaultHostJavabase();
  }
  return host_javabase;
}

void BlazeStartupOptions::Copy(
    const BlazeStartupOptions &rhs, BlazeStartupOptions *lhs) {
  assert(lhs);

  lhs->product_name = rhs.product_name;
  lhs->output_base = rhs.output_base;
  lhs->install_base = rhs.install_base;
  lhs->output_root = rhs.output_root;
  lhs->output_user_root = rhs.output_user_root;
  lhs->deep_execroot = rhs.deep_execroot;
  lhs->block_for_lock = rhs.block_for_lock;
  lhs->host_jvm_debug = rhs.host_jvm_debug;
  lhs->host_jvm_profile = rhs.host_jvm_profile;
  lhs->host_javabase = rhs.host_javabase;
  lhs->host_jvm_args = rhs.host_jvm_args;
  lhs->batch = rhs.batch;
  lhs->batch_cpu_scheduling = rhs.batch_cpu_scheduling;
  lhs->io_nice_level = rhs.io_nice_level;
  lhs->max_idle_secs = rhs.max_idle_secs;
  lhs->command_port = rhs.command_port;
  lhs->oom_more_eagerly = rhs.oom_more_eagerly;
  lhs->watchfs = rhs.watchfs;
  lhs->allow_configurable_attributes = rhs.allow_configurable_attributes;
  lhs->fatal_event_bus_exceptions = rhs.fatal_event_bus_exceptions;
  lhs->option_sources = rhs.option_sources;
  lhs->invocation_policy = rhs.invocation_policy;
}

blaze_exit_code::ExitCode BlazeStartupOptions::ProcessArg(
      const string &argstr, const string &next_argstr, const string &rcfile,
      bool *is_space_separated, string *error) {
  // We have to parse a specific option syntax, so GNU getopts won't do.  All
  // options begin with "--" or "-". Values are given together with the option
  // delimited by '=' or in the next option.
  const char* arg = argstr.c_str();
  const char* next_arg = next_argstr.empty() ? NULL : next_argstr.c_str();
  const char* value = NULL;

  if ((value = GetUnaryOption(arg, next_arg, "--output_base")) != NULL) {
    output_base = MakeAbsolute(value);
    option_sources["output_base"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg,
                                     "--install_base")) != NULL) {
    install_base = MakeAbsolute(value);
    option_sources["install_base"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg,
                                     "--output_user_root")) != NULL) {
    output_user_root = MakeAbsolute(value);
    option_sources["output_user_root"] = rcfile;
  } else if (GetNullaryOption(arg, "--deep_execroot")) {
    deep_execroot = true;
    option_sources["deep_execroot"] = rcfile;
  } else if (GetNullaryOption(arg, "--nodeep_execroot")) {
    deep_execroot = false;
    option_sources["deep_execroot"] = rcfile;
  } else if (GetNullaryOption(arg, "--noblock_for_lock")) {
    block_for_lock = false;
    option_sources["block_for_lock"] = rcfile;
  } else if (GetNullaryOption(arg, "--host_jvm_debug")) {
    host_jvm_debug = true;
    option_sources["host_jvm_debug"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg,
                                     "--host_jvm_profile")) != NULL) {
    host_jvm_profile = value;
    option_sources["host_jvm_profile"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg,
                                     "--host_javabase")) != NULL) {
    // TODO(bazel-team): Consider examining the javabase and re-execing in case
    // of architecture mismatch.
    host_javabase = MakeAbsolute(value);
    option_sources["host_javabase"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg, "--host_jvm_args")) !=
             NULL) {
    host_jvm_args.push_back(value);
    option_sources["host_jvm_args"] = rcfile;  // NB: This is incorrect
  } else if ((value = GetUnaryOption(arg, next_arg, "--bazelrc")) != NULL) {
    if (rcfile != "") {
      *error = "Can't specify --bazelrc in the .bazelrc file.";
      return blaze_exit_code::BAD_ARGV;
    }
  } else if ((value = GetUnaryOption(arg, next_arg, "--blazerc")) != NULL) {
    if (rcfile != "") {
      *error = "Can't specify --blazerc in the .blazerc file.";
      return blaze_exit_code::BAD_ARGV;
    }
  } else if (GetNullaryOption(arg, "--nomaster_blazerc") ||
             GetNullaryOption(arg, "--master_blazerc")) {
    if (rcfile != "") {
      *error = "Can't specify --[no]master_blazerc in .blazerc file.";
      return blaze_exit_code::BAD_ARGV;
    }
    option_sources["blazerc"] = rcfile;
  } else if (GetNullaryOption(arg, "--nomaster_bazelrc") ||
             GetNullaryOption(arg, "--master_bazelrc")) {
    if (rcfile != "") {
      *error = "Can't specify --[no]master_bazelrc in .bazelrc file.";
      return blaze_exit_code::BAD_ARGV;
    }
    option_sources["blazerc"] = rcfile;
  } else if (GetNullaryOption(arg, "--batch")) {
    batch = true;
    option_sources["batch"] = rcfile;
  } else if (GetNullaryOption(arg, "--nobatch")) {
    batch = false;
    option_sources["batch"] = rcfile;
  } else if (GetNullaryOption(arg, "--batch_cpu_scheduling")) {
    batch_cpu_scheduling = true;
    option_sources["batch_cpu_scheduling"] = rcfile;
  } else if (GetNullaryOption(arg, "--nobatch_cpu_scheduling")) {
    batch_cpu_scheduling = false;
    option_sources["batch_cpu_scheduling"] = rcfile;
  } else if (GetNullaryOption(arg, "--allow_configurable_attributes")) {
    allow_configurable_attributes = true;
    option_sources["allow_configurable_attributes"] = rcfile;
  } else if (GetNullaryOption(arg, "--noallow_configurable_attributes")) {
    allow_configurable_attributes = false;
    option_sources["allow_configurable_attributes"] = rcfile;
  } else if (GetNullaryOption(arg, "--fatal_event_bus_exceptions")) {
    fatal_event_bus_exceptions = true;
    option_sources["fatal_event_bus_exceptions"] = rcfile;
  } else if (GetNullaryOption(arg, "--nofatal_event_bus_exceptions")) {
    fatal_event_bus_exceptions = false;
    option_sources["fatal_event_bus_exceptions"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg,
                                     "--io_nice_level")) != NULL) {
    if (!blaze_util::safe_strto32(value, &io_nice_level) ||
        io_nice_level > 7) {
      blaze_util::StringPrintf(error,
          "Invalid argument to --io_nice_level: '%s'. Must not exceed 7.",
          value);
      return blaze_exit_code::BAD_ARGV;
    }
    option_sources["io_nice_level"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg,
                                     "--max_idle_secs")) != NULL) {
    if (!blaze_util::safe_strto32(value, &max_idle_secs) ||
        max_idle_secs < 0) {
      blaze_util::StringPrintf(error,
          "Invalid argument to --max_idle_secs: '%s'.", value);
      return blaze_exit_code::BAD_ARGV;
    }
    option_sources["max_idle_secs"] = rcfile;
  } else if (GetNullaryOption(arg, "-x")) {
    fprintf(stderr, "WARNING: The -x startup option is now ignored "
            "and will be removed in a future release\n");
  } else if (GetNullaryOption(arg, "--experimental_oom_more_eagerly")) {
    oom_more_eagerly = true;
    option_sources["experimental_oom_more_eagerly"] = rcfile;
  } else if (GetNullaryOption(arg, "--noexperimental_oom_more_eagerly")) {
    oom_more_eagerly = false;
    option_sources["experimental_oom_more_eagerly"] = rcfile;
  } else if ((value = GetUnaryOption(
                  arg, next_arg,
                  "--experimental_oom_more_eagerly_threshold")) != NULL) {
    if (!blaze_util::safe_strto32(value, &oom_more_eagerly_threshold) ||
        oom_more_eagerly_threshold < 0) {
      blaze_util::StringPrintf(error,
                               "Invalid argument to "
                               "--experimental_oom_more_eagerly_threshold: "
                               "'%s'.",
                               value);
      return blaze_exit_code::BAD_ARGV;
    }
    option_sources["experimental_oom_more_eagerly_threshold"] = rcfile;
  } else if (GetNullaryOption(arg, "--watchfs")) {
    watchfs = true;
    option_sources["watchfs"] = rcfile;
  } else if (GetNullaryOption(arg, "--nowatchfs")) {
    watchfs = false;
    option_sources["watchfs"] = rcfile;
  } else if ((value = GetUnaryOption(
      arg, next_arg, "--command_port")) != NULL) {
    if (!blaze_util::safe_strto32(value, &command_port) ||
        command_port < -1 || command_port > 65535) {
      blaze_util::StringPrintf(error,
          "Invalid argument to --command_port: '%s'. "
          "Must be a valid port number or -1 to disable the gRPC server.\n",
          value);
      return blaze_exit_code::BAD_ARGV;
    }
    option_sources["webstatusserver"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg, "--invocation_policy"))
              != NULL) {
    if (invocation_policy == NULL) {
      invocation_policy = value;
      option_sources["invocation_policy"] = rcfile;
    } else {
      *error = "The startup flag --invocation_policy cannot be specified "
          "multiple times.";
      return blaze_exit_code::BAD_ARGV;
    }
  } else {
    bool extra_argument_processed;
    blaze_exit_code::ExitCode process_extra_arg_exit_code = ProcessArgExtra(
        arg, next_arg, rcfile, &value, &extra_argument_processed, error);
    if (process_extra_arg_exit_code != blaze_exit_code::SUCCESS) {
      return process_extra_arg_exit_code;
    }
    if (!extra_argument_processed) {
      blaze_util::StringPrintf(
          error,
          "Unknown %s startup option: '%s'.\n"
          "  For more info, run '%s help startup_options'.",
          product_name.c_str(), arg, product_name.c_str());
      return blaze_exit_code::BAD_ARGV;
    }
  }

  *is_space_separated = ((value == next_arg) && (value != NULL));
  return blaze_exit_code::SUCCESS;
}

}  // namespace blaze
<commit_msg>Add omitted initialization in BlazeStartupOptions::Copy.<commit_after>// Copyright 2014 The Bazel Authors. 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 "src/main/cpp/blaze_startup_options.h"

#include <cassert>
#include <cstdio>
#include <cstdlib>

#include "src/main/cpp/blaze_util.h"
#include "src/main/cpp/blaze_util_platform.h"
#include "src/main/cpp/util/exit_code.h"
#include "src/main/cpp/util/file.h"
#include "src/main/cpp/util/numbers.h"
#include "src/main/cpp/util/strings.h"

#ifndef PRODUCT_NAME
#define PRODUCT_NAME "Bazel"
#endif

namespace blaze {

void BlazeStartupOptions::Init() {
  bool testing = getenv("TEST_TMPDIR") != NULL;
  if (testing) {
    output_root = MakeAbsolute(getenv("TEST_TMPDIR"));
  } else {
    output_root = GetOutputRoot();
  }

  product_name = PRODUCT_NAME;
  string product_name_lower = PRODUCT_NAME;
  blaze_util::ToLower(&product_name_lower);
  output_user_root = blaze_util::JoinPath(
      output_root, "_" + product_name_lower + "_" + GetUserName());
  deep_execroot = true;
  block_for_lock = true;
  host_jvm_debug = false;
  host_javabase = "";
  batch = false;
  batch_cpu_scheduling = false;
  allow_configurable_attributes = false;
  fatal_event_bus_exceptions = false;
  io_nice_level = -1;
  // 3 hours (but only 15 seconds if used within a test)
  max_idle_secs = testing ? 15 : (3 * 3600);
  oom_more_eagerly_threshold = 100;
  command_port = -1;
  oom_more_eagerly = false;
  watchfs = false;
  invocation_policy = NULL;
}

string BlazeStartupOptions::GetHostJavabase() {
  if (host_javabase.empty()) {
    host_javabase = GetDefaultHostJavabase();
  }
  return host_javabase;
}

void BlazeStartupOptions::Copy(
    const BlazeStartupOptions &rhs, BlazeStartupOptions *lhs) {
  assert(lhs);

  lhs->product_name = rhs.product_name;
  lhs->output_base = rhs.output_base;
  lhs->install_base = rhs.install_base;
  lhs->output_root = rhs.output_root;
  lhs->output_user_root = rhs.output_user_root;
  lhs->deep_execroot = rhs.deep_execroot;
  lhs->block_for_lock = rhs.block_for_lock;
  lhs->host_jvm_debug = rhs.host_jvm_debug;
  lhs->host_jvm_profile = rhs.host_jvm_profile;
  lhs->host_javabase = rhs.host_javabase;
  lhs->host_jvm_args = rhs.host_jvm_args;
  lhs->batch = rhs.batch;
  lhs->batch_cpu_scheduling = rhs.batch_cpu_scheduling;
  lhs->io_nice_level = rhs.io_nice_level;
  lhs->max_idle_secs = rhs.max_idle_secs;
  lhs->command_port = rhs.command_port;
  lhs->oom_more_eagerly = rhs.oom_more_eagerly;
  lhs->oom_more_eagerly_threshold = rhs.oom_more_eagerly_threshold;
  lhs->watchfs = rhs.watchfs;
  lhs->allow_configurable_attributes = rhs.allow_configurable_attributes;
  lhs->fatal_event_bus_exceptions = rhs.fatal_event_bus_exceptions;
  lhs->option_sources = rhs.option_sources;
  lhs->invocation_policy = rhs.invocation_policy;
}

blaze_exit_code::ExitCode BlazeStartupOptions::ProcessArg(
      const string &argstr, const string &next_argstr, const string &rcfile,
      bool *is_space_separated, string *error) {
  // We have to parse a specific option syntax, so GNU getopts won't do.  All
  // options begin with "--" or "-". Values are given together with the option
  // delimited by '=' or in the next option.
  const char* arg = argstr.c_str();
  const char* next_arg = next_argstr.empty() ? NULL : next_argstr.c_str();
  const char* value = NULL;

  if ((value = GetUnaryOption(arg, next_arg, "--output_base")) != NULL) {
    output_base = MakeAbsolute(value);
    option_sources["output_base"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg,
                                     "--install_base")) != NULL) {
    install_base = MakeAbsolute(value);
    option_sources["install_base"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg,
                                     "--output_user_root")) != NULL) {
    output_user_root = MakeAbsolute(value);
    option_sources["output_user_root"] = rcfile;
  } else if (GetNullaryOption(arg, "--deep_execroot")) {
    deep_execroot = true;
    option_sources["deep_execroot"] = rcfile;
  } else if (GetNullaryOption(arg, "--nodeep_execroot")) {
    deep_execroot = false;
    option_sources["deep_execroot"] = rcfile;
  } else if (GetNullaryOption(arg, "--noblock_for_lock")) {
    block_for_lock = false;
    option_sources["block_for_lock"] = rcfile;
  } else if (GetNullaryOption(arg, "--host_jvm_debug")) {
    host_jvm_debug = true;
    option_sources["host_jvm_debug"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg,
                                     "--host_jvm_profile")) != NULL) {
    host_jvm_profile = value;
    option_sources["host_jvm_profile"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg,
                                     "--host_javabase")) != NULL) {
    // TODO(bazel-team): Consider examining the javabase and re-execing in case
    // of architecture mismatch.
    host_javabase = MakeAbsolute(value);
    option_sources["host_javabase"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg, "--host_jvm_args")) !=
             NULL) {
    host_jvm_args.push_back(value);
    option_sources["host_jvm_args"] = rcfile;  // NB: This is incorrect
  } else if ((value = GetUnaryOption(arg, next_arg, "--bazelrc")) != NULL) {
    if (rcfile != "") {
      *error = "Can't specify --bazelrc in the .bazelrc file.";
      return blaze_exit_code::BAD_ARGV;
    }
  } else if ((value = GetUnaryOption(arg, next_arg, "--blazerc")) != NULL) {
    if (rcfile != "") {
      *error = "Can't specify --blazerc in the .blazerc file.";
      return blaze_exit_code::BAD_ARGV;
    }
  } else if (GetNullaryOption(arg, "--nomaster_blazerc") ||
             GetNullaryOption(arg, "--master_blazerc")) {
    if (rcfile != "") {
      *error = "Can't specify --[no]master_blazerc in .blazerc file.";
      return blaze_exit_code::BAD_ARGV;
    }
    option_sources["blazerc"] = rcfile;
  } else if (GetNullaryOption(arg, "--nomaster_bazelrc") ||
             GetNullaryOption(arg, "--master_bazelrc")) {
    if (rcfile != "") {
      *error = "Can't specify --[no]master_bazelrc in .bazelrc file.";
      return blaze_exit_code::BAD_ARGV;
    }
    option_sources["blazerc"] = rcfile;
  } else if (GetNullaryOption(arg, "--batch")) {
    batch = true;
    option_sources["batch"] = rcfile;
  } else if (GetNullaryOption(arg, "--nobatch")) {
    batch = false;
    option_sources["batch"] = rcfile;
  } else if (GetNullaryOption(arg, "--batch_cpu_scheduling")) {
    batch_cpu_scheduling = true;
    option_sources["batch_cpu_scheduling"] = rcfile;
  } else if (GetNullaryOption(arg, "--nobatch_cpu_scheduling")) {
    batch_cpu_scheduling = false;
    option_sources["batch_cpu_scheduling"] = rcfile;
  } else if (GetNullaryOption(arg, "--allow_configurable_attributes")) {
    allow_configurable_attributes = true;
    option_sources["allow_configurable_attributes"] = rcfile;
  } else if (GetNullaryOption(arg, "--noallow_configurable_attributes")) {
    allow_configurable_attributes = false;
    option_sources["allow_configurable_attributes"] = rcfile;
  } else if (GetNullaryOption(arg, "--fatal_event_bus_exceptions")) {
    fatal_event_bus_exceptions = true;
    option_sources["fatal_event_bus_exceptions"] = rcfile;
  } else if (GetNullaryOption(arg, "--nofatal_event_bus_exceptions")) {
    fatal_event_bus_exceptions = false;
    option_sources["fatal_event_bus_exceptions"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg,
                                     "--io_nice_level")) != NULL) {
    if (!blaze_util::safe_strto32(value, &io_nice_level) ||
        io_nice_level > 7) {
      blaze_util::StringPrintf(error,
          "Invalid argument to --io_nice_level: '%s'. Must not exceed 7.",
          value);
      return blaze_exit_code::BAD_ARGV;
    }
    option_sources["io_nice_level"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg,
                                     "--max_idle_secs")) != NULL) {
    if (!blaze_util::safe_strto32(value, &max_idle_secs) ||
        max_idle_secs < 0) {
      blaze_util::StringPrintf(error,
          "Invalid argument to --max_idle_secs: '%s'.", value);
      return blaze_exit_code::BAD_ARGV;
    }
    option_sources["max_idle_secs"] = rcfile;
  } else if (GetNullaryOption(arg, "-x")) {
    fprintf(stderr, "WARNING: The -x startup option is now ignored "
            "and will be removed in a future release\n");
  } else if (GetNullaryOption(arg, "--experimental_oom_more_eagerly")) {
    oom_more_eagerly = true;
    option_sources["experimental_oom_more_eagerly"] = rcfile;
  } else if (GetNullaryOption(arg, "--noexperimental_oom_more_eagerly")) {
    oom_more_eagerly = false;
    option_sources["experimental_oom_more_eagerly"] = rcfile;
  } else if ((value = GetUnaryOption(
                  arg, next_arg,
                  "--experimental_oom_more_eagerly_threshold")) != NULL) {
    if (!blaze_util::safe_strto32(value, &oom_more_eagerly_threshold) ||
        oom_more_eagerly_threshold < 0) {
      blaze_util::StringPrintf(error,
                               "Invalid argument to "
                               "--experimental_oom_more_eagerly_threshold: "
                               "'%s'.",
                               value);
      return blaze_exit_code::BAD_ARGV;
    }
    option_sources["experimental_oom_more_eagerly_threshold"] = rcfile;
  } else if (GetNullaryOption(arg, "--watchfs")) {
    watchfs = true;
    option_sources["watchfs"] = rcfile;
  } else if (GetNullaryOption(arg, "--nowatchfs")) {
    watchfs = false;
    option_sources["watchfs"] = rcfile;
  } else if ((value = GetUnaryOption(
      arg, next_arg, "--command_port")) != NULL) {
    if (!blaze_util::safe_strto32(value, &command_port) ||
        command_port < -1 || command_port > 65535) {
      blaze_util::StringPrintf(error,
          "Invalid argument to --command_port: '%s'. "
          "Must be a valid port number or -1 to disable the gRPC server.\n",
          value);
      return blaze_exit_code::BAD_ARGV;
    }
    option_sources["webstatusserver"] = rcfile;
  } else if ((value = GetUnaryOption(arg, next_arg, "--invocation_policy"))
              != NULL) {
    if (invocation_policy == NULL) {
      invocation_policy = value;
      option_sources["invocation_policy"] = rcfile;
    } else {
      *error = "The startup flag --invocation_policy cannot be specified "
          "multiple times.";
      return blaze_exit_code::BAD_ARGV;
    }
  } else {
    bool extra_argument_processed;
    blaze_exit_code::ExitCode process_extra_arg_exit_code = ProcessArgExtra(
        arg, next_arg, rcfile, &value, &extra_argument_processed, error);
    if (process_extra_arg_exit_code != blaze_exit_code::SUCCESS) {
      return process_extra_arg_exit_code;
    }
    if (!extra_argument_processed) {
      blaze_util::StringPrintf(
          error,
          "Unknown %s startup option: '%s'.\n"
          "  For more info, run '%s help startup_options'.",
          product_name.c_str(), arg, product_name.c_str());
      return blaze_exit_code::BAD_ARGV;
    }
  }

  *is_space_separated = ((value == next_arg) && (value != NULL));
  return blaze_exit_code::SUCCESS;
}

}  // namespace blaze
<|endoftext|>


<commit_before>/*
 * (C) Copyright 2015 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * 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.
 *
 */

#define BOOST_TEST_STATIC_LINK
#define BOOST_TEST_PROTECTED_VIRTUAL

#include <boost/test/included/unit_test.hpp>
#include <MediaPipelineImpl.hpp>
#include <objects/WebRtcEndpointImpl.hpp>
#include <IceCandidate.hpp>
#include <mutex>
#include <condition_variable>
#include <ModuleManager.hpp>
#include <KurentoException.hpp>
#include <MediaSet.hpp>
#include <MediaElementImpl.hpp>
#include <ConnectionState.hpp>

using namespace kurento;
using namespace boost::unit_test;

boost::property_tree::ptree config;
std::string mediaPipelineId;
ModuleManager moduleManager;

struct GF {
  GF();
  ~GF();
};

BOOST_GLOBAL_FIXTURE (GF)

GF::GF()
{
  boost::property_tree::ptree ac, audioCodecs, vc, videoCodecs;
  gst_init (NULL, NULL);

  moduleManager.loadModulesFromDirectories ("../../src/server");

  config.add ("configPath", "../../../tests" );
  config.add ("modules.kurento.SdpEndpoint.numAudioMedias", 1);
  config.add ("modules.kurento.SdpEndpoint.numVideoMedias", 1);

  ac.put ("name", "opus/48000/2");
  audioCodecs.push_back (std::make_pair ("", ac) );
  config.add_child ("modules.kurento.SdpEndpoint.audioCodecs", audioCodecs);

  vc.put ("name", "VP8/90000");
  videoCodecs.push_back (std::make_pair ("", vc) );
  config.add_child ("modules.kurento.SdpEndpoint.videoCodecs", videoCodecs);

  mediaPipelineId = moduleManager.getFactory ("MediaPipeline")->createObject (
                      config, "",
                      Json::Value() )->getId();
}

GF::~GF()
{
  MediaSet::deleteMediaSet();
}

static std::shared_ptr <WebRtcEndpointImpl>
createWebrtc (void)
{
  std::shared_ptr <kurento::MediaObjectImpl> webrtcEndpoint;
  Json::Value constructorParams;

  constructorParams ["mediaPipeline"] = mediaPipelineId;

  webrtcEndpoint = moduleManager.getFactory ("WebRtcEndpoint")->createObject (
                     config, "",
                     constructorParams );

  return std::dynamic_pointer_cast <WebRtcEndpointImpl> (webrtcEndpoint);
}

static void
releaseWebRtc (std::shared_ptr<WebRtcEndpointImpl> &ep)
{
  std::string id = ep->getId();

  ep.reset();
  MediaSet::getMediaSet ()->release (id);
}

static std::shared_ptr <MediaElementImpl>
createTestSrc (void)
{
  std::shared_ptr <MediaElementImpl> src = std::dynamic_pointer_cast
      <MediaElementImpl> (MediaSet::getMediaSet()->ref (new  MediaElementImpl (
                            boost::property_tree::ptree(),
                            MediaSet::getMediaSet()->getMediaObject (mediaPipelineId),
                            "dummysrc") ) );

  g_object_set (src->getGstreamerElement(), "audio", TRUE, "video", TRUE, NULL);

  return std::dynamic_pointer_cast <MediaElementImpl> (src);
}

static void
releaseTestSrc (std::shared_ptr<MediaElementImpl> &ep)
{
  std::string id = ep->getId();

  ep.reset();
  MediaSet::getMediaSet ()->release (id);
}

static void
gathering_done ()
{
  std::atomic<bool> gathering_done (false);
  std::condition_variable cv;
  std::mutex mtx;
  std::unique_lock<std::mutex> lck (mtx);
  std::shared_ptr <WebRtcEndpointImpl> webRtcEp = createWebrtc();

  webRtcEp->signalOnIceGatheringDone.connect ([&] (OnIceGatheringDone event) {
    gathering_done = true;
    cv.notify_one();
  });

  webRtcEp->generateOffer ();
  webRtcEp->gatherCandidates ();

  cv.wait (lck, [&] () {
    return gathering_done.load();
  });

  if (!gathering_done) {
    BOOST_ERROR ("Gathering not done");
  }

  releaseWebRtc (webRtcEp);
}

static  void
ice_state_changes()
{
  std::atomic<bool> ice_state_changed (false);
  std::condition_variable cv;
  std::mutex mtx;
  std::unique_lock<std::mutex> lck (mtx);

  std::shared_ptr <WebRtcEndpointImpl> webRtcEpOfferer = createWebrtc();
  std::shared_ptr <WebRtcEndpointImpl> webRtcEpAnswerer = createWebrtc();

  webRtcEpOfferer->setName ("offerer");
  webRtcEpAnswerer->setName ("answerer");

  webRtcEpOfferer->signalOnIceCandidate.connect ([&] (OnIceCandidate event) {
    webRtcEpAnswerer->addIceCandidate (event.getCandidate() );
  });

  webRtcEpAnswerer->signalOnIceCandidate.connect ([&] (OnIceCandidate event) {
    webRtcEpOfferer->addIceCandidate (event.getCandidate() );
  });

  webRtcEpOfferer->signalOnIceComponentStateChanged.connect ([&] (
  OnIceComponentStateChanged event) {
    ice_state_changed = true;
    cv.notify_one();
  });

  std::string offer = webRtcEpOfferer->generateOffer ();
  std::string answer = webRtcEpAnswerer->processOffer (offer);
  webRtcEpOfferer->processAnswer (answer);

  webRtcEpOfferer->gatherCandidates ();
  webRtcEpAnswerer->gatherCandidates ();

  cv.wait (lck, [&] () {
    return ice_state_changed.load();
  });

  if (!ice_state_changed) {
    BOOST_ERROR ("ICE state not chagned");
  }

  releaseWebRtc (webRtcEpOfferer);
  releaseWebRtc (webRtcEpAnswerer);
}

static  void
stun_turn_properties ()
{
  std::string stunServerAddress ("10.0.0.1");
  int stunServerPort = 2345;
  std::string turnUrl ("user0:pass0@10.0.0.2:3456");

  std::shared_ptr <WebRtcEndpointImpl> webRtcEp  = createWebrtc();

  webRtcEp->setStunServerAddress (stunServerAddress);
  std::string stunServerAddressRet = webRtcEp->getStunServerAddress ();
  BOOST_CHECK (stunServerAddressRet == stunServerAddress);

  webRtcEp->setStunServerPort (stunServerPort);
  int stunServerPortRet = webRtcEp->getStunServerPort ();
  BOOST_CHECK (stunServerPortRet == stunServerPort);

  webRtcEp->setTurnUrl (turnUrl);
  std::string turnUrlRet = webRtcEp->getTurnUrl ();
  BOOST_CHECK (turnUrlRet == turnUrl);

  releaseWebRtc (webRtcEp);
}

static void
media_state_changes ()
{
  std::atomic<bool> media_state_changed (false);
  std::condition_variable cv;
  std::mutex mtx;
  std::unique_lock<std::mutex> lck (mtx);

  std::shared_ptr <WebRtcEndpointImpl> webRtcEpOfferer = createWebrtc();
  std::shared_ptr <WebRtcEndpointImpl> webRtcEpAnswerer = createWebrtc();
  std::shared_ptr <MediaElementImpl> src = createTestSrc();

  src->connect (webRtcEpOfferer);

  webRtcEpOfferer->signalOnIceCandidate.connect ([&] (OnIceCandidate event) {
    BOOST_TEST_MESSAGE ("Offerer: adding candidate " +
                        event.getCandidate()->getCandidate() );
    webRtcEpAnswerer->addIceCandidate (event.getCandidate() );
  });

  webRtcEpAnswerer->signalOnIceCandidate.connect ([&] (OnIceCandidate event) {
    BOOST_TEST_MESSAGE ("Answerer: adding candidate " +
                        event.getCandidate()->getCandidate() );
    webRtcEpOfferer->addIceCandidate (event.getCandidate() );
  });

  webRtcEpOfferer->signalOnIceGatheringDone.connect ([&] (
  OnIceGatheringDone event) {
    BOOST_TEST_MESSAGE ("Offerer: Gathering done");
  });

  webRtcEpAnswerer->signalOnIceGatheringDone.connect ([&] (
  OnIceGatheringDone event) {
    BOOST_TEST_MESSAGE ("Answerer: Gathering done");
  });

  webRtcEpAnswerer->signalMediaStateChanged.connect ([&] (
  MediaStateChanged event) {
    media_state_changed = true;
    cv.notify_one();
  });

  std::string offer = webRtcEpOfferer->generateOffer ();
  BOOST_TEST_MESSAGE ("offer: " + offer);

  std::string answer = webRtcEpAnswerer->processOffer (offer);
  BOOST_TEST_MESSAGE ("answer: " + answer);

  webRtcEpOfferer->processAnswer (answer);

  webRtcEpOfferer->gatherCandidates ();
  webRtcEpAnswerer->gatherCandidates ();

  cv.wait (lck, [&] () {
    return media_state_changed.load();
  });

  if (!media_state_changed) {
    BOOST_ERROR ("Not media state chagned");
  }

  releaseTestSrc (src);
  releaseWebRtc (webRtcEpOfferer);
  releaseWebRtc (webRtcEpAnswerer);
}

static void
connection_state_changes ()
{
  std::atomic<bool> conn_state_changed (false);
  std::condition_variable cv;
  std::mutex mtx;
  std::unique_lock<std::mutex> lck (mtx);

  std::shared_ptr <WebRtcEndpointImpl> webRtcEpOfferer = createWebrtc();
  std::shared_ptr <WebRtcEndpointImpl> webRtcEpAnswerer = createWebrtc();

  webRtcEpOfferer->signalOnIceCandidate.connect ([&] (OnIceCandidate event) {
    BOOST_TEST_MESSAGE ("Offerer: adding candidate " +
                        event.getCandidate()->getCandidate() );
    webRtcEpAnswerer->addIceCandidate (event.getCandidate() );
  });

  webRtcEpAnswerer->signalOnIceCandidate.connect ([&] (OnIceCandidate event) {
    BOOST_TEST_MESSAGE ("Answerer: adding candidate " +
                        event.getCandidate()->getCandidate() );
    webRtcEpOfferer->addIceCandidate (event.getCandidate() );
  });

  webRtcEpOfferer->signalOnIceGatheringDone.connect ([&] (
  OnIceGatheringDone event) {
    BOOST_TEST_MESSAGE ("Offerer: Gathering done");
  });

  webRtcEpAnswerer->signalOnIceGatheringDone.connect ([&] (
  OnIceGatheringDone event) {
    BOOST_TEST_MESSAGE ("Answerer: Gathering done");
  });

  webRtcEpAnswerer->signalConnectionStateChanged.connect ([&] (
  ConnectionStateChanged event) {
    conn_state_changed = true;
    cv.notify_one();
  });

  std::string offer = webRtcEpOfferer->generateOffer ();
  BOOST_TEST_MESSAGE ("offer: " + offer);

  std::string answer = webRtcEpAnswerer->processOffer (offer);
  BOOST_TEST_MESSAGE ("answer: " + answer);

  webRtcEpOfferer->processAnswer (answer);

  if (webRtcEpAnswerer->getConnectionState ()->getValue () !=
      ConnectionState::DISCONNECTED) {
    BOOST_ERROR ("Connection must be disconnected");
  }

  webRtcEpOfferer->gatherCandidates ();
  webRtcEpAnswerer->gatherCandidates ();

  cv.wait (lck, [&] () {
    return conn_state_changed.load();
  });

  if (!conn_state_changed) {
    BOOST_ERROR ("Not conn state chagned");
  }

  if (webRtcEpAnswerer->getConnectionState ()->getValue () !=
      ConnectionState::CONNECTED) {
    BOOST_ERROR ("Connection must be connected");
  }

  releaseWebRtc (webRtcEpOfferer);
  releaseWebRtc (webRtcEpAnswerer);
}

test_suite *
init_unit_test_suite ( int , char* [] )
{
  test_suite *test = BOOST_TEST_SUITE ( "WebRtcEndpoint" );
  test->add (BOOST_TEST_CASE ( &gathering_done ), 0, /* timeout */ 15);
  test->add (BOOST_TEST_CASE ( &ice_state_changes ), 0, /* timeout */ 15);
  test->add (BOOST_TEST_CASE ( &stun_turn_properties ), 0, /* timeout */ 15);
  test->add (BOOST_TEST_CASE ( &media_state_changes ), 0, /* timeout */ 15);
  test->add (BOOST_TEST_CASE ( &connection_state_changes ), 0, /* timeout */ 15);

  return test;
}
<commit_msg>webRtcEndpoint: Add test to enable/disable latency stats<commit_after>/*
 * (C) Copyright 2015 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * 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.
 *
 */

#define BOOST_TEST_STATIC_LINK
#define BOOST_TEST_PROTECTED_VIRTUAL

#include <boost/test/included/unit_test.hpp>
#include <MediaPipelineImpl.hpp>
#include <objects/WebRtcEndpointImpl.hpp>
#include <IceCandidate.hpp>
#include <mutex>
#include <condition_variable>
#include <ModuleManager.hpp>
#include <KurentoException.hpp>
#include <MediaSet.hpp>
#include <MediaElementImpl.hpp>
#include <ConnectionState.hpp>

using namespace kurento;
using namespace boost::unit_test;

boost::property_tree::ptree config;
std::string mediaPipelineId;
ModuleManager moduleManager;

struct GF {
  GF();
  ~GF();
};

BOOST_GLOBAL_FIXTURE (GF)

GF::GF()
{
  boost::property_tree::ptree ac, audioCodecs, vc, videoCodecs;
  gst_init (NULL, NULL);

  moduleManager.loadModulesFromDirectories ("../../src/server");

  config.add ("configPath", "../../../tests" );
  config.add ("modules.kurento.SdpEndpoint.numAudioMedias", 1);
  config.add ("modules.kurento.SdpEndpoint.numVideoMedias", 1);

  ac.put ("name", "opus/48000/2");
  audioCodecs.push_back (std::make_pair ("", ac) );
  config.add_child ("modules.kurento.SdpEndpoint.audioCodecs", audioCodecs);

  vc.put ("name", "VP8/90000");
  videoCodecs.push_back (std::make_pair ("", vc) );
  config.add_child ("modules.kurento.SdpEndpoint.videoCodecs", videoCodecs);

  mediaPipelineId = moduleManager.getFactory ("MediaPipeline")->createObject (
                      config, "",
                      Json::Value() )->getId();
}

GF::~GF()
{
  MediaSet::deleteMediaSet();
}

static std::shared_ptr <WebRtcEndpointImpl>
createWebrtc (void)
{
  std::shared_ptr <kurento::MediaObjectImpl> webrtcEndpoint;
  Json::Value constructorParams;

  constructorParams ["mediaPipeline"] = mediaPipelineId;

  webrtcEndpoint = moduleManager.getFactory ("WebRtcEndpoint")->createObject (
                     config, "",
                     constructorParams );

  return std::dynamic_pointer_cast <WebRtcEndpointImpl> (webrtcEndpoint);
}

static void
releaseWebRtc (std::shared_ptr<WebRtcEndpointImpl> &ep)
{
  std::string id = ep->getId();

  ep.reset();
  MediaSet::getMediaSet ()->release (id);
}

static std::shared_ptr <MediaElementImpl>
createTestSrc (void)
{
  std::shared_ptr <MediaElementImpl> src = std::dynamic_pointer_cast
      <MediaElementImpl> (MediaSet::getMediaSet()->ref (new  MediaElementImpl (
                            boost::property_tree::ptree(),
                            MediaSet::getMediaSet()->getMediaObject (mediaPipelineId),
                            "dummysrc") ) );

  g_object_set (src->getGstreamerElement(), "audio", TRUE, "video", TRUE, NULL);

  return std::dynamic_pointer_cast <MediaElementImpl> (src);
}

static void
releaseTestSrc (std::shared_ptr<MediaElementImpl> &ep)
{
  std::string id = ep->getId();

  ep.reset();
  MediaSet::getMediaSet ()->release (id);
}

static void
gathering_done ()
{
  std::atomic<bool> gathering_done (false);
  std::condition_variable cv;
  std::mutex mtx;
  std::unique_lock<std::mutex> lck (mtx);
  std::shared_ptr <WebRtcEndpointImpl> webRtcEp = createWebrtc();

  webRtcEp->signalOnIceGatheringDone.connect ([&] (OnIceGatheringDone event) {
    gathering_done = true;
    cv.notify_one();
  });

  webRtcEp->generateOffer ();
  webRtcEp->gatherCandidates ();

  cv.wait (lck, [&] () {
    return gathering_done.load();
  });

  if (!gathering_done) {
    BOOST_ERROR ("Gathering not done");
  }

  releaseWebRtc (webRtcEp);
}

static  void
ice_state_changes()
{
  std::atomic<bool> ice_state_changed (false);
  std::condition_variable cv;
  std::mutex mtx;
  std::unique_lock<std::mutex> lck (mtx);

  std::shared_ptr <WebRtcEndpointImpl> webRtcEpOfferer = createWebrtc();
  std::shared_ptr <WebRtcEndpointImpl> webRtcEpAnswerer = createWebrtc();

  webRtcEpOfferer->setName ("offerer");
  webRtcEpAnswerer->setName ("answerer");

  webRtcEpOfferer->signalOnIceCandidate.connect ([&] (OnIceCandidate event) {
    webRtcEpAnswerer->addIceCandidate (event.getCandidate() );
  });

  webRtcEpAnswerer->signalOnIceCandidate.connect ([&] (OnIceCandidate event) {
    webRtcEpOfferer->addIceCandidate (event.getCandidate() );
  });

  webRtcEpOfferer->signalOnIceComponentStateChanged.connect ([&] (
  OnIceComponentStateChanged event) {
    ice_state_changed = true;
    cv.notify_one();
  });

  std::string offer = webRtcEpOfferer->generateOffer ();
  std::string answer = webRtcEpAnswerer->processOffer (offer);
  webRtcEpOfferer->processAnswer (answer);

  webRtcEpOfferer->gatherCandidates ();
  webRtcEpAnswerer->gatherCandidates ();

  cv.wait (lck, [&] () {
    return ice_state_changed.load();
  });

  if (!ice_state_changed) {
    BOOST_ERROR ("ICE state not chagned");
  }

  releaseWebRtc (webRtcEpOfferer);
  releaseWebRtc (webRtcEpAnswerer);
}

static  void
stun_turn_properties ()
{
  std::string stunServerAddress ("10.0.0.1");
  int stunServerPort = 2345;
  std::string turnUrl ("user0:pass0@10.0.0.2:3456");

  std::shared_ptr <WebRtcEndpointImpl> webRtcEp  = createWebrtc();

  webRtcEp->setStunServerAddress (stunServerAddress);
  std::string stunServerAddressRet = webRtcEp->getStunServerAddress ();
  BOOST_CHECK (stunServerAddressRet == stunServerAddress);

  webRtcEp->setStunServerPort (stunServerPort);
  int stunServerPortRet = webRtcEp->getStunServerPort ();
  BOOST_CHECK (stunServerPortRet == stunServerPort);

  webRtcEp->setTurnUrl (turnUrl);
  std::string turnUrlRet = webRtcEp->getTurnUrl ();
  BOOST_CHECK (turnUrlRet == turnUrl);

  releaseWebRtc (webRtcEp);
}

static void
media_state_changes ()
{
  std::atomic<bool> media_state_changed (false);
  std::condition_variable cv;
  std::mutex mtx;
  std::unique_lock<std::mutex> lck (mtx);

  std::shared_ptr <WebRtcEndpointImpl> webRtcEpOfferer = createWebrtc();
  std::shared_ptr <WebRtcEndpointImpl> webRtcEpAnswerer = createWebrtc();
  std::shared_ptr <MediaElementImpl> src = createTestSrc();

  src->connect (webRtcEpOfferer);

  webRtcEpOfferer->signalOnIceCandidate.connect ([&] (OnIceCandidate event) {
    BOOST_TEST_MESSAGE ("Offerer: adding candidate " +
                        event.getCandidate()->getCandidate() );
    webRtcEpAnswerer->addIceCandidate (event.getCandidate() );
  });

  webRtcEpAnswerer->signalOnIceCandidate.connect ([&] (OnIceCandidate event) {
    BOOST_TEST_MESSAGE ("Answerer: adding candidate " +
                        event.getCandidate()->getCandidate() );
    webRtcEpOfferer->addIceCandidate (event.getCandidate() );
  });

  webRtcEpOfferer->signalOnIceGatheringDone.connect ([&] (
  OnIceGatheringDone event) {
    BOOST_TEST_MESSAGE ("Offerer: Gathering done");
  });

  webRtcEpAnswerer->signalOnIceGatheringDone.connect ([&] (
  OnIceGatheringDone event) {
    BOOST_TEST_MESSAGE ("Answerer: Gathering done");
  });

  webRtcEpAnswerer->signalMediaStateChanged.connect ([&] (
  MediaStateChanged event) {
    media_state_changed = true;
    cv.notify_one();
  });

  std::string offer = webRtcEpOfferer->generateOffer ();
  BOOST_TEST_MESSAGE ("offer: " + offer);

  std::string answer = webRtcEpAnswerer->processOffer (offer);
  BOOST_TEST_MESSAGE ("answer: " + answer);

  webRtcEpOfferer->processAnswer (answer);

  webRtcEpOfferer->gatherCandidates ();
  webRtcEpAnswerer->gatherCandidates ();

  cv.wait (lck, [&] () {
    return media_state_changed.load();
  });

  if (!media_state_changed) {
    BOOST_ERROR ("Not media state chagned");
  }

  releaseTestSrc (src);
  releaseWebRtc (webRtcEpOfferer);
  releaseWebRtc (webRtcEpAnswerer);
}

static void
connectWebrtcEndpoints (std::shared_ptr <WebRtcEndpointImpl> webRtcEpOfferer,
                        std::shared_ptr <WebRtcEndpointImpl> webRtcEpAnswerer)
{
  std::atomic<bool> conn_state_changed (false);
  std::condition_variable cv;
  std::mutex mtx;
  std::unique_lock<std::mutex> lck (mtx);

  webRtcEpOfferer->signalOnIceCandidate.connect ([&] (OnIceCandidate event) {
    BOOST_TEST_MESSAGE ("Offerer: adding candidate " +
                        event.getCandidate()->getCandidate() );
    webRtcEpAnswerer->addIceCandidate (event.getCandidate() );
  });

  webRtcEpAnswerer->signalOnIceCandidate.connect ([&] (OnIceCandidate event) {
    BOOST_TEST_MESSAGE ("Answerer: adding candidate " +
                        event.getCandidate()->getCandidate() );
    webRtcEpOfferer->addIceCandidate (event.getCandidate() );
  });

  webRtcEpOfferer->signalOnIceGatheringDone.connect ([&] (
  OnIceGatheringDone event) {
    BOOST_TEST_MESSAGE ("Offerer: Gathering done");
  });

  webRtcEpAnswerer->signalOnIceGatheringDone.connect ([&] (
  OnIceGatheringDone event) {
    BOOST_TEST_MESSAGE ("Answerer: Gathering done");
  });

  webRtcEpAnswerer->signalConnectionStateChanged.connect ([&] (
  ConnectionStateChanged event) {
    conn_state_changed = true;
    cv.notify_one();
  });

  std::string offer = webRtcEpOfferer->generateOffer ();
  BOOST_TEST_MESSAGE ("offer: " + offer);

  std::string answer = webRtcEpAnswerer->processOffer (offer);
  BOOST_TEST_MESSAGE ("answer: " + answer);

  webRtcEpOfferer->processAnswer (answer);

  if (webRtcEpAnswerer->getConnectionState ()->getValue () !=
      ConnectionState::DISCONNECTED) {
    BOOST_ERROR ("Connection must be disconnected");
  }

  webRtcEpOfferer->gatherCandidates ();
  webRtcEpAnswerer->gatherCandidates ();

  cv.wait (lck, [&] () {
    return conn_state_changed.load();
  });

  if (!conn_state_changed) {
    BOOST_ERROR ("Not conn state chagned");
  }

  if (webRtcEpAnswerer->getConnectionState ()->getValue () !=
      ConnectionState::CONNECTED) {
    BOOST_ERROR ("Connection must be connected");
  }
}

static void
connection_state_changes ()
{
  std::shared_ptr <WebRtcEndpointImpl> webRtcEpOfferer = createWebrtc();
  std::shared_ptr <WebRtcEndpointImpl> webRtcEpAnswerer = createWebrtc();

  connectWebrtcEndpoints (webRtcEpOfferer, webRtcEpAnswerer);

  releaseWebRtc (webRtcEpOfferer);
  releaseWebRtc (webRtcEpAnswerer);
}

static void
check_webrtc_stats ()
{
  std::map <std::string, std::shared_ptr<Stats>> stats;
  std::shared_ptr <WebRtcEndpointImpl> webRtcEpOfferer = createWebrtc();
  std::shared_ptr <WebRtcEndpointImpl> webRtcEpAnswerer = createWebrtc();
  std::shared_ptr<MediaPipelineImpl> pipeline;

  connectWebrtcEndpoints (webRtcEpOfferer, webRtcEpAnswerer);

  /* Now webrtcEndPoints are connected it's time to get stats */
  stats = webRtcEpAnswerer->getStats();

  if (stats.find (webRtcEpAnswerer->getId() ) != stats.end() ) {
    BOOST_ERROR ("No latency stats enabled");
  }

  /* Enable latency stats */
  pipeline = std::dynamic_pointer_cast<MediaPipelineImpl>
             (webRtcEpAnswerer->getMediaPipeline () );
  pipeline->setLatencyStats (true);

  stats = webRtcEpAnswerer->getStats();

  if (stats.find (webRtcEpAnswerer->getId() ) == stats.end() ) {
    BOOST_ERROR ("Stats for this element should be in stats report");
  }

  /* Disable latency stats */
  pipeline = std::dynamic_pointer_cast<MediaPipelineImpl>
             (webRtcEpAnswerer->getMediaPipeline () );
  pipeline->setLatencyStats (false);

  stats = webRtcEpAnswerer->getStats();

  if (stats.find (webRtcEpAnswerer->getId() ) != stats.end() ) {
    BOOST_ERROR ("No latency stats enabled");
  }

  releaseWebRtc (webRtcEpOfferer);
  releaseWebRtc (webRtcEpAnswerer);
}

test_suite *
init_unit_test_suite ( int , char *[] )
{
  test_suite *test = BOOST_TEST_SUITE ( "WebRtcEndpoint" );

  test->add (BOOST_TEST_CASE ( &gathering_done ), 0, /* timeout */ 15);
  test->add (BOOST_TEST_CASE ( &ice_state_changes ), 0, /* timeout */ 15);
  test->add (BOOST_TEST_CASE ( &stun_turn_properties ), 0, /* timeout */ 15);
  test->add (BOOST_TEST_CASE ( &media_state_changes ), 0, /* timeout */ 15);
  test->add (BOOST_TEST_CASE ( &connection_state_changes ), 0, /* timeout */ 15);
  test->add (BOOST_TEST_CASE ( &check_webrtc_stats ), 0, /* timeout */ 15);

  return test;
}
<|endoftext|>


<commit_before>//===-- GenericSpecializer.cpp - Specialization of generic functions ------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Specialize calls to generic functions by substituting static type
// information.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sil-generic-specializer"

#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SILOptimizer/Utils/Generics.h"
#include "swift/SILOptimizer/Utils/Local.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "llvm/ADT/SmallVector.h"

using namespace swift;

namespace {

class GenericSpecializer : public SILFunctionTransform {

  bool specializeAppliesInFunction(SILFunction &F);

  /// The entry point to the transformation.
  void run() override {
    SILFunction &F = *getFunction();
    DEBUG(llvm::dbgs() << "***** GenericSpecializer on function:" << F.getName()
                       << " *****\n");

    if (specializeAppliesInFunction(F))
      invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
  }

  StringRef getName() override { return "Generic Specializer"; }
};

} // end anonymous namespace

bool GenericSpecializer::specializeAppliesInFunction(SILFunction &F) {
  bool Changed = false;
  llvm::SmallVector<SILInstruction *, 8> DeadApplies;

  for (auto &BB : F) {
    for (auto It = BB.begin(), End = BB.end(); It != End;) {
      auto &I = *It++;

      // Skip non-apply instructions, apply instructions with no
      // substitutions, apply instructions where we do not statically
      // know the called function, and apply instructions where we do
      // not have the body of the called function.

      ApplySite Apply = ApplySite::isa(&I);
      if (!Apply || !Apply.hasSubstitutions())
        continue;

      auto *Callee = Apply.getCalleeFunction();
      if (!Callee || !Callee->isDefinition())
        continue;

      // We have a call that can potentially be specialized, so
      // attempt to do so.

      // The specializer helper function currently expects a collector
      // argument, but we aren't going to make use of the results so
      // we'll have our filter always return false;
      auto Filter = [](SILInstruction *I) -> bool { return false; };
      CloneCollector Collector(Filter);

      SILFunction *SpecializedFunction;

      auto Specialized =
          trySpecializeApplyOfGeneric(Apply, SpecializedFunction, Collector);

      if (Specialized) {
        Changed = true;

        // If calling the specialization utility resulted in a new
        // function (as opposed to returning a previous
        // specialization), we need to notify the pass manager so that
        // the new function gets optimized.
        if (SpecializedFunction)
          notifyPassManagerOfFunction(SpecializedFunction);

        auto *AI = Apply.getInstruction();

        if (!isa<TryApplyInst>(AI))
          AI->replaceAllUsesWith(Specialized.getInstruction());

        DeadApplies.push_back(AI);
      }
    }
  }

  // Remove all the now-dead applies.
  while (!DeadApplies.empty()) {
    auto *AI = DeadApplies.pop_back_val();
    recursivelyDeleteTriviallyDeadInstructions(AI, true);
  }

  return Changed;
}

SILTransform *swift::createGenericSpecializer() {
  return new GenericSpecializer();
}
<commit_msg>Change the invalidation kind for the generic specializer.<commit_after>//===-- GenericSpecializer.cpp - Specialization of generic functions ------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Specialize calls to generic functions by substituting static type
// information.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sil-generic-specializer"

#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SILOptimizer/Utils/Generics.h"
#include "swift/SILOptimizer/Utils/Local.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "llvm/ADT/SmallVector.h"

using namespace swift;

namespace {

class GenericSpecializer : public SILFunctionTransform {

  bool specializeAppliesInFunction(SILFunction &F);

  /// The entry point to the transformation.
  void run() override {
    SILFunction &F = *getFunction();
    DEBUG(llvm::dbgs() << "***** GenericSpecializer on function:" << F.getName()
                       << " *****\n");

    if (specializeAppliesInFunction(F))
      invalidateAnalysis(SILAnalysis::InvalidationKind::Everything);
  }

  StringRef getName() override { return "Generic Specializer"; }
};

} // end anonymous namespace

bool GenericSpecializer::specializeAppliesInFunction(SILFunction &F) {
  bool Changed = false;
  llvm::SmallVector<SILInstruction *, 8> DeadApplies;

  for (auto &BB : F) {
    for (auto It = BB.begin(), End = BB.end(); It != End;) {
      auto &I = *It++;

      // Skip non-apply instructions, apply instructions with no
      // substitutions, apply instructions where we do not statically
      // know the called function, and apply instructions where we do
      // not have the body of the called function.

      ApplySite Apply = ApplySite::isa(&I);
      if (!Apply || !Apply.hasSubstitutions())
        continue;

      auto *Callee = Apply.getCalleeFunction();
      if (!Callee || !Callee->isDefinition())
        continue;

      // We have a call that can potentially be specialized, so
      // attempt to do so.

      // The specializer helper function currently expects a collector
      // argument, but we aren't going to make use of the results so
      // we'll have our filter always return false;
      auto Filter = [](SILInstruction *I) -> bool { return false; };
      CloneCollector Collector(Filter);

      SILFunction *SpecializedFunction;

      auto Specialized =
          trySpecializeApplyOfGeneric(Apply, SpecializedFunction, Collector);

      if (Specialized) {
        Changed = true;

        // If calling the specialization utility resulted in a new
        // function (as opposed to returning a previous
        // specialization), we need to notify the pass manager so that
        // the new function gets optimized.
        if (SpecializedFunction)
          notifyPassManagerOfFunction(SpecializedFunction);

        auto *AI = Apply.getInstruction();

        if (!isa<TryApplyInst>(AI))
          AI->replaceAllUsesWith(Specialized.getInstruction());

        DeadApplies.push_back(AI);
      }
    }
  }

  // Remove all the now-dead applies.
  while (!DeadApplies.empty()) {
    auto *AI = DeadApplies.pop_back_val();
    recursivelyDeleteTriviallyDeadInstructions(AI, true);
  }

  return Changed;
}

SILTransform *swift::createGenericSpecializer() {
  return new GenericSpecializer();
}
<|endoftext|>


<commit_before>#include <QSettings>
#include <QDir>
#include <QDirIterator>
#include <QCryptographicHash>
#include <QMessageBox>
#include "md5-fix.h"
#include "ui_md5-fix.h"
#include "functions.h"
#include "helpers.h"

md5Fix::md5Fix(Profile *profile, QWidget *parent)
	: QDialog(parent), ui(new Ui::md5Fix), m_profile(profile)
{
	ui->setupUi(this);

	QSettings *settings = profile->getSettings();
	ui->lineFolder->setText(settings->value("Save/path").toString());
	ui->lineFilename->setText(settings->value("Save/filename").toString());
	ui->progressBar->hide();

	resize(size().width(), 0);
}

md5Fix::~md5Fix()
{
	delete ui;
}

void md5Fix::on_buttonCancel_clicked()
{
	emit rejected();
	close();
}

void md5Fix::on_buttonStart_clicked()
{
	ui->buttonStart->setEnabled(false);

	// Check that directory exists
	QDir dir(ui->lineFolder->text());
	if (!dir.exists())
	{
		error(this, tr("This folder does not exist."));
		ui->buttonStart->setEnabled(true);
		return;
	}

	// Make sure the input is valid
	if (!ui->radioForce->isChecked() && !ui->lineFilename->text().contains("%md5%"))
	{
		error(this, tr("If you want to get the MD5 from the filename, you have to include the %md5% token in it."));
		ui->buttonStart->setEnabled(true);
		return;
	}

	// Get all files from the destination directory
	typedef QPair<QString,QString> QStringPair;
	QVector<QStringPair> files = QVector<QStringPair>();
	QDirIterator it(dir, QDirIterator::Subdirectories);
	while (it.hasNext())
	{
		it.next();
		if (!it.fileInfo().isDir())
		{
			int len = it.filePath().length() - dir.absolutePath().length() - 1;
			files.append(QPair<QString,QString>(it.filePath().right(len), it.filePath()));
		}
	}

	if (files.count() > 0)
	{
		// Show progresss bar
		ui->progressBar->setValue(0);
		ui->progressBar->setMaximum(files.size());
		ui->progressBar->show();

		// Open MD5 file
		QFile f(m_profile->getPath() + "/md5s.txt");
		if (!f.open(QFile::WriteOnly | QFile::Truncate))
		{
			error(this, tr("Unable to open the MD5 file."));
			ui->progressBar->hide();
			ui->buttonStart->setEnabled(true);
			return;
		}

		// Parse all files
		for (QStringPair file : files)
		{
			QString md5 = "";
			if (ui->radioForce->isChecked())
			{
				QFile fle(file.second);
				fle.open(QFile::ReadOnly);
				md5 = QCryptographicHash::hash(fle.readAll(), QCryptographicHash::Md5).toHex();
			}
			else
			{
				QRegExp regx("%([^%]*)%");
				QString reg = QRegExp::escape(ui->lineFilename->text());
				int pos = 0, cur = 0, id = -1;
				while ((pos = regx.indexIn(ui->lineFilename->text(), pos)) != -1)
				{
					pos += regx.matchedLength();
					reg.replace(regx.cap(0), "(.+)");
					if (regx.cap(1) == "md5")
					{ id = cur; }
					cur++;
				}
				QRegExp rx(reg);
				rx.setMinimal(true);
				pos = 0;
				while ((pos = rx.indexIn(file.first, pos)) != -1)
				{
					pos += rx.matchedLength();
					md5 = rx.cap(id + 1);
				}
			}
			if (!md5.isEmpty())
			{ f.write(QString(md5 + file.second + "\n").toUtf8()); }
			ui->progressBar->setValue(ui->progressBar->value() + 1);
		}
		f.close();
	}

	// Hide progresss bar
	ui->progressBar->hide();
	ui->progressBar->setValue(0);
	ui->progressBar->setMaximum(0);

	ui->buttonStart->setEnabled(true);

	QMessageBox::information(this, tr("Finished"), tr("%n MD5(s) loaded", "", files.count()));
}
<commit_msg>Fix md5 list fixer not saving after program is closed<commit_after>#include <QSettings>
#include <QDir>
#include <QDirIterator>
#include <QCryptographicHash>
#include <QMessageBox>
#include "md5-fix.h"
#include "ui_md5-fix.h"
#include "functions.h"
#include "helpers.h"

md5Fix::md5Fix(Profile *profile, QWidget *parent)
	: QDialog(parent), ui(new Ui::md5Fix), m_profile(profile)
{
	ui->setupUi(this);

	QSettings *settings = profile->getSettings();
	ui->lineFolder->setText(settings->value("Save/path").toString());
	ui->lineFilename->setText(settings->value("Save/filename").toString());
	ui->progressBar->hide();

	resize(size().width(), 0);
}

md5Fix::~md5Fix()
{
	delete ui;
}

void md5Fix::on_buttonCancel_clicked()
{
	emit rejected();
	close();
}

void md5Fix::on_buttonStart_clicked()
{
	ui->buttonStart->setEnabled(false);

	// Check that directory exists
	QDir dir(ui->lineFolder->text());
	if (!dir.exists())
	{
		error(this, tr("This folder does not exist."));
		ui->buttonStart->setEnabled(true);
		return;
	}

	// Make sure the input is valid
	if (!ui->radioForce->isChecked() && !ui->lineFilename->text().contains("%md5%"))
	{
		error(this, tr("If you want to get the MD5 from the filename, you have to include the %md5% token in it."));
		ui->buttonStart->setEnabled(true);
		return;
	}

	// Get all files from the destination directory
	typedef QPair<QString,QString> QStringPair;
	QVector<QStringPair> files = QVector<QStringPair>();
	QDirIterator it(dir, QDirIterator::Subdirectories);
	while (it.hasNext())
	{
		it.next();
		if (!it.fileInfo().isDir())
		{
			int len = it.filePath().length() - dir.absolutePath().length() - 1;
			files.append(QPair<QString,QString>(it.filePath().right(len), it.filePath()));
		}
	}

	if (files.count() > 0)
	{
		// Show progresss bar
		ui->progressBar->setValue(0);
		ui->progressBar->setMaximum(files.size());
		ui->progressBar->show();

		// Parse all files
		for (QStringPair file : files)
		{
			QString md5 = "";
			if (ui->radioForce->isChecked())
			{
				QFile fle(file.second);
				fle.open(QFile::ReadOnly);
				md5 = QCryptographicHash::hash(fle.readAll(), QCryptographicHash::Md5).toHex();
			}
			else
			{
				QRegExp regx("%([^%]*)%");
				QString reg = QRegExp::escape(ui->lineFilename->text());
				int pos = 0, cur = 0, id = -1;
				while ((pos = regx.indexIn(ui->lineFilename->text(), pos)) != -1)
				{
					pos += regx.matchedLength();
					reg.replace(regx.cap(0), "(.+)");
					if (regx.cap(1) == "md5")
					{ id = cur; }
					cur++;
				}
				QRegExp rx(reg);
				rx.setMinimal(true);
				pos = 0;
				while ((pos = rx.indexIn(file.first, pos)) != -1)
				{
					pos += rx.matchedLength();
					md5 = rx.cap(id + 1);
				}
			}
			if (!md5.isEmpty())
			{ m_profile->addMd5(md5, file.second); }
			ui->progressBar->setValue(ui->progressBar->value() + 1);
		}
	}

	// Hide progresss bar
	ui->progressBar->hide();
	ui->progressBar->setValue(0);
	ui->progressBar->setMaximum(0);

	ui->buttonStart->setEnabled(true);

	QMessageBox::information(this, tr("Finished"), tr("%n MD5(s) loaded", "", files.count()));
}
<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS adarefilterteam29 (1.153.28); FILE MERGED 2004/10/12 13:00:03 mmaher 1.153.28.3: RESYNC: (1.155-1.156); FILE MERGED 2004/08/11 15:15:31 mmaher 1.153.28.2: RESYNC: (1.153-1.155); FILE MERGED 2004/07/07 15:15:54 mmaher 1.153.28.1: #i30198# If there is no header or footer then negative top and bottom page margins don't mean anything<commit_after><|endoftext|>


<commit_before>#include "phOutput.h"
#include "phIO.h"
#include <sstream>
#include <PCU.h>

namespace ph {

static std::string buildGeomBCFileName(Input& in)
{
  std::stringstream ss;
  int rank = PCU_Comm_Self() + 1;
  ss << "geombc.dat." << rank;
  return ss.str();
}

/* note: doing this as an "int" will almost certainly
   overflow for billion-element meshes.
   but, thats the format used in previous geombc. */
int getTotalNodes(apf::Mesh* m)
{
  int n = apf::countOwned(m, 0);
  PCU_Add_Ints(&n, 1);
  return n;
}

enum {
  MAX_PARAMS = 8
};

void getInteriorConnectivity(Output& o, int block, apf::DynamicArray<int>& c)
{
  int nelem = o.blocks.interior.nElements[block];
  int nvert = o.blocks.interior.keys[block].nElementVertices;
  c.setSize(nelem * nvert);
  size_t i = 0;
  for (int vert = 0; vert < nvert; ++vert)
    for (int elem = 0; elem < nelem; ++elem)
      c[i++] = o.arrays.ien[block][elem][vert];
  assert(i == c.getSize());
}

void getBoundaryConnectivity(Output& o, int block, apf::DynamicArray<int>& c)
{
  int nelem = o.blocks.boundary.nElements[block];
  int nvert = o.blocks.boundary.keys[block].nElementVertices;
  c.setSize(nelem * nvert);
  size_t i = 0;
  for (int vert = 0; vert < nvert; ++vert)
    for (int elem = 0; elem < nelem; ++elem)
      c[i++] = o.arrays.ienb[block][elem][vert];
  assert(i == c.getSize());
}

void getNaturalBCCodes(Output& o, int block, apf::DynamicArray<int>& codes)
{
  int nelem = o.blocks.boundary.nElements[block];
  codes.setSize(nelem * 2);
  size_t i = 0;
  for (int j = 0; j < 2; ++j)
    for (int elem = 0; elem < nelem; ++elem)
      codes[i++] = o.arrays.ibcb[block][elem][j];
  assert(i == codes.getSize());
}

void getNaturalBCValues(Output& o, int block, apf::DynamicArray<double>& values)
{
  int nelem = o.blocks.boundary.nElements[block];
  int nbc = countNaturalBCs(*o.in);
  values.setSize(nelem * nbc);
  size_t i = 0;
  for (int bc = 0; bc < nbc; ++bc)
    for (int elem = 0; elem < nelem; ++elem)
      values[i++] = o.arrays.bcb[block][elem][bc];
  assert(i == values.getSize());
}

void getEssentialBCValues(Output& o, apf::DynamicArray<double>& values)
{
  int nnode = o.nEssentialBCNodes;
  int nbc = countEssentialBCs(*o.in);
  values.setSize(nnode * nbc);
  size_t i = 0;
  for (int bc = 0; bc < nbc; ++bc)
    for (int node = 0; node < nnode; ++node)
      values[i++] = o.arrays.bc[node][bc];
  assert(i == values.getSize());
}

void fillBlockKeyParams(int* params, BlockKey& k)
{
  params[1] = k.nElementVertices;
  params[2] = k.polynomialOrder;
  params[3] = k.nElementVertices; /* num nodes */
  params[4] = k.nBoundaryFaceEdges; /* num boundary nodes */
  params[5] = k.nBoundaryFaceEdges;
  params[6] = k.elementType;
}

void writeBlocks(FILE* f, Output& o)
{
  apf::DynamicArray<int> c;
  int params[MAX_PARAMS];
  for (int i = 0; i < o.blocks.interior.getSize(); ++i) {
    BlockKey& k = o.blocks.interior.keys[i];
    std::string phrase = getBlockKeyPhrase(k, "connectivity interior ");
    params[0] = o.blocks.interior.nElements[i];
    fillBlockKeyParams(params, k);
    getInteriorConnectivity(o, i, c);
    ph_write_ints(f, phrase.c_str(), &c[0], c.getSize(), 7, params);
  }
  for (int i = 0; i < o.blocks.boundary.getSize(); ++i) {
    BlockKey& k = o.blocks.boundary.keys[i];
    std::string phrase = getBlockKeyPhrase(k, "connectivity boundary ");
    params[0] = o.blocks.interior.nElements[i];
    fillBlockKeyParams(params, k);
    params[7] = countNaturalBCs(*o.in);
    getBoundaryConnectivity(o, i, c);
    ph_write_ints(f, phrase.c_str(), &c[0], c.getSize(), 8, params);
    phrase = getBlockKeyPhrase(k, "nbc codes ");
    apf::DynamicArray<int> codes;
    getNaturalBCCodes(o, i, codes);
    ph_write_ints(f, phrase.c_str(), &codes[0], codes.getSize(), 8, params);
    phrase = getBlockKeyPhrase(k, "nbc values ");
    apf::DynamicArray<double> values;
    getNaturalBCValues(o, i, values);
    ph_write_doubles(f, phrase.c_str(), &values[0], values.getSize(), 8, params);
  }
}

static void writeInt(FILE* f, const char* name, int i)
{
  ph_write_header(f, name, 0, 1, &i);
}

static void writeInts(FILE* f, const char* name, int* i, int n)
{
  ph_write_ints(f, name, i, n, 1, &n);
}

static void writeDoubles(FILE* f, const char* name, double* d, int n)
{
  ph_write_doubles(f, name, d, n, 1, &n);
}

void writeGeomBC(Output& o, std::string path)
{
  double t0 = MPI_Wtime();
  apf::Mesh* m = o.mesh;
  path += buildGeomBCFileName(*o.in);
  FILE* f = fopen(path.c_str(), "w");
  ph_write_preamble(f);
  int params[MAX_PARAMS];
/* all of these strings are looked for by the other programs
   reading this format, so don't fix spelling errors or
   other silliness, it has already been set in stone */
  writeInt(f, "number of nodes", m->count(0));
  writeInt(f, "number of nodes in the mesh", o.nGlobalEntities[0]);
  writeInt(f, "number of edges in the mesh", o.nGlobalEntities[1]);
  writeInt(f, "number of faces in the mesh", o.nGlobalEntities[2]);
  writeInt(f, "number of modes", o.nOverlapNodes);
  writeInt(f, "number of shapefunctions soved on processor", o.nOwnedNodes);
  writeInt(f, "number of global modes", o.nGlobalNodes);
  writeInt(f, "number of interior elements", m->count(m->getDimension()));
  writeInt(f, "number of boundary elements", o.nBoundaryElements);
  writeInt(f, "maximum number of element nodes", o.nMaxElementNodes);
  writeInt(f, "number of interior tpblocks", o.blocks.interior.getSize());
  writeInt(f, "number of boundary tpblocks", o.blocks.boundary.getSize());
  writeInt(f, "number of nodes with Dirichlet BCs", o.nEssentialBCNodes);
  params[0] = m->count(0);
  params[1] = 3;
  ph_write_doubles(f, "co-ordinates", o.arrays.coordinates,
      params[0] * params[1], 2, params);
  writeInt(f, "number of processors", PCU_Comm_Peers());
  writeInt(f, "size of ilwork array", o.nlwork);
  if (o.nlwork)
    writeInts(f, "ilwork", o.arrays.ilwork, o.nlwork);
  params[0] = m->count(0);
  writeInts(f, " mode number map from partition to global",
      o.arrays.globalNodeNumbers, m->count(0));
  writeBlocks(f, o);
  writeInts(f, "bc mapping array", o.arrays.nbc, m->count(0));
  writeInts(f, "bc codes array", o.arrays.ibc, o.nEssentialBCNodes);
  apf::DynamicArray<double> bc;
  getEssentialBCValues(o, bc);
  writeDoubles(f, "boundary condition array", &bc[0], bc.getSize());
  writeInts(f, "periodic masters array", o.arrays.iper, m->count(0));
  fclose(f);
  double t1 = MPI_Wtime();
  if (!PCU_Comm_Self())
    printf("geombc file written in %f seconds\n", t1 - t0);
}

}
<commit_msg>converting output arrays to fortran indexing<commit_after>#include "phOutput.h"
#include "phIO.h"
#include <sstream>
#include <PCU.h>

namespace ph {

static std::string buildGeomBCFileName(Input& in)
{
  std::stringstream ss;
  int rank = PCU_Comm_Self() + 1;
  ss << "geombc.dat." << rank;
  return ss.str();
}

/* note: doing this as an "int" will almost certainly
   overflow for billion-element meshes.
   but, thats the format used in previous geombc. */
int getTotalNodes(apf::Mesh* m)
{
  int n = apf::countOwned(m, 0);
  PCU_Add_Ints(&n, 1);
  return n;
}

enum {
  MAX_PARAMS = 8
};

void getInteriorConnectivity(Output& o, int block, apf::DynamicArray<int>& c)
{
  int nelem = o.blocks.interior.nElements[block];
  int nvert = o.blocks.interior.keys[block].nElementVertices;
  c.setSize(nelem * nvert);
  size_t i = 0;
  for (int vert = 0; vert < nvert; ++vert)
    for (int elem = 0; elem < nelem; ++elem)
      c[i++] = o.arrays.ien[block][elem][vert] + 1; /* FORTRAN indexing */
  assert(i == c.getSize());
}

void getBoundaryConnectivity(Output& o, int block, apf::DynamicArray<int>& c)
{
  int nelem = o.blocks.boundary.nElements[block];
  int nvert = o.blocks.boundary.keys[block].nElementVertices;
  c.setSize(nelem * nvert);
  size_t i = 0;
  for (int vert = 0; vert < nvert; ++vert)
    for (int elem = 0; elem < nelem; ++elem)
      c[i++] = o.arrays.ienb[block][elem][vert] + 1;
  assert(i == c.getSize());
}

void getNaturalBCCodes(Output& o, int block, apf::DynamicArray<int>& codes)
{
  int nelem = o.blocks.boundary.nElements[block];
  codes.setSize(nelem * 2);
  size_t i = 0;
  for (int j = 0; j < 2; ++j)
    for (int elem = 0; elem < nelem; ++elem)
      codes[i++] = o.arrays.ibcb[block][elem][j];
  assert(i == codes.getSize());
}

void getNaturalBCValues(Output& o, int block, apf::DynamicArray<double>& values)
{
  int nelem = o.blocks.boundary.nElements[block];
  int nbc = countNaturalBCs(*o.in);
  values.setSize(nelem * nbc);
  size_t i = 0;
  for (int bc = 0; bc < nbc; ++bc)
    for (int elem = 0; elem < nelem; ++elem)
      values[i++] = o.arrays.bcb[block][elem][bc];
  assert(i == values.getSize());
}

void getEssentialBCMap(Output& o, apf::DynamicArray<int>& map)
{
  int nnode = o.mesh->count(0);
  map.setSize(nnode);
  for (int node = 0; node < nnode; ++node)
    map[node] = o.arrays.nbc[node] + 1;
}

void getEssentialBCValues(Output& o, apf::DynamicArray<double>& values)
{
  int nnode = o.nEssentialBCNodes;
  int nbc = countEssentialBCs(*o.in);
  values.setSize(nnode * nbc);
  size_t i = 0;
  for (int bc = 0; bc < nbc; ++bc)
    for (int node = 0; node < nnode; ++node)
      values[i++] = o.arrays.bc[node][bc];
  assert(i == values.getSize());
}

void fillBlockKeyParams(int* params, BlockKey& k)
{
  params[1] = k.nElementVertices;
  params[2] = k.polynomialOrder;
  params[3] = k.nElementVertices; /* num nodes */
  params[4] = k.nBoundaryFaceEdges; /* num boundary nodes */
  params[5] = k.nBoundaryFaceEdges;
  params[6] = k.elementType;
}

void writeBlocks(FILE* f, Output& o)
{
  apf::DynamicArray<int> c;
  int params[MAX_PARAMS];
  for (int i = 0; i < o.blocks.interior.getSize(); ++i) {
    BlockKey& k = o.blocks.interior.keys[i];
    std::string phrase = getBlockKeyPhrase(k, "connectivity interior ");
    params[0] = o.blocks.interior.nElements[i];
    fillBlockKeyParams(params, k);
    getInteriorConnectivity(o, i, c);
    ph_write_ints(f, phrase.c_str(), &c[0], c.getSize(), 7, params);
  }
  for (int i = 0; i < o.blocks.boundary.getSize(); ++i) {
    BlockKey& k = o.blocks.boundary.keys[i];
    std::string phrase = getBlockKeyPhrase(k, "connectivity boundary ");
    params[0] = o.blocks.interior.nElements[i];
    fillBlockKeyParams(params, k);
    params[7] = countNaturalBCs(*o.in);
    getBoundaryConnectivity(o, i, c);
    ph_write_ints(f, phrase.c_str(), &c[0], c.getSize(), 8, params);
    phrase = getBlockKeyPhrase(k, "nbc codes ");
    apf::DynamicArray<int> codes;
    getNaturalBCCodes(o, i, codes);
    ph_write_ints(f, phrase.c_str(), &codes[0], codes.getSize(), 8, params);
    phrase = getBlockKeyPhrase(k, "nbc values ");
    apf::DynamicArray<double> values;
    getNaturalBCValues(o, i, values);
    ph_write_doubles(f, phrase.c_str(), &values[0], values.getSize(), 8, params);
  }
}

static void writeInt(FILE* f, const char* name, int i)
{
  ph_write_header(f, name, 0, 1, &i);
}

static void writeInts(FILE* f, const char* name, int* i, int n)
{
  ph_write_ints(f, name, i, n, 1, &n);
}

static void writeDoubles(FILE* f, const char* name, double* d, int n)
{
  ph_write_doubles(f, name, d, n, 1, &n);
}

void writeGeomBC(Output& o, std::string path)
{
  double t0 = MPI_Wtime();
  apf::Mesh* m = o.mesh;
  path += buildGeomBCFileName(*o.in);
  FILE* f = fopen(path.c_str(), "w");
  ph_write_preamble(f);
  int params[MAX_PARAMS];
/* all of these strings are looked for by the other programs
   reading this format, so don't fix spelling errors or
   other silliness, it has already been set in stone */
  writeInt(f, "number of nodes", m->count(0));
  writeInt(f, "number of nodes in the mesh", o.nGlobalEntities[0]);
  writeInt(f, "number of edges in the mesh", o.nGlobalEntities[1]);
  writeInt(f, "number of faces in the mesh", o.nGlobalEntities[2]);
  writeInt(f, "number of modes", o.nOverlapNodes);
  writeInt(f, "number of shapefunctions soved on processor", o.nOwnedNodes);
  writeInt(f, "number of global modes", o.nGlobalNodes);
  writeInt(f, "number of interior elements", m->count(m->getDimension()));
  writeInt(f, "number of boundary elements", o.nBoundaryElements);
  writeInt(f, "maximum number of element nodes", o.nMaxElementNodes);
  writeInt(f, "number of interior tpblocks", o.blocks.interior.getSize());
  writeInt(f, "number of boundary tpblocks", o.blocks.boundary.getSize());
  writeInt(f, "number of nodes with Dirichlet BCs", o.nEssentialBCNodes);
  params[0] = m->count(0);
  params[1] = 3;
  ph_write_doubles(f, "co-ordinates", o.arrays.coordinates,
      params[0] * params[1], 2, params);
  writeInt(f, "number of processors", PCU_Comm_Peers());
  writeInt(f, "size of ilwork array", o.nlwork);
  if (o.nlwork)
    writeInts(f, "ilwork", o.arrays.ilwork, o.nlwork);
  params[0] = m->count(0);
  writeInts(f, " mode number map from partition to global",
      o.arrays.globalNodeNumbers, m->count(0));
  writeBlocks(f, o);
  apf::DynamicArray<int> nbc;
  getEssentialBCMap(o, nbc);
  writeInts(f, "bc mapping array", &nbc[0], m->count(0));
  writeInts(f, "bc codes array", o.arrays.ibc, o.nEssentialBCNodes);
  apf::DynamicArray<double> bc;
  getEssentialBCValues(o, bc);
  writeDoubles(f, "boundary condition array", &bc[0], bc.getSize());
  writeInts(f, "periodic masters array", o.arrays.iper, m->count(0));
  fclose(f);
  double t1 = MPI_Wtime();
  if (!PCU_Comm_Self())
    printf("geombc file written in %f seconds\n", t1 - t0);
}

}
<|endoftext|>


<commit_before>// Cos neuron activation function layer.
// Adapted from TanH layer code

#include <vector>

#include "caffe/layers/trig_layer.hpp"

namespace caffe {

template <typename Dtype>
void TrigLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top) {
  func = this->layer_param_.trig_param().function();
}

template <typename Dtype>
void TrigLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
    const vector<Blob<Dtype>*>& top) {
  const Dtype* bottom_data = bottom[0]->cpu_data();
  Dtype* top_data = top[0]->mutable_cpu_data();
  const int count = bottom[0]->count();
  for (int i = 0; i < count; ++i) {
    if(func == TrigParameter_Function_COS)
      top_data[i] = cos(bottom_data[i]);
    else if(func == TrigParameter_Function_SIN)
      top_data[i] = cos(bottom_data[i]);
    else
      CHECK(0) << "Unsupported trig function";
  }
}

template <typename Dtype>
void TrigLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
    const vector<bool>& propagate_down,
    const vector<Blob<Dtype>*>& bottom) {
  if (propagate_down[0]) {
    const Dtype* bottom_data = bottom[0]->cpu_data();
    const Dtype* top_diff = top[0]->cpu_diff();
    Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
    const int count = bottom[0]->count();
    Dtype x, deriv;
    for (int i = 0; i < count; ++i) {
      x = bottom_data[i];
      if(func == TrigParameter_Function_COS)
        deriv = -sin(x);
      else if(func == TrigParameter_Function_SIN)
        deriv = cos(x);
      else
        CHECK(0) << "Unsupported trig function";
      bottom_diff[i] = top_diff[i] * deriv;
    }
  }
}

#ifdef CPU_ONLY
STUB_GPU(TrigLayer);
#endif

INSTANTIATE_CLASS(TrigLayer);
REGISTER_LAYER_CLASS(Trig);

}  // namespace caffe
<commit_msg>Fix CPU sin Trig layer to actually compute sin<commit_after>// Cos neuron activation function layer.
// Adapted from TanH layer code

#include <vector>

#include "caffe/layers/trig_layer.hpp"

namespace caffe {

template <typename Dtype>
void TrigLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top) {
  func = this->layer_param_.trig_param().function();
}

template <typename Dtype>
void TrigLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
    const vector<Blob<Dtype>*>& top) {
  const Dtype* bottom_data = bottom[0]->cpu_data();
  Dtype* top_data = top[0]->mutable_cpu_data();
  const int count = bottom[0]->count();
  for (int i = 0; i < count; ++i) {
    if(func == TrigParameter_Function_COS)
      top_data[i] = cos(bottom_data[i]);
    else if(func == TrigParameter_Function_SIN)
      top_data[i] = sin(bottom_data[i]);
    else
      CHECK(0) << "Unsupported trig function";
  }
}

template <typename Dtype>
void TrigLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
    const vector<bool>& propagate_down,
    const vector<Blob<Dtype>*>& bottom) {
  if (propagate_down[0]) {
    const Dtype* bottom_data = bottom[0]->cpu_data();
    const Dtype* top_diff = top[0]->cpu_diff();
    Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
    const int count = bottom[0]->count();
    Dtype x, deriv;
    for (int i = 0; i < count; ++i) {
      x = bottom_data[i];
      if(func == TrigParameter_Function_COS)
        deriv = -sin(x);
      else if(func == TrigParameter_Function_SIN)
        deriv = cos(x);
      else
        CHECK(0) << "Unsupported trig function";
      bottom_diff[i] = top_diff[i] * deriv;
    }
  }
}

#ifdef CPU_ONLY
STUB_GPU(TrigLayer);
#endif

INSTANTIATE_CLASS(TrigLayer);
REGISTER_LAYER_CLASS(Trig);

}  // namespace caffe
<|endoftext|>


<commit_before>#include "Normals.h"

using namespace osg;

Normals::Normals( Node *node, float scale, Mode mode )
{
    MakeNormalsVisitor mnv(scale,mode);
    node->accept( mnv );

    ref_ptr<Vec3Array> coords = mnv.getCoords();
    ref_ptr<Vec4Array> colors = new Vec4Array;
    if( mode == SurfaceNormals )
        colors->push_back( Vec4( 0, 1, 0, 1 ));
    else if( mode == VertexNormals )
        colors->push_back( Vec4( 1, 0, 0, 1 ));

    ref_ptr<Geometry> geom = new Geometry;
    geom->setVertexArray( coords.get() );
    geom->setColorArray( colors.get() );
    geom->setColorBinding( Geometry::BIND_OVERALL );

    geom->addPrimitiveSet( new DrawArrays( PrimitiveSet::LINES, 0, coords->size()));

    StateSet *sset = new StateSet;
    sset->setMode( GL_LIGHTING,   StateAttribute::OFF);
    geom->setStateSet( sset );
    addDrawable( geom.get() );
}

Normals::MakeNormalsVisitor::MakeNormalsVisitor( float normalScale, Mode mode):
            NodeVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN),
            _normal_scale(normalScale),
            _mode(mode)
{
    _local_coords = new Vec3Array;
    _mat = osg::Matrix::identity();
}

void Normals::MakeNormalsVisitor::apply(osg::MatrixTransform& tx)
{
    _matStack.push( _mat );
    _mat = _mat * tx.getMatrix();

    traverse( tx );

    _mat = _matStack.top();
    _matStack.pop();
}

void Normals::MakeNormalsVisitor::apply( Geode &geode )
{
    for( unsigned int i = 0; i < geode.getNumDrawables(); i++ )
    {
        Geometry *geom = dynamic_cast<Geometry *>(geode.getDrawable(i));
        if( geom )
        {
            Vec3Array *coords   = dynamic_cast<Vec3Array*>(geom->getVertexArray());
            if( coords == 0L )
                continue;

            Vec3Array *normals  = dynamic_cast<Vec3Array*>(geom->getNormalArray());
            if( normals == 0L )
                continue;

            Geometry::AttributeBinding binding = geom->getNormalBinding();
            if( binding == Geometry::BIND_OFF )
                continue;

            if( binding == Geometry::BIND_OVERALL )
            {
                Vec3 v(0,0,0);
                Vec3 n = normals->front();

                Vec3Array::iterator coord_index = coords->begin();
                while( coord_index != coords->end() )
                  v += *(coord_index++) * _mat;
                v /= (float)(coords->size());

                n *= _normal_scale;
                _local_coords->push_back( v );
                _local_coords->push_back( (v + n));
            }
            else // BIND_PER_PRIMTIVE_SET, BIND_PER_PRIMTITIV, BIND_PER_VERTEX
            {
                Geometry::PrimitiveSetList& primitiveSets = geom->getPrimitiveSetList();
                Geometry::PrimitiveSetList::iterator itr;

                Vec3Array::iterator coord_index   = coords->begin();
                Vec3Array::iterator normals_index = normals->begin();

                for(itr=primitiveSets.begin(); itr!=primitiveSets.end(); ++itr)
                {
#ifdef DEBUG
                    _printPrimitiveType( (*itr).get() );
#endif
                    if( binding == Geometry::BIND_PER_PRIMITIVE_SET )
                    {
                        Vec3 v(0,0,0);
                        Vec3 n = *(normals_index++);
                        int ni = (*itr)->getNumIndices();
                        for( int i = 0; i < ni; i++ )
                            v += *(coord_index++) * _mat;
                        v /= (float)(ni);

                        n *= _normal_scale;
                        _local_coords->push_back( v );
                        _local_coords->push_back( (v + n));

                    }
                    else
                    {
                        switch((*itr)->getMode())
                        {
                            case(PrimitiveSet::TRIANGLES):
                                for( unsigned int j = 0; j < (*itr)->getNumPrimitives(); j++ )
                                {
                                    _processPrimitive( 3, coord_index, normals_index, binding );
                                    coord_index += 3;
                                    if( binding == Geometry::BIND_PER_PRIMITIVE )
                                        normals_index++;
                                    else
                                        normals_index+=3;

                                }
                                break;

                            case(PrimitiveSet::TRIANGLE_STRIP):
                                for( unsigned int j = 0; j < (*itr)->getNumIndices()-2; j++ )
                                {
                                    _processPrimitive( 3, coord_index, normals_index, binding );
                                    coord_index++;
                                    normals_index++;
                                }
                                coord_index += 2;
                                if( binding == Geometry::BIND_PER_VERTEX )
                                    normals_index += 2;
                                break;

                            case(PrimitiveSet::TRIANGLE_FAN):
                                break;

                            case(PrimitiveSet::QUADS):
                                for( unsigned int j = 0; j < (*itr)->getNumPrimitives(); j++ )
                                {
                                    _processPrimitive( 4, coord_index, normals_index, binding );
                                    coord_index += 4;
                                    if( binding == Geometry::BIND_PER_PRIMITIVE )
                                        normals_index++;
                                    else
                                        normals_index+=4;
                                }
                                break;

                            case(PrimitiveSet::QUAD_STRIP):
                            case(PrimitiveSet::POLYGON):
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
        }
    }
    traverse( geode );
}

void Normals::MakeNormalsVisitor::_processPrimitive(  unsigned int nv,
                        Vec3Array::iterator coords,
                        Vec3Array::iterator normals,
                        Geometry::AttributeBinding binding )
{
    Vec3 v(0,0,0);
    Vec3 n(0,0,0);
    if( _mode == SurfaceNormals || binding == Geometry::BIND_PER_PRIMITIVE )
    {
        if( binding == Geometry::BIND_PER_PRIMITIVE )
        {
            n = *(normals++);
        }
        else if( binding == Geometry::BIND_PER_VERTEX )
        {
            for( unsigned int i = 0; i < nv; i++ )
                n += *(normals++);
            n /= (float)(nv);
        }

        for( unsigned int i = 0; i < nv; i++ )
            v += *(coords++) *  _mat;
        v /= (float)(nv);

        n *= _normal_scale;
        _local_coords->push_back( v );
        _local_coords->push_back( (v + n));
    }
    else if( _mode == VertexNormals )
    {
        for( unsigned int i = 0; i < nv; i++ )
        {
            v = *(coords++) * _mat;
            n = *(normals++);
            n *= _normal_scale;
            _local_coords->push_back( v );
            _local_coords->push_back( (v + n));
        }
    }
}

#ifdef DEBUG
void Normals::_printPrimitiveType( osg::PrimitiveSet *pset )
{
    std::cout << (
            pset->getMode() == PrimitiveSet::POINTS ? "POINTS" :
            pset->getMode() == PrimitiveSet::LINES ? "LINES" :
            pset->getMode() == PrimitiveSet::LINE_STRIP ? "LINE_STRIP" :
            pset->getMode() == PrimitiveSet::LINE_LOOP ? "LINE_LOOP" :
            pset->getMode() == PrimitiveSet::TRIANGLES ? "TRIANGLES" :
            pset->getMode() == PrimitiveSet::TRIANGLE_STRIP ? "TRIANGLE_STRIP" :
            pset->getMode() == PrimitiveSet::TRIANGLE_FAN ? "TRIANGLE_FAN" :
            pset->getMode() == PrimitiveSet::QUADS ? "QUADS" :
            pset->getMode() == PrimitiveSet::QUAD_STRIP ? "QUAD_STRIP" :
            pset->getMode() == PrimitiveSet::POLYGON ? "POLYGON" : "Dunno" )  << std::endl;
}
#endif

<commit_msg>Tweak for VS6.0 build<commit_after>#include "Normals.h"

using namespace osg;

Normals::Normals( Node *node, float scale, Mode mode )
{
    MakeNormalsVisitor mnv(scale,mode);
    node->accept( mnv );

    ref_ptr<Vec3Array> coords = mnv.getCoords();
    ref_ptr<Vec4Array> colors = new Vec4Array;
    if( mode == SurfaceNormals )
        colors->push_back( Vec4( 0, 1, 0, 1 ));
    else if( mode == VertexNormals )
        colors->push_back( Vec4( 1, 0, 0, 1 ));

    ref_ptr<Geometry> geom = new Geometry;
    geom->setVertexArray( coords.get() );
    geom->setColorArray( colors.get() );
    geom->setColorBinding( Geometry::BIND_OVERALL );

    geom->addPrimitiveSet( new DrawArrays( PrimitiveSet::LINES, 0, coords->size()));

    StateSet *sset = new StateSet;
    sset->setMode( GL_LIGHTING,   StateAttribute::OFF);
    geom->setStateSet( sset );
    addDrawable( geom.get() );
}

Normals::MakeNormalsVisitor::MakeNormalsVisitor( float normalScale, Mode mode):
            NodeVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN),
            _normal_scale(normalScale),
            _mode(mode)
{
    _local_coords = new Vec3Array;
    _mat = osg::Matrix::identity();
}

void Normals::MakeNormalsVisitor::apply(osg::MatrixTransform& tx)
{
    _matStack.push( _mat );
    _mat = _mat * tx.getMatrix();

    traverse( tx );

    _mat = _matStack.top();
    _matStack.pop();
}

void Normals::MakeNormalsVisitor::apply( Geode &geode )
{
    for( unsigned int i = 0; i < geode.getNumDrawables(); i++ )
    {
        Geometry *geom = dynamic_cast<Geometry *>(geode.getDrawable(i));
        if( geom )
        {
            Vec3Array *coords   = dynamic_cast<Vec3Array*>(geom->getVertexArray());
            if( coords == 0L )
                continue;

            Vec3Array *normals  = dynamic_cast<Vec3Array*>(geom->getNormalArray());
            if( normals == 0L )
                continue;

            Geometry::AttributeBinding binding = geom->getNormalBinding();
            if( binding == Geometry::BIND_OFF )
                continue;

            if( binding == Geometry::BIND_OVERALL )
            {
                Vec3 v(0,0,0);
                Vec3 n = normals->front();

                Vec3Array::iterator coord_index = coords->begin();
                while( coord_index != coords->end() )
                  v += *(coord_index++) * _mat;
                v /= (float)(coords->size());

                n *= _normal_scale;
                _local_coords->push_back( v );
                _local_coords->push_back( (v + n));
            }
            else // BIND_PER_PRIMTIVE_SET, BIND_PER_PRIMTITIV, BIND_PER_VERTEX
            {
                Geometry::PrimitiveSetList& primitiveSets = geom->getPrimitiveSetList();
                Geometry::PrimitiveSetList::iterator itr;

                Vec3Array::iterator coord_index   = coords->begin();
                Vec3Array::iterator normals_index = normals->begin();

                for(itr=primitiveSets.begin(); itr!=primitiveSets.end(); ++itr)
                {
#ifdef DEBUG
                    _printPrimitiveType( (*itr).get() );
#endif
                    if( binding == Geometry::BIND_PER_PRIMITIVE_SET )
                    {
                        Vec3 v(0,0,0);
                        Vec3 n = *(normals_index++);
                        int ni = (*itr)->getNumIndices();
                        for( int i = 0; i < ni; i++ )
                            v += *(coord_index++) * _mat;
                        v /= (float)(ni);

                        n *= _normal_scale;
                        _local_coords->push_back( v );
                        _local_coords->push_back( (v + n));

                    }
                    else
                    {
                        switch((*itr)->getMode())
                        {
                            case(PrimitiveSet::TRIANGLES):
                            {
                                for( unsigned int j = 0; j < (*itr)->getNumPrimitives(); j++ )
                                {
                                    _processPrimitive( 3, coord_index, normals_index, binding );
                                    coord_index += 3;
                                    if( binding == Geometry::BIND_PER_PRIMITIVE )
                                        normals_index++;
                                    else
                                        normals_index+=3;

                                }
                                break;
                            }
                            case(PrimitiveSet::TRIANGLE_STRIP):
                            {
                                for( unsigned int j = 0; j < (*itr)->getNumIndices()-2; j++ )
                                {
                                    _processPrimitive( 3, coord_index, normals_index, binding );
                                    coord_index++;
                                    normals_index++;
                                }
                                coord_index += 2;
                                if( binding == Geometry::BIND_PER_VERTEX )
                                    normals_index += 2;
                                break;
                            }
                            case(PrimitiveSet::TRIANGLE_FAN):
                                break;

                            case(PrimitiveSet::QUADS):
                            {
                                for( unsigned int j = 0; j < (*itr)->getNumPrimitives(); j++ )
                                {
                                    _processPrimitive( 4, coord_index, normals_index, binding );
                                    coord_index += 4;
                                    if( binding == Geometry::BIND_PER_PRIMITIVE )
                                        normals_index++;
                                    else
                                        normals_index+=4;
                                }
                                break;
                            }
                            case(PrimitiveSet::QUAD_STRIP):
                            case(PrimitiveSet::POLYGON):
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
        }
    }
    traverse( geode );
}

void Normals::MakeNormalsVisitor::_processPrimitive(  unsigned int nv,
                        Vec3Array::iterator coords,
                        Vec3Array::iterator normals,
                        Geometry::AttributeBinding binding )
{
    Vec3 v(0,0,0);
    Vec3 n(0,0,0);
    if( _mode == SurfaceNormals || binding == Geometry::BIND_PER_PRIMITIVE )
    {
        if( binding == Geometry::BIND_PER_PRIMITIVE )
        {
            n = *(normals++);
        }
        else if( binding == Geometry::BIND_PER_VERTEX )
        {
            for( unsigned int i = 0; i < nv; i++ )
                n += *(normals++);
            n /= (float)(nv);
        }

        for( unsigned int i = 0; i < nv; i++ )
            v += *(coords++) *  _mat;
        v /= (float)(nv);

        n *= _normal_scale;
        _local_coords->push_back( v );
        _local_coords->push_back( (v + n));
    }
    else if( _mode == VertexNormals )
    {
        for( unsigned int i = 0; i < nv; i++ )
        {
            v = *(coords++) * _mat;
            n = *(normals++);
            n *= _normal_scale;
            _local_coords->push_back( v );
            _local_coords->push_back( (v + n));
        }
    }
}

#ifdef DEBUG
void Normals::_printPrimitiveType( osg::PrimitiveSet *pset )
{
    std::cout << (
            pset->getMode() == PrimitiveSet::POINTS ? "POINTS" :
            pset->getMode() == PrimitiveSet::LINES ? "LINES" :
            pset->getMode() == PrimitiveSet::LINE_STRIP ? "LINE_STRIP" :
            pset->getMode() == PrimitiveSet::LINE_LOOP ? "LINE_LOOP" :
            pset->getMode() == PrimitiveSet::TRIANGLES ? "TRIANGLES" :
            pset->getMode() == PrimitiveSet::TRIANGLE_STRIP ? "TRIANGLE_STRIP" :
            pset->getMode() == PrimitiveSet::TRIANGLE_FAN ? "TRIANGLE_FAN" :
            pset->getMode() == PrimitiveSet::QUADS ? "QUADS" :
            pset->getMode() == PrimitiveSet::QUAD_STRIP ? "QUAD_STRIP" :
            pset->getMode() == PrimitiveSet::POLYGON ? "POLYGON" : "Dunno" )  << std::endl;
}
#endif

<|endoftext|>