<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.h"

namespace {

void ExpectVolumeNear(int expected, int actual) {
  // The hardware volume may be more coarsely quantized than [0, 255], so
  // it is not always reasonable to expect to get exactly what we set. This
  // allows for some error.
  const int kMaxVolumeError = 10;
  EXPECT_NEAR(expected, actual, kMaxVolumeError);
  EXPECT_GE(actual, 0);
  EXPECT_LE(actual, 255);
}

}  // namespace

class VolumeTest : public AfterStreamingFixture {
};

// TODO(phoglund): a number of tests are disabled here on Linux, all pending
// investigation in
// http://code.google.com/p/webrtc/issues/detail?id=367

TEST_F(VolumeTest, DefaultSpeakerVolumeIsAtMost255) {
  unsigned int volume = 1000;
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(volume));
  EXPECT_LE(volume, 255u);
}

TEST_F(VolumeTest, SetVolumeBeforePlayoutWorks) {
  // This is a rather specialized test, intended to exercise some PulseAudio
  // code. However, these conditions should be satisfied on any platform.
  unsigned int original_volume = 0;
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(original_volume));
  Sleep(1000);

  EXPECT_EQ(0, voe_volume_control_->SetSpeakerVolume(200));
  unsigned int volume;
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(volume));
  ExpectVolumeNear(200u, volume);

  PausePlaying();
  ResumePlaying();
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(volume));
  // Ensure the volume has not changed after resuming playout.
  ExpectVolumeNear(200u, volume);

  PausePlaying();
  EXPECT_EQ(0, voe_volume_control_->SetSpeakerVolume(100));
  ResumePlaying();
  // Ensure the volume set while paused is retained.
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(volume));
  ExpectVolumeNear(100u, volume);

  EXPECT_EQ(0, voe_volume_control_->SetSpeakerVolume(original_volume));
}

TEST_F(VolumeTest, ManualSetVolumeWorks) {
  unsigned int original_volume = 0;
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(original_volume));
  Sleep(1000);

  TEST_LOG("Setting speaker volume to 0 out of 255.\n");
  EXPECT_EQ(0, voe_volume_control_->SetSpeakerVolume(0));
  unsigned int volume;
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(volume));
  ExpectVolumeNear(0u, volume);
  Sleep(1000);

  TEST_LOG("Setting speaker volume to 100 out of 255.\n");
  EXPECT_EQ(0, voe_volume_control_->SetSpeakerVolume(100));
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(volume));
  ExpectVolumeNear(100u, volume);
  Sleep(1000);

  // Set the volume to 255 very briefly so we don't blast the poor user
  // listening to this. This is just to test the call succeeds.
  EXPECT_EQ(0, voe_volume_control_->SetSpeakerVolume(255));
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(volume));
  ExpectVolumeNear(255u, volume);

  TEST_LOG("Setting speaker volume to the original %d out of 255.\n",
      original_volume);
  EXPECT_EQ(0, voe_volume_control_->SetSpeakerVolume(original_volume));
  Sleep(1000);
}

TEST_F(VolumeTest, DISABLED_ON_LINUX(DefaultMicrophoneVolumeIsAtMost255)) {
  unsigned int volume = 1000;
  EXPECT_EQ(0, voe_volume_control_->GetMicVolume(volume));
  EXPECT_LE(volume, 255u);
}

TEST_F(VolumeTest, DISABLED_ON_LINUX(
          ManualRequiresMicrophoneCanSetMicrophoneVolumeWithAcgOff)) {
  SwitchToManualMicrophone();
  EXPECT_EQ(0, voe_apm_->SetAgcStatus(false));

  unsigned int original_volume = 0;
  EXPECT_EQ(0, voe_volume_control_->GetMicVolume(original_volume));

  TEST_LOG("Setting microphone volume to 0.\n");
  EXPECT_EQ(0, voe_volume_control_->SetMicVolume(channel_));
  Sleep(1000);
  TEST_LOG("Setting microphone volume to 255.\n");
  EXPECT_EQ(0, voe_volume_control_->SetMicVolume(255));
  Sleep(1000);
  TEST_LOG("Setting microphone volume back to saved value.\n");
  EXPECT_EQ(0, voe_volume_control_->SetMicVolume(original_volume));
  Sleep(1000);
}

TEST_F(VolumeTest, ChannelScalingIsOneByDefault) {
  float scaling = -1.0f;

  EXPECT_EQ(0, voe_volume_control_->GetChannelOutputVolumeScaling(
      channel_, scaling));
  EXPECT_FLOAT_EQ(1.0f, scaling);
}

TEST_F(VolumeTest, ManualCanSetChannelScaling) {
  EXPECT_EQ(0, voe_volume_control_->SetChannelOutputVolumeScaling(
      channel_, 0.1f));

  float scaling = 1.0f;
  EXPECT_EQ(0, voe_volume_control_->GetChannelOutputVolumeScaling(
      channel_, scaling));

  EXPECT_FLOAT_EQ(0.1f, scaling);

  TEST_LOG("Channel scaling set to 0.1: audio should be barely audible.\n");
  Sleep(2000);
}

TEST_F(VolumeTest, InputMutingIsNotEnabledByDefault) {
  bool is_muted = true;
  EXPECT_EQ(0, voe_volume_control_->GetInputMute(channel_, is_muted));
  EXPECT_FALSE(is_muted);
}

TEST_F(VolumeTest, DISABLED_ON_LINUX(ManualInputMutingMutesMicrophone)) {
  SwitchToManualMicrophone();

  // Enable muting.
  EXPECT_EQ(0, voe_volume_control_->SetInputMute(channel_, true));
  bool is_muted = false;
  EXPECT_EQ(0, voe_volume_control_->GetInputMute(channel_, is_muted));
  EXPECT_TRUE(is_muted);

  TEST_LOG("Muted: talk into microphone and verify you can't hear yourself.\n");
  Sleep(2000);

  // Test that we can disable muting.
  EXPECT_EQ(0, voe_volume_control_->SetInputMute(channel_, false));
  EXPECT_EQ(0, voe_volume_control_->GetInputMute(channel_, is_muted));
  EXPECT_FALSE(is_muted);

  TEST_LOG("Unmuted: talk into microphone and verify you can hear yourself.\n");
  Sleep(2000);
}

TEST_F(VolumeTest, DISABLED_ON_LINUX(SystemInputMutingIsNotEnabledByDefault)) {
  bool is_muted = true;
  EXPECT_EQ(0, voe_volume_control_->GetSystemInputMute(is_muted));
  EXPECT_FALSE(is_muted);
}

TEST_F(VolumeTest, DISABLED_ON_LINUX(ManualSystemInputMutingMutesMicrophone)) {
  SwitchToManualMicrophone();

  // Enable system input muting.
  EXPECT_EQ(0, voe_volume_control_->SetSystemInputMute(true));
  bool is_muted = false;
  EXPECT_EQ(0, voe_volume_control_->GetSystemInputMute(is_muted));
  EXPECT_TRUE(is_muted);

  TEST_LOG("Muted: talk into microphone and verify you can't hear yourself.\n");
  Sleep(2000);

  // Test that we can disable system input muting.
  EXPECT_EQ(0, voe_volume_control_->SetSystemInputMute(false));
  EXPECT_EQ(0, voe_volume_control_->GetSystemInputMute(is_muted));
  EXPECT_FALSE(is_muted);

  TEST_LOG("Unmuted: talk into microphone and verify you can hear yourself.\n");
  Sleep(2000);
}

TEST_F(VolumeTest, DISABLED_ON_LINUX(SystemOutputMutingIsNotEnabledByDefault)) {
  bool is_muted = true;
  EXPECT_EQ(0, voe_volume_control_->GetSystemOutputMute(is_muted));
  EXPECT_FALSE(is_muted);
}

TEST_F(VolumeTest, ManualSystemOutputMutingMutesOutput) {
  // Enable muting.
  EXPECT_EQ(0, voe_volume_control_->SetSystemOutputMute(true));
  bool is_muted = false;
  EXPECT_EQ(0, voe_volume_control_->GetSystemOutputMute(is_muted));
  EXPECT_TRUE(is_muted);

  TEST_LOG("Muted: you should hear no audio.\n");
  Sleep(2000);

  // Test that we can disable muting.
  EXPECT_EQ(0, voe_volume_control_->SetSystemOutputMute(false));
  EXPECT_EQ(0, voe_volume_control_->GetSystemOutputMute(is_muted));
  EXPECT_FALSE(is_muted);

  TEST_LOG("Unmuted: you should hear audio.\n");
  Sleep(2000);
}

TEST_F(VolumeTest, ManualTestInputAndOutputLevels) {
  SwitchToManualMicrophone();

  TEST_LOG("Speak and verify that the following levels look right:\n");
  for (int i = 0; i < 5; i++) {
    Sleep(1000);
    unsigned int input_level = 0;
    unsigned int output_level = 0;
    unsigned int input_level_full_range = 0;
    unsigned int output_level_full_range = 0;

    EXPECT_EQ(0, voe_volume_control_->GetSpeechInputLevel(
        input_level));
    EXPECT_EQ(0, voe_volume_control_->GetSpeechOutputLevel(
        channel_, output_level));
    EXPECT_EQ(0, voe_volume_control_->GetSpeechInputLevelFullRange(
        input_level_full_range));
    EXPECT_EQ(0, voe_volume_control_->GetSpeechOutputLevelFullRange(
        channel_, output_level_full_range));

    TEST_LOG("    warped levels (0-9)    : in=%5d, out=%5d\n",
        input_level, output_level);
    TEST_LOG("    linear levels (0-32768): in=%5d, out=%5d\n",
        input_level_full_range, output_level_full_range);
  }
}

TEST_F(VolumeTest, ChannelsAreNotPannedByDefault) {
  float left = -1.0;
  float right = -1.0;

  EXPECT_EQ(0, voe_volume_control_->GetOutputVolumePan(channel_, left, right));
  EXPECT_FLOAT_EQ(1.0, left);
  EXPECT_FLOAT_EQ(1.0, right);
}

TEST_F(VolumeTest, ManualTestChannelPanning) {
  TEST_LOG("Panning left.\n");
  EXPECT_EQ(0, voe_volume_control_->SetOutputVolumePan(channel_, 0.8f, 0.1f));
  Sleep(1000);

  TEST_LOG("Back to center.\n");
  EXPECT_EQ(0, voe_volume_control_->SetOutputVolumePan(channel_, 1.0f, 1.0f));
  Sleep(1000);

  TEST_LOG("Panning right.\n");
  EXPECT_EQ(0, voe_volume_control_->SetOutputVolumePan(channel_, 0.1f, 0.8f));
  Sleep(1000);

  // To finish, verify that the getter works.
  float left = 0.0f;
  float right = 0.0f;

  EXPECT_EQ(0, voe_volume_control_->GetOutputVolumePan(channel_, left, right));
  EXPECT_FLOAT_EQ(0.1f, left);
  EXPECT_FLOAT_EQ(0.8f, right);
}
<commit_msg>Enables VolumeTest.DefaultMicrophoneVolumeIsAtMost255<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.h"

namespace {

void ExpectVolumeNear(int expected, int actual) {
  // The hardware volume may be more coarsely quantized than [0, 255], so
  // it is not always reasonable to expect to get exactly what we set. This
  // allows for some error.
  const int kMaxVolumeError = 10;
  EXPECT_NEAR(expected, actual, kMaxVolumeError);
  EXPECT_GE(actual, 0);
  EXPECT_LE(actual, 255);
}

}  // namespace

class VolumeTest : public AfterStreamingFixture {
};

// TODO(phoglund): a number of tests are disabled here on Linux, all pending
// investigation in
// http://code.google.com/p/webrtc/issues/detail?id=367

TEST_F(VolumeTest, DefaultSpeakerVolumeIsAtMost255) {
  unsigned int volume = 1000;
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(volume));
  EXPECT_LE(volume, 255u);
}

TEST_F(VolumeTest, SetVolumeBeforePlayoutWorks) {
  // This is a rather specialized test, intended to exercise some PulseAudio
  // code. However, these conditions should be satisfied on any platform.
  unsigned int original_volume = 0;
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(original_volume));
  Sleep(1000);

  EXPECT_EQ(0, voe_volume_control_->SetSpeakerVolume(200));
  unsigned int volume;
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(volume));
  ExpectVolumeNear(200u, volume);

  PausePlaying();
  ResumePlaying();
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(volume));
  // Ensure the volume has not changed after resuming playout.
  ExpectVolumeNear(200u, volume);

  PausePlaying();
  EXPECT_EQ(0, voe_volume_control_->SetSpeakerVolume(100));
  ResumePlaying();
  // Ensure the volume set while paused is retained.
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(volume));
  ExpectVolumeNear(100u, volume);

  EXPECT_EQ(0, voe_volume_control_->SetSpeakerVolume(original_volume));
}

TEST_F(VolumeTest, ManualSetVolumeWorks) {
  unsigned int original_volume = 0;
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(original_volume));
  Sleep(1000);

  TEST_LOG("Setting speaker volume to 0 out of 255.\n");
  EXPECT_EQ(0, voe_volume_control_->SetSpeakerVolume(0));
  unsigned int volume;
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(volume));
  ExpectVolumeNear(0u, volume);
  Sleep(1000);

  TEST_LOG("Setting speaker volume to 100 out of 255.\n");
  EXPECT_EQ(0, voe_volume_control_->SetSpeakerVolume(100));
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(volume));
  ExpectVolumeNear(100u, volume);
  Sleep(1000);

  // Set the volume to 255 very briefly so we don't blast the poor user
  // listening to this. This is just to test the call succeeds.
  EXPECT_EQ(0, voe_volume_control_->SetSpeakerVolume(255));
  EXPECT_EQ(0, voe_volume_control_->GetSpeakerVolume(volume));
  ExpectVolumeNear(255u, volume);

  TEST_LOG("Setting speaker volume to the original %d out of 255.\n",
      original_volume);
  EXPECT_EQ(0, voe_volume_control_->SetSpeakerVolume(original_volume));
  Sleep(1000);
}

TEST_F(VolumeTest, DefaultMicrophoneVolumeIsAtMost255) {
  unsigned int volume = 1000;
  if (voe_volume_control_->GetMicVolume(volume) == 0)
    EXPECT_LE(volume, 255u);
  else
    EXPECT_EQ(1000u, volume);
}

TEST_F(VolumeTest, DISABLED_ON_LINUX(
          ManualRequiresMicrophoneCanSetMicrophoneVolumeWithAcgOff)) {
  SwitchToManualMicrophone();
  EXPECT_EQ(0, voe_apm_->SetAgcStatus(false));

  unsigned int original_volume = 0;
  EXPECT_EQ(0, voe_volume_control_->GetMicVolume(original_volume));

  TEST_LOG("Setting microphone volume to 0.\n");
  EXPECT_EQ(0, voe_volume_control_->SetMicVolume(channel_));
  Sleep(1000);
  TEST_LOG("Setting microphone volume to 255.\n");
  EXPECT_EQ(0, voe_volume_control_->SetMicVolume(255));
  Sleep(1000);
  TEST_LOG("Setting microphone volume back to saved value.\n");
  EXPECT_EQ(0, voe_volume_control_->SetMicVolume(original_volume));
  Sleep(1000);
}

TEST_F(VolumeTest, ChannelScalingIsOneByDefault) {
  float scaling = -1.0f;

  EXPECT_EQ(0, voe_volume_control_->GetChannelOutputVolumeScaling(
      channel_, scaling));
  EXPECT_FLOAT_EQ(1.0f, scaling);
}

TEST_F(VolumeTest, ManualCanSetChannelScaling) {
  EXPECT_EQ(0, voe_volume_control_->SetChannelOutputVolumeScaling(
      channel_, 0.1f));

  float scaling = 1.0f;
  EXPECT_EQ(0, voe_volume_control_->GetChannelOutputVolumeScaling(
      channel_, scaling));

  EXPECT_FLOAT_EQ(0.1f, scaling);

  TEST_LOG("Channel scaling set to 0.1: audio should be barely audible.\n");
  Sleep(2000);
}

TEST_F(VolumeTest, InputMutingIsNotEnabledByDefault) {
  bool is_muted = true;
  EXPECT_EQ(0, voe_volume_control_->GetInputMute(channel_, is_muted));
  EXPECT_FALSE(is_muted);
}

TEST_F(VolumeTest, DISABLED_ON_LINUX(ManualInputMutingMutesMicrophone)) {
  SwitchToManualMicrophone();

  // Enable muting.
  EXPECT_EQ(0, voe_volume_control_->SetInputMute(channel_, true));
  bool is_muted = false;
  EXPECT_EQ(0, voe_volume_control_->GetInputMute(channel_, is_muted));
  EXPECT_TRUE(is_muted);

  TEST_LOG("Muted: talk into microphone and verify you can't hear yourself.\n");
  Sleep(2000);

  // Test that we can disable muting.
  EXPECT_EQ(0, voe_volume_control_->SetInputMute(channel_, false));
  EXPECT_EQ(0, voe_volume_control_->GetInputMute(channel_, is_muted));
  EXPECT_FALSE(is_muted);

  TEST_LOG("Unmuted: talk into microphone and verify you can hear yourself.\n");
  Sleep(2000);
}

TEST_F(VolumeTest, DISABLED_ON_LINUX(SystemInputMutingIsNotEnabledByDefault)) {
  bool is_muted = true;
  EXPECT_EQ(0, voe_volume_control_->GetSystemInputMute(is_muted));
  EXPECT_FALSE(is_muted);
}

TEST_F(VolumeTest, DISABLED_ON_LINUX(ManualSystemInputMutingMutesMicrophone)) {
  SwitchToManualMicrophone();

  // Enable system input muting.
  EXPECT_EQ(0, voe_volume_control_->SetSystemInputMute(true));
  bool is_muted = false;
  EXPECT_EQ(0, voe_volume_control_->GetSystemInputMute(is_muted));
  EXPECT_TRUE(is_muted);

  TEST_LOG("Muted: talk into microphone and verify you can't hear yourself.\n");
  Sleep(2000);

  // Test that we can disable system input muting.
  EXPECT_EQ(0, voe_volume_control_->SetSystemInputMute(false));
  EXPECT_EQ(0, voe_volume_control_->GetSystemInputMute(is_muted));
  EXPECT_FALSE(is_muted);

  TEST_LOG("Unmuted: talk into microphone and verify you can hear yourself.\n");
  Sleep(2000);
}

TEST_F(VolumeTest, DISABLED_ON_LINUX(SystemOutputMutingIsNotEnabledByDefault)) {
  bool is_muted = true;
  EXPECT_EQ(0, voe_volume_control_->GetSystemOutputMute(is_muted));
  EXPECT_FALSE(is_muted);
}

TEST_F(VolumeTest, ManualSystemOutputMutingMutesOutput) {
  // Enable muting.
  EXPECT_EQ(0, voe_volume_control_->SetSystemOutputMute(true));
  bool is_muted = false;
  EXPECT_EQ(0, voe_volume_control_->GetSystemOutputMute(is_muted));
  EXPECT_TRUE(is_muted);

  TEST_LOG("Muted: you should hear no audio.\n");
  Sleep(2000);

  // Test that we can disable muting.
  EXPECT_EQ(0, voe_volume_control_->SetSystemOutputMute(false));
  EXPECT_EQ(0, voe_volume_control_->GetSystemOutputMute(is_muted));
  EXPECT_FALSE(is_muted);

  TEST_LOG("Unmuted: you should hear audio.\n");
  Sleep(2000);
}

TEST_F(VolumeTest, ManualTestInputAndOutputLevels) {
  SwitchToManualMicrophone();

  TEST_LOG("Speak and verify that the following levels look right:\n");
  for (int i = 0; i < 5; i++) {
    Sleep(1000);
    unsigned int input_level = 0;
    unsigned int output_level = 0;
    unsigned int input_level_full_range = 0;
    unsigned int output_level_full_range = 0;

    EXPECT_EQ(0, voe_volume_control_->GetSpeechInputLevel(
        input_level));
    EXPECT_EQ(0, voe_volume_control_->GetSpeechOutputLevel(
        channel_, output_level));
    EXPECT_EQ(0, voe_volume_control_->GetSpeechInputLevelFullRange(
        input_level_full_range));
    EXPECT_EQ(0, voe_volume_control_->GetSpeechOutputLevelFullRange(
        channel_, output_level_full_range));

    TEST_LOG("    warped levels (0-9)    : in=%5d, out=%5d\n",
        input_level, output_level);
    TEST_LOG("    linear levels (0-32768): in=%5d, out=%5d\n",
        input_level_full_range, output_level_full_range);
  }
}

TEST_F(VolumeTest, ChannelsAreNotPannedByDefault) {
  float left = -1.0;
  float right = -1.0;

  EXPECT_EQ(0, voe_volume_control_->GetOutputVolumePan(channel_, left, right));
  EXPECT_FLOAT_EQ(1.0, left);
  EXPECT_FLOAT_EQ(1.0, right);
}

TEST_F(VolumeTest, ManualTestChannelPanning) {
  TEST_LOG("Panning left.\n");
  EXPECT_EQ(0, voe_volume_control_->SetOutputVolumePan(channel_, 0.8f, 0.1f));
  Sleep(1000);

  TEST_LOG("Back to center.\n");
  EXPECT_EQ(0, voe_volume_control_->SetOutputVolumePan(channel_, 1.0f, 1.0f));
  Sleep(1000);

  TEST_LOG("Panning right.\n");
  EXPECT_EQ(0, voe_volume_control_->SetOutputVolumePan(channel_, 0.1f, 0.8f));
  Sleep(1000);

  // To finish, verify that the getter works.
  float left = 0.0f;
  float right = 0.0f;

  EXPECT_EQ(0, voe_volume_control_->GetOutputVolumePan(channel_, left, right));
  EXPECT_FLOAT_EQ(0.1f, left);
  EXPECT_FLOAT_EQ(0.8f, right);
}
<|endoftext|>


<commit_before>/*
 Copyright (C) 2015 Vladimir "allejo" Jimenez

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

#include <sstream>

#include "bzfsAPI.h"
#include "bztoolkit/bzToolkitApi.h"

// Define plug-in name
const std::string PLUGIN_NAME = "Match Trainer Assistant";

// Define plug-in version numbering
const int MAJOR = 1;
const int MINOR = 0;
const int REV = 0;
const int BUILD = 1;

class MatchTrainerAssistant : public bz_Plugin, public bz_CustomSlashCommandHandler
{
public:
    virtual const char* Name ();
    virtual void Init (const char* config);
    virtual void Event (bz_EventData *eventData);
    virtual void Cleanup (void);

    virtual bool SlashCommand (int playerID, bz_ApiString, bz_ApiString, bz_APIStringList*);

    bool  handleSpawn[256];
    float lastDeaths[256][4];
};

BZ_PLUGIN(MatchTrainerAssistant)

const char* MatchTrainerAssistant::Name (void)
{
    static std::string pluginBuild = "";

    if (!pluginBuild.size())
    {
        std::ostringstream pluginBuildStream;

        pluginBuildStream << PLUGIN_NAME << " " << MAJOR << "." << MINOR << "." << REV << " (" << BUILD << ")";
        pluginBuild = pluginBuildStream.str();
    }

    return pluginBuild.c_str();
}

void MatchTrainerAssistant::Init (const char* commandLine)
{
    // Register our events with Register()
    Register(bz_eGetPlayerSpawnPosEvent);
    Register(bz_ePlayerDieEvent);

    // Register our custom slash commands
    bz_registerCustomSlashCommand("spawn", this);
    bz_registerCustomSlashCommand("flag", this);
    bz_registerCustomSlashCommand("die", this);
}

void MatchTrainerAssistant::Cleanup (void)
{
    Flush(); // Clean up all the events

    // Clean up our custom slash commands
    bz_removeCustomSlashCommand("spawn");
    bz_removeCustomSlashCommand("flag");
    bz_removeCustomSlashCommand("die");
}

void MatchTrainerAssistant::Event (bz_EventData *eventData)
{
    switch (eventData->eventType)
    {
        case bz_eGetPlayerSpawnPosEvent: // This event is called each time the server needs a new spawn postion
        {
            bz_GetPlayerSpawnPosEventData_V1* spawnData = (bz_GetPlayerSpawnPosEventData_V1*)eventData;

            if (handleSpawn[spawnData->playerID])
            {
                spawnData->handled = handleSpawn[spawnData->playerID];
                spawnData->pos[0]  = lastDeaths[spawnData->playerID][0];
                spawnData->pos[1]  = lastDeaths[spawnData->playerID][1];
                spawnData->pos[2]  = lastDeaths[spawnData->playerID][2];
                spawnData->rot     = lastDeaths[spawnData->playerID][3];

                handleSpawn[spawnData->playerID] = false;
            }
        }
        break;

        case bz_ePlayerDieEvent: // This event is called each time a tank is killed.
        {
            bz_PlayerDieEventData_V1* dieData = (bz_PlayerDieEventData_V1*)eventData;

            lastDeaths[dieData->playerID][0] = dieData->state.pos[0];
            lastDeaths[dieData->playerID][1] = dieData->state.pos[1];
            lastDeaths[dieData->playerID][2] = dieData->state.pos[2];
            lastDeaths[dieData->playerID][3] = dieData->state.rotation;
        }
        break;

        default: break;
    }
}

bool MatchTrainerAssistant::SlashCommand(int playerID, bz_ApiString command, bz_ApiString /*message*/, bz_APIStringList *params)
{
    std::unique_ptr<bz_BasePlayerRecord> pr(bz_getPlayerByIndex(playerID));

    if (command == "spawn")
    {
        if (pr->team == eObservers)
        {
            bz_sendTextMessage(BZ_SERVER, playerID, "Only players may execute this command.");
            return true;
        }

        if (pr->spawned)
        {
            bz_killPlayer(playerID, BZ_SERVER);
        }

        if (params->size() > 0)
        {
            if (params->size() != 1 && params->size() != 4)
            {
                bz_sendTextMessage(BZ_SERVER, playerID, "Spawn Command Usage");
                bz_sendTextMessage(BZ_SERVER, playerID, "---");
                bz_sendTextMessage(BZ_SERVER, playerID, "/spawn");
                bz_sendTextMessage(BZ_SERVER, playerID, "   - Respawn at the location of your last death");
                bz_sendTextMessage(BZ_SERVER, playerID, "/spawn <id|callsign>");
                bz_sendTextMessage(BZ_SERVER, playerID, "   - Respawn at the location of another player's location or location of death");
                bz_sendTextMessage(BZ_SERVER, playerID, "/spawn <x> <y> <z> <rotation>");
                bz_sendTextMessage(BZ_SERVER, playerID, "   - Respawn at specified location; don't spawn inside a building!");

                return true;
            }
            else if (params->size() == 1)
            {
                std::unique_ptr<bz_BasePlayerRecord> target(bz_getPlayerBySlotOrCallsign(params->get(0).c_str()));

                lastDeaths[playerID][0] = target->lastKnownState.pos[0];
                lastDeaths[playerID][1] = target->lastKnownState.pos[1];
                lastDeaths[playerID][2] = target->lastKnownState.pos[2];
                lastDeaths[playerID][3] = target->lastKnownState.rotation;
            }
            else
            {
                lastDeaths[playerID][0] = std::atoi(params->get(0).c_str());
                lastDeaths[playerID][1] = std::atoi(params->get(1).c_str());
                lastDeaths[playerID][2] = std::atoi(params->get(2).c_str());
                lastDeaths[playerID][3] = std::atoi(params->get(3).c_str());
            }
        }

        bztk_forcePlayerSpawn(playerID);
        handleSpawn[playerID] = true;

        return true;
    }
    else if (command == "flag")
    {
        bz_givePlayerFlag(playerID, bztk_getFlagFromTeam(pr->team), false);

        return false;
    }
    else if (command == "die")
    {
        bz_killPlayer(playerID, BZ_SERVER);

        return true;
    }

    return false;
}
<commit_msg>Only players can use all the commands<commit_after>/*
 Copyright (C) 2015 Vladimir "allejo" Jimenez

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

#include <sstream>

#include "bzfsAPI.h"
#include "bztoolkit/bzToolkitApi.h"

// Define plug-in name
const std::string PLUGIN_NAME = "Match Trainer Assistant";

// Define plug-in version numbering
const int MAJOR = 1;
const int MINOR = 0;
const int REV = 0;
const int BUILD = 1;

class MatchTrainerAssistant : public bz_Plugin, public bz_CustomSlashCommandHandler
{
public:
    virtual const char* Name ();
    virtual void Init (const char* config);
    virtual void Event (bz_EventData *eventData);
    virtual void Cleanup (void);

    virtual bool SlashCommand (int playerID, bz_ApiString, bz_ApiString, bz_APIStringList*);

    bool  handleSpawn[256];
    float lastDeaths[256][4];
};

BZ_PLUGIN(MatchTrainerAssistant)

const char* MatchTrainerAssistant::Name (void)
{
    static std::string pluginBuild = "";

    if (!pluginBuild.size())
    {
        std::ostringstream pluginBuildStream;

        pluginBuildStream << PLUGIN_NAME << " " << MAJOR << "." << MINOR << "." << REV << " (" << BUILD << ")";
        pluginBuild = pluginBuildStream.str();
    }

    return pluginBuild.c_str();
}

void MatchTrainerAssistant::Init (const char* commandLine)
{
    // Register our events with Register()
    Register(bz_eGetPlayerSpawnPosEvent);
    Register(bz_ePlayerDieEvent);

    // Register our custom slash commands
    bz_registerCustomSlashCommand("spawn", this);
    bz_registerCustomSlashCommand("flag", this);
    bz_registerCustomSlashCommand("die", this);
}

void MatchTrainerAssistant::Cleanup (void)
{
    Flush(); // Clean up all the events

    // Clean up our custom slash commands
    bz_removeCustomSlashCommand("spawn");
    bz_removeCustomSlashCommand("flag");
    bz_removeCustomSlashCommand("die");
}

void MatchTrainerAssistant::Event (bz_EventData *eventData)
{
    switch (eventData->eventType)
    {
        case bz_eGetPlayerSpawnPosEvent: // This event is called each time the server needs a new spawn postion
        {
            bz_GetPlayerSpawnPosEventData_V1* spawnData = (bz_GetPlayerSpawnPosEventData_V1*)eventData;

            if (handleSpawn[spawnData->playerID])
            {
                spawnData->handled = handleSpawn[spawnData->playerID];
                spawnData->pos[0]  = lastDeaths[spawnData->playerID][0];
                spawnData->pos[1]  = lastDeaths[spawnData->playerID][1];
                spawnData->pos[2]  = lastDeaths[spawnData->playerID][2];
                spawnData->rot     = lastDeaths[spawnData->playerID][3];

                handleSpawn[spawnData->playerID] = false;
            }
        }
        break;

        case bz_ePlayerDieEvent: // This event is called each time a tank is killed.
        {
            bz_PlayerDieEventData_V1* dieData = (bz_PlayerDieEventData_V1*)eventData;

            lastDeaths[dieData->playerID][0] = dieData->state.pos[0];
            lastDeaths[dieData->playerID][1] = dieData->state.pos[1];
            lastDeaths[dieData->playerID][2] = dieData->state.pos[2];
            lastDeaths[dieData->playerID][3] = dieData->state.rotation;
        }
        break;

        default: break;
    }
}

bool MatchTrainerAssistant::SlashCommand(int playerID, bz_ApiString command, bz_ApiString /*message*/, bz_APIStringList *params)
{
    std::unique_ptr<bz_BasePlayerRecord> pr(bz_getPlayerByIndex(playerID));

    if (pr->team == eObservers)
    {
        bz_sendTextMessage(BZ_SERVER, playerID, "These commands are intended for players only.");

        return true;
    }

    if (command == "spawn")
    {
        if (pr->spawned)
        {
            bz_killPlayer(playerID, BZ_SERVER);
        }

        if (params->size() > 0)
        {
            if (params->size() != 1 && params->size() != 4)
            {
                bz_sendTextMessage(BZ_SERVER, playerID, "Spawn Command Usage");
                bz_sendTextMessage(BZ_SERVER, playerID, "---");
                bz_sendTextMessage(BZ_SERVER, playerID, "/spawn");
                bz_sendTextMessage(BZ_SERVER, playerID, "   - Respawn at the location of your last death");
                bz_sendTextMessage(BZ_SERVER, playerID, "/spawn <id|callsign>");
                bz_sendTextMessage(BZ_SERVER, playerID, "   - Respawn at the location of another player's location or location of death");
                bz_sendTextMessage(BZ_SERVER, playerID, "/spawn <x> <y> <z> <rotation>");
                bz_sendTextMessage(BZ_SERVER, playerID, "   - Respawn at specified location; don't spawn inside a building!");

                return true;
            }
            else if (params->size() == 1)
            {
                std::unique_ptr<bz_BasePlayerRecord> target(bz_getPlayerBySlotOrCallsign(params->get(0).c_str()));

                lastDeaths[playerID][0] = target->lastKnownState.pos[0];
                lastDeaths[playerID][1] = target->lastKnownState.pos[1];
                lastDeaths[playerID][2] = target->lastKnownState.pos[2];
                lastDeaths[playerID][3] = target->lastKnownState.rotation;
            }
            else
            {
                lastDeaths[playerID][0] = std::atoi(params->get(0).c_str());
                lastDeaths[playerID][1] = std::atoi(params->get(1).c_str());
                lastDeaths[playerID][2] = std::atoi(params->get(2).c_str());
                lastDeaths[playerID][3] = std::atoi(params->get(3).c_str());
            }
        }

        bztk_forcePlayerSpawn(playerID);
        handleSpawn[playerID] = true;

        return true;
    }
    else if (command == "flag")
    {
        bz_givePlayerFlag(playerID, bztk_getFlagFromTeam(pr->team), false);

        return false;
    }
    else if (command == "die")
    {
        bz_killPlayer(playerID, BZ_SERVER);

        return true;
    }

    return false;
}
<|endoftext|>


<commit_before>#include "FuzzyLogic.h"
#include "InputFuzzySetTriangular.h"
#include "InputFuzzySetTrapezoidal.h"
#include "OutputFuzzySetTriangular.h"
#include "OutputFuzzySetTrapezoidal.h"
#include <unittest++/UnitTest++.h>
#include <iostream>

using namespace std;

SUITE(FuzzyEngine)
{
  TEST(mbs_InputFuzzySetTriangular)
  {
    cout << "-- InputFuzzySetTriangular mbs" << endl;
    InputFuzzySetTriangular ifz("Test", 5, 10, 15);
    ifz.setInput(2.5);
    CHECK_EQUAL(0.0, ifz.getMbs());
    ifz.setInput(7.5);
    CHECK_EQUAL(0.5, ifz.getMbs());
    ifz.setInput(12.5);
    CHECK_EQUAL(0.5, ifz.getMbs());
    ifz.setInput(15.0);
    CHECK_EQUAL(0.0, ifz.getMbs());
    ifz.setInput(17.5);
    CHECK_EQUAL(0.0, ifz.getMbs());
    cout << endl;
  }

  TEST(mbs_InputFuzzySetTrapezoidal)
  {
    cout << "-- InputFuzzySetTrapezoidal mbs" << endl;
    InputFuzzySetTrapezoidal ifz("Test", 0, 5, 10, 15);
    ifz.setInput(2.5);
    CHECK_EQUAL(0.5, ifz.getMbs());
    ifz.setInput(7.5);
    CHECK_EQUAL(1.0, ifz.getMbs());
    ifz.setInput(12.5);
    CHECK_EQUAL(0.5, ifz.getMbs());
    ifz.setInput(-5);
    CHECK_EQUAL(0.0, ifz.getMbs());
    cout << endl;
  }

  TEST(MOMsym_OutputFuzzySetTriangular)
  {
    cout << "-- OutputFuzzySetTriangular symmetrical MOM" << endl;
    OutputFuzzySetTriangular ofz("Test", 0, 5, 10);
    ofz.setMbs(0.5);
    CHECK_EQUAL(5.0, ofz.meanOfMaximum());
    ofz.setMbs(0.1);
    CHECK_EQUAL(5.0, ofz.meanOfMaximum());
    cout << endl;
  }

  TEST(MOM_OutputFuzzySetTriangular)
  {
    cout << "-- OutputFuzzySetTriangular not symmetrical MOM" << endl;
    OutputFuzzySetTriangular ofz("Test", 0, 10, 30);
    ofz.setMbs(0.5);
    CHECK_EQUAL(25.0 / 2, ofz.meanOfMaximum());
    cout << endl;
  }

  TEST(MOMsym_OutputFuzzySetTrapezoidal)
  {
    cout << "-- OutputFuzzySetTrapezoidal symmetrical MOM" << endl;
    OutputFuzzySetTrapezoidal ifz("Test", 0, 5, 10, 15);
    ifz.setMbs(0.5);
    CHECK_EQUAL(7.5, ifz.meanOfMaximum());
    ifz.setMbs(0.1);
    CHECK_EQUAL(7.5, ifz.meanOfMaximum());
    cout << endl;
  }

  TEST(MOM_OutputFuzzySetTrapezoidal)
  {
    cout << "-- OutputFuzzySetTrapezoidal not symmetrical MOM" << endl;
    OutputFuzzySetTrapezoidal ifz("Test", 0, 10, 20, 40);
    ifz.setMbs(0.5);
    CHECK_EQUAL(35.0 / 2, ifz.meanOfMaximum());
    cout << endl;
  }

  TEST(FuzzyLogic_or)
  {
    cout << "-- Fuzzy logic OR" << endl;
    InputFuzzySetTriangular ifz1("Test", 5, 10, 15);
    InputFuzzySetTriangular ifz2("Test", 10, 15, 20);
    OutputFuzzySetTriangular ofz("Test", 0, 5, 10);
    ifz1.setInput(12.5);
    ifz2.setInput(12.5);
    ofz = ifz1 or ifz2;
    CHECK_EQUAL(0.5, ofz.getMbs());
    cout << endl;
  }

  TEST(FuzzyLogic_and)
  {
    cout << "-- Fuzzy logic AND" << endl;
    InputFuzzySetTriangular ifz1("Test", 5, 10, 15);
    InputFuzzySetTriangular ifz2("Test", 10, 15, 20);
    OutputFuzzySetTriangular ofz("Test", 0, 5, 10);
    ifz1.setInput(10);
    ifz2.setInput(10);
    ofz = ifz1 and ifz2;
    CHECK_EQUAL(0, ofz.getMbs());
    cout << endl;
  }

  TEST(FuzzyLogic_not)
  {
    cout << "-- Fuzzy logic NOT" << endl;
    InputFuzzySetTriangular ifz1("Test", 5, 10, 15);
    InputFuzzySetTriangular ifz2("Test", 10, 15, 20);
    OutputFuzzySetTriangular ofz("Test", 0, 5, 10);
    ifz1.setInput(12.5);
    ifz2.setInput(12.5);
    ofz = not(ifz1 or ifz2);
    CHECK_EQUAL(0.5, ofz.getMbs());
    cout << endl;
  }

}

int main()
{
  auto result = UnitTest::RunAllTests();
  cout << endl;
  return result;
}
<commit_msg>More fuzzy logic not tests.<commit_after>#include "FuzzyLogic.h"
#include "InputFuzzySetTriangular.h"
#include "InputFuzzySetTrapezoidal.h"
#include "OutputFuzzySetTriangular.h"
#include "OutputFuzzySetTrapezoidal.h"
#include <unittest++/UnitTest++.h>
#include <iostream>

using namespace std;

SUITE(FuzzyEngine)
{
  TEST(mbs_InputFuzzySetTriangular)
  {
    cout << "-- InputFuzzySetTriangular mbs" << endl;
    InputFuzzySetTriangular ifz("Test", 5, 10, 15);

    ifz.setInput(2.5);
    CHECK_EQUAL(0.0, ifz.getMbs());
    ifz.setInput(7.5);
    CHECK_EQUAL(0.5, ifz.getMbs());
    ifz.setInput(12.5);
    CHECK_EQUAL(0.5, ifz.getMbs());
    ifz.setInput(15.0);
    CHECK_EQUAL(0.0, ifz.getMbs());
    ifz.setInput(17.5);
    CHECK_EQUAL(0.0, ifz.getMbs());
    cout << endl;
  }

  TEST(mbs_InputFuzzySetTrapezoidal)
  {
    cout << "-- InputFuzzySetTrapezoidal mbs" << endl;
    InputFuzzySetTrapezoidal ifz("Test", 0, 5, 10, 15);

    ifz.setInput(2.5);
    CHECK_EQUAL(0.5, ifz.getMbs());
    ifz.setInput(7.5);
    CHECK_EQUAL(1.0, ifz.getMbs());
    ifz.setInput(12.5);
    CHECK_EQUAL(0.5, ifz.getMbs());
    ifz.setInput(-5);
    CHECK_EQUAL(0.0, ifz.getMbs());
    cout << endl;
  }

  TEST(MOMsym_OutputFuzzySetTriangular)
  {
    cout << "-- OutputFuzzySetTriangular symmetrical MOM" << endl;
    OutputFuzzySetTriangular ofz("Test", 0, 5, 10);

    ofz.setMbs(0.5);
    CHECK_EQUAL(5.0, ofz.meanOfMaximum());
    ofz.setMbs(0.1);
    CHECK_EQUAL(5.0, ofz.meanOfMaximum());
    cout << endl;
  }

  TEST(MOM_OutputFuzzySetTriangular)
  {
    cout << "-- OutputFuzzySetTriangular not symmetrical MOM" << endl;
    OutputFuzzySetTriangular ofz("Test", 0, 10, 30);

    ofz.setMbs(0.5);
    CHECK_EQUAL(25.0 / 2, ofz.meanOfMaximum());
    cout << endl;
  }

  TEST(MOMsym_OutputFuzzySetTrapezoidal)
  {
    cout << "-- OutputFuzzySetTrapezoidal symmetrical MOM" << endl;
    OutputFuzzySetTrapezoidal ifz("Test", 0, 5, 10, 15);

    ifz.setMbs(0.5);
    CHECK_EQUAL(7.5, ifz.meanOfMaximum());
    ifz.setMbs(0.1);
    CHECK_EQUAL(7.5, ifz.meanOfMaximum());
    cout << endl;
  }

  TEST(MOM_OutputFuzzySetTrapezoidal)
  {
    cout << "-- OutputFuzzySetTrapezoidal not symmetrical MOM" << endl;
    OutputFuzzySetTrapezoidal ifz("Test", 0, 10, 20, 40);

    ifz.setMbs(0.5);
    CHECK_EQUAL(35.0 / 2, ifz.meanOfMaximum());
    cout << endl;
  }

  TEST(FuzzyLogic_or)
  {
    cout << "-- Fuzzy logic OR" << endl;
    InputFuzzySetTriangular ifz1("Test", 5, 10, 15);
    InputFuzzySetTriangular ifz2("Test", 10, 15, 20);
    OutputFuzzySetTriangular ofz("Test", 0, 5, 10);

    ifz1.setInput(12.5);
    ifz2.setInput(12.5);
    ofz = ifz1 or ifz2;
    CHECK_EQUAL(0.5, ofz.getMbs());
    cout << endl;
  }

  TEST(FuzzyLogic_and)
  {
    cout << "-- Fuzzy logic AND" << endl;
    InputFuzzySetTriangular ifz1("Test", 5, 10, 15);
    InputFuzzySetTriangular ifz2("Test", 10, 15, 20);
    OutputFuzzySetTriangular ofz("Test", 0, 5, 10);

    ifz1.setInput(10);
    ifz2.setInput(10);
    ofz = ifz1 and ifz2;
    CHECK_EQUAL(0, ofz.getMbs());
    cout << endl;
  }

  TEST(FuzzyLogic_not)
  {
    cout << "-- Fuzzy logic NOT" << endl;
    InputFuzzySetTriangular ifz("Test", 5, 10, 15);
    OutputFuzzySetTriangular ofz("Test", 0, 5, 10);

    ifz.setInput(13.75);
    ofz = not ifz;
    CHECK_EQUAL(0.75, ofz.getMbs());

    ifz.setInput(20);
    ofz = not ifz;
    CHECK_EQUAL(1.0, ofz.getMbs());
    cout << endl;
  }

}

int main()
{
  auto result = UnitTest::RunAllTests();
  cout << endl;
  return result;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2010, 2011 Esrille Inc.
 *
 * 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 "U16InputStream.h"

#include <assert.h>
#include <string.h>

#include <unicode/ucnv.h>

#include <algorithm>

const char* U16InputStream::DefaultEncoding = "windows-1252";

namespace {

struct Override
{
    const char* input;
    const char* replacement;
};

Override overrides[] = {
    { "euc-kr", "windows-949" },
    { "gb2312", "gbk" },
    { "gb_2312-80", "gbk" },
    { "iso-8859-1", "windows-1252" },
    { "iso-8859-9", "windows-1254" },
    { "iso-8859-11", "windows-874" },
    { "ks_c_5601-1987", "windows-949" },
    { "shift_jis", "windows-31j" },
    { "tis-620", "windows-874" },
    { "us-ascii", "windows-1252" }
};

}  // namespace

U16InputStream::U16InputStream(std::istream& stream, const std::string optionalEncoding) :
    confidence(Certain),
    stream(stream)
{
    initializeConverter();
    encoding = checkEncoding(optionalEncoding);
}

U16InputStream::~U16InputStream()
{
    if (converter)
        ucnv_close(converter);
}

const char* U16InputStream::skipSpace(const char* p)
{
    while (*p) {
        if (strchr(" \t\r\n\f", *p) == 0)
            return p;
        ++p;
    }
    return p;
};

const char* U16InputStream::skipOver(const char* p, const char* target, size_t length)
{
    while (*p) {
        if (strncmp(p, target, length) == 0)
            return p + length;
        ++p;
    }
    return p;
};

void U16InputStream::detect(const char* p)
{
    if (strncmp(p, "\xfe\xff", 2) == 0) {
        encoding = "utf-16be";
        return;
    }
    if (strncmp(p, "\xff\xfe", 2) == 0) {
        encoding = "utf-16le";
        return;
    }
    if (strncmp(p, "\xef\xbb\xbf", 3) == 0) {
        encoding = "utf-8";
        return;
    }
    encoding = "";
}

std::string U16InputStream::checkEncoding(std::string value)
{
    // Remove any leading or trailing space characters
    std::string::iterator i = value.begin();
    while (i < value.end() && strchr("\t\n\f\r ", *i))
        ++i;
    value.erase(value.begin(), i);
    int j;
    for (j = value.length(); 0 < j && strchr("\t\n\f\r ", value[j - 1]); --j)
        ;
    value.erase(j, value.length());

    if (value.empty())
        return "";

    // Override character encoding
    for (Override* override = overrides;
         override < &overrides[sizeof overrides / sizeof overrides[0]];
         ++override) {
        if (!strcasecmp(value.c_str(), override->input)) {
            value = override->replacement;
            break;
        }
    }
    return value;
}

void U16InputStream::setEncoding(std::string value)
{
    value = checkEncoding(value);
    if (value.empty())
        value = DefaultEncoding;

    // Re-check encoding with ICU for conversion
    UErrorCode error = U_ZERO_ERROR;
    converter = ucnv_open(value.c_str(), &error);
    if (!converter) {
        value = DefaultEncoding;
        converter = ucnv_open(value.c_str(), &error);
        if (!converter)
            eof = true;
    }
    encoding = value;
}

void U16InputStream::initializeConverter()
{
    flush = false;
    eof = !stream;
    converter = 0;
    source = sourceLimit = sourceBuffer;
    target = targetBuffer;
    nextChar = target;
    lastChar = 0;
}

void U16InputStream::updateSource()
{
    assert(!flush);
    size_t count = sourceLimit - source;
    if (0 < count && sourceBuffer != source)
        memmove(sourceBuffer, source, count);
    source = sourceBuffer;
    sourceLimit = sourceBuffer + count;
    count = ChunkSize - count;
    if (0 < count) {
        stream.read(sourceLimit, count);
        count = stream.gcount();
        if (!converter) {
            if (encoding.empty()) {
                sourceLimit[count] = '\0';
                detect(sourceLimit);
            }
            setEncoding(encoding);
        }
        sourceLimit += count;
        if (count == 0)
            flush = true;
    }
}

void U16InputStream::readChunk()
{
    nextChar = target = targetBuffer;
    updateSource();
    UErrorCode err = U_ZERO_ERROR;
    ucnv_toUnicode(converter,
                   reinterpret_cast<UChar**>(&target),
                   reinterpret_cast<UChar*>(targetBuffer) + ChunkSize,
                   const_cast<const char**>(&source),
                   sourceLimit, 0, flush, &err);
}

U16InputStream::operator std::u16string()
{
    std::u16string text;
    char16_t c;
    while (getChar(c))
        text += c;
    return text;
}<commit_msg>(overrides) : Update the list.<commit_after>/*
 * Copyright 2010, 2011 Esrille Inc.
 *
 * 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 "U16InputStream.h"

#include <assert.h>
#include <string.h>

#include <unicode/ucnv.h>

#include <algorithm>

const char* U16InputStream::DefaultEncoding = "windows-1252";

namespace {

struct Override
{
    const char* input;
    const char* replacement;
};

// cf. HTML Living Standard 13.2.2.2 Character encodings
Override overrides[] = {
    { "euc-kr", "windows-949" },
    { "euc-jp", "cp51932" },
    { "gb2312", "gbk" },
    { "gb_2312-80", "gbk" },
    { "iso-2022-jp", "cp50220" },
    { "iso-8859-1", "windows-1252" },
    { "iso-8859-9", "windows-1254" },
    { "iso-8859-11", "windows-874" },
    { "ks_c_5601-1987", "windows-949" },
    { "shift_jis", "windows-31j" },
    { "tis-620", "windows-874" },
    { "us-ascii", "windows-1252" }
};

}  // namespace

U16InputStream::U16InputStream(std::istream& stream, const std::string optionalEncoding) :
    confidence(Certain),
    stream(stream)
{
    initializeConverter();
    encoding = checkEncoding(optionalEncoding);
}

U16InputStream::~U16InputStream()
{
    if (converter)
        ucnv_close(converter);
}

const char* U16InputStream::skipSpace(const char* p)
{
    while (*p) {
        if (strchr(" \t\r\n\f", *p) == 0)
            return p;
        ++p;
    }
    return p;
};

const char* U16InputStream::skipOver(const char* p, const char* target, size_t length)
{
    while (*p) {
        if (strncmp(p, target, length) == 0)
            return p + length;
        ++p;
    }
    return p;
};

void U16InputStream::detect(const char* p)
{
    if (strncmp(p, "\xfe\xff", 2) == 0) {
        encoding = "utf-16be";
        return;
    }
    if (strncmp(p, "\xff\xfe", 2) == 0) {
        encoding = "utf-16le";
        return;
    }
    if (strncmp(p, "\xef\xbb\xbf", 3) == 0) {
        encoding = "utf-8";
        return;
    }
    encoding = "";
}

std::string U16InputStream::checkEncoding(std::string value)
{
    // Remove any leading or trailing space characters
    std::string::iterator i = value.begin();
    while (i < value.end() && strchr("\t\n\f\r ", *i))
        ++i;
    value.erase(value.begin(), i);
    int j;
    for (j = value.length(); 0 < j && strchr("\t\n\f\r ", value[j - 1]); --j)
        ;
    value.erase(j, value.length());

    if (value.empty())
        return "";

    // Override character encoding
    for (Override* override = overrides;
         override < &overrides[sizeof overrides / sizeof overrides[0]];
         ++override) {
        if (!strcasecmp(value.c_str(), override->input)) {
            value = override->replacement;
            break;
        }
    }
    return value;
}

void U16InputStream::setEncoding(std::string value)
{
    value = checkEncoding(value);
    if (value.empty())
        value = DefaultEncoding;

    // Re-check encoding with ICU for conversion
    UErrorCode error = U_ZERO_ERROR;
    converter = ucnv_open(value.c_str(), &error);
    if (!converter) {
        value = DefaultEncoding;
        converter = ucnv_open(value.c_str(), &error);
        if (!converter)
            eof = true;
    }
    encoding = value;
}

void U16InputStream::initializeConverter()
{
    flush = false;
    eof = !stream;
    converter = 0;
    source = sourceLimit = sourceBuffer;
    target = targetBuffer;
    nextChar = target;
    lastChar = 0;
}

void U16InputStream::updateSource()
{
    assert(!flush);
    size_t count = sourceLimit - source;
    if (0 < count && sourceBuffer != source)
        memmove(sourceBuffer, source, count);
    source = sourceBuffer;
    sourceLimit = sourceBuffer + count;
    count = ChunkSize - count;
    if (0 < count) {
        stream.read(sourceLimit, count);
        count = stream.gcount();
        if (!converter) {
            if (encoding.empty()) {
                sourceLimit[count] = '\0';
                detect(sourceLimit);
            }
            setEncoding(encoding);
        }
        sourceLimit += count;
        if (count == 0)
            flush = true;
    }
}

void U16InputStream::readChunk()
{
    nextChar = target = targetBuffer;
    updateSource();
    UErrorCode err = U_ZERO_ERROR;
    ucnv_toUnicode(converter,
                   reinterpret_cast<UChar**>(&target),
                   reinterpret_cast<UChar*>(targetBuffer) + ChunkSize,
                   const_cast<const char**>(&source),
                   sourceLimit, 0, flush, &err);
}

U16InputStream::operator std::u16string()
{
    std::u16string text;
    char16_t c;
    while (getChar(c))
        text += c;
    return text;
}<|endoftext|>


<commit_before>///
/// @file  BitSieve.hpp
/// @brief The BitSieve class is a bit array for prime sieving
///        that packs 64 numbers into 8 bytes i.e. each bit
///        corresponds to one integer.
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef BITSIEVE_HPP
#define BITSIEVE_HPP

#include <cassert>
#include <cstddef>
#include <vector>
#include <stdint.h>

namespace primecount {

class BitSieve
{
public:
  BitSieve(std::size_t size);

  /// Pre-sieve the multiples (>= low) of the first c primes.
  /// @param sieve_primes true  to cross-off multiples,
  ///                     false to cross-off multiples and primes.
  /// @pre c < 10
  ///
  void pre_sieve(uint64_t c,
                 uint64_t low,
                 bool sieve_primes = false);

  /// Count the number of 1 bits inside [start, stop]
  uint64_t count(uint64_t start,
                 uint64_t stop) const;

  /// Count the number of 1 bits inside [0, stop]
  uint64_t count(uint64_t stop) const
  {
    return count(0, stop);
  }

  /// Count the number of 1 bits inside [start, stop].
  /// As an optimization this method counts either forwards or
  /// backwards depending on what's faster.
  ///
  uint64_t count(uint64_t start,
                 uint64_t stop,
                 uint64_t low,
                 uint64_t high,
                 uint64_t count_0_start,
                 uint64_t count_low_high) const
  {
    if (start > stop)
      return 0;

    if (stop - start < high - low - stop)
      return count(start, stop);
    else
      // optimization, same as count(start, stop)
      return count_low_high - count_0_start - count(stop + 1, (high - 1) - low);
  }

  bool operator[](uint64_t pos) const
  {
    assert(pos < size_);
    return (sieve_[pos >> 6] >> (pos & 63)) & 1;
  }

  void set(uint64_t pos)
  {
    assert(pos < size_);
    sieve_[pos >> 6] |= ((uint64_t) 1) << (pos & 63);
  }

  void unset(uint64_t pos)
  {
    assert(pos < size_);
    sieve_[pos >> 6] &= unset_bit_[pos & 63];
  }

  std::size_t size() const
  {
    return size_;
  }
private:
  static const uint64_t unset_bit_[64];
  std::vector<uint64_t> sieve_;
  std::size_t size_;
};

} // namespace

#endif
<commit_msg>Refactoring<commit_after>///
/// @file  BitSieve.hpp
/// @brief The BitSieve class is a bit array for prime sieving
///        that packs 64 numbers into 8 bytes i.e. each bit
///        corresponds to one integer.
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef BITSIEVE_HPP
#define BITSIEVE_HPP

#include <cassert>
#include <cstddef>
#include <vector>
#include <stdint.h>

namespace primecount {

class BitSieve
{
public:
  BitSieve(std::size_t size);

  /// Pre-sieve the multiples (>= low) of the first c primes.
  /// @param sieve_primes true  to cross-off multiples,
  ///                     false to cross-off multiples and primes.
  /// @pre c < 10
  ///
  void pre_sieve(uint64_t c,
                 uint64_t low,
                 bool sieve_primes = false);

  /// Count the number of 1 bits inside [start, stop]
  uint64_t count(uint64_t start,
                 uint64_t stop) const;

  /// Count the number of 1 bits inside [0, stop]
  uint64_t count(uint64_t stop) const
  {
    return count(0, stop);
  }

  /// Count the number of 1 bits inside [start, stop].
  /// As an optimization this method counts either forwards or
  /// backwards depending on what's faster.
  ///
  uint64_t count(uint64_t start,
                 uint64_t stop,
                 uint64_t low,
                 uint64_t high,
                 uint64_t count_0_start,
                 uint64_t count_low_high) const
  {
    if (start > stop)
      return 0;

    if (stop - start < high - low - stop)
      return count(start, stop);
    else
      // optimization, same as count(start, stop)
      return count_low_high - count_0_start - count(stop + 1, (high - 1) - low);
  }

  void set(uint64_t pos)
  {
    assert(pos < size_);
    sieve_[pos >> 6] |= ((uint64_t) 1) << (pos & 63);
  }

  void unset(uint64_t pos)
  {
    assert(pos < size_);
    sieve_[pos >> 6] &= unset_bit_[pos & 63];
  }

  bool operator[](uint64_t pos) const
  {
    assert(pos < size_);
    return (sieve_[pos >> 6] >> (pos & 63)) & 1;
  }

  std::size_t size() const
  {
    return size_;
  }
private:
  static const uint64_t unset_bit_[64];
  std::vector<uint64_t> sieve_;
  std::size_t size_;
};

} // namespace

#endif
<|endoftext|>


<commit_before>// Copyright 2012 Alessio Sclocco <a.sclocco@vu.nl>
//
// 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 <fstream>
#include <vector>
#include <string>
#include <cmath>
#include <exception>
#include <H5Cpp.h>
#include <dada_hdu.h>
#include <ascii_header.h>

#include <Observation.hpp>
#include <utils.hpp>

#ifndef READ_DATA_HPP
#define READ_DATA_HPP

namespace AstroData {

// Exception: the PSRDada ring buffer does not work
class RingBufferError : public std::exception {
public:
  RingBufferError();
  ~RingBufferError() throw ();

  const char * what() const throw ();
};

template< typename T > void readSIGPROC(const Observation & observation, const uint8_t inputBits, const unsigned int bytesToSkip, const std::string & inputFilename, std::vector< std::vector< T > * > & data, const unsigned int firstSecond = 0);
template< typename T > void readLOFAR(std::string headerFilename, std::string rawFilename, Observation & observation, std::vector< std::vector< T > * > & data, unsigned int nrSeconds = 0, unsigned int firstSecond = 0);
template< typename T > void readPSRDadaHeader(Observation & observation, dada_hdu_t & ringBuffer) throw(RingBufferError);
template< typename T > inline void readPSRDada(Observation & observation, dada_hdu_t & ringBuffer, std::vector< T > * data) throw(RingBufferError);

// Implementation

template< typename T > void readSIGPROC(const Observation & observation, const uint8_t inputBits, const unsigned int bytesToSkip, const std::string & inputFilename, std::vector< std::vector< T > * > & data, const unsigned int firstSecond = 0) {
	std::ifstream inputFile;
	const unsigned int BUFFER_DIM = sizeof(T);
	char * buffer = new char [BUFFER_DIM];

	inputFile.open(inputFilename.c_str(), std::ios::binary);
	inputFile.sync_with_stdio(false);
	inputFile.seekg(bytesToSkip, std::ios::beg);
	for ( unsigned int second = 0; second < observation.getNrSeconds(); second++ ) {
    if ( inputBits >= 8 ) {
      data.at(second) = new std::vector< T >(observation.getNrChannels() * observation.getNrSamplesPerPaddedSecond());
      for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
        for ( unsigned int channel = observation.getNrChannels(); channel > 0; channel-- ) {
          inputFile.read(buffer, BUFFER_DIM);
          data.at(second)->at((static_cast< uint64_t >(channel - 1) * observation.getNrSamplesPerPaddedSecond()) + sample) = *(reinterpret_cast< T * >(buffer));
        }
      }
    } else {
      data.at(second) = new std::vector< T >(observation.getNrChannels() * isa::utils::pad(observation.getNrSamplesPerSecond() / (8 / inputBits), observation.getPadding()));
      for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
        unsigned int sampleByte = sample / (8 / inputBits);
        uint8_t sampleFirstBit = (sample % (8 / inputBits)) * inputBits;

        for ( int channel = observation.getNrChannels(); channel > 0; channel -= (8 / inputBits) ) {
          inputFile.read(buffer, BUFFER_DIM);
          for ( unsigned int item = 0; item < (8 / inputBits); item++ ) {
            uint8_t channelFirstBit = item * inputBits;
            uint8_t sampleBuffer = 0;

            if ( (channel - 1) - item >= observation.getNrChannels() ) {
              break;
            }
            sampleBuffer = data.at(second)->at((static_cast< uint64_t >((channel - 1) - item) * isa::utils::pad(observation.getNrSamplesPerSecond() / (8 / inputBits), observation.getPadding())) + sampleByte);
            for ( uint8_t bit = 0; bit < inputBits; bit++ ) {
              isa::utils::setBit(sampleBuffer, isa::utils::getBit(*buffer, channelFirstBit + bit), sampleFirstBit + bit);
            }
            data.at(second)->at((static_cast< uint64_t >((channel - 1) - item) * isa::utils::pad(observation.getNrSamplesPerSecond() / (8 / inputBits), observation.getPadding())) + sampleByte) = sampleBuffer;
          }
        }
      }
    }
	}
	inputFile.close();

	delete [] buffer;
}

template< typename T > void readLOFAR(std::string headerFilename, std::string rawFilename, Observation & observation, std::vector< std::vector< T > * > & data, unsigned int nrSeconds, unsigned int firstSecond) {
  unsigned int nrSubbands, nrChannels;
  float minFreq, channelBandwidth;
	// Read the HDF5 file with the metadata
	H5::H5File headerFile = H5::H5File(headerFilename, H5F_ACC_RDONLY);
	H5::FloatType typeDouble = H5::FloatType(H5::PredType::NATIVE_DOUBLE);
	double valueDouble = 0.0;
	H5::IntType typeUInt = H5::IntType(H5::PredType::NATIVE_UINT);
	unsigned int valueUInt = 0;

	H5::Group currentNode = headerFile.openGroup("/");
	currentNode.openAttribute("OBSERVATION_FREQUENCY_MIN").read(typeDouble, reinterpret_cast< void * >(&valueDouble));
  minFreq = valueDouble;
	currentNode = currentNode.openGroup(currentNode.getObjnameByIdx(0));
	currentNode.openAttribute("TOTAL_INTEGRATION_TIME").read(typeDouble, reinterpret_cast< void * >(&valueDouble));
	double totalIntegrationTime = valueDouble;
	currentNode.openAttribute("NOF_BEAMS").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	observation.setNrBeams(valueUInt);
	currentNode = currentNode.openGroup(currentNode.getObjnameByIdx(0));
	currentNode.openAttribute("NOF_SAMPLES").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	unsigned int totalSamples = valueUInt;
	currentNode.openAttribute("NOF_STATIONS").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	observation.setNrStations(valueUInt);
	currentNode.openAttribute("CHANNELS_PER_SUBBAND").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	nrChannels = valueUInt;
	currentNode.openAttribute("CHANNEL_WIDTH").read(typeDouble, reinterpret_cast< void * >(&valueDouble));
  channelBandwidth = valueDouble / 1000000;
	H5::DataSet currentData = currentNode.openDataSet("STOKES_0");
	currentData.openAttribute("NOF_SUBBANDS").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	nrSubbands = valueUInt;
	headerFile.close();

	observation.setNrSamplesPerSecond(static_cast< unsigned int >(totalSamples / totalIntegrationTime));
	if ( nrSeconds == 0 ) {
		observation.setNrSeconds(static_cast< unsigned int >(totalIntegrationTime));
	} else {
		if ( static_cast< unsigned int >(totalIntegrationTime) >= (firstSecond + nrSeconds) ) {
			observation.setNrSeconds(nrSeconds);
		} else {
			observation.setNrSeconds(static_cast< unsigned int >(totalIntegrationTime) - firstSecond);
		}
	}
  observation.setFrequencyRange(nrSubbands * nrChannels, minFreq, channelBandwidth);

	// Read the raw file with the actual data
	std::ifstream rawFile;
	rawFile.open(rawFilename.c_str(), std::ios::binary);
	rawFile.sync_with_stdio(false);
	if ( firstSecond > 0 ) {
		rawFile.seekg(firstSecond * observation.getNrSamplesPerSecond() * nrSubbands * nrChannels, std::ios::beg);
	}
	data.resize(observation.getNrSeconds());

	char * word = new char [4];
	for ( unsigned int second = 0; second < observation.getNrSeconds(); second++ ) {
		data.at(second) = new std::vector< T >(observation.getNrChannels() * observation.getNrSamplesPerPaddedSecond());
		for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
			for ( unsigned int subband = 0; subband < nrSubbands; subband++ ) {
				for ( unsigned int channel = 0; channel < nrChannels; channel++ ) {
          unsigned int globalChannel = (subband * nrChannels) + channel;

					rawFile.read(word, 4);
          isa::utils::bigEndianToLittleEndian(word);
          data.at(second)->at((globalChannel * observation.getNrSamplesPerPaddedSecond()) + sample) = *(reinterpret_cast< T * >(word));
				}
			}
		}
	}
	rawFile.close();
	delete [] word;
}

template< typename T > void readPSRDadaHeader(Observation & observation, dada_hdu_t & ringBuffer) throw(RingBufferError) {
  // Staging variables for the header elements
  unsigned int uintValue = 0;
  float floatValue[2] = {0.0f, 0.0f};
  // Header string
  uint64_t headerBytes = 0;
  char * header = 0;

  header = ipcbuf_get_next_read(ringBuffer.header_block, &headerBytes);

  if ( (header == 0) || (headerBytes == 0 ) ) {
    throw RingBufferError();
  }

  ascii_header_get(header, "SAMPLES_PER_SECOND", "%d", &uintValue);
  observation.setNrSamplesPerSecond(uintValue);
  ascii_header_get(header, "CHANNELS", "%d", &uintValue);
  ascii_header_get(header, "MIN_FREQUENCY", "%f", &floatValue[0]);
  ascii_header_get(header, "CHANNEL_BANDWIDTH", "%f", &floatValue[1]);
  observation.setFrequencyRange(uintValue, floatValue[0], floatValue[1]);
  ipcbuf_mark_cleared(ringBuffer.header_block);

  delete header;
}

template< typename T > inline void readPSRDada(Observation & observation, dada_hdu_t & ringBuffer, std::vector< T > * data) throw(RingBufferError) {
  if ( (ipcio_read(ringBuffer.data_block, reinterpret_cast< char * >(data->data()), observation.getNrChannels() * observation.getNrSamplesPerPaddedSecond() * sizeof(T))) < 0 ) {
    throw RingBufferError();
  }
}

} // AstroData

#endif // READ_DATA_HPP

<commit_msg>Fixing a bug in the SIGPROC reader when samples < 8 bits.<commit_after>// Copyright 2012 Alessio Sclocco <a.sclocco@vu.nl>
//
// 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 <fstream>
#include <vector>
#include <string>
#include <cmath>
#include <exception>
#include <H5Cpp.h>
#include <dada_hdu.h>
#include <ascii_header.h>

#include <Observation.hpp>
#include <utils.hpp>

#ifndef READ_DATA_HPP
#define READ_DATA_HPP

namespace AstroData {

// Exception: the PSRDada ring buffer does not work
class RingBufferError : public std::exception {
public:
  RingBufferError();
  ~RingBufferError() throw ();

  const char * what() const throw ();
};

template< typename T > void readSIGPROC(const Observation & observation, const uint8_t inputBits, const unsigned int bytesToSkip, const std::string & inputFilename, std::vector< std::vector< T > * > & data, const unsigned int firstSecond = 0);
template< typename T > void readLOFAR(std::string headerFilename, std::string rawFilename, Observation & observation, std::vector< std::vector< T > * > & data, unsigned int nrSeconds = 0, unsigned int firstSecond = 0);
template< typename T > void readPSRDadaHeader(Observation & observation, dada_hdu_t & ringBuffer) throw(RingBufferError);
template< typename T > inline void readPSRDada(Observation & observation, dada_hdu_t & ringBuffer, std::vector< T > * data) throw(RingBufferError);

// Implementation

template< typename T > void readSIGPROC(const Observation & observation, const uint8_t inputBits, const unsigned int bytesToSkip, const std::string & inputFilename, std::vector< std::vector< T > * > & data, const unsigned int firstSecond = 0) {
	std::ifstream inputFile;
	const unsigned int BUFFER_DIM = sizeof(T);
	char * buffer = new char [BUFFER_DIM];

	inputFile.open(inputFilename.c_str(), std::ios::binary);
	inputFile.sync_with_stdio(false);
	inputFile.seekg(bytesToSkip, std::ios::beg);
	for ( unsigned int second = 0; second < observation.getNrSeconds(); second++ ) {
    if ( inputBits >= 8 ) {
      data.at(second) = new std::vector< T >(observation.getNrChannels() * observation.getNrSamplesPerPaddedSecond());
      for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
        for ( unsigned int channel = observation.getNrChannels(); channel > 0; channel-- ) {
          inputFile.read(buffer, BUFFER_DIM);
          data.at(second)->at((static_cast< uint64_t >(channel - 1) * observation.getNrSamplesPerPaddedSecond()) + sample) = *(reinterpret_cast< T * >(buffer));
        }
      }
    } else {
      uint64_t bytesToRead = static_cast< uint64_t >(observation.getNrSamplesPerSecond() * std::ceil(observation.getNrChannels() / (8.0 / inputBits)));

      data.at(second) = new std::vector< T >(observation.getNrChannels() * isa::utils::pad(observation.getNrSamplesPerSecond() / (8 / inputBits), observation.getPadding()));
      for ( uint64_t byte = 0; byte < bytesToRead; byte++ ) {
        unsigned int channel = (observation.getNrChannels() - 1) - ((byte * (8 / iputBits)) % observation.getNrChannels());
        unsigned int sample = (byte * (8 / iputBits)) / observation.getNrChannels();
        unsigned int sampleByte = sample / (8 / inputBits);
        uint8_t sampleFirstBit = (sample % (8 / inputBits)) * inputBits;

        inputFile.read(buffer, BUFFER_DIM);
        for ( unsigned int item = 0; item < 8 / inputBits; item++ ) {
          uint8_t channelFirstBit = item * inputBits;
          uint8_t sampleBuffer = 0;

          if ( item > channel ) {
            // All channels read, the remaining elements are from the next sample
            channel = (observation.getNrChannels() - 1);
            sample += 1;
            sampleByte = sample / (8 / inputBits);
            sampleFirstBit = (sample % (8 / inputBits)) * inputBits;

            while ( item < (8 / inputBits) ) {
              channelFirstBit = item * inputBits;
              sampleBuffer = data.at(second)->at((static_cast< uint64_t >(channel - item) * isa::utils::pad(observation.getNrSamplesPerSecond() / (8 / inputBits), observation.getPadding())) + sampleByte);
              for ( uint8_t bit = 0; bit < inputBits; bit++ ) {
                isa::utils::setBit(sampleBuffer, isa::utils::getBit(*buffer, channelFirstBit + bit), sampleFirstBit + bit);
              }
              data.at(second)->at((static_cast< uint64_t >(channel - item) * isa::utils::pad(observation.getNrSamplesPerSecond() / (8 / inputBits), observation.getPadding())) + sampleByte) = sampleBuffer;
              item++;
            }

            break;
          }
          sampleBuffer = data.at(second)->at((static_cast< uint64_t >(channel - item) * isa::utils::pad(observation.getNrSamplesPerSecond() / (8 / inputBits), observation.getPadding())) + sampleByte);
          for ( uint8_t bit = 0; bit < inputBits; bit++ ) {
            isa::utils::setBit(sampleBuffer, isa::utils::getBit(*buffer, channelFirstBit + bit), sampleFirstBit + bit);
          }
          data.at(second)->at((static_cast< uint64_t >(channel - item) * isa::utils::pad(observation.getNrSamplesPerSecond() / (8 / inputBits), observation.getPadding())) + sampleByte) = sampleBuffer;
        }
      }
    }
	}
	inputFile.close();

	delete [] buffer;
}

template< typename T > void readLOFAR(std::string headerFilename, std::string rawFilename, Observation & observation, std::vector< std::vector< T > * > & data, unsigned int nrSeconds, unsigned int firstSecond) {
  unsigned int nrSubbands, nrChannels;
  float minFreq, channelBandwidth;
	// Read the HDF5 file with the metadata
	H5::H5File headerFile = H5::H5File(headerFilename, H5F_ACC_RDONLY);
	H5::FloatType typeDouble = H5::FloatType(H5::PredType::NATIVE_DOUBLE);
	double valueDouble = 0.0;
	H5::IntType typeUInt = H5::IntType(H5::PredType::NATIVE_UINT);
	unsigned int valueUInt = 0;

	H5::Group currentNode = headerFile.openGroup("/");
	currentNode.openAttribute("OBSERVATION_FREQUENCY_MIN").read(typeDouble, reinterpret_cast< void * >(&valueDouble));
  minFreq = valueDouble;
	currentNode = currentNode.openGroup(currentNode.getObjnameByIdx(0));
	currentNode.openAttribute("TOTAL_INTEGRATION_TIME").read(typeDouble, reinterpret_cast< void * >(&valueDouble));
	double totalIntegrationTime = valueDouble;
	currentNode.openAttribute("NOF_BEAMS").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	observation.setNrBeams(valueUInt);
	currentNode = currentNode.openGroup(currentNode.getObjnameByIdx(0));
	currentNode.openAttribute("NOF_SAMPLES").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	unsigned int totalSamples = valueUInt;
	currentNode.openAttribute("NOF_STATIONS").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	observation.setNrStations(valueUInt);
	currentNode.openAttribute("CHANNELS_PER_SUBBAND").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	nrChannels = valueUInt;
	currentNode.openAttribute("CHANNEL_WIDTH").read(typeDouble, reinterpret_cast< void * >(&valueDouble));
  channelBandwidth = valueDouble / 1000000;
	H5::DataSet currentData = currentNode.openDataSet("STOKES_0");
	currentData.openAttribute("NOF_SUBBANDS").read(typeUInt, reinterpret_cast< void * >(&valueUInt));
	nrSubbands = valueUInt;
	headerFile.close();

	observation.setNrSamplesPerSecond(static_cast< unsigned int >(totalSamples / totalIntegrationTime));
	if ( nrSeconds == 0 ) {
		observation.setNrSeconds(static_cast< unsigned int >(totalIntegrationTime));
	} else {
		if ( static_cast< unsigned int >(totalIntegrationTime) >= (firstSecond + nrSeconds) ) {
			observation.setNrSeconds(nrSeconds);
		} else {
			observation.setNrSeconds(static_cast< unsigned int >(totalIntegrationTime) - firstSecond);
		}
	}
  observation.setFrequencyRange(nrSubbands * nrChannels, minFreq, channelBandwidth);

	// Read the raw file with the actual data
	std::ifstream rawFile;
	rawFile.open(rawFilename.c_str(), std::ios::binary);
	rawFile.sync_with_stdio(false);
	if ( firstSecond > 0 ) {
		rawFile.seekg(firstSecond * observation.getNrSamplesPerSecond() * nrSubbands * nrChannels, std::ios::beg);
	}
	data.resize(observation.getNrSeconds());

	char * word = new char [4];
	for ( unsigned int second = 0; second < observation.getNrSeconds(); second++ ) {
		data.at(second) = new std::vector< T >(observation.getNrChannels() * observation.getNrSamplesPerPaddedSecond());
		for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
			for ( unsigned int subband = 0; subband < nrSubbands; subband++ ) {
				for ( unsigned int channel = 0; channel < nrChannels; channel++ ) {
          unsigned int globalChannel = (subband * nrChannels) + channel;

					rawFile.read(word, 4);
          isa::utils::bigEndianToLittleEndian(word);
          data.at(second)->at((globalChannel * observation.getNrSamplesPerPaddedSecond()) + sample) = *(reinterpret_cast< T * >(word));
				}
			}
		}
	}
	rawFile.close();
	delete [] word;
}

template< typename T > void readPSRDadaHeader(Observation & observation, dada_hdu_t & ringBuffer) throw(RingBufferError) {
  // Staging variables for the header elements
  unsigned int uintValue = 0;
  float floatValue[2] = {0.0f, 0.0f};
  // Header string
  uint64_t headerBytes = 0;
  char * header = 0;

  header = ipcbuf_get_next_read(ringBuffer.header_block, &headerBytes);

  if ( (header == 0) || (headerBytes == 0 ) ) {
    throw RingBufferError();
  }

  ascii_header_get(header, "SAMPLES_PER_SECOND", "%d", &uintValue);
  observation.setNrSamplesPerSecond(uintValue);
  ascii_header_get(header, "CHANNELS", "%d", &uintValue);
  ascii_header_get(header, "MIN_FREQUENCY", "%f", &floatValue[0]);
  ascii_header_get(header, "CHANNEL_BANDWIDTH", "%f", &floatValue[1]);
  observation.setFrequencyRange(uintValue, floatValue[0], floatValue[1]);
  ipcbuf_mark_cleared(ringBuffer.header_block);

  delete header;
}

template< typename T > inline void readPSRDada(Observation & observation, dada_hdu_t & ringBuffer, std::vector< T > * data) throw(RingBufferError) {
  if ( (ipcio_read(ringBuffer.data_block, reinterpret_cast< char * >(data->data()), observation.getNrChannels() * observation.getNrSamplesPerPaddedSecond() * sizeof(T))) < 0 ) {
    throw RingBufferError();
  }
}

} // AstroData

#endif // READ_DATA_HPP

<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3 -*-

Copyright 2010, 2011, 2012, 2013
Raffaello D. Di Napoli

This file is part of Application-Building Components (henceforth referred to as ABC).

ABC is free software: you can redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

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

You should have received a copy of the GNU General Public License along with ABC. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef ABC_CORE_HXX
#define ABC_CORE_HXX

#include <limits.h> // CHAR_BIT *_MAX *_MIN
#include <stdint.h> // *int*_t __WORDSIZE (if supported)
#include <stddef.h> // size_t

#if defined(__GNUC__)
	// Make version checks for GCC less cumbersome.
	#define _GCC_VER \
		(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
	#if _GCC_VER < 40300
		#error Unsupported version of GCC (>= 4.3.0 required)
	#endif
#elif defined(_MSC_VER)
	#if _MSC_VER < 1600
		#error Unsupported version of MSC (>= MSC 16 / VC++ 10 / VS 2010 required)
	#endif
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc globals - HOST_* and OUTPUT_*

#define ABC_HOST_API_WIN32 0
#define ABC_HOST_API_WIN64 0
#define ABC_HOST_API_LINUX 0
#define ABC_HOST_API_POSIX 0
#define ABC_OUTPUT_WIN32_DLL 0
#define ABC_OUTPUT_WIN32_EXE 0
#define ABC_OUTPUT_POSIX_EXE 0

#if defined(_WIN32)
	// Compiling for Win32.
	#undef ABC_HOST_API_WIN32
	#define ABC_HOST_API_WIN32 1
	#ifdef _WIN64
		// Compiling for Win64 (coexists with ABC_HOST_API_WIN32).
		#undef ABC_HOST_API_WIN64
		#define ABC_HOST_API_WIN64 1
	#endif
	#ifdef _WINDLL
		#undef ABC_OUTPUT_WIN32_DLL
		#define ABC_OUTPUT_WIN32_DLL 1
	#else
		#undef ABC_OUTPUT_WIN32_EXE
		#define ABC_OUTPUT_WIN32_EXE 1
	#endif
#elif defined(__linux__)
	// Compiling for Linux.
	#undef ABC_HOST_API_LINUX
	#define ABC_HOST_API_LINUX 1
	#undef ABC_HOST_API_POSIX
	#define ABC_HOST_API_POSIX 1
	#undef ABC_OUTPUT_POSIX_EXE
	#define ABC_OUTPUT_POSIX_EXE 1
#elif defined(__posix__)
	// Compiling for POSIX.
	#undef ABC_HOST_API_POSIX
	#define ABC_HOST_API_POSIX 1
	#undef ABC_OUTPUT_POSIX_EXE
	#define ABC_OUTPUT_POSIX_EXE 1
#endif

/** Machine word size for this microarchitecture. */
#if ABC_HOST_API_WIN32
	#ifdef _WIN64
		#define ABC_HOST_WORD_SIZE 64
	#else
		#define ABC_HOST_WORD_SIZE 32
	#endif
#elif defined(__WORDSIZE)
	#define ABC_HOST_WORD_SIZE __WORDSIZE
#else
	#error Unable to determine the word size for this microarchitecture
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc globals - platform-dependent fixes

#if ABC_HOST_API_POSIX

	// This prevents stat() from failing for files bigger than 2 GiB.
	#define _FILE_OFFSET_BITS 64

#elif ABC_HOST_API_WIN32

	// Make sure WINVER is defined.
	#ifndef WINVER
		// Pick a default Windows version.
		#ifdef _WIN64
			// The earliest Win64 implementations are Windows Server 2003 (5.2) and Windows XP x64
			// Edition (5.2).
			#define WINVER 0x0502
		#else
			// The earliest Win32 implementations are Windows 95 (4.0) and Windows NT 4 (4.0).
			#define WINVER 0x0400
		#endif
	#endif

	// Make sure _WIN32_WINNT is defined for WINVER values representing NT-only Windows versions.
	// The first NT-only version of Windows is 5.0 (Windows 2000; Windows Me is 4.9).
	#if !defined(_WIN32_WINNT) && WINVER >= 0x0500
		#define _WIN32_WINNT WINVER
	#endif

	// Make sure UNICODE and _UNICODE are coherent; UNICODE wins.
	#if defined(UNICODE) && !defined(_UNICODE)
		#define _UNICODE
	#elif !defined(UNICODE) && defined(_UNICODE)
		#undef _UNICODE
	#endif

	#define WIN32_LEAN_AND_MEAN
	#include <Windows.h>
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc globals - C++11 compiler support

/** If defined, the compiler supports defining conversion operators as explicit, to avoid executing
them implicitly (N2437). */
#if defined(_GCC_VER) && _GCC_VER >= 40500
	#define ABC_CXX_EXPLICIT_CONVERSION_OPERATORS
#endif

/** If defined, the compiler allows to delete a specific (overload of a) function, method or
constructor (N2346). */
#if defined(_GCC_VER) && _GCC_VER >= 40400
	#define ABC_CXX_FUNCTION_DELETE
#endif

/** If defined, the compiler supports template friend declarations (N1791). */
#if (defined(_GCC_VER) && _GCC_VER >= 40500) || defined(_MSC_VER)
	#define ABC_CXX_TEMPLATE_FRIENDS
#endif

/** If defined, the compiler supports variadic templates (N2242). */
#if defined(_GCC_VER)
	#define ABC_CXX_VARIADIC_TEMPLATES
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc globals - non-standard, but commonly available, extensions

/** If defined, the compiler supports #pragma once, which tells the preprocessor not to parsing a
(header) file more than once, speeding up compilation. */
#if defined(_MSC_VER)
	#define ABC_CXX_PRAGMA_ONCE

	// Use it now for this file.
	#pragma once
#endif

/** Defines a function as never returning (e.g. by causing the process to terminate, or by throwing
an exception). This allows optimizations based on the fact that code following its call cannot be
reached. */
#if defined(_GCC_VER)
	#define ABC_FUNC_NORETURN \
		__attribute__((noreturn))
#elif defined(_MSC_VER)
	#define ABC_FUNC_NORETURN \
		__declspec(noreturn)
#else
	#define ABC_FUNC_NORETURN
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc globals - extended features that can take advantage of C++11 or fallback to more risky, but
// still functional alternatives

/** Makes the class un-copiable. Move constructors and/or assignment operators may be still
available, though.

TODO: comment signature.
*/
#ifdef ABC_CXX_FUNCTION_DELETE
	#define ABC_CLASS_PREVENT_COPYING(cls) \
		public: \
		\
			cls(cls const &) = delete; \
			\
			cls & operator=(cls const &) = delete;
#else
	#define ABC_CLASS_PREVENT_COPYING(cls) \
		private: \
		\
			cls(cls const &) { \
				class_ ## cls ## _cannot_be_copied(); \
			} \
			\
			cls & operator=(cls const &) { \
				class_ ## cls ## _cannot_be_copied(); \
			}
#endif

namespace abc {

/** Declares an explicit conversion operator to bool.
*/
#ifdef ABC_CXX_EXPLICIT_CONVERSION_OPERATORS

	#define explicit_operator_bool \
		explicit operator bool

	/** A class derived from this one receives support for C++11 explicit operator bool even on
	non-compliant compilers.
	*/
	template <typename T>
	struct support_explicit_operator_bool {};

#else //ifdef ABC_CXX_EXPLICIT_CONVERSION_OPERATORS

	#define explicit_operator_bool \
		bool _explicit_operator_bool

	/** Non-template helper for support_explicit_operator_bool.
	*/
	struct _explob_helper {

		/** Non-bool boolean type. */
		typedef void (_explob_helper::* bool_type)() const;

		/** A pointer to this method is used as a boolean true by support_explicit_operator_bool.
		*/
		void bool_true() const;
	};

	/** A class derived from this one receives support for C++11 explicit operator bool even on
	non-compliant compilers.
	*/
	template <typename T>
	struct support_explicit_operator_bool {

		/** Non-bool boolean conversion operator, safer than operator bool(), and almost as good as
		explicit operator bool().

		TODO: comment signature.
		*/
		operator _explob_helper::bool_type() const {
			if (static_cast<T const *>(this)->_explicit_operator_bool()) {
				return &_explob_helper::bool_true;
			} else {
				return 0;
			}
		}
	};

	// Disable relational operators for support_explicit_operator_bool.

	#ifdef ABC_CXX_FUNCTION_DELETE

		#define ABC_RELOP_IMPL(op) \
			template <typename T1, typename T2> \
			bool operator op( \
				support_explicit_operator_bool<T1> const &, support_explicit_operator_bool<T2> const & \
			) = delete;

	#else //ifdef ABC_CXX_FUNCTION_DELETE

		#define ABC_RELOP_IMPL(op) \
			template <typename T1, typename T2> \
			inline bool operator op( \
				support_explicit_operator_bool<T1> const & lhs, \
				support_explicit_operator_bool<T2> const & rhs \
			) { \
				cannot_compare_to(lhs, rhs); \
				return false; \
			}

	#endif //ifdef ABC_CXX_FUNCTION_DELETE … else

	ABC_RELOP_IMPL(==)
	ABC_RELOP_IMPL(!=)
	#undef ABC_RELOP_IMPL

#endif //ifdef ABC_CXX_EXPLICIT_CONVERSION_OPERATORS … else

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc globals - other

namespace std {

/** Type whose alignment requirement is at least as large as that of every scalar type (see C++11 §
18.2 “<cstddef>”).
*/
union max_align_t {
	double d;
	long double ld;
	long long ll;
};

} //namespace std

// Support loose exception specifications.
#if defined(_GCC_VER) && _GCC_VER >= 40600
	#define noexcept_false \
		noexcept(false)
	#define noexcept_true \
		noexcept(true)
	#define noexcept_if(cond) \
		noexcept(cond)
#else
	#define noexcept_false
	#define noexcept_true \
		throw()
	#define noexcept_if(cond)
#endif

// Support for pre-C++11 declarations. Use double parentheses for the list.
#define decl_throw(list) \
	throw list

/** Avoids compiler warnings about purposely unused parameters. Win32 has UNREFERENCED_PARAMETER for
this purpose, but this is noticeably shorter :)

TODO: comment signature.
*/
#define UNUSED_ARG(x) \
	static_cast<void>(x)

/** Tells the compiler that a switch statement that apparently doesn’t test for all possible cases
for its argument (e.g. skips some values of an enum), does cover 100% of the actually possible
cases.

It can avoid warnings about not testing for all possible values for an enum, or cases where a
variable would seem to be left uninitialized if the switch argument has a value that’s not one of
those expected by the case labels.
*/
#if defined(_MSC_VER)
	#define no_default \
		default: \
			__assume(0)
#else
	#define no_default \
		default: \
			break
#endif

/** Returns the number of items in a (static) array.

TODO: comment signature.
*/
#undef countof
#define countof(array) \
	(sizeof(array) / sizeof((array)[0]))

/** Returns the offset, in bytes, of a struct/class member. It doesn’t trigger warnings, since it
doesn’t use NULL as the fake address.

TODO: comment signature.
*/
#undef offsetof
#define offsetof(type, member) \
	(reinterpret_cast<size_t>(&reinterpret_cast<type *>(1024)->member) - 1024)

/** Returns the compiler-computed alignment for the specified data type. When compiler support is
lacking, this can be inaccurate for long double.

TODO: comment signature.
*/
#undef alignof
#if defined(_GCC_VER)
	#define alignof(type) \
		__alignof__(type)
#elif defined(_MSC_VER)
	#define alignof(type) \
		__alignof(type)
#else
	#define alignof(type) \
		offsetof(abc::_alignof_helper<type>, t)

	namespace abc {

	template <typename T>
	struct _alignof_helper {
		int8_t misaligner;
		T t;
	};

	} //namespace abc
#endif

/** Returns a size rounded (ceiling) to a count of std::max_align_t units. This allows to declare
storage with alignment suitable for any type, just like ::malloc() does. Identical to
bitmanip::ceiling_to_pow2_multiple(cb, sizeof(std::max_align_t)).

TODO: comment signature.
*/
#define ABC_ALIGNED_SIZE(cb) \
	((size_t(cb) + sizeof(std::max_align_t) - 1) / sizeof(std::max_align_t))

namespace abc {

/** TODO: comment.

TODO maybe move to other header file?
*/
template <typename T>
union force_max_align {
public:

	/** Actual storage. */
	T t;

private:

	/** Forces the whole union to have the most generic alignment; on many architectures this will be
	2 * word size. In any case, this makes the union aligned the same way malloc() aligns the
	pointers it returns. */
	std::max_align_t aligner[ABC_ALIGNED_SIZE(sizeof(T))];
};

/** See unsafe. */
struct unsafe_t {};

/** Constant used as extra argument for functions to force clients to acknowledge they are
performing unsafe operations. */
extern unsafe_t const unsafe;

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif //ifndef ABC_CORE_HXX

<commit_msg>Fix ill-conceived implementation of ABC_CLASS_PREVENT_COPYING for MSC16<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3 -*-

Copyright 2010, 2011, 2012, 2013
Raffaello D. Di Napoli

This file is part of Application-Building Components (henceforth referred to as ABC).

ABC is free software: you can redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

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

You should have received a copy of the GNU General Public License along with ABC. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef ABC_CORE_HXX
#define ABC_CORE_HXX

#include <limits.h> // CHAR_BIT *_MAX *_MIN
#include <stdint.h> // *int*_t __WORDSIZE (if supported)
#include <stddef.h> // size_t

#if defined(__GNUC__)
	// Make version checks for GCC less cumbersome.
	#define _GCC_VER \
		(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
	#if _GCC_VER < 40300
		#error Unsupported version of GCC (>= 4.3.0 required)
	#endif
#elif defined(_MSC_VER)
	#if _MSC_VER < 1600
		#error Unsupported version of MSC (>= MSC 16 / VC++ 10 / VS 2010 required)
	#endif
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc globals - HOST_* and OUTPUT_*

#define ABC_HOST_API_WIN32 0
#define ABC_HOST_API_WIN64 0
#define ABC_HOST_API_LINUX 0
#define ABC_HOST_API_POSIX 0
#define ABC_OUTPUT_WIN32_DLL 0
#define ABC_OUTPUT_WIN32_EXE 0
#define ABC_OUTPUT_POSIX_EXE 0

#if defined(_WIN32)
	// Compiling for Win32.
	#undef ABC_HOST_API_WIN32
	#define ABC_HOST_API_WIN32 1
	#ifdef _WIN64
		// Compiling for Win64 (coexists with ABC_HOST_API_WIN32).
		#undef ABC_HOST_API_WIN64
		#define ABC_HOST_API_WIN64 1
	#endif
	#ifdef _WINDLL
		#undef ABC_OUTPUT_WIN32_DLL
		#define ABC_OUTPUT_WIN32_DLL 1
	#else
		#undef ABC_OUTPUT_WIN32_EXE
		#define ABC_OUTPUT_WIN32_EXE 1
	#endif
#elif defined(__linux__)
	// Compiling for Linux.
	#undef ABC_HOST_API_LINUX
	#define ABC_HOST_API_LINUX 1
	#undef ABC_HOST_API_POSIX
	#define ABC_HOST_API_POSIX 1
	#undef ABC_OUTPUT_POSIX_EXE
	#define ABC_OUTPUT_POSIX_EXE 1
#elif defined(__posix__)
	// Compiling for POSIX.
	#undef ABC_HOST_API_POSIX
	#define ABC_HOST_API_POSIX 1
	#undef ABC_OUTPUT_POSIX_EXE
	#define ABC_OUTPUT_POSIX_EXE 1
#endif

/** Machine word size for this microarchitecture. */
#if ABC_HOST_API_WIN32
	#ifdef _WIN64
		#define ABC_HOST_WORD_SIZE 64
	#else
		#define ABC_HOST_WORD_SIZE 32
	#endif
#elif defined(__WORDSIZE)
	#define ABC_HOST_WORD_SIZE __WORDSIZE
#else
	#error Unable to determine the word size for this microarchitecture
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc globals - platform-dependent fixes

#if ABC_HOST_API_POSIX

	// This prevents stat() from failing for files bigger than 2 GiB.
	#define _FILE_OFFSET_BITS 64

#elif ABC_HOST_API_WIN32

	// Make sure WINVER is defined.
	#ifndef WINVER
		// Pick a default Windows version.
		#ifdef _WIN64
			// The earliest Win64 implementations are Windows Server 2003 (5.2) and Windows XP x64
			// Edition (5.2).
			#define WINVER 0x0502
		#else
			// The earliest Win32 implementations are Windows 95 (4.0) and Windows NT 4 (4.0).
			#define WINVER 0x0400
		#endif
	#endif

	// Make sure _WIN32_WINNT is defined for WINVER values representing NT-only Windows versions.
	// The first NT-only version of Windows is 5.0 (Windows 2000; Windows Me is 4.9).
	#if !defined(_WIN32_WINNT) && WINVER >= 0x0500
		#define _WIN32_WINNT WINVER
	#endif

	// Make sure UNICODE and _UNICODE are coherent; UNICODE wins.
	#if defined(UNICODE) && !defined(_UNICODE)
		#define _UNICODE
	#elif !defined(UNICODE) && defined(_UNICODE)
		#undef _UNICODE
	#endif

	#define WIN32_LEAN_AND_MEAN
	#include <Windows.h>
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc globals - C++11 compiler support

/** If defined, the compiler supports defining conversion operators as explicit, to avoid executing
them implicitly (N2437). */
#if defined(_GCC_VER) && _GCC_VER >= 40500
	#define ABC_CXX_EXPLICIT_CONVERSION_OPERATORS
#endif

/** If defined, the compiler allows to delete a specific (overload of a) function, method or
constructor (N2346). */
#if defined(_GCC_VER) && _GCC_VER >= 40400
	#define ABC_CXX_FUNCTION_DELETE
#endif

/** If defined, the compiler supports template friend declarations (N1791). */
#if (defined(_GCC_VER) && _GCC_VER >= 40500) || defined(_MSC_VER)
	#define ABC_CXX_TEMPLATE_FRIENDS
#endif

/** If defined, the compiler supports variadic templates (N2242). */
#if defined(_GCC_VER)
	#define ABC_CXX_VARIADIC_TEMPLATES
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc globals - non-standard, but commonly available, extensions

/** If defined, the compiler supports #pragma once, which tells the preprocessor not to parsing a
(header) file more than once, speeding up compilation. */
#if defined(_MSC_VER)
	#define ABC_CXX_PRAGMA_ONCE

	// Use it now for this file.
	#pragma once
#endif

/** Defines a function as never returning (e.g. by causing the process to terminate, or by throwing
an exception). This allows optimizations based on the fact that code following its call cannot be
reached. */
#if defined(_GCC_VER)
	#define ABC_FUNC_NORETURN \
		__attribute__((noreturn))
#elif defined(_MSC_VER)
	#define ABC_FUNC_NORETURN \
		__declspec(noreturn)
#else
	#define ABC_FUNC_NORETURN
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc globals - extended features that can take advantage of C++11 or fallback to more risky, but
// still functional alternatives

/** Makes the class un-copiable. Move constructors and/or assignment operators may be still
available, though.

TODO: comment signature.
*/
#ifdef ABC_CXX_FUNCTION_DELETE
	#define ABC_CLASS_PREVENT_COPYING(cls) \
		public: \
		\
			cls(cls const &) = delete; \
			\
			cls & operator=(cls const &) = delete;
#else
	#define ABC_CLASS_PREVENT_COPYING(cls) \
		private: \
		\
			cls(cls const &); \
		\
			cls & operator=(cls const &);
#endif

namespace abc {

/** Declares an explicit conversion operator to bool.
*/
#ifdef ABC_CXX_EXPLICIT_CONVERSION_OPERATORS

	#define explicit_operator_bool \
		explicit operator bool

	/** A class derived from this one receives support for C++11 explicit operator bool even on
	non-compliant compilers.
	*/
	template <typename T>
	struct support_explicit_operator_bool {};

#else //ifdef ABC_CXX_EXPLICIT_CONVERSION_OPERATORS

	#define explicit_operator_bool \
		bool _explicit_operator_bool

	/** Non-template helper for support_explicit_operator_bool.
	*/
	struct _explob_helper {

		/** Non-bool boolean type. */
		typedef void (_explob_helper::* bool_type)() const;

		/** A pointer to this method is used as a boolean true by support_explicit_operator_bool.
		*/
		void bool_true() const;
	};

	/** A class derived from this one receives support for C++11 explicit operator bool even on
	non-compliant compilers.
	*/
	template <typename T>
	struct support_explicit_operator_bool {

		/** Non-bool boolean conversion operator, safer than operator bool(), and almost as good as
		explicit operator bool().

		TODO: comment signature.
		*/
		operator _explob_helper::bool_type() const {
			if (static_cast<T const *>(this)->_explicit_operator_bool()) {
				return &_explob_helper::bool_true;
			} else {
				return 0;
			}
		}
	};

	// Disable relational operators for support_explicit_operator_bool.

	#ifdef ABC_CXX_FUNCTION_DELETE

		#define ABC_RELOP_IMPL(op) \
			template <typename T1, typename T2> \
			bool operator op( \
				support_explicit_operator_bool<T1> const &, support_explicit_operator_bool<T2> const & \
			) = delete;

	#else //ifdef ABC_CXX_FUNCTION_DELETE

		#define ABC_RELOP_IMPL(op) \
			template <typename T1, typename T2> \
			inline bool operator op( \
				support_explicit_operator_bool<T1> const & lhs, \
				support_explicit_operator_bool<T2> const & rhs \
			) { \
				cannot_compare_to(lhs, rhs); \
				return false; \
			}

	#endif //ifdef ABC_CXX_FUNCTION_DELETE … else

	ABC_RELOP_IMPL(==)
	ABC_RELOP_IMPL(!=)
	#undef ABC_RELOP_IMPL

#endif //ifdef ABC_CXX_EXPLICIT_CONVERSION_OPERATORS … else

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc globals - other

namespace std {

/** Type whose alignment requirement is at least as large as that of every scalar type (see C++11 §
18.2 “<cstddef>”).
*/
union max_align_t {
	double d;
	long double ld;
	long long ll;
};

} //namespace std

// Support loose exception specifications.
#if defined(_GCC_VER) && _GCC_VER >= 40600
	#define noexcept_false \
		noexcept(false)
	#define noexcept_true \
		noexcept(true)
	#define noexcept_if(cond) \
		noexcept(cond)
#else
	#define noexcept_false
	#define noexcept_true \
		throw()
	#define noexcept_if(cond)
#endif

// Support for pre-C++11 declarations. Use double parentheses for the list.
#define decl_throw(list) \
	throw list

/** Avoids compiler warnings about purposely unused parameters. Win32 has UNREFERENCED_PARAMETER for
this purpose, but this is noticeably shorter :)

TODO: comment signature.
*/
#define UNUSED_ARG(x) \
	static_cast<void>(x)

/** Tells the compiler that a switch statement that apparently doesn’t test for all possible cases
for its argument (e.g. skips some values of an enum), does cover 100% of the actually possible
cases.

It can avoid warnings about not testing for all possible values for an enum, or cases where a
variable would seem to be left uninitialized if the switch argument has a value that’s not one of
those expected by the case labels.
*/
#if defined(_MSC_VER)
	#define no_default \
		default: \
			__assume(0)
#else
	#define no_default \
		default: \
			break
#endif

/** Returns the number of items in a (static) array.

TODO: comment signature.
*/
#undef countof
#define countof(array) \
	(sizeof(array) / sizeof((array)[0]))

/** Returns the offset, in bytes, of a struct/class member. It doesn’t trigger warnings, since it
doesn’t use NULL as the fake address.

TODO: comment signature.
*/
#undef offsetof
#define offsetof(type, member) \
	(reinterpret_cast<size_t>(&reinterpret_cast<type *>(1024)->member) - 1024)

/** Returns the compiler-computed alignment for the specified data type. When compiler support is
lacking, this can be inaccurate for long double.

TODO: comment signature.
*/
#undef alignof
#if defined(_GCC_VER)
	#define alignof(type) \
		__alignof__(type)
#elif defined(_MSC_VER)
	#define alignof(type) \
		__alignof(type)
#else
	#define alignof(type) \
		offsetof(abc::_alignof_helper<type>, t)

	namespace abc {

	template <typename T>
	struct _alignof_helper {
		int8_t misaligner;
		T t;
	};

	} //namespace abc
#endif

/** Returns a size rounded (ceiling) to a count of std::max_align_t units. This allows to declare
storage with alignment suitable for any type, just like ::malloc() does. Identical to
bitmanip::ceiling_to_pow2_multiple(cb, sizeof(std::max_align_t)).

TODO: comment signature.
*/
#define ABC_ALIGNED_SIZE(cb) \
	((size_t(cb) + sizeof(std::max_align_t) - 1) / sizeof(std::max_align_t))

namespace abc {

/** TODO: comment.

TODO maybe move to other header file?
*/
template <typename T>
union force_max_align {
public:

	/** Actual storage. */
	T t;

private:

	/** Forces the whole union to have the most generic alignment; on many architectures this will be
	2 * word size. In any case, this makes the union aligned the same way malloc() aligns the
	pointers it returns. */
	std::max_align_t aligner[ABC_ALIGNED_SIZE(sizeof(T))];
};

/** See unsafe. */
struct unsafe_t {};

/** Constant used as extra argument for functions to force clients to acknowledge they are
performing unsafe operations. */
extern unsafe_t const unsafe;

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif //ifndef ABC_CORE_HXX

<|endoftext|>