<commit_before>#include "disassembler.h"
#include "util.h"
#include "symtab.h"

using namespace std;

enum ByteTypeGuess {
	UNINITIALIZED,
	UNKNOWN,
	CHAR_DATA,
	UNINITIALIZED_CHAR_DATA,
	WORD_DATA,
	UNINITIALIZED_WORD_DATA,
	CODE,
};

struct program {
	ByteTypeGuess byte_type_guess[65536];
	char memory[65536];
	bool is_labelled[65536];

	string name;
	string starting_address;
	int length_of_program;
	string first_executable_instruction;
	program() {
		for ( int i = 0 ; i < 65536 ; i++ ) {
			byte_type_guess[i] = UNINITIALIZED;
			memory[i] = 0;
			is_labelled[i] = false;
		}
		name = "";
		starting_address = "";
		length_of_program = 0;
		first_executable_instruction = "";
	}
};

bool read_record(ifstream &ifile, string &record);
void record_to_memory(const string record, program &p);
void analyze_code_data(program &p);
void write_assembly(const program &p, ofstream &ofile);

bool disassemble(ifstream &ifile, ofstream &ofile) {
	string record;
	program p;
	while ( read_record(ifile, record) ) {
		record_to_memory(record, p);
	}
	status("Done reading records");
	analyze_code_data(p);
	status("Done analyzing program for code and data");
	write_assembly(p, ofile);
	status("Done writing output file");
	return true;
}

string read_columns(ifstream &ifile, int col_begin, int col_end, char record_type = 'a') { // inclusive of both
	string ret;
	char t;
	for ( int col = col_begin ; col <= col_end ; col++ ) {
		t = ifile.get();
		if ( t == EOF ) {
			fatal("Unexpected end of " + record_type + string(" record"));
		}
		ret += t;
	}
	return ret;
}

string read_hex_columns(ifstream &ifile, int col_begin, int col_end, char record_type = 'a') { // inclusive of both
	string ret;
	ret = read_columns(ifile,col_begin,col_end,record_type);
	if ( !is_hex_string(ret) ) {
		fatal("Unexpected non-hexadecimal character found in "+record_type+string(" record"));
	}
	return ret;
}

bool read_record(ifstream &ifile, string &record) {
	int temp_int;
	string temp_str;
	char t;

	do {
		t = ifile.get();
		if ( t == EOF ) {
			return false;
		}
	} while ( t == '\n' || t == ' ' );
	record = "";
	record += t;

	switch (t) {
		case 'H': // Header
			record += read_columns(ifile,2,7,'H');
			record += read_hex_columns(ifile,8,19,'H');
			break;
		case 'T': // Text
			record += read_hex_columns(ifile,2,7,'T');
			temp_str = read_hex_columns(ifile,8,9,'T');
			temp_int = hex2int(temp_str);
			record += temp_str;
			record +=  read_hex_columns(ifile,10,9+2*temp_int,'T');
			break;
		case 'E': // End
			record += read_hex_columns(ifile,2,7,'E');
			break;
		default:
			fatal("Unknown record type " + t);
	}
	return true;
}

void record_to_memory(const string record, program &p) {
	const char * c_record = record.c_str();
	switch (*c_record) {
		case 'H': // Header
			if ( p.name.length() != 0 ) {
				fatal("Multiple H records");
			}
			p.name = record.substr(1,6);
			p.starting_address = record.substr(7,6);
			p.length_of_program = hex2int(record.substr(13,6));
			break;
		case 'T': // Text
			{
				int text_start = hex2int(record.substr(1,6));
				int bit_length = hex2int(record.substr(7,2));
				for ( int i = 0 ; i < bit_length ; i++ ) {
					p.memory[i+text_start] = hex2int(record.substr(9+2*i,2));
					p.byte_type_guess[i+text_start] = UNKNOWN;
				}
			}
			break;
		case 'E': // End
			if ( p.first_executable_instruction.length() != 0 ) {
				fatal("Multiple E records");
			}
			p.first_executable_instruction = record.substr(1,6);
			break;
		default:
			fatal("Unknown record type " + *c_record);
	}
}

void mark_code_data(program &p, int location, ByteTypeGuess btg) {
	if ( location >= hex2int(p.starting_address) + p.length_of_program ) {
		return;
	}
	switch (btg) {
		case UNINITIALIZED:
		case UNKNOWN:
			break;
		case CHAR_DATA:
		case UNINITIALIZED_CHAR_DATA:
			{
				if ( p.byte_type_guess[location] == UNINITIALIZED )
					btg = UNINITIALIZED_CHAR_DATA;
				p.byte_type_guess[location] = btg;
				break;
			}
		case WORD_DATA:
		case UNINITIALIZED_WORD_DATA:
			{
				if ( p.byte_type_guess[location] == UNINITIALIZED )
					btg = UNINITIALIZED_WORD_DATA;
				p.byte_type_guess[location+0] = btg;
				p.byte_type_guess[location+1] = btg;
				p.byte_type_guess[location+2] = btg;
				break;
			}
		case CODE:
			{
				if ( p.byte_type_guess[location] == UNINITIALIZED ) {
					fatal("Attempting to use uninitialized section as code");
				}
				if ( p.byte_type_guess[location] == CODE ) {
					break;
				}
				p.byte_type_guess[location+0] = btg;
				p.byte_type_guess[location+1] = btg;
				p.byte_type_guess[location+2] = btg;

				string opcode_val = byte2hex(p.memory[location]);
				string opcode;
				string operand = byte2hex(p.memory[location+1])+byte2hex(p.memory[location+2]);
				operand = int2hex(hex2int(operand)&0x7FFF); // remove index flag
				if ( ! find_from_symtab(opcode,opcode_val) ) {
					fatal("Unknown opcode " + opcode_val + " at location " + int2hex(location));
				}

				if ( opcode == "ADD"  ||
					 opcode == "AND"  ||
					 opcode == "COMP" ||
					 opcode == "DIV"  ||
					 opcode == "LDA"  ||
					 opcode == "LDL"  ||
					 opcode == "LDX"  ||
					 opcode == "MUL"  ||
					 opcode == "OR"   ||
					 opcode == "STA"  ||
					 opcode == "STL"  ||
					 opcode == "STX"  ||
					 opcode == "SUB"  ||
					 opcode == "TIX" ) {
					give_label(operand);
					p.is_labelled[hex2int(operand)] = true;
					mark_code_data(p,hex2int(operand),WORD_DATA);
				}

				if ( opcode == "LDCH" ||
					 opcode == "STCH" ) {
					give_label(operand);
					p.is_labelled[hex2int(operand)] = true;
					mark_code_data(p,hex2int(operand),CHAR_DATA);
				}

				if ( opcode == "J"    ||
					 opcode == "JEQ"  ||
					 opcode == "JGT"  ||
					 opcode == "JLT"  ||
					 opcode == "JSUB" ||
					 opcode == "RSUB" ) {
					give_label(operand);
					p.is_labelled[hex2int(operand)] = true;
					mark_code_data(p,hex2int(operand),CODE);
				}

				if ( opcode != "J" &&
					 opcode != "RSUB" ) {
					mark_code_data(p,location+3,btg);
				}

				break;
			}
	}
}

void analyze_code_data(program &p) {
	if ( p.name.length() == 0 ) {
		fatal("No Header record");
	}
	if ( p.first_executable_instruction.length() == 0 ) {
		fatal("No End record");
	}
	initialize_symtab();
	add_to_symtab("FIRST",p.first_executable_instruction);
	p.is_labelled[hex2int(p.first_executable_instruction)] = true;
	mark_code_data(p,hex2int(p.first_executable_instruction),CODE);
}

string asm_to_line(string label, string opcode, string operand, bool is_indexed) {
	const int labellength = 8;
	const int opcodelength = 6;
	string ret = "";
	ret += label + string(labellength-label.length(),' ');
	ret += opcode + string(opcodelength-opcode.length(),' ');
	ret += operand;
	if ( is_indexed ) {
		ret += ",X";
	}
	ret += '\n';
	return ret;
}

void write_assembly(const program &p, ofstream &ofile) {
	ofile << asm_to_line(p.name,"START",p.starting_address,false);
	int start_of_program = hex2int(p.starting_address);
	int end_of_program = start_of_program + p.length_of_program;
	for ( int locctr = start_of_program ; locctr < end_of_program ; locctr++ ) {
		// TODO
	}
	ofile << asm_to_line("","END","FIRST",false);
}<commit_msg>Prevent errors from showing up weird<commit_after>#include "disassembler.h"
#include "util.h"
#include "symtab.h"

using namespace std;

enum ByteTypeGuess {
	UNINITIALIZED,
	UNKNOWN,
	CHAR_DATA,
	UNINITIALIZED_CHAR_DATA,
	WORD_DATA,
	UNINITIALIZED_WORD_DATA,
	CODE,
};

struct program {
	ByteTypeGuess byte_type_guess[65536];
	char memory[65536];
	bool is_labelled[65536];

	string name;
	string starting_address;
	int length_of_program;
	string first_executable_instruction;
	program() {
		for ( int i = 0 ; i < 65536 ; i++ ) {
			byte_type_guess[i] = UNINITIALIZED;
			memory[i] = 0;
			is_labelled[i] = false;
		}
		name = "";
		starting_address = "";
		length_of_program = 0;
		first_executable_instruction = "";
	}
};

bool read_record(ifstream &ifile, string &record);
void record_to_memory(const string record, program &p);
void analyze_code_data(program &p);
void write_assembly(const program &p, ofstream &ofile);

bool disassemble(ifstream &ifile, ofstream &ofile) {
	string record;
	program p;
	while ( read_record(ifile, record) ) {
		record_to_memory(record, p);
	}
	status("Done reading records");
	analyze_code_data(p);
	status("Done analyzing program for code and data");
	write_assembly(p, ofile);
	status("Done writing output file");
	return true;
}

string read_columns(ifstream &ifile, int col_begin, int col_end, char record_type = 'a') { // inclusive of both
	string ret;
	char t;
	for ( int col = col_begin ; col <= col_end ; col++ ) {
		t = ifile.get();
		if ( t == EOF || t == '\n' ) {
			string errstr;
			errstr += "Unexpected end of ";
			errstr += record_type;
			errstr += " record";
			fatal(errstr);
		}
		ret += t;
	}
	return ret;
}

string read_hex_columns(ifstream &ifile, int col_begin, int col_end, char record_type = 'a') { // inclusive of both
	string ret;
	ret = read_columns(ifile,col_begin,col_end,record_type);
	if ( !is_hex_string(ret) ) {
		string errstr;
		errstr += "Unexpected non-hexadecimal character found in ";
		errstr += record_type;
		errstr += " record";
		fatal(errstr);
	}
	return ret;
}

bool read_record(ifstream &ifile, string &record) {
	int temp_int;
	string temp_str;
	char t;

	do {
		t = ifile.get();
		if ( t == EOF ) {
			return false;
		}
	} while ( t == '\n' || t == ' ' );
	record = "";
	record += t;

	switch (t) {
		case 'H': // Header
			record += read_columns(ifile,2,7,'H');
			record += read_hex_columns(ifile,8,19,'H');
			break;
		case 'T': // Text
			record += read_hex_columns(ifile,2,7,'T');
			temp_str = read_hex_columns(ifile,8,9,'T');
			temp_int = hex2int(temp_str);
			record += temp_str;
			record +=  read_hex_columns(ifile,10,9+2*temp_int,'T');
			break;
		case 'E': // End
			record += read_hex_columns(ifile,2,7,'E');
			break;
		default:
			{
				string errstr = "Unknown record type ";
				errstr += t;
				fatal(errstr);
			}
	}
	return true;
}

void record_to_memory(const string record, program &p) {
	const char * c_record = record.c_str();
	switch (*c_record) {
		case 'H': // Header
			if ( p.name.length() != 0 ) {
				fatal("Multiple H records");
			}
			p.name = record.substr(1,6);
			p.starting_address = record.substr(7,6);
			p.length_of_program = hex2int(record.substr(13,6));
			break;
		case 'T': // Text
			{
				int text_start = hex2int(record.substr(1,6));
				int bit_length = hex2int(record.substr(7,2));
				for ( int i = 0 ; i < bit_length ; i++ ) {
					p.memory[i+text_start] = hex2int(record.substr(9+2*i,2));
					p.byte_type_guess[i+text_start] = UNKNOWN;
				}
			}
			break;
		case 'E': // End
			if ( p.first_executable_instruction.length() != 0 ) {
				fatal("Multiple E records");
			}
			p.first_executable_instruction = record.substr(1,6);
			break;
		default:
			{
				string errstr;
				errstr += "Unknown record type ";
				errstr += *c_record;
				fatal(errstr);
			}
	}
}

void mark_code_data(program &p, int location, ByteTypeGuess btg) {
	if ( location >= hex2int(p.starting_address) + p.length_of_program ) {
		return;
	}
	switch (btg) {
		case UNINITIALIZED:
		case UNKNOWN:
			break;
		case CHAR_DATA:
		case UNINITIALIZED_CHAR_DATA:
			{
				if ( p.byte_type_guess[location] == UNINITIALIZED )
					btg = UNINITIALIZED_CHAR_DATA;
				p.byte_type_guess[location] = btg;
				break;
			}
		case WORD_DATA:
		case UNINITIALIZED_WORD_DATA:
			{
				if ( p.byte_type_guess[location] == UNINITIALIZED )
					btg = UNINITIALIZED_WORD_DATA;
				p.byte_type_guess[location+0] = btg;
				p.byte_type_guess[location+1] = btg;
				p.byte_type_guess[location+2] = btg;
				break;
			}
		case CODE:
			{
				if ( p.byte_type_guess[location] == UNINITIALIZED ) {
					fatal("Attempting to use uninitialized section as code");
				}
				if ( p.byte_type_guess[location] == CODE ) {
					break;
				}
				p.byte_type_guess[location+0] = btg;
				p.byte_type_guess[location+1] = btg;
				p.byte_type_guess[location+2] = btg;

				string opcode_val = byte2hex(p.memory[location]);
				string opcode;
				string operand = byte2hex(p.memory[location+1])+byte2hex(p.memory[location+2]);
				operand = int2hex(hex2int(operand)&0x7FFF); // remove index flag
				if ( ! find_from_symtab(opcode,opcode_val) ) {
					string errstr;
					errstr += "Unknown opcode ";
					errstr += opcode_val;
					errstr += " at location ";
					errstr += int2hex(location);
					fatal(errstr);
				}

				if ( opcode == "ADD"  ||
					 opcode == "AND"  ||
					 opcode == "COMP" ||
					 opcode == "DIV"  ||
					 opcode == "LDA"  ||
					 opcode == "LDL"  ||
					 opcode == "LDX"  ||
					 opcode == "MUL"  ||
					 opcode == "OR"   ||
					 opcode == "STA"  ||
					 opcode == "STL"  ||
					 opcode == "STX"  ||
					 opcode == "SUB"  ||
					 opcode == "TIX" ) {
					give_label(operand);
					p.is_labelled[hex2int(operand)] = true;
					mark_code_data(p,hex2int(operand),WORD_DATA);
				}

				if ( opcode == "LDCH" ||
					 opcode == "STCH" ) {
					give_label(operand);
					p.is_labelled[hex2int(operand)] = true;
					mark_code_data(p,hex2int(operand),CHAR_DATA);
				}

				if ( opcode == "J"    ||
					 opcode == "JEQ"  ||
					 opcode == "JGT"  ||
					 opcode == "JLT"  ||
					 opcode == "JSUB" ||
					 opcode == "RSUB" ) {
					give_label(operand);
					p.is_labelled[hex2int(operand)] = true;
					mark_code_data(p,hex2int(operand),CODE);
				}

				if ( opcode != "J" &&
					 opcode != "RSUB" ) {
					mark_code_data(p,location+3,btg);
				}

				break;
			}
	}
}

void analyze_code_data(program &p) {
	if ( p.name.length() == 0 ) {
		fatal("No Header record");
	}
	if ( p.first_executable_instruction.length() == 0 ) {
		fatal("No End record");
	}
	initialize_symtab();
	add_to_symtab("FIRST",p.first_executable_instruction);
	p.is_labelled[hex2int(p.first_executable_instruction)] = true;
	mark_code_data(p,hex2int(p.first_executable_instruction),CODE);
}

string asm_to_line(string label, string opcode, string operand, bool is_indexed) {
	const int labellength = 8;
	const int opcodelength = 6;
	string ret = "";
	ret += label + string(labellength-label.length(),' ');
	ret += opcode + string(opcodelength-opcode.length(),' ');
	ret += operand;
	if ( is_indexed ) {
		ret += ",X";
	}
	ret += '\n';
	return ret;
}

void write_assembly(const program &p, ofstream &ofile) {
	ofile << asm_to_line(p.name,"START",p.starting_address,false);
	int start_of_program = hex2int(p.starting_address);
	int end_of_program = start_of_program + p.length_of_program;
	for ( int locctr = start_of_program ; locctr < end_of_program ; locctr++ ) {
		// TODO
	}
	ofile << asm_to_line("","END","FIRST",false);
}<|endoftext|>


<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/modules/audio_processing/audio_buffer.h"

#include "webrtc/common_audio/include/audio_util.h"
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"

namespace webrtc {
namespace {

enum {
  kSamplesPer8kHzChannel = 80,
  kSamplesPer16kHzChannel = 160,
  kSamplesPer32kHzChannel = 320
};

void StereoToMono(const int16_t* left, const int16_t* right,
                  int16_t* out, int samples_per_channel) {
  assert(left != NULL && right != NULL && out != NULL);
  for (int i = 0; i < samples_per_channel; i++) {
    int32_t data32 = (static_cast<int32_t>(left[i]) +
                      static_cast<int32_t>(right[i])) >> 1;

    out[i] = WebRtcSpl_SatW32ToW16(data32);
  }
}
}  // namespace

struct AudioChannel {
  AudioChannel() {
    memset(data, 0, sizeof(data));
  }

  int16_t data[kSamplesPer32kHzChannel];
};

struct SplitAudioChannel {
  SplitAudioChannel() {
    memset(low_pass_data, 0, sizeof(low_pass_data));
    memset(high_pass_data, 0, sizeof(high_pass_data));
    memset(analysis_filter_state1, 0, sizeof(analysis_filter_state1));
    memset(analysis_filter_state2, 0, sizeof(analysis_filter_state2));
    memset(synthesis_filter_state1, 0, sizeof(synthesis_filter_state1));
    memset(synthesis_filter_state2, 0, sizeof(synthesis_filter_state2));
  }

  int16_t low_pass_data[kSamplesPer16kHzChannel];
  int16_t high_pass_data[kSamplesPer16kHzChannel];

  int32_t analysis_filter_state1[6];
  int32_t analysis_filter_state2[6];
  int32_t synthesis_filter_state1[6];
  int32_t synthesis_filter_state2[6];
};

// TODO(andrew): check range of input parameters?
AudioBuffer::AudioBuffer(int max_num_channels,
                         int samples_per_channel)
  : max_num_channels_(max_num_channels),
    num_channels_(0),
    num_mixed_channels_(0),
    num_mixed_low_pass_channels_(0),
    data_was_mixed_(false),
    samples_per_channel_(samples_per_channel),
    samples_per_split_channel_(samples_per_channel),
    reference_copied_(false),
    activity_(AudioFrame::kVadUnknown),
    is_muted_(false),
    data_(NULL),
    channels_(NULL),
    split_channels_(NULL),
    mixed_channels_(NULL),
    mixed_low_pass_channels_(NULL),
    low_pass_reference_channels_(NULL) {
  channels_.reset(new AudioChannel[max_num_channels_]);
  mixed_channels_.reset(new AudioChannel[max_num_channels_]);
  mixed_low_pass_channels_.reset(new AudioChannel[max_num_channels_]);
  low_pass_reference_channels_.reset(new AudioChannel[max_num_channels_]);

  if (samples_per_channel_ == kSamplesPer32kHzChannel) {
    split_channels_.reset(new SplitAudioChannel[max_num_channels_]);
    samples_per_split_channel_ = kSamplesPer16kHzChannel;
  }
}

AudioBuffer::~AudioBuffer() {}

void AudioBuffer::InitForNewData(int num_channels) {
  num_channels_ = num_channels;
  data_ = NULL;
  data_was_mixed_ = false;
  num_mixed_channels_ = 0;
  num_mixed_low_pass_channels_ = 0;
  reference_copied_ = false;
  activity_ = AudioFrame::kVadUnknown;
  is_muted_ = false;
}

int16_t* AudioBuffer::data(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  if (data_ != NULL) {
    return data_;
  }

  return channels_[channel].data;
}

int16_t* AudioBuffer::low_pass_split_data(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  if (split_channels_.get() == NULL) {
    return data(channel);
  }

  return split_channels_[channel].low_pass_data;
}

int16_t* AudioBuffer::high_pass_split_data(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  if (split_channels_.get() == NULL) {
    return NULL;
  }

  return split_channels_[channel].high_pass_data;
}

int16_t* AudioBuffer::mixed_data(int channel) const {
  assert(channel >= 0 && channel < num_mixed_channels_);

  return mixed_channels_[channel].data;
}

int16_t* AudioBuffer::mixed_low_pass_data(int channel) const {
  assert(channel >= 0 && channel < num_mixed_low_pass_channels_);

  return mixed_low_pass_channels_[channel].data;
}

int16_t* AudioBuffer::low_pass_reference(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  if (!reference_copied_) {
    return NULL;
  }

  return low_pass_reference_channels_[channel].data;
}

int32_t* AudioBuffer::analysis_filter_state1(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  return split_channels_[channel].analysis_filter_state1;
}

int32_t* AudioBuffer::analysis_filter_state2(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  return split_channels_[channel].analysis_filter_state2;
}

int32_t* AudioBuffer::synthesis_filter_state1(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  return split_channels_[channel].synthesis_filter_state1;
}

int32_t* AudioBuffer::synthesis_filter_state2(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  return split_channels_[channel].synthesis_filter_state2;
}

void AudioBuffer::set_activity(AudioFrame::VADActivity activity) {
  activity_ = activity;
}

AudioFrame::VADActivity AudioBuffer::activity() const {
  return activity_;
}

bool AudioBuffer::is_muted() const {
  return is_muted_;
}

int AudioBuffer::num_channels() const {
  return num_channels_;
}

int AudioBuffer::samples_per_channel() const {
  return samples_per_channel_;
}

int AudioBuffer::samples_per_split_channel() const {
  return samples_per_split_channel_;
}

// TODO(andrew): Do deinterleaving and mixing in one step?
void AudioBuffer::DeinterleaveFrom(AudioFrame* frame) {
  assert(frame->num_channels_ <= max_num_channels_);
  assert(frame->samples_per_channel_ ==  samples_per_channel_);

  InitForNewData(frame->num_channels_);
  activity_ = frame->vad_activity_;
  if (frame->energy_ == 0) {
    is_muted_ = true;
  }

  if (num_channels_ == 1) {
    // We can get away with a pointer assignment in this case.
    data_ = frame->data_;
    return;
  }

  int16_t* interleaved = frame->data_;
  for (int i = 0; i < num_channels_; i++) {
    int16_t* deinterleaved = channels_[i].data;
    int interleaved_idx = i;
    for (int j = 0; j < samples_per_channel_; j++) {
      deinterleaved[j] = interleaved[interleaved_idx];
      interleaved_idx += num_channels_;
    }
  }
}

void AudioBuffer::InterleaveTo(AudioFrame* frame, bool data_changed) const {
  assert(frame->num_channels_ == num_channels_);
  assert(frame->samples_per_channel_ == samples_per_channel_);
  frame->vad_activity_ = activity_;

  if (!data_changed) {
    return;
  }

  if (num_channels_ == 1) {
    if (data_was_mixed_) {
      memcpy(frame->data_,
             channels_[0].data,
             sizeof(int16_t) * samples_per_channel_);
    } else {
      // These should point to the same buffer in this case.
      assert(data_ == frame->data_);
    }

    return;
  }

  int16_t* interleaved = frame->data_;
  for (int i = 0; i < num_channels_; i++) {
    int16_t* deinterleaved = channels_[i].data;
    int interleaved_idx = i;
    for (int j = 0; j < samples_per_channel_; j++) {
      interleaved[interleaved_idx] = deinterleaved[j];
      interleaved_idx += num_channels_;
    }
  }
}

void AudioBuffer::CopyFrom(const float* const* data, int samples_per_channel,
                           int num_channels) {
  assert(num_channels <= max_num_channels_);
  assert(samples_per_channel ==  samples_per_channel_);

  InitForNewData(num_channels);
  for (int i = 0; i < num_channels_; ++i) {
    ScaleAndRoundToInt16(data[i], samples_per_channel, channels_[i].data);
  }
}

void AudioBuffer::CopyTo(int samples_per_channel, int num_channels,
                         float* const* data) const {
  assert(num_channels == num_channels_);
  assert(samples_per_channel == samples_per_channel_);
  for (int i = 0; i < num_channels_; ++i) {
    ScaleToFloat(channels_[i].data, samples_per_channel, data[i]);
  }
}

// TODO(andrew): would be good to support the no-mix case with pointer
// assignment.
// TODO(andrew): handle mixing to multiple channels?
void AudioBuffer::Mix(int num_mixed_channels) {
  // We currently only support the stereo to mono case.
  assert(num_channels_ == 2);
  assert(num_mixed_channels == 1);

  StereoToMono(channels_[0].data,
               channels_[1].data,
               channels_[0].data,
               samples_per_channel_);

  num_channels_ = num_mixed_channels;
  data_was_mixed_ = true;
}

void AudioBuffer::CopyAndMix(int num_mixed_channels) {
  // We currently only support the stereo to mono case.
  assert(num_channels_ == 2);
  assert(num_mixed_channels == 1);

  StereoToMono(channels_[0].data,
               channels_[1].data,
               mixed_channels_[0].data,
               samples_per_channel_);

  num_mixed_channels_ = num_mixed_channels;
}

void AudioBuffer::CopyAndMixLowPass(int num_mixed_channels) {
  // We currently only support the stereo to mono case.
  assert(num_channels_ == 2);
  assert(num_mixed_channels == 1);

  StereoToMono(low_pass_split_data(0),
               low_pass_split_data(1),
               mixed_low_pass_channels_[0].data,
               samples_per_split_channel_);

  num_mixed_low_pass_channels_ = num_mixed_channels;
}

void AudioBuffer::CopyLowPassToReference() {
  reference_copied_ = true;
  for (int i = 0; i < num_channels_; i++) {
    memcpy(low_pass_reference_channels_[i].data,
           low_pass_split_data(i),
           sizeof(int16_t) * samples_per_split_channel_);
  }
}
}  // namespace webrtc
<commit_msg>StereoToMono: Remove useless call to WebRtcSpl_SatW32ToW16<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/modules/audio_processing/audio_buffer.h"

#include "webrtc/common_audio/include/audio_util.h"
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"

namespace webrtc {
namespace {

enum {
  kSamplesPer8kHzChannel = 80,
  kSamplesPer16kHzChannel = 160,
  kSamplesPer32kHzChannel = 320
};

void StereoToMono(const int16_t* left, const int16_t* right,
                  int16_t* out, int samples_per_channel) {
  assert(left != NULL && right != NULL && out != NULL);
  for (int i = 0; i < samples_per_channel; i++)
    out[i] = (static_cast<int32_t>(left[i]) +
              static_cast<int32_t>(right[i])) >> 1;
}
}  // namespace

struct AudioChannel {
  AudioChannel() {
    memset(data, 0, sizeof(data));
  }

  int16_t data[kSamplesPer32kHzChannel];
};

struct SplitAudioChannel {
  SplitAudioChannel() {
    memset(low_pass_data, 0, sizeof(low_pass_data));
    memset(high_pass_data, 0, sizeof(high_pass_data));
    memset(analysis_filter_state1, 0, sizeof(analysis_filter_state1));
    memset(analysis_filter_state2, 0, sizeof(analysis_filter_state2));
    memset(synthesis_filter_state1, 0, sizeof(synthesis_filter_state1));
    memset(synthesis_filter_state2, 0, sizeof(synthesis_filter_state2));
  }

  int16_t low_pass_data[kSamplesPer16kHzChannel];
  int16_t high_pass_data[kSamplesPer16kHzChannel];

  int32_t analysis_filter_state1[6];
  int32_t analysis_filter_state2[6];
  int32_t synthesis_filter_state1[6];
  int32_t synthesis_filter_state2[6];
};

// TODO(andrew): check range of input parameters?
AudioBuffer::AudioBuffer(int max_num_channels,
                         int samples_per_channel)
  : max_num_channels_(max_num_channels),
    num_channels_(0),
    num_mixed_channels_(0),
    num_mixed_low_pass_channels_(0),
    data_was_mixed_(false),
    samples_per_channel_(samples_per_channel),
    samples_per_split_channel_(samples_per_channel),
    reference_copied_(false),
    activity_(AudioFrame::kVadUnknown),
    is_muted_(false),
    data_(NULL),
    channels_(NULL),
    split_channels_(NULL),
    mixed_channels_(NULL),
    mixed_low_pass_channels_(NULL),
    low_pass_reference_channels_(NULL) {
  channels_.reset(new AudioChannel[max_num_channels_]);
  mixed_channels_.reset(new AudioChannel[max_num_channels_]);
  mixed_low_pass_channels_.reset(new AudioChannel[max_num_channels_]);
  low_pass_reference_channels_.reset(new AudioChannel[max_num_channels_]);

  if (samples_per_channel_ == kSamplesPer32kHzChannel) {
    split_channels_.reset(new SplitAudioChannel[max_num_channels_]);
    samples_per_split_channel_ = kSamplesPer16kHzChannel;
  }
}

AudioBuffer::~AudioBuffer() {}

void AudioBuffer::InitForNewData(int num_channels) {
  num_channels_ = num_channels;
  data_ = NULL;
  data_was_mixed_ = false;
  num_mixed_channels_ = 0;
  num_mixed_low_pass_channels_ = 0;
  reference_copied_ = false;
  activity_ = AudioFrame::kVadUnknown;
  is_muted_ = false;
}

int16_t* AudioBuffer::data(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  if (data_ != NULL) {
    return data_;
  }

  return channels_[channel].data;
}

int16_t* AudioBuffer::low_pass_split_data(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  if (split_channels_.get() == NULL) {
    return data(channel);
  }

  return split_channels_[channel].low_pass_data;
}

int16_t* AudioBuffer::high_pass_split_data(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  if (split_channels_.get() == NULL) {
    return NULL;
  }

  return split_channels_[channel].high_pass_data;
}

int16_t* AudioBuffer::mixed_data(int channel) const {
  assert(channel >= 0 && channel < num_mixed_channels_);

  return mixed_channels_[channel].data;
}

int16_t* AudioBuffer::mixed_low_pass_data(int channel) const {
  assert(channel >= 0 && channel < num_mixed_low_pass_channels_);

  return mixed_low_pass_channels_[channel].data;
}

int16_t* AudioBuffer::low_pass_reference(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  if (!reference_copied_) {
    return NULL;
  }

  return low_pass_reference_channels_[channel].data;
}

int32_t* AudioBuffer::analysis_filter_state1(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  return split_channels_[channel].analysis_filter_state1;
}

int32_t* AudioBuffer::analysis_filter_state2(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  return split_channels_[channel].analysis_filter_state2;
}

int32_t* AudioBuffer::synthesis_filter_state1(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  return split_channels_[channel].synthesis_filter_state1;
}

int32_t* AudioBuffer::synthesis_filter_state2(int channel) const {
  assert(channel >= 0 && channel < num_channels_);
  return split_channels_[channel].synthesis_filter_state2;
}

void AudioBuffer::set_activity(AudioFrame::VADActivity activity) {
  activity_ = activity;
}

AudioFrame::VADActivity AudioBuffer::activity() const {
  return activity_;
}

bool AudioBuffer::is_muted() const {
  return is_muted_;
}

int AudioBuffer::num_channels() const {
  return num_channels_;
}

int AudioBuffer::samples_per_channel() const {
  return samples_per_channel_;
}

int AudioBuffer::samples_per_split_channel() const {
  return samples_per_split_channel_;
}

// TODO(andrew): Do deinterleaving and mixing in one step?
void AudioBuffer::DeinterleaveFrom(AudioFrame* frame) {
  assert(frame->num_channels_ <= max_num_channels_);
  assert(frame->samples_per_channel_ ==  samples_per_channel_);

  InitForNewData(frame->num_channels_);
  activity_ = frame->vad_activity_;
  if (frame->energy_ == 0) {
    is_muted_ = true;
  }

  if (num_channels_ == 1) {
    // We can get away with a pointer assignment in this case.
    data_ = frame->data_;
    return;
  }

  int16_t* interleaved = frame->data_;
  for (int i = 0; i < num_channels_; i++) {
    int16_t* deinterleaved = channels_[i].data;
    int interleaved_idx = i;
    for (int j = 0; j < samples_per_channel_; j++) {
      deinterleaved[j] = interleaved[interleaved_idx];
      interleaved_idx += num_channels_;
    }
  }
}

void AudioBuffer::InterleaveTo(AudioFrame* frame, bool data_changed) const {
  assert(frame->num_channels_ == num_channels_);
  assert(frame->samples_per_channel_ == samples_per_channel_);
  frame->vad_activity_ = activity_;

  if (!data_changed) {
    return;
  }

  if (num_channels_ == 1) {
    if (data_was_mixed_) {
      memcpy(frame->data_,
             channels_[0].data,
             sizeof(int16_t) * samples_per_channel_);
    } else {
      // These should point to the same buffer in this case.
      assert(data_ == frame->data_);
    }

    return;
  }

  int16_t* interleaved = frame->data_;
  for (int i = 0; i < num_channels_; i++) {
    int16_t* deinterleaved = channels_[i].data;
    int interleaved_idx = i;
    for (int j = 0; j < samples_per_channel_; j++) {
      interleaved[interleaved_idx] = deinterleaved[j];
      interleaved_idx += num_channels_;
    }
  }
}

void AudioBuffer::CopyFrom(const float* const* data, int samples_per_channel,
                           int num_channels) {
  assert(num_channels <= max_num_channels_);
  assert(samples_per_channel ==  samples_per_channel_);

  InitForNewData(num_channels);
  for (int i = 0; i < num_channels_; ++i) {
    ScaleAndRoundToInt16(data[i], samples_per_channel, channels_[i].data);
  }
}

void AudioBuffer::CopyTo(int samples_per_channel, int num_channels,
                         float* const* data) const {
  assert(num_channels == num_channels_);
  assert(samples_per_channel == samples_per_channel_);
  for (int i = 0; i < num_channels_; ++i) {
    ScaleToFloat(channels_[i].data, samples_per_channel, data[i]);
  }
}

// TODO(andrew): would be good to support the no-mix case with pointer
// assignment.
// TODO(andrew): handle mixing to multiple channels?
void AudioBuffer::Mix(int num_mixed_channels) {
  // We currently only support the stereo to mono case.
  assert(num_channels_ == 2);
  assert(num_mixed_channels == 1);

  StereoToMono(channels_[0].data,
               channels_[1].data,
               channels_[0].data,
               samples_per_channel_);

  num_channels_ = num_mixed_channels;
  data_was_mixed_ = true;
}

void AudioBuffer::CopyAndMix(int num_mixed_channels) {
  // We currently only support the stereo to mono case.
  assert(num_channels_ == 2);
  assert(num_mixed_channels == 1);

  StereoToMono(channels_[0].data,
               channels_[1].data,
               mixed_channels_[0].data,
               samples_per_channel_);

  num_mixed_channels_ = num_mixed_channels;
}

void AudioBuffer::CopyAndMixLowPass(int num_mixed_channels) {
  // We currently only support the stereo to mono case.
  assert(num_channels_ == 2);
  assert(num_mixed_channels == 1);

  StereoToMono(low_pass_split_data(0),
               low_pass_split_data(1),
               mixed_low_pass_channels_[0].data,
               samples_per_split_channel_);

  num_mixed_low_pass_channels_ = num_mixed_channels;
}

void AudioBuffer::CopyLowPassToReference() {
  reference_copied_ = true;
  for (int i = 0; i < num_channels_; i++) {
    memcpy(low_pass_reference_channels_[i].data,
           low_pass_split_data(i),
           sizeof(int16_t) * samples_per_split_channel_);
  }
}
}  // namespace webrtc
<|endoftext|>


<commit_before>/****************************************************************/
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*          All contents are licensed under LGPL V2.1           */
/*             See LICENSE for full restrictions                */
/****************************************************************/
#include "Q2PAction.h"

#include "Factory.h"
#include "FEProblem.h"
#include "Parser.h"
#include "libmesh/string_to_enum.h"

template<>
InputParameters validParams<Q2PAction>()
{
  MooseEnum orders("CONSTANT FIRST SECOND THIRD FOURTH", "FIRST");

  InputParameters params = validParams<Action>();
  params.addRequiredParam<NonlinearVariableName>("porepressure", "The porepressure variable");
  params.addRequiredParam<NonlinearVariableName>("saturation", "The water saturation variable");
  params.addRequiredParam<UserObjectName>("water_density", "A RichardsDensity UserObject that defines the water density as a function of porepressure.");
  params.addRequiredParam<UserObjectName>("water_relperm", "A RichardsRelPerm UserObject that defines the water relative permeability as a function of water saturation (eg RichardsRelPermPower).");
  params.addParam<UserObjectName>("water_relperm_for_diffusion", "A RichardsRelPerm UserObject that defines the water relative permeability as a function of water saturation that will be used in the diffusivity Kernel (eg RichardsRelPermPower).  If not given, water_relperm will be used instead, which is the most common use-case.");
  params.addRequiredParam<Real>("water_viscosity", "The water viscosity");
  params.addRequiredParam<UserObjectName>("gas_density", "A RichardsDensity UserObject that defines the gas density as a function of porepressure.");
  params.addRequiredParam<UserObjectName>("gas_relperm", "A RichardsRelPerm UserObject that defines the gas relative permeability as a function of water saturation (eg Q2PRelPermPowerGas).");
  params.addRequiredParam<Real>("gas_viscosity", "The gas viscosity");
  params.addRequiredParam<Real>("diffusivity", "The diffusivity");
  params.addParam<std::vector<OutputName> >("output_nodal_masses_to", "Output Nodal masses to this Output object.  If you don't want any outputs, don't input anything here");
  params.addParam<std::vector<OutputName> >("output_total_masses_to", "Output total water and gas mass to this Output object.  If you don't want any outputs, don't input anything here");
  params.addParam<MooseEnum>("ORDER", orders, "The order for the porepressure and saturation: " + orders.getRawNames() + " (only needed if you're calculating masses)");
  return params;
}

Q2PAction::Q2PAction(const InputParameters & params) :
    Action(params),
    _pp_var(getParam<NonlinearVariableName>("porepressure")),
    _sat_var(getParam<NonlinearVariableName>("saturation")),
    _water_density(getParam<UserObjectName>("water_density")),
    _water_relperm(getParam<UserObjectName>("water_relperm")),
    _water_relperm_for_diffusivity(isParamValid("water_relperm_for_diffusivity") ? getParam<UserObjectName>("water_relperm_for_diffusivity") : getParam<UserObjectName>("water_relperm")),
    _water_viscosity(getParam<Real>("water_viscosity")),
    _gas_density(getParam<UserObjectName>("gas_density")),
    _gas_relperm(getParam<UserObjectName>("gas_relperm")),
    _gas_viscosity(getParam<Real>("gas_viscosity")),
    _diffusivity(getParam<Real>("diffusivity")),
    _output_nodal_masses_to(getParam<std::vector<OutputName> >("output_nodal_masses_to")),
    _output_total_masses_to(getParam<std::vector<OutputName> >("output_total_masses_to"))
{
  _nodal_masses_not_outputted = false;
  if (_output_nodal_masses_to.size() == 0)
    _nodal_masses_not_outputted = true;

  _total_masses_not_outputted = false;
  if (_output_total_masses_to.size() == 0)
    _total_masses_not_outputted = true;

  _no_mass_calculations = (_nodal_masses_not_outputted && _total_masses_not_outputted);
}

void
Q2PAction::act()
{
  // add the kernels
  if (_current_task == "add_kernel")
  {
    std::string kernel_name;
    std::string kernel_type;
    InputParameters params = _factory.getValidParams("Q2PNodalMass");

    kernel_name = "Q2P_nodal_water_mass";
    kernel_type = "Q2PNodalMass";
    params = _factory.getValidParams(kernel_type);
    params.set<NonlinearVariableName>("variable") = _sat_var;
    params.set<std::vector<VariableName> >("other_var") = std::vector<VariableName>(1, _pp_var);
    params.set<bool>("var_is_porepressure") = false;
    if (!_no_mass_calculations)
      params.set<std::vector<AuxVariableName> >("save_in") = std::vector<AuxVariableName>(1, "Q2P_nodal_water_mass_divided_by_dt");
    params.set<UserObjectName>("fluid_density") = _water_density;
    _problem->addKernel(kernel_type, kernel_name, params);

    kernel_name = "Q2P_nodal_gas_mass";
    kernel_type = "Q2PNodalMass";
    params = _factory.getValidParams(kernel_type);
    params.set<NonlinearVariableName>("variable") = _pp_var;
    params.set<std::vector<VariableName> >("other_var") = std::vector<VariableName>(1, _sat_var);
    params.set<bool>("var_is_porepressure") = true;
    if (!_no_mass_calculations)
      params.set<std::vector<AuxVariableName> >("save_in") = std::vector<AuxVariableName>(1, "Q2P_nodal_gas_mass_divided_by_dt");
    params.set<UserObjectName>("fluid_density") = _gas_density;
    _problem->addKernel(kernel_type, kernel_name, params);

    kernel_name = "Q2P_nodal_water_mass_old";
    kernel_type = "Q2PNegativeNodalMassOld";
    params = _factory.getValidParams(kernel_type);
    params.set<NonlinearVariableName>("variable") = _sat_var;
    params.set<std::vector<VariableName> >("other_var") = std::vector<VariableName>(1, _pp_var);
    params.set<bool>("var_is_porepressure") = false;
    params.set<UserObjectName>("fluid_density") = _water_density;
    _problem->addKernel(kernel_type, kernel_name, params);

    kernel_name = "Q2P_nodal_gas_mass_old";
    kernel_type = "Q2PNegativeNodalMassOld";
    params = _factory.getValidParams(kernel_type);
    params.set<NonlinearVariableName>("variable") = _pp_var;
    params.set<std::vector<VariableName> >("other_var") = std::vector<VariableName>(1, _sat_var);
    params.set<bool>("var_is_porepressure") = true;
    params.set<UserObjectName>("fluid_density") = _gas_density;
    _problem->addKernel(kernel_type, kernel_name, params);

    kernel_name = "Q2P_water_flux";
    kernel_type = "Q2PSaturationFlux";
    params = _factory.getValidParams(kernel_type);
    params.set<NonlinearVariableName>("variable") = _sat_var;
    params.set<std::vector<VariableName> >("porepressure_variable") = std::vector<VariableName>(1, _pp_var);
    params.set<UserObjectName>("fluid_density") = _water_density;
    params.set<UserObjectName>("fluid_relperm") = _water_relperm;
    params.set<Real>("fluid_viscosity") = _water_viscosity;
    _problem->addKernel(kernel_type, kernel_name, params);

    kernel_name = "Q2P_gas_flux";
    kernel_type = "Q2PPorepressureFlux";
    params = _factory.getValidParams(kernel_type);
    params.set<NonlinearVariableName>("variable") = _pp_var;
    params.set<std::vector<VariableName> >("saturation_variable") = std::vector<VariableName>(1, _sat_var);
    params.set<UserObjectName>("fluid_density") = _gas_density;
    params.set<UserObjectName>("fluid_relperm") = _gas_relperm;
    params.set<Real>("fluid_viscosity") = _gas_viscosity;
    _problem->addKernel(kernel_type, kernel_name, params);

    kernel_name = "Q2P_liquid_diffusion";
    kernel_type = "Q2PSaturationDiffusion";
    params = _factory.getValidParams(kernel_type);
    params.set<NonlinearVariableName>("variable") = _sat_var;
    params.set<std::vector<VariableName> >("porepressure_variable") = std::vector<VariableName>(1, _pp_var);
    params.set<UserObjectName>("fluid_density") = _water_density;
    params.set<UserObjectName>("fluid_relperm") = _water_relperm_for_diffusivity;
    params.set<Real>("fluid_viscosity") = _water_viscosity;
    params.set<Real>("diffusivity") = _diffusivity;
    _problem->addKernel(kernel_type, kernel_name, params);
  }

  if (_current_task == "add_aux_variable")
  {
    if (!_no_mass_calculations)
    {
      // user wants nodal masses or total masses
      _problem->addAuxVariable("Q2P_nodal_water_mass_divided_by_dt",
                               FEType(Utility::string_to_enum<Order>(getParam<MooseEnum>("ORDER")),
                                      Utility::string_to_enum<FEFamily>("LAGRANGE")));
      _problem->addAuxVariable("Q2P_nodal_gas_mass_divided_by_dt",
                               FEType(Utility::string_to_enum<Order>(getParam<MooseEnum>("ORDER")),
                                      Utility::string_to_enum<FEFamily>("LAGRANGE")));
    }
  }

  if (_current_task == "add_function" && _output_total_masses_to.size() > 0)
  {
    // user wants total masses, so need to build Functions to do this
    InputParameters params = _factory.getValidParams("ParsedFunction");

    params.set<std::string>("value") = "a*b";

    std::vector<std::string> vars;
    vars.push_back("a");
    vars.push_back("b");
    params.set<std::vector<std::string> >("vars") = vars;

    std::vector<std::string> vals_water;
    vals_water.push_back("Q2P_mass_water_divided_by_dt");
    vals_water.push_back("Q2P_dt");
    params.set<std::vector<std::string> >("vals") = vals_water;
    _problem->addFunction("ParsedFunction", "Q2P_water_mass_fcn", params, /*auto_parsed=*/ true);

    std::vector<std::string> vals_gas;
    vals_gas.push_back("Q2P_mass_gas_divided_by_dt");
    vals_gas.push_back("Q2P_dt");
    params.set<std::vector<std::string> >("vals") = vals_gas;
    _problem->addFunction("ParsedFunction", "Q2P_gas_mass_fcn", params, /*auto_parsed=*/ true);
  }

  if (_current_task == "add_postprocessor" && _output_total_masses_to.size() > 0)
  {
    // user wants total masses, so need to build Postprocessors to do this

    InputParameters params = _factory.getValidParams("TimestepSize");

    params.set<MultiMooseEnum>("execute_on") = "timestep_begin";
    params.set<std::vector<OutputName> >("outputs") = std::vector<OutputName>(1, "none");
    _problem->addPostprocessor("TimestepSize", "Q2P_dt", params);

    params = _factory.getValidParams("NodalSum");
    params.set<std::vector<OutputName> >("outputs") = std::vector<OutputName>(1, "none");
    params.set<std::vector<VariableName> >("variable") = std::vector<VariableName>(1, "Q2P_nodal_water_mass_divided_by_dt");
    _problem->addPostprocessor("NodalSum", "Q2P_mass_water_divided_by_dt", params);

    params = _factory.getValidParams("FunctionValuePostprocessor");
    params.set<FunctionName>("function") = "Q2P_water_mass_fcn";
    params.set<std::vector<OutputName> >("outputs") = _output_total_masses_to;
    _problem->addPostprocessor("FunctionValuePostprocessor", "mass_water", params);

    params = _factory.getValidParams("NodalSum");
    params.set<std::vector<OutputName> >("outputs") = std::vector<OutputName>(1, "none");
    params.set<std::vector<VariableName> >("variable") = std::vector<VariableName>(1, "Q2P_nodal_gas_mass_divided_by_dt");
    _problem->addPostprocessor("NodalSum", "Q2P_mass_gas_divided_by_dt", params);

    params = _factory.getValidParams("FunctionValuePostprocessor");
    params.set<FunctionName>("function") = "Q2P_gas_mass_fcn";
    params.set<std::vector<OutputName> >("outputs") = _output_total_masses_to;
    _problem->addPostprocessor("FunctionValuePostprocessor", "mass_gas", params);
  }

}

<commit_msg>Remove wrong auto-parse parameter (#6250)<commit_after>/****************************************************************/
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*          All contents are licensed under LGPL V2.1           */
/*             See LICENSE for full restrictions                */
/****************************************************************/
#include "Q2PAction.h"

#include "Factory.h"
#include "FEProblem.h"
#include "Parser.h"
#include "libmesh/string_to_enum.h"

template<>
InputParameters validParams<Q2PAction>()
{
  MooseEnum orders("CONSTANT FIRST SECOND THIRD FOURTH", "FIRST");

  InputParameters params = validParams<Action>();
  params.addRequiredParam<NonlinearVariableName>("porepressure", "The porepressure variable");
  params.addRequiredParam<NonlinearVariableName>("saturation", "The water saturation variable");
  params.addRequiredParam<UserObjectName>("water_density", "A RichardsDensity UserObject that defines the water density as a function of porepressure.");
  params.addRequiredParam<UserObjectName>("water_relperm", "A RichardsRelPerm UserObject that defines the water relative permeability as a function of water saturation (eg RichardsRelPermPower).");
  params.addParam<UserObjectName>("water_relperm_for_diffusion", "A RichardsRelPerm UserObject that defines the water relative permeability as a function of water saturation that will be used in the diffusivity Kernel (eg RichardsRelPermPower).  If not given, water_relperm will be used instead, which is the most common use-case.");
  params.addRequiredParam<Real>("water_viscosity", "The water viscosity");
  params.addRequiredParam<UserObjectName>("gas_density", "A RichardsDensity UserObject that defines the gas density as a function of porepressure.");
  params.addRequiredParam<UserObjectName>("gas_relperm", "A RichardsRelPerm UserObject that defines the gas relative permeability as a function of water saturation (eg Q2PRelPermPowerGas).");
  params.addRequiredParam<Real>("gas_viscosity", "The gas viscosity");
  params.addRequiredParam<Real>("diffusivity", "The diffusivity");
  params.addParam<std::vector<OutputName> >("output_nodal_masses_to", "Output Nodal masses to this Output object.  If you don't want any outputs, don't input anything here");
  params.addParam<std::vector<OutputName> >("output_total_masses_to", "Output total water and gas mass to this Output object.  If you don't want any outputs, don't input anything here");
  params.addParam<MooseEnum>("ORDER", orders, "The order for the porepressure and saturation: " + orders.getRawNames() + " (only needed if you're calculating masses)");
  return params;
}

Q2PAction::Q2PAction(const InputParameters & params) :
    Action(params),
    _pp_var(getParam<NonlinearVariableName>("porepressure")),
    _sat_var(getParam<NonlinearVariableName>("saturation")),
    _water_density(getParam<UserObjectName>("water_density")),
    _water_relperm(getParam<UserObjectName>("water_relperm")),
    _water_relperm_for_diffusivity(isParamValid("water_relperm_for_diffusivity") ? getParam<UserObjectName>("water_relperm_for_diffusivity") : getParam<UserObjectName>("water_relperm")),
    _water_viscosity(getParam<Real>("water_viscosity")),
    _gas_density(getParam<UserObjectName>("gas_density")),
    _gas_relperm(getParam<UserObjectName>("gas_relperm")),
    _gas_viscosity(getParam<Real>("gas_viscosity")),
    _diffusivity(getParam<Real>("diffusivity")),
    _output_nodal_masses_to(getParam<std::vector<OutputName> >("output_nodal_masses_to")),
    _output_total_masses_to(getParam<std::vector<OutputName> >("output_total_masses_to"))
{
  _nodal_masses_not_outputted = false;
  if (_output_nodal_masses_to.size() == 0)
    _nodal_masses_not_outputted = true;

  _total_masses_not_outputted = false;
  if (_output_total_masses_to.size() == 0)
    _total_masses_not_outputted = true;

  _no_mass_calculations = (_nodal_masses_not_outputted && _total_masses_not_outputted);
}

void
Q2PAction::act()
{
  // add the kernels
  if (_current_task == "add_kernel")
  {
    std::string kernel_name;
    std::string kernel_type;
    InputParameters params = _factory.getValidParams("Q2PNodalMass");

    kernel_name = "Q2P_nodal_water_mass";
    kernel_type = "Q2PNodalMass";
    params = _factory.getValidParams(kernel_type);
    params.set<NonlinearVariableName>("variable") = _sat_var;
    params.set<std::vector<VariableName> >("other_var") = std::vector<VariableName>(1, _pp_var);
    params.set<bool>("var_is_porepressure") = false;
    if (!_no_mass_calculations)
      params.set<std::vector<AuxVariableName> >("save_in") = std::vector<AuxVariableName>(1, "Q2P_nodal_water_mass_divided_by_dt");
    params.set<UserObjectName>("fluid_density") = _water_density;
    _problem->addKernel(kernel_type, kernel_name, params);

    kernel_name = "Q2P_nodal_gas_mass";
    kernel_type = "Q2PNodalMass";
    params = _factory.getValidParams(kernel_type);
    params.set<NonlinearVariableName>("variable") = _pp_var;
    params.set<std::vector<VariableName> >("other_var") = std::vector<VariableName>(1, _sat_var);
    params.set<bool>("var_is_porepressure") = true;
    if (!_no_mass_calculations)
      params.set<std::vector<AuxVariableName> >("save_in") = std::vector<AuxVariableName>(1, "Q2P_nodal_gas_mass_divided_by_dt");
    params.set<UserObjectName>("fluid_density") = _gas_density;
    _problem->addKernel(kernel_type, kernel_name, params);

    kernel_name = "Q2P_nodal_water_mass_old";
    kernel_type = "Q2PNegativeNodalMassOld";
    params = _factory.getValidParams(kernel_type);
    params.set<NonlinearVariableName>("variable") = _sat_var;
    params.set<std::vector<VariableName> >("other_var") = std::vector<VariableName>(1, _pp_var);
    params.set<bool>("var_is_porepressure") = false;
    params.set<UserObjectName>("fluid_density") = _water_density;
    _problem->addKernel(kernel_type, kernel_name, params);

    kernel_name = "Q2P_nodal_gas_mass_old";
    kernel_type = "Q2PNegativeNodalMassOld";
    params = _factory.getValidParams(kernel_type);
    params.set<NonlinearVariableName>("variable") = _pp_var;
    params.set<std::vector<VariableName> >("other_var") = std::vector<VariableName>(1, _sat_var);
    params.set<bool>("var_is_porepressure") = true;
    params.set<UserObjectName>("fluid_density") = _gas_density;
    _problem->addKernel(kernel_type, kernel_name, params);

    kernel_name = "Q2P_water_flux";
    kernel_type = "Q2PSaturationFlux";
    params = _factory.getValidParams(kernel_type);
    params.set<NonlinearVariableName>("variable") = _sat_var;
    params.set<std::vector<VariableName> >("porepressure_variable") = std::vector<VariableName>(1, _pp_var);
    params.set<UserObjectName>("fluid_density") = _water_density;
    params.set<UserObjectName>("fluid_relperm") = _water_relperm;
    params.set<Real>("fluid_viscosity") = _water_viscosity;
    _problem->addKernel(kernel_type, kernel_name, params);

    kernel_name = "Q2P_gas_flux";
    kernel_type = "Q2PPorepressureFlux";
    params = _factory.getValidParams(kernel_type);
    params.set<NonlinearVariableName>("variable") = _pp_var;
    params.set<std::vector<VariableName> >("saturation_variable") = std::vector<VariableName>(1, _sat_var);
    params.set<UserObjectName>("fluid_density") = _gas_density;
    params.set<UserObjectName>("fluid_relperm") = _gas_relperm;
    params.set<Real>("fluid_viscosity") = _gas_viscosity;
    _problem->addKernel(kernel_type, kernel_name, params);

    kernel_name = "Q2P_liquid_diffusion";
    kernel_type = "Q2PSaturationDiffusion";
    params = _factory.getValidParams(kernel_type);
    params.set<NonlinearVariableName>("variable") = _sat_var;
    params.set<std::vector<VariableName> >("porepressure_variable") = std::vector<VariableName>(1, _pp_var);
    params.set<UserObjectName>("fluid_density") = _water_density;
    params.set<UserObjectName>("fluid_relperm") = _water_relperm_for_diffusivity;
    params.set<Real>("fluid_viscosity") = _water_viscosity;
    params.set<Real>("diffusivity") = _diffusivity;
    _problem->addKernel(kernel_type, kernel_name, params);
  }

  if (_current_task == "add_aux_variable")
  {
    if (!_no_mass_calculations)
    {
      // user wants nodal masses or total masses
      _problem->addAuxVariable("Q2P_nodal_water_mass_divided_by_dt",
                               FEType(Utility::string_to_enum<Order>(getParam<MooseEnum>("ORDER")),
                                      Utility::string_to_enum<FEFamily>("LAGRANGE")));
      _problem->addAuxVariable("Q2P_nodal_gas_mass_divided_by_dt",
                               FEType(Utility::string_to_enum<Order>(getParam<MooseEnum>("ORDER")),
                                      Utility::string_to_enum<FEFamily>("LAGRANGE")));
    }
  }

  if (_current_task == "add_function" && _output_total_masses_to.size() > 0)
  {
    // user wants total masses, so need to build Functions to do this
    InputParameters params = _factory.getValidParams("ParsedFunction");

    params.set<std::string>("value") = "a*b";

    std::vector<std::string> vars;
    vars.push_back("a");
    vars.push_back("b");
    params.set<std::vector<std::string> >("vars") = vars;

    std::vector<std::string> vals_water;
    vals_water.push_back("Q2P_mass_water_divided_by_dt");
    vals_water.push_back("Q2P_dt");
    params.set<std::vector<std::string> >("vals") = vals_water;
    _problem->addFunction("ParsedFunction", "Q2P_water_mass_fcn", params);

    std::vector<std::string> vals_gas;
    vals_gas.push_back("Q2P_mass_gas_divided_by_dt");
    vals_gas.push_back("Q2P_dt");
    params.set<std::vector<std::string> >("vals") = vals_gas;
    _problem->addFunction("ParsedFunction", "Q2P_gas_mass_fcn", params);
  }

  if (_current_task == "add_postprocessor" && _output_total_masses_to.size() > 0)
  {
    // user wants total masses, so need to build Postprocessors to do this

    InputParameters params = _factory.getValidParams("TimestepSize");

    params.set<MultiMooseEnum>("execute_on") = "timestep_begin";
    params.set<std::vector<OutputName> >("outputs") = std::vector<OutputName>(1, "none");
    _problem->addPostprocessor("TimestepSize", "Q2P_dt", params);

    params = _factory.getValidParams("NodalSum");
    params.set<std::vector<OutputName> >("outputs") = std::vector<OutputName>(1, "none");
    params.set<std::vector<VariableName> >("variable") = std::vector<VariableName>(1, "Q2P_nodal_water_mass_divided_by_dt");
    _problem->addPostprocessor("NodalSum", "Q2P_mass_water_divided_by_dt", params);

    params = _factory.getValidParams("FunctionValuePostprocessor");
    params.set<FunctionName>("function") = "Q2P_water_mass_fcn";
    params.set<std::vector<OutputName> >("outputs") = _output_total_masses_to;
    _problem->addPostprocessor("FunctionValuePostprocessor", "mass_water", params);

    params = _factory.getValidParams("NodalSum");
    params.set<std::vector<OutputName> >("outputs") = std::vector<OutputName>(1, "none");
    params.set<std::vector<VariableName> >("variable") = std::vector<VariableName>(1, "Q2P_nodal_gas_mass_divided_by_dt");
    _problem->addPostprocessor("NodalSum", "Q2P_mass_gas_divided_by_dt", params);

    params = _factory.getValidParams("FunctionValuePostprocessor");
    params.set<FunctionName>("function") = "Q2P_gas_mass_fcn";
    params.set<std::vector<OutputName> >("outputs") = _output_total_masses_to;
    _problem->addPostprocessor("FunctionValuePostprocessor", "mass_gas", params);
  }

}
<|endoftext|>


<commit_before>#include <cmath>
#include "DataStruct.h"

ClassImp(Event)
ClassImp(Dimuon)
ClassImp(Spill)
ClassImp(Track)

#define SPILLID_MIN_57 303215
#define SPILLID_MAX_57 370100
#define SPILLID_MIN_59 370110
#define SPILLID_MAX_59 388580
#define SPILLID_MIN_61 391072
#define SPILLID_MAX_61 391100
#define SPILLID_MIN_62 394308
#define SPILLID_MAX_62 482573
#define SPILLID_MIN_67 484946
#define SPILLID_MAX_67 676224
#define SPILLID_MIN_70 676498
#define SPILLID_MAX_70 696455

Event::Event() : runID(-1), spillID(-1), eventID(-1), status(-1), MATRIX1(-1), weight(0.), intensity(0.)
{}

bool Event::goodEvent()
{
    return MATRIX1 > 0;
}

bool Dimuon::goodDimuon()
{
    if(fabs(dx) > 2. || fabs(dy) > 2.) return false;
    if(dz < -300. || dz > 150.) return false;
    if(fabs(dpx) > 3. || fabs(dpy) > 3.) return false;
    if(dpz < 30. || dpz > 120.) return false;
    if(x1 < 0. || x1 > 1.) return false;
    if(x2 < 0. || x2 > 1.) return false;
    if(xF < -1. || xF > 1.) return false;
    if(fabs(trackSeparation) > 200.) return false;
    if(chisq_dimuon > 25.) return false;
    if(px1 < 0. || px2 > 0.) return false;

    return true;
}

bool Dimuon::targetDimuon()
{
    if(dz > -90. || dz < -300.) return false;
    return true;
}

bool Dimuon::dumpDimuon()
{
    if(dz < 0. || dz > 150.) return false;
    return true;
}

Spill::Spill() : spillID(-1), quality(-1), targetPos(-1), TARGPOS_CONTROL(-1), skipflag(false)
{}

bool Spill::goodSpill()
{
    return skipflag || (goodTargetPos() && goodTSGo() && goodScaler() && goodBeam() && goodBeamDAQ());
}

bool Spill::goodTargetPos()
{
    if(targetPos != TARGPOS_CONTROL) return false;
    if(targetPos < 1 || targetPos > 7) return false;

    return true;
}

bool Spill::goodTSGo()
{
    int trigSet = triggerSet();
    if(trigSet < 0)
    {
        return false;
    }
    else if(trigSet <= 61)
    {
        if(TSGo < 1E3 || TSGo > 8E3) return false;
    }
    else if(trigSet <= 70)
    {
        if(TSGo < 1E2 || TSGo > 6E3) return false;
    }
    else
    {
        return false;
    }

    return true;
}

bool Spill::goodScaler()
{
    int trigSet = triggerSet();
    if(trigSet < 0)
    {
        return false;
    }
    else if(trigSet <= 61)
    {
        if(acceptedMatrix1 < 1E3 || acceptedMatrix1 > 8E3) return false;
        if(afterInhMatrix1 < 1E3 || afterInhMatrix1 > 3E4) return false;
        if(acceptedMatrix1/afterInhMatrix1 < 0.2 || acceptedMatrix1/afterInhMatrix1 > 0.9) return false;
    }
    else if(trigSet <= 70)
    {
        if(acceptedMatrix1 < 1E2 || acceptedMatrix1 > 6E3) return false;
        if(afterInhMatrix1 < 1E2 || afterInhMatrix1 > 1E4) return false;
        if(acceptedMatrix1/afterInhMatrix1 < 0.2 || acceptedMatrix1/afterInhMatrix1 > 1.05) return false;
    }
    else
    {
        return false;
    }

    return true;
}

bool Spill::goodBeam()
{
    int trigSet = triggerSet();
    if(trigSet < 0)
    {
        return false;
    }
    else if(trigSet <= 61)
    {
        //if(NM3ION < 2E12 || NM3ION > 1E13) return false;
        if(G2SEM < 2E12 || G2SEM > 1E13) return false;
        if(dutyFactor < 15. || dutyFactor > 60.) return false;
    }
    else if(trigSet <= 70)
    {
        //if(NM3ION < 2E12 || NM3ION > 1E13) return false;
        if(G2SEM < 2E12 || G2SEM > 1E13) return false;
        if(dutyFactor < 10. || dutyFactor > 60.) return false;
    }
    else
    {
        return false;
    }

    return true;
}

bool Spill::goodBeamDAQ()
{
    int trigSet = triggerSet();
    if(trigSet < 0)
    {
        return false;
    }
    else if(trigSet <= 61)
    {
        if(QIESum < 4E10 || QIESum > 1E12) return false;
        if(inhibitSum < 4E9 || inhibitSum > 1E11) return false;
        if(busySum < 4E9 || busySum > 1E11) return false;
    }
    else if(trigSet <= 70)
    {
        if(QIESum < 4E10 || QIESum > 1E12) return false;
        if(inhibitSum < 4E9 || inhibitSum > 2E11) return false;
        if(busySum < 4E9 || busySum > 1E11) return false;
    }
    else
    {
        return false;
    }

    return true;
}

int Spill::triggerSet()
{
    if(spillID >= SPILLID_MIN_57 && spillID <= SPILLID_MAX_57) return 57;
    if(spillID >= SPILLID_MIN_59 && spillID <= SPILLID_MAX_59) return 59;
    if(spillID >= SPILLID_MIN_61 && spillID <= SPILLID_MAX_61) return 61;
    if(spillID >= SPILLID_MIN_62 && spillID <= SPILLID_MAX_62) return 62;
    if(spillID >= SPILLID_MIN_67 && spillID <= SPILLID_MAX_67) return 67;
    if(spillID >= SPILLID_MIN_70 && spillID <= SPILLID_MAX_70) return 70;
    return -1;
}

void Spill::print()
{
    using namespace std;
    cout << " trigge set:        " << triggerSet() << endl;
    cout << " targetPos:         " << targetPos << "  " << TARGPOS_CONTROL << endl;
    cout << " TSGo:              " << TSGo << endl;
    cout << " acceptedMatrix1:   " << acceptedMatrix1 << endl;
    cout << " afterInhMatrix1:   " << afterInhMatrix1 << endl;
    cout << " NM3ION:            " << NM3ION << endl;
    cout << " G2SEM:             " << G2SEM << endl;
    cout << " QIESum:            " << QIESum << endl;
    cout << " inhibitSum:        " << inhibitSum << endl;
    cout << " busySum:           " << busySum << endl;
    cout << " dutyFactor:        " << dutyFactor << endl;
    cout << " liveG2SEM:         " << liveG2SEM << endl;
}

bool Track::goodTrack()
{
    if(nHits <= 14) return false;
    if(chisq/(nHits - 5) > 6.) return false;
    if(nHits < 18 && pz1 < 18.) return false;

    return true;
}

bool Track::targetTrack()
{
    if(z0 <= -300. || z0 >= 0.) return false;
    if(sqrt(xD*xD + yD*yD) - sqrt(xT*xT + yT*yT) < 9.4431 - 0.356141*pzv + 0.00566071*pzv*pzv - 3.05556E-5*pzv*pzv*pzv) return false;

    return true;
}

bool Track::dumpTrack()
{
    if(z0 <= 0. && z0 >= 150.) return false;
    if(sqrt(xT*xT + yT*yT) - sqrt(xD*xD + yD*yD) < 9.4431 - 0.356141*pzv + 0.00566071*pzv*pzv - 3.05556E-5*pzv*pzv*pzv) return false;

    return true;
}
<commit_msg>Minor typo fix<commit_after>#include <cmath>
#include "DataStruct.h"

ClassImp(Event)
ClassImp(Dimuon)
ClassImp(Spill)
ClassImp(Track)

#define SPILLID_MIN_57 303215
#define SPILLID_MAX_57 370100
#define SPILLID_MIN_59 370110
#define SPILLID_MAX_59 388580
#define SPILLID_MIN_61 388611
#define SPILLID_MAX_61 391100
#define SPILLID_MIN_62 394308
#define SPILLID_MAX_62 482573
#define SPILLID_MIN_67 484946
#define SPILLID_MAX_67 676224
#define SPILLID_MIN_70 676498
#define SPILLID_MAX_70 696455

Event::Event() : runID(-1), spillID(-1), eventID(-1), status(-1), MATRIX1(-1), weight(0.), intensity(0.)
{}

bool Event::goodEvent()
{
    return MATRIX1 > 0;
}

bool Dimuon::goodDimuon()
{
    if(fabs(dx) > 2. || fabs(dy) > 2.) return false;
    if(dz < -300. || dz > 150.) return false;
    if(fabs(dpx) > 3. || fabs(dpy) > 3.) return false;
    if(dpz < 30. || dpz > 120.) return false;
    if(x1 < 0. || x1 > 1.) return false;
    if(x2 < 0. || x2 > 1.) return false;
    if(xF < -1. || xF > 1.) return false;
    if(fabs(trackSeparation) > 200.) return false;
    if(chisq_dimuon > 25.) return false;
    if(px1 < 0. || px2 > 0.) return false;

    return true;
}

bool Dimuon::targetDimuon()
{
    if(dz > -90. || dz < -300.) return false;
    return true;
}

bool Dimuon::dumpDimuon()
{
    if(dz < 0. || dz > 150.) return false;
    return true;
}

Spill::Spill() : spillID(-1), quality(-1), targetPos(-1), TARGPOS_CONTROL(-1), skipflag(false)
{}

bool Spill::goodSpill()
{
    return skipflag || (goodTargetPos() && goodTSGo() && goodScaler() && goodBeam() && goodBeamDAQ());
}

bool Spill::goodTargetPos()
{
    if(targetPos != TARGPOS_CONTROL) return false;
    if(targetPos < 1 || targetPos > 7) return false;

    return true;
}

bool Spill::goodTSGo()
{
    int trigSet = triggerSet();
    if(trigSet < 0)
    {
        return false;
    }
    else if(trigSet <= 61)
    {
        if(TSGo < 1E3 || TSGo > 8E3) return false;
    }
    else if(trigSet <= 70)
    {
        if(TSGo < 1E2 || TSGo > 6E3) return false;
    }
    else
    {
        return false;
    }

    return true;
}

bool Spill::goodScaler()
{
    int trigSet = triggerSet();
    if(trigSet < 0)
    {
        return false;
    }
    else if(trigSet <= 61)
    {
        if(acceptedMatrix1 < 1E3 || acceptedMatrix1 > 8E3) return false;
        if(afterInhMatrix1 < 1E3 || afterInhMatrix1 > 3E4) return false;
        if(acceptedMatrix1/afterInhMatrix1 < 0.2 || acceptedMatrix1/afterInhMatrix1 > 0.9) return false;
    }
    else if(trigSet <= 70)
    {
        if(acceptedMatrix1 < 1E2 || acceptedMatrix1 > 6E3) return false;
        if(afterInhMatrix1 < 1E2 || afterInhMatrix1 > 1E4) return false;
        if(acceptedMatrix1/afterInhMatrix1 < 0.2 || acceptedMatrix1/afterInhMatrix1 > 1.05) return false;
    }
    else
    {
        return false;
    }

    return true;
}

bool Spill::goodBeam()
{
    int trigSet = triggerSet();
    if(trigSet < 0)
    {
        return false;
    }
    else if(trigSet <= 61)
    {
        //if(NM3ION < 2E12 || NM3ION > 1E13) return false;
        if(G2SEM < 2E12 || G2SEM > 1E13) return false;
        if(dutyFactor < 15. || dutyFactor > 60.) return false;
    }
    else if(trigSet <= 70)
    {
        //if(NM3ION < 2E12 || NM3ION > 1E13) return false;
        if(G2SEM < 2E12 || G2SEM > 1E13) return false;
        if(dutyFactor < 10. || dutyFactor > 60.) return false;
    }
    else
    {
        return false;
    }

    return true;
}

bool Spill::goodBeamDAQ()
{
    int trigSet = triggerSet();
    if(trigSet < 0)
    {
        return false;
    }
    else if(trigSet <= 61)
    {
        if(QIESum < 4E10 || QIESum > 1E12) return false;
        if(inhibitSum < 4E9 || inhibitSum > 1E11) return false;
        if(busySum < 4E9 || busySum > 1E11) return false;
    }
    else if(trigSet <= 70)
    {
        if(QIESum < 4E10 || QIESum > 1E12) return false;
        if(inhibitSum < 4E9 || inhibitSum > 2E11) return false;
        if(busySum < 4E9 || busySum > 1E11) return false;
    }
    else
    {
        return false;
    }

    return true;
}

int Spill::triggerSet()
{
    if(spillID >= SPILLID_MIN_57 && spillID <= SPILLID_MAX_57) return 57;
    if(spillID >= SPILLID_MIN_59 && spillID <= SPILLID_MAX_59) return 59;
    if(spillID >= SPILLID_MIN_61 && spillID <= SPILLID_MAX_61) return 61;
    if(spillID >= SPILLID_MIN_62 && spillID <= SPILLID_MAX_62) return 62;
    if(spillID >= SPILLID_MIN_67 && spillID <= SPILLID_MAX_67) return 67;
    if(spillID >= SPILLID_MIN_70 && spillID <= SPILLID_MAX_70) return 70;
    return -1;
}

void Spill::print()
{
    using namespace std;
    cout << " trigge set:        " << triggerSet() << endl;
    cout << " targetPos:         " << targetPos << "  " << TARGPOS_CONTROL << endl;
    cout << " TSGo:              " << TSGo << endl;
    cout << " acceptedMatrix1:   " << acceptedMatrix1 << endl;
    cout << " afterInhMatrix1:   " << afterInhMatrix1 << endl;
    cout << " NM3ION:            " << NM3ION << endl;
    cout << " G2SEM:             " << G2SEM << endl;
    cout << " QIESum:            " << QIESum << endl;
    cout << " inhibitSum:        " << inhibitSum << endl;
    cout << " busySum:           " << busySum << endl;
    cout << " dutyFactor:        " << dutyFactor << endl;
    cout << " liveG2SEM:         " << liveG2SEM << endl;
}

bool Track::goodTrack()
{
    if(nHits <= 14) return false;
    if(chisq/(nHits - 5) > 6.) return false;
    if(nHits < 18 && pz1 < 18.) return false;

    return true;
}

bool Track::targetTrack()
{
    if(z0 <= -300. || z0 >= 0.) return false;
    if(sqrt(xD*xD + yD*yD) - sqrt(xT*xT + yT*yT) < 9.4431 - 0.356141*pzv + 0.00566071*pzv*pzv - 3.05556E-5*pzv*pzv*pzv) return false;

    return true;
}

bool Track::dumpTrack()
{
    if(z0 <= 0. && z0 >= 150.) return false;
    if(sqrt(xT*xT + yT*yT) - sqrt(xD*xD + yD*yD) < 9.4431 - 0.356141*pzv + 0.00566071*pzv*pzv - 3.05556E-5*pzv*pzv*pzv) return false;

    return true;
}
<|endoftext|>


<commit_before>// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)

// This sample teaches how to reuse a test fixture in multiple test
// cases by deriving sub-fixtures from it.
//
// When you define a test fixture, you specify the name of the test
// case that will use this fixture.  Therefore, a test fixture can
// be used by only one test case.
//
// Sometimes, more than one test cases may want to use the same or
// slightly different test fixtures.  For example, you may want to
// make sure that all tests for a GUI library don't leak important
// system resources like fonts and brushes.  In Google Test, you do
// this by putting the shared logic in a super (as in "super class")
// test fixture, and then have each test case use a fixture derived
// from this super fixture.

#include <limits.h>
#include <time.h>
#include "sample3-inl.h"
#include "gtest/gtest.h"
#include "sample1.h"

// In this sample, we want to ensure that every test finishes within
// ~5 seconds.  If a test takes longer to run, we consider it a
// failure.
//
// We put the code for timing a test in a test fixture called
// "QuickTest".  QuickTest is intended to be the super fixture that
// other fixtures derive from, therefore there is no test case with
// the name "QuickTest".  This is OK.
//
// Later, we will derive multiple test fixtures from QuickTest.
class QuickTest : public testing::Test {
 protected:
  // Remember that SetUp() is run immediately before a test starts.
  // This is a good place to record the start time.
  virtual void SetUp() {
    start_time_ = time(NULL);
  }

  // TearDown() is invoked immediately after a test finishes.  Here we
  // check if the test was too slow.
  virtual void TearDown() {
    // Gets the time when the test finishes
    const time_t end_time = time(NULL);

    // Asserts that the test took no more than ~5 seconds.  Did you
    // know that you can use assertions in SetUp() and TearDown() as
    // well?
    EXPECT_TRUE(end_time - start_time_ <= 5) << "The test took too long.";
  }

  // The UTC time (in seconds) when the test starts
  time_t start_time_;
};

// We derive a fixture named IntegerFunctionTest from the QuickTest
// fixture.  All tests using this fixture will be automatically
// required to be quick.
class IntegerFunctionTest : public QuickTest {
  // We don't need any more logic than already in the QuickTest fixture.
  // Therefore the body is empty.
};

// Now we can write tests in the IntegerFunctionTest test case.

// Tests Factorial()
TEST_F(IntegerFunctionTest, Factorial) {
  // Tests factorial of negative numbers.
  EXPECT_EQ(1, Factorial(-5));
  EXPECT_EQ(1, Factorial(-1));
  EXPECT_TRUE(Factorial(-10) > 0);

  // Tests factorial of 0.
  EXPECT_EQ(1, Factorial(0));

  // Tests factorial of positive numbers.
  EXPECT_EQ(1, Factorial(1));
  EXPECT_EQ(2, Factorial(2));
  EXPECT_EQ(6, Factorial(3));
  EXPECT_EQ(40320, Factorial(8));
}

// Tests IsPrime()
TEST_F(IntegerFunctionTest, IsPrime) {
  // Tests negative input.
  EXPECT_TRUE(!IsPrime(-1));
  EXPECT_TRUE(!IsPrime(-2));
  EXPECT_TRUE(!IsPrime(INT_MIN));

  // Tests some trivial cases.
  EXPECT_TRUE(!IsPrime(0));
  EXPECT_TRUE(!IsPrime(1));
  EXPECT_TRUE(IsPrime(2));
  EXPECT_TRUE(IsPrime(3));

  // Tests positive input.
  EXPECT_TRUE(!IsPrime(4));
  EXPECT_TRUE(IsPrime(5));
  EXPECT_TRUE(!IsPrime(6));
  EXPECT_TRUE(IsPrime(23));
}

// The next test case (named "QueueTest") also needs to be quick, so
// we derive another fixture from QuickTest.
//
// The QueueTest test fixture has some logic and shared objects in
// addition to what's in QuickTest already.  We define the additional
// stuff inside the body of the test fixture, as usual.
class QueueTest : public QuickTest {
 protected:
  virtual void SetUp() {
    // First, we need to set up the super fixture (QuickTest).
    QuickTest::SetUp();

    // Second, some additional setup for this fixture.
    q1_.Enqueue(1);
    q2_.Enqueue(2);
    q2_.Enqueue(3);
  }

  // By default, TearDown() inherits the behavior of
  // QuickTest::TearDown().  As we have no additional cleaning work
  // for QueueTest, we omit it here.
  //
  // virtual void TearDown() {
  //   QuickTest::TearDown();
  // }

  Queue<int> q0_;
  Queue<int> q1_;
  Queue<int> q2_;
};

// Now, let's write tests using the QueueTest fixture.

// Tests the default constructor.
TEST_F(QueueTest, DefaultConstructor) {
  EXPECT_EQ(0u, q0_.Size());
}

// Tests Dequeue().
TEST_F(QueueTest, Dequeue) {
  int* n = q0_.Dequeue();
  EXPECT_TRUE(n == NULL);

  n = q1_.Dequeue();
  EXPECT_TRUE(n != NULL);
  EXPECT_EQ(1, *n);
  EXPECT_EQ(0u, q1_.Size());
  delete n;

  n = q2_.Dequeue();
  EXPECT_TRUE(n != NULL);
  EXPECT_EQ(2, *n);
  EXPECT_EQ(1u, q2_.Size());
  delete n;
}

// If necessary, you can derive further test fixtures from a derived
// fixture itself.  For example, you can derive another fixture from
// QueueTest.  Google Test imposes no limit on how deep the hierarchy
// can be.  In practice, however, you probably don't want it to be too
// deep as to be confusing.
<commit_msg>Simplifies test assertions in sample5.<commit_after>// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)

// This sample teaches how to reuse a test fixture in multiple test
// cases by deriving sub-fixtures from it.
//
// When you define a test fixture, you specify the name of the test
// case that will use this fixture.  Therefore, a test fixture can
// be used by only one test case.
//
// Sometimes, more than one test cases may want to use the same or
// slightly different test fixtures.  For example, you may want to
// make sure that all tests for a GUI library don't leak important
// system resources like fonts and brushes.  In Google Test, you do
// this by putting the shared logic in a super (as in "super class")
// test fixture, and then have each test case use a fixture derived
// from this super fixture.

#include <limits.h>
#include <time.h>
#include "sample3-inl.h"
#include "gtest/gtest.h"
#include "sample1.h"

// In this sample, we want to ensure that every test finishes within
// ~5 seconds.  If a test takes longer to run, we consider it a
// failure.
//
// We put the code for timing a test in a test fixture called
// "QuickTest".  QuickTest is intended to be the super fixture that
// other fixtures derive from, therefore there is no test case with
// the name "QuickTest".  This is OK.
//
// Later, we will derive multiple test fixtures from QuickTest.
class QuickTest : public testing::Test {
 protected:
  // Remember that SetUp() is run immediately before a test starts.
  // This is a good place to record the start time.
  virtual void SetUp() {
    start_time_ = time(NULL);
  }

  // TearDown() is invoked immediately after a test finishes.  Here we
  // check if the test was too slow.
  virtual void TearDown() {
    // Gets the time when the test finishes
    const time_t end_time = time(NULL);

    // Asserts that the test took no more than ~5 seconds.  Did you
    // know that you can use assertions in SetUp() and TearDown() as
    // well?
    EXPECT_TRUE(end_time - start_time_ <= 5) << "The test took too long.";
  }

  // The UTC time (in seconds) when the test starts
  time_t start_time_;
};

// We derive a fixture named IntegerFunctionTest from the QuickTest
// fixture.  All tests using this fixture will be automatically
// required to be quick.
class IntegerFunctionTest : public QuickTest {
  // We don't need any more logic than already in the QuickTest fixture.
  // Therefore the body is empty.
};

// Now we can write tests in the IntegerFunctionTest test case.

// Tests Factorial()
TEST_F(IntegerFunctionTest, Factorial) {
  // Tests factorial of negative numbers.
  EXPECT_EQ(1, Factorial(-5));
  EXPECT_EQ(1, Factorial(-1));
  EXPECT_TRUE(Factorial(-10) > 0);

  // Tests factorial of 0.
  EXPECT_EQ(1, Factorial(0));

  // Tests factorial of positive numbers.
  EXPECT_EQ(1, Factorial(1));
  EXPECT_EQ(2, Factorial(2));
  EXPECT_EQ(6, Factorial(3));
  EXPECT_EQ(40320, Factorial(8));
}

// Tests IsPrime()
TEST_F(IntegerFunctionTest, IsPrime) {
  // Tests negative input.
  EXPECT_FALSE(IsPrime(-1));
  EXPECT_FALSE(IsPrime(-2));
  EXPECT_FALSE(IsPrime(INT_MIN));

  // Tests some trivial cases.
  EXPECT_FALSE(IsPrime(0));
  EXPECT_FALSE(IsPrime(1));
  EXPECT_TRUE(IsPrime(2));
  EXPECT_TRUE(IsPrime(3));

  // Tests positive input.
  EXPECT_FALSE(IsPrime(4));
  EXPECT_TRUE(IsPrime(5));
  EXPECT_FALSE(IsPrime(6));
  EXPECT_TRUE(IsPrime(23));
}

// The next test case (named "QueueTest") also needs to be quick, so
// we derive another fixture from QuickTest.
//
// The QueueTest test fixture has some logic and shared objects in
// addition to what's in QuickTest already.  We define the additional
// stuff inside the body of the test fixture, as usual.
class QueueTest : public QuickTest {
 protected:
  virtual void SetUp() {
    // First, we need to set up the super fixture (QuickTest).
    QuickTest::SetUp();

    // Second, some additional setup for this fixture.
    q1_.Enqueue(1);
    q2_.Enqueue(2);
    q2_.Enqueue(3);
  }

  // By default, TearDown() inherits the behavior of
  // QuickTest::TearDown().  As we have no additional cleaning work
  // for QueueTest, we omit it here.
  //
  // virtual void TearDown() {
  //   QuickTest::TearDown();
  // }

  Queue<int> q0_;
  Queue<int> q1_;
  Queue<int> q2_;
};

// Now, let's write tests using the QueueTest fixture.

// Tests the default constructor.
TEST_F(QueueTest, DefaultConstructor) {
  EXPECT_EQ(0u, q0_.Size());
}

// Tests Dequeue().
TEST_F(QueueTest, Dequeue) {
  int* n = q0_.Dequeue();
  EXPECT_TRUE(n == NULL);

  n = q1_.Dequeue();
  EXPECT_TRUE(n != NULL);
  EXPECT_EQ(1, *n);
  EXPECT_EQ(0u, q1_.Size());
  delete n;

  n = q2_.Dequeue();
  EXPECT_TRUE(n != NULL);
  EXPECT_EQ(2, *n);
  EXPECT_EQ(1u, q2_.Size());
  delete n;
}

// If necessary, you can derive further test fixtures from a derived
// fixture itself.  For example, you can derive another fixture from
// QueueTest.  Google Test imposes no limit on how deep the hierarchy
// can be.  In practice, however, you probably don't want it to be too
// deep as to be confusing.
<|endoftext|>


<commit_before>/*
 * Copyright 2010-2012 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 = "utf-8";

namespace {

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

// cf. HTML Living Standard 13.2.2.2 Character encodings
// cf. http://bugs.icu-project.org/trac/browser/icu/trunk/source/data/mappings/convrtrs.txt
Override overrides[] = {
    { "euc-kr", "windows-949" },
    { "euc-jp", "windows-51932" },    // ucnv_open() may not understand 'CP51932'.
    { "gb2312", "GBK" },
    { "gb_2312-80", "GBK" },
    // { "iso-2022-jp", "CP50220" },  // ucnv_open() may not understand 'CP50220'; iso-2022-jp appears to be the same as CP50220 in ICU.
    { "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),
    encoding(optionalEncoding),
    stream(stream)
{
    initializeConverter();
    encoding = checkEncoding(encoding);
    if (encoding.empty())
        confidence = Tentative;
}

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 (confidence != Tentative)
        return;
    if (strncmp(p, "\xfe\xff", 2) == 0) {
        encoding = "utf-16be";
        confidence = Irrelevant;
        return;
    }
    if (strncmp(p, "\xff\xfe", 2) == 0) {
        encoding = "utf-16le";
        confidence = Irrelevant;
        return;
    }
    if (strncmp(p, "\xef\xbb\xbf", 3) == 0) {
        encoding = "utf-8";
        confidence = Irrelevant;
        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>(U16InputStream::detect) : Support the utf-16 encodings without BOM; cf. at-charset-029.<commit_after>/*
 * Copyright 2010-2012 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 = "utf-8";

namespace {

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

// cf. HTML Living Standard 13.2.2.2 Character encodings
// cf. http://bugs.icu-project.org/trac/browser/icu/trunk/source/data/mappings/convrtrs.txt
Override overrides[] = {
    { "euc-kr", "windows-949" },
    { "euc-jp", "windows-51932" },    // ucnv_open() may not understand 'CP51932'.
    { "gb2312", "GBK" },
    { "gb_2312-80", "GBK" },
    // { "iso-2022-jp", "CP50220" },  // ucnv_open() may not understand 'CP50220'; iso-2022-jp appears to be the same as CP50220 in ICU.
    { "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),
    encoding(optionalEncoding),
    stream(stream)
{
    initializeConverter();
    encoding = checkEncoding(encoding);
    if (encoding.empty())
        confidence = Tentative;
}

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)
{
    static char le[] = { 0x40, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x73, 0x00, 0x65, 0x00, 0x74, 0x00 };
    static char be[] = { 0x00, 0x40, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x73, 0x00, 0x65, 0x00, 0x74 };

    if (confidence != Tentative)
        return;
    if (strncmp(p, "\xfe\xff", 2) == 0 || strncmp(p, be, sizeof(be)) == 0) {
        encoding = "utf-16be";
        confidence = Irrelevant;
        return;
    }
    if (strncmp(p, "\xff\xfe", 2) == 0 || strncmp(p, le, sizeof(le)) == 0) {
        encoding = "utf-16le";
        confidence = Irrelevant;
        return;
    }
    if (strncmp(p, "\xef\xbb\xbf", 3) == 0) {
        encoding = "utf-8";
        confidence = Irrelevant;
        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|>