<commit_before>/*
 * Copyright 2018 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. Neither the name of the copyright holder 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 HOLDER 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.
 */

// Implementation of bed_reader.h
#include "third_party/nucleus/io/bed_reader.h"

#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_split.h"

#include "third_party/nucleus/protos/bed.pb.h"
#include "third_party/nucleus/util/utils.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/platform/logging.h"
#include "third_party/nucleus/platform/types.h"

namespace nucleus {

namespace tf = tensorflow;

// 256 KB read buffer.
constexpr int READER_BUFFER_SIZE = 256 * 1024;

// BED-specific attributes.
constexpr char BED_COMMENT_PREFIX[] = "#";

// -----------------------------------------------------------------------------
//
// Reader for BED format data.
//
// -----------------------------------------------------------------------------

namespace {

bool ValidNumBedFields(const int fields) {
  return (fields == 3 || fields == 4 || fields == 5 || fields == 6 ||
          fields == 8 || fields == 9 || fields == 12);
}

// Read the next non-comment line.
tf::Status NextNonCommentLine(TextReader& text_reader,
                              string* line) {
  CHECK(line != nullptr);
  string tmp;
  do {
    StatusOr<string> line_or = text_reader.ReadLine();
    TF_RETURN_IF_ERROR(line_or.status());
    tmp = line_or.ValueOrDie();
  } while (absl::StartsWith(tmp, BED_COMMENT_PREFIX));

  *line = tmp;
  return tf::Status::OK();
}

tf::Status ConvertToPb(const string& line, const int desiredNumFields,
                       int* numTokensSeen,
                       nucleus::genomics::v1::BedRecord* record) {
  CHECK(record != nullptr) << "BED record cannot be null";
  record->Clear();

  std::vector<string> tokens = absl::StrSplit(line, '\t');
  int numTokens = static_cast<int>(tokens.size());
  *numTokensSeen = numTokens;
  if (!ValidNumBedFields(numTokens)) {
    return tf::errors::Unknown("BED record has invalid number of fields");
  }
  int numFields =
      desiredNumFields == 0 ? numTokens : std::min(numTokens, desiredNumFields);
  int64 int64Value;
  record->set_reference_name(tokens[0]);
  CHECK(absl::SimpleAtoi(tokens[1], &int64Value));
  record->set_start(int64Value);
  CHECK(absl::SimpleAtoi(tokens[2], &int64Value));
  record->set_end(int64Value);
  if (numFields > 3) record->set_name(tokens[3]);
  if (numFields > 4) {
    double value;
    CHECK(absl::SimpleAtod(tokens[4].c_str(), &value));
    record->set_score(value);
  }
  if (numFields > 5) {
    if (tokens[5] == "+")
      record->set_strand(nucleus::genomics::v1::BedRecord::FORWARD_STRAND);
    else if (tokens[5] == "-")
      record->set_strand(nucleus::genomics::v1::BedRecord::REVERSE_STRAND);
    else if (tokens[5] == ".")
      record->set_strand(nucleus::genomics::v1::BedRecord::NO_STRAND);
    else
      return tf::errors::Unknown("Invalid BED record with unknown strand");
  }
  if (numFields > 7) {
    CHECK(absl::SimpleAtoi(tokens[6], &int64Value));
    record->set_thick_start(int64Value);
    CHECK(absl::SimpleAtoi(tokens[7], &int64Value));
    record->set_thick_end(int64Value);
  }
  if (numFields > 8) record->set_item_rgb(tokens[8]);
  if (numFields >= 12) {
    int32 int32Value;
    CHECK(absl::SimpleAtoi(tokens[9], &int32Value));
    record->set_block_count(int32Value);
    record->set_block_sizes(tokens[10]);
    record->set_block_starts(tokens[11]);
  }

  return tf::Status::OK();
}

// Peeks into the path to the first BED record and returns the number of fields
// in the record.
// NOTE: This is quite heavyweight. Reading upon initialization and then
// rewinding the stream to 0 would be a nicer solution.
tf::Status GetNumFields(const string& path, int* numFields) {
  CHECK(numFields != nullptr);
  string line;
  StatusOr<std::unique_ptr<TextReader>> status_or = TextReader::FromFile(path);
  TF_RETURN_IF_ERROR(status_or.status());
  std::unique_ptr<TextReader> text_reader = std::move(status_or.ValueOrDie());
  TF_RETURN_IF_ERROR(NextNonCommentLine(*text_reader, &line));
  TF_RETURN_IF_ERROR(text_reader->Close());
  std::vector<string> tokens = absl::StrSplit(line, '\t');
  *numFields = static_cast<int>(tokens.size());
  return tf::Status::OK();
}
}  // namespace

// Iterable class for traversing all BED records in the file.
class BedFullFileIterable : public BedIterable {
 public:
  // Advance to the next record.
  StatusOr<bool> Next(nucleus::genomics::v1::BedRecord* out) override;

  // Constructor is invoked via BedReader::Iterate.
  BedFullFileIterable(const BedReader* reader);
  ~BedFullFileIterable() override;
};

StatusOr<std::unique_ptr<BedReader>> BedReader::FromFile(
    const string& bed_path,
    const nucleus::genomics::v1::BedReaderOptions& options) {
  int numFieldsInBed;
  TF_RETURN_IF_ERROR(GetNumFields(bed_path, &numFieldsInBed));
  nucleus::genomics::v1::BedHeader header;
  header.set_num_fields(numFieldsInBed);
  // Ensure options are valid.
  if (options.num_fields() != 0 && (options.num_fields() > numFieldsInBed ||
                                    !ValidNumBedFields(options.num_fields()))) {
    return tf::errors::InvalidArgument(
        "Invalid requested number of fields to parse");
  }
  StatusOr<std::unique_ptr<TextReader>> status_or =
      TextReader::FromFile(bed_path);
  TF_RETURN_IF_ERROR(status_or.status());
  return std::unique_ptr<BedReader>(
      new BedReader(std::move(status_or.ValueOrDie()), options, header));
}

BedReader::BedReader(std::unique_ptr<TextReader> text_reader,
                     const nucleus::genomics::v1::BedReaderOptions& options,
                     const nucleus::genomics::v1::BedHeader& header)
    : options_(options), header_(header), text_reader_(std::move(text_reader))
{}

BedReader::~BedReader() {
  if (text_reader_) {
    TF_CHECK_OK(Close());
  }
}

tf::Status BedReader::Close() {
  if (!text_reader_) {
    return tf::errors::FailedPrecondition("BedReader already closed");
  }
  tf::Status status = text_reader_->Close();
  text_reader_ = nullptr;
  return status;
}

// Ensures the number of fields is consistent across all records in the BED.
tf::Status BedReader::Validate(const int numTokens) const {
  if (header_.num_fields() != numTokens) {
    return tf::errors::Unknown(
        "Invalid BED with varying number of fields in file");
  }
  return tf::Status::OK();
}

StatusOr<std::shared_ptr<BedIterable>> BedReader::Iterate() const {
  if (!text_reader_)
    return tf::errors::FailedPrecondition("Cannot Iterate a closed BedReader.");
  return StatusOr<std::shared_ptr<BedIterable>>(
      MakeIterable<BedFullFileIterable>(this));
}

// Iterable class definitions.
StatusOr<bool> BedFullFileIterable::Next(
    nucleus::genomics::v1::BedRecord* out) {
  TF_RETURN_IF_ERROR(CheckIsAlive());
  const BedReader* bed_reader = static_cast<const BedReader*>(reader_);
  string line;
  tf::Status status = NextNonCommentLine(*bed_reader->text_reader_, &line);
  if (tf::errors::IsOutOfRange(status)) {
    return false;
  } else if (!status.ok()) {
    return status;
  }
  int numTokens;
  TF_RETURN_IF_ERROR(
      ConvertToPb(line, bed_reader->Options().num_fields(), &numTokens, out));
  TF_RETURN_IF_ERROR(bed_reader->Validate(numTokens));
  return true;
}

BedFullFileIterable::~BedFullFileIterable() {}

BedFullFileIterable::BedFullFileIterable(const BedReader* reader)
    : Iterable(reader) {}

}  // namespace nucleus
<commit_msg>nucleus: Remove unused constant (nit) PiperOrigin-RevId: 199496113<commit_after>/*
 * Copyright 2018 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. Neither the name of the copyright holder 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 HOLDER 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.
 */

// Implementation of bed_reader.h
#include "third_party/nucleus/io/bed_reader.h"

#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_split.h"

#include "third_party/nucleus/protos/bed.pb.h"
#include "third_party/nucleus/util/utils.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/platform/logging.h"
#include "third_party/nucleus/platform/types.h"

namespace nucleus {

namespace tf = tensorflow;

// BED-specific attributes.
constexpr char BED_COMMENT_PREFIX[] = "#";

// -----------------------------------------------------------------------------
//
// Reader for BED format data.
//
// -----------------------------------------------------------------------------

namespace {

bool ValidNumBedFields(const int fields) {
  return (fields == 3 || fields == 4 || fields == 5 || fields == 6 ||
          fields == 8 || fields == 9 || fields == 12);
}

// Read the next non-comment line.
tf::Status NextNonCommentLine(TextReader& text_reader,
                              string* line) {
  CHECK(line != nullptr);
  string tmp;
  do {
    StatusOr<string> line_or = text_reader.ReadLine();
    TF_RETURN_IF_ERROR(line_or.status());
    tmp = line_or.ValueOrDie();
  } while (absl::StartsWith(tmp, BED_COMMENT_PREFIX));

  *line = tmp;
  return tf::Status::OK();
}

tf::Status ConvertToPb(const string& line, const int desiredNumFields,
                       int* numTokensSeen,
                       nucleus::genomics::v1::BedRecord* record) {
  CHECK(record != nullptr) << "BED record cannot be null";
  record->Clear();

  std::vector<string> tokens = absl::StrSplit(line, '\t');
  int numTokens = static_cast<int>(tokens.size());
  *numTokensSeen = numTokens;
  if (!ValidNumBedFields(numTokens)) {
    return tf::errors::Unknown("BED record has invalid number of fields");
  }
  int numFields =
      desiredNumFields == 0 ? numTokens : std::min(numTokens, desiredNumFields);
  int64 int64Value;
  record->set_reference_name(tokens[0]);
  CHECK(absl::SimpleAtoi(tokens[1], &int64Value));
  record->set_start(int64Value);
  CHECK(absl::SimpleAtoi(tokens[2], &int64Value));
  record->set_end(int64Value);
  if (numFields > 3) record->set_name(tokens[3]);
  if (numFields > 4) {
    double value;
    CHECK(absl::SimpleAtod(tokens[4].c_str(), &value));
    record->set_score(value);
  }
  if (numFields > 5) {
    if (tokens[5] == "+")
      record->set_strand(nucleus::genomics::v1::BedRecord::FORWARD_STRAND);
    else if (tokens[5] == "-")
      record->set_strand(nucleus::genomics::v1::BedRecord::REVERSE_STRAND);
    else if (tokens[5] == ".")
      record->set_strand(nucleus::genomics::v1::BedRecord::NO_STRAND);
    else
      return tf::errors::Unknown("Invalid BED record with unknown strand");
  }
  if (numFields > 7) {
    CHECK(absl::SimpleAtoi(tokens[6], &int64Value));
    record->set_thick_start(int64Value);
    CHECK(absl::SimpleAtoi(tokens[7], &int64Value));
    record->set_thick_end(int64Value);
  }
  if (numFields > 8) record->set_item_rgb(tokens[8]);
  if (numFields >= 12) {
    int32 int32Value;
    CHECK(absl::SimpleAtoi(tokens[9], &int32Value));
    record->set_block_count(int32Value);
    record->set_block_sizes(tokens[10]);
    record->set_block_starts(tokens[11]);
  }

  return tf::Status::OK();
}

// Peeks into the path to the first BED record and returns the number of fields
// in the record.
// NOTE: This is quite heavyweight. Reading upon initialization and then
// rewinding the stream to 0 would be a nicer solution.
tf::Status GetNumFields(const string& path, int* numFields) {
  CHECK(numFields != nullptr);
  string line;
  StatusOr<std::unique_ptr<TextReader>> status_or = TextReader::FromFile(path);
  TF_RETURN_IF_ERROR(status_or.status());
  std::unique_ptr<TextReader> text_reader = std::move(status_or.ValueOrDie());
  TF_RETURN_IF_ERROR(NextNonCommentLine(*text_reader, &line));
  TF_RETURN_IF_ERROR(text_reader->Close());
  std::vector<string> tokens = absl::StrSplit(line, '\t');
  *numFields = static_cast<int>(tokens.size());
  return tf::Status::OK();
}
}  // namespace

// Iterable class for traversing all BED records in the file.
class BedFullFileIterable : public BedIterable {
 public:
  // Advance to the next record.
  StatusOr<bool> Next(nucleus::genomics::v1::BedRecord* out) override;

  // Constructor is invoked via BedReader::Iterate.
  BedFullFileIterable(const BedReader* reader);
  ~BedFullFileIterable() override;
};

StatusOr<std::unique_ptr<BedReader>> BedReader::FromFile(
    const string& bed_path,
    const nucleus::genomics::v1::BedReaderOptions& options) {
  int numFieldsInBed;
  TF_RETURN_IF_ERROR(GetNumFields(bed_path, &numFieldsInBed));
  nucleus::genomics::v1::BedHeader header;
  header.set_num_fields(numFieldsInBed);
  // Ensure options are valid.
  if (options.num_fields() != 0 && (options.num_fields() > numFieldsInBed ||
                                    !ValidNumBedFields(options.num_fields()))) {
    return tf::errors::InvalidArgument(
        "Invalid requested number of fields to parse");
  }
  StatusOr<std::unique_ptr<TextReader>> status_or =
      TextReader::FromFile(bed_path);
  TF_RETURN_IF_ERROR(status_or.status());
  return std::unique_ptr<BedReader>(
      new BedReader(std::move(status_or.ValueOrDie()), options, header));
}

BedReader::BedReader(std::unique_ptr<TextReader> text_reader,
                     const nucleus::genomics::v1::BedReaderOptions& options,
                     const nucleus::genomics::v1::BedHeader& header)
    : options_(options), header_(header), text_reader_(std::move(text_reader))
{}

BedReader::~BedReader() {
  if (text_reader_) {
    TF_CHECK_OK(Close());
  }
}

tf::Status BedReader::Close() {
  if (!text_reader_) {
    return tf::errors::FailedPrecondition("BedReader already closed");
  }
  tf::Status status = text_reader_->Close();
  text_reader_ = nullptr;
  return status;
}

// Ensures the number of fields is consistent across all records in the BED.
tf::Status BedReader::Validate(const int numTokens) const {
  if (header_.num_fields() != numTokens) {
    return tf::errors::Unknown(
        "Invalid BED with varying number of fields in file");
  }
  return tf::Status::OK();
}

StatusOr<std::shared_ptr<BedIterable>> BedReader::Iterate() const {
  if (!text_reader_)
    return tf::errors::FailedPrecondition("Cannot Iterate a closed BedReader.");
  return StatusOr<std::shared_ptr<BedIterable>>(
      MakeIterable<BedFullFileIterable>(this));
}

// Iterable class definitions.
StatusOr<bool> BedFullFileIterable::Next(
    nucleus::genomics::v1::BedRecord* out) {
  TF_RETURN_IF_ERROR(CheckIsAlive());
  const BedReader* bed_reader = static_cast<const BedReader*>(reader_);
  string line;
  tf::Status status = NextNonCommentLine(*bed_reader->text_reader_, &line);
  if (tf::errors::IsOutOfRange(status)) {
    return false;
  } else if (!status.ok()) {
    return status;
  }
  int numTokens;
  TF_RETURN_IF_ERROR(
      ConvertToPb(line, bed_reader->Options().num_fields(), &numTokens, out));
  TF_RETURN_IF_ERROR(bed_reader->Validate(numTokens));
  return true;
}

BedFullFileIterable::~BedFullFileIterable() {}

BedFullFileIterable::BedFullFileIterable(const BedReader* reader)
    : Iterable(reader) {}

}  // namespace nucleus
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//  Fast Fourier Transform
//
//  fft  X_k =         \sum_{j=0}^{N - 1} x_k e^{-i * 2pi * j * k / N}
//  ifft x_k = (1/N) * \sum_{j=0}^{N - 1} x_k e^{ i * 2pi * j * k / N}
//  ex:
//  [1, 2, 3, 4]
//  [5, 6, 7, 8]
//  66: 5 * 1 + 6 * 4 + 7 * 3 + 8 * 2
//  68: 5 * 2 + 6 * 1 + 7 * 4 + 8 * 3
//  66: 5 * 3 + 6 * 2 + 7 * 1 + 8 * 4
//  60: 5 * 4 + 6 * 3 + 7 * 2 + 8 * 1
//  Usage
//  Given x[0...N-1], y[0...N-1]
//  The convolution z[n] = sum of x[k]y[n-k] (k = 0,...,N-1)
//  The index is cyclic: x[-1]=x[N-1], etc.
//  To find z[] in O(NlgN)
//     1. Compute X = fft(x), Y = fft(y)
//     2. fft(z) = Z = X * Y (element-wise multiplication)
//     3. z = ifft(Z)
///////////////////////////////////////////////////////////////////////////////

#include <bits/stdc++.h>

using namespace std;

#define SZ(x) ((int)(x).size())
#define PB(x) push_back(x)
#define MEMSET(x,v) memset(x,v,sizeof(x))
#define REP(i,n) for(int (i)=0;(i)<(n);++(i))

typedef complex<double> cpx;
class FFT {
public:
    static int rev(int n, int x) {
        int r = 0;
        for (int i = 0; i < n; i++)
            if (x & (1 << i))
                r |= (1 << (n - i - 1));
        return r;
    }
    // Size of a must be a power of 2
    static vector<cpx> fft(const vector<cpx> &f, bool inv) {
        const double TWO_PI = 2 * acos(-1);
        int n = SZ(f);
        assert(__builtin_popcount(n) == 1);
        vector<cpx> v(n);
        int r = __builtin_ctz(n);
        REP(i, n) v[rev(r, i)] = f[i];
        REP(s, r) {
            int m = 1 << (s + 1);
            double a = (inv ? 1 : -1) * TWO_PI / double(m);
            cpx b(cos(a), sin(a));
            for (int k = 0; k < n; k += m) {
                cpx w(1, 0);
                int h = m >> 1;
                for (int j = 0; j < h; j++) {
                    cpx t = w * v[k + j + h];
                    cpx u = v[k + j];
                    v[k + j] = u + t;
                    v[k + j + h] = u - t;
                    w *= b;
                }
            }
        }
        if (inv) for (int i = 0; i < n; i++) v[i] /= n;
        return v;
    }
    static vector<cpx> multiply(vector<cpx> &a, vector<cpx> &b) {
        int n = SZ(a);
        vector<cpx> A = fft(a, false);
        vector<cpx> B = fft(b, false);
        REP(i, n) A[i] *= B[i];
        return fft(A, true);
    }
};

int main() {
    vector<cpx> a = {1, 2, 3, 4};
    vector<cpx> b = {5, 6, 7, 8};
    vector<cpx> c = FFT::multiply(a, b);
    for (auto x : c) cout << x << " ";
    cout << endl;
    return 0;
}
<commit_msg>Update FFT.cpp<commit_after>///////////////////////////////////////////////////////////////////////////////
//  Fast Fourier Transform
//
//  fft  X_k =         \sum_{j=0}^{N - 1} x_k e^{-i * 2pi * j * k / N}
//  ifft x_k = (1/N) * \sum_{j=0}^{N - 1} x_k e^{ i * 2pi * j * k / N}
//  ex:
//  [1, 2, 3, 4]
//  [5, 6, 7, 8]
//  66: 5 * 1 + 6 * 4 + 7 * 3 + 8 * 2
//  68: 5 * 2 + 6 * 1 + 7 * 4 + 8 * 3
//  66: 5 * 3 + 6 * 2 + 7 * 1 + 8 * 4
//  60: 5 * 4 + 6 * 3 + 7 * 2 + 8 * 1
//  Usage
//  Given x[0...N-1], y[0...N-1]
//  The convolution z[n] = sum of x[k]y[n-k] (k = 0,...,N-1)
//  The index is cyclic: x[-1]=x[N-1], etc.
//  To find z[] in O(NlgN)
//     1. Compute X = fft(x), Y = fft(y)
//     2. fft(z) = Z = X * Y (element-wise multiplication)
//     3. z = ifft(Z)
///////////////////////////////////////////////////////////////////////////////

#include <bits/stdc++.h>

using namespace std;

#define SZ(x) ((int)(x).size())
#define PB(x) push_back(x)
#define MEMSET(x,v) memset(x,v,sizeof(x))
#define REP(i,n) for(int (i)=0;(i)<(n);++(i))

typedef complex<double> cpx;
class FFT {
public:
    static int rev(int n, int x) {
        int r = 0;
        for (int i = 0; i < n; i++)
            if (x & (1 << i))
                r |= (1 << (n - i - 1));
        return r;
    }
    // Size of a must be a power of 2
    static vector<cpx> fft(const vector<cpx> &f, bool inv) {
        const double TWO_PI = 2 * acos(-1);
        int n = SZ(f);
        assert(__builtin_popcount(n) == 1);
        vector<cpx> v(n);
        int r = __builtin_ctz(n);
        REP(i, n) v[rev(r, i)] = f[i];
        REP(s, r) {
            int m = 1 << (s + 1);
            double a = (inv ? 1 : -1) * TWO_PI / m;
            cpx b(cos(a), sin(a));
            for (int k = 0; k < n; k += m) {
                cpx w(1, 0);
                int h = m >> 1;
                for (int j = 0; j < h; j++) {
                    cpx t = w * v[k + j + h];
                    cpx u = v[k + j];
                    v[k + j] = u + t;
                    v[k + j + h] = u - t;
                    w *= b;
                }
            }
        }
        if (inv) for (int i = 0; i < n; i++) v[i] /= n;
        return v;
    }
    static vector<cpx> multiply(vector<cpx> &a, vector<cpx> &b) {
        int n = SZ(a);
        vector<cpx> A = fft(a, false);
        vector<cpx> B = fft(b, false);
        REP(i, n) A[i] *= B[i];
        return fft(A, true);
    }
};

int main() {
    vector<cpx> a = {1, 2, 3, 4};
    vector<cpx> b = {5, 6, 7, 8};
    vector<cpx> c = FFT::multiply(a, b);
    for (auto x : c) cout << x << " ";
    cout << endl;
    return 0;
}
<|endoftext|>


<commit_before>/* openrtb_exchange_connector.cc
   Eric Robert, 7 May 2013

   Implementation of the OpenRTB exchange connector.
*/

#include "openrtb_exchange_connector.h"
#include "rtbkit/common/testing/exchange_source.h"
#include "rtbkit/plugins/bid_request/openrtb_bid_request.h"
#include "rtbkit/plugins/bid_request/openrtb_bid_source.h"
#include "rtbkit/plugins/exchange/http_auction_handler.h"
#include "rtbkit/core/agent_configuration/agent_config.h"
#include "openrtb/openrtb_parsing.h"
#include "soa/types/json_printing.h"
#include <boost/any.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
#include "jml/utils/file_functions.h"
#include "jml/arch/info.h"
#include "jml/utils/rng.h"

using namespace Datacratic;

namespace Datacratic {

template<typename T, int I, typename S>
Json::Value jsonEncode(const ML::compact_vector<T, I, S> & vec)
{
    Json::Value result(Json::arrayValue);
    for (unsigned i = 0;  i < vec.size();  ++i)
        result[i] = jsonEncode(vec[i]);
    return result;
}

template<typename T, int I, typename S>
ML::compact_vector<T, I, S>
jsonDecode(const Json::Value & val, ML::compact_vector<T, I, S> *)
{
    ExcAssert(val.isArray());
    ML::compact_vector<T, I, S> res;
    res.reserve(val.size());
    for (unsigned i = 0;  i < val.size();  ++i)
        res.push_back(jsonDecode(val[i], (T*)0));
    return res;
}

} // namespace Datacratic

namespace OpenRTB {

template<typename T>
Json::Value jsonEncode(const OpenRTB::List<T> & vec)
{
    using Datacratic::jsonEncode;
    Json::Value result(Json::arrayValue);
    for (unsigned i = 0;  i < vec.size();  ++i)
        result[i] = jsonEncode(vec[i]);
    return result;
}

template<typename T>
OpenRTB::List<T>
jsonDecode(const Json::Value & val, OpenRTB::List<T> *)
{
    using Datacratic::jsonDecode;
    ExcAssert(val.isArray());
    OpenRTB::List<T> res;
    res.reserve(val.size());
    for (unsigned i = 0;  i < val.size();  ++i)
        res.push_back(jsonDecode(val[i], (T*)0));
    return res;
}

} // namespace OpenRTB

namespace RTBKIT {

BOOST_STATIC_ASSERT(hasFromJson<Datacratic::Id>::value == true);
BOOST_STATIC_ASSERT(hasFromJson<int>::value == false);

/*****************************************************************************/
/* OPENRTB EXCHANGE CONNECTOR                                                */
/*****************************************************************************/

OpenRTBExchangeConnector::
OpenRTBExchangeConnector(ServiceBase & owner, const std::string & name)
    : HttpExchangeConnector(name, owner)
{
}

OpenRTBExchangeConnector::
OpenRTBExchangeConnector(const std::string & name,
                         std::shared_ptr<ServiceProxies> proxies)
    : HttpExchangeConnector(name, proxies)
{
}

std::shared_ptr<BidRequest>
OpenRTBExchangeConnector::
parseBidRequest(HttpAuctionHandler & connection,
                const HttpHeader & header,
                const std::string & payload)
{
    std::shared_ptr<BidRequest> res;

    // Check for JSON content-type
    if (!header.contentType.empty()) {
        static const std::string delimiter = ";";

        std::string content = header.contentType.substr(0, header.contentType.find(delimiter));
        #if 0
        std::string charset = header.contentType.substr(header.contentType.find(delimiter), header.contentType.length());
        #endif
        if(content != "application/json") {
            connection.sendErrorResponse("non-JSON request");
            return res;
        }

    }
    else {
        connection.sendErrorResponse("non-JSON request");
        return res;
    }

    // Check for the x-openrtb-version header
    auto it = header.headers.find("x-openrtb-version");
    if (it == header.headers.end()) {
        connection.sendErrorResponse("no OpenRTB version header supplied");
        return res;
    }

    // Check that it's version 2.1
    std::string openRtbVersion = it->second;
    if (openRtbVersion != "2.1") {
        connection.sendErrorResponse("expected OpenRTB version 2.1; got " + openRtbVersion);
        return res;
    }

    // Parse the bid request
    ML::Parse_Context context("Bid Request", payload.c_str(), payload.size());
    res.reset(OpenRtbBidRequestParser::parseBidRequest(context,
                                                       exchangeName(),
                                                       exchangeName()));
    return res;
}

double
OpenRTBExchangeConnector::
getTimeAvailableMs(HttpAuctionHandler & connection,
                   const HttpHeader & header,
                   const std::string & payload)
{
    // Scan the payload quickly for the tmax parameter.
    static const std::string toFind = "\"tmax\":";
    std::string::size_type pos = payload.find(toFind);
    if (pos == std::string::npos)
        return 30.0;

    int tmax = atoi(payload.c_str() + pos + toFind.length());
    return tmax;
}

HttpResponse
OpenRTBExchangeConnector::
getResponse(const HttpAuctionHandler & connection,
            const HttpHeader & requestHeader,
            const Auction & auction) const
{
    const Auction::Data * current = auction.getCurrentData();

    if (current->hasError())
        return getErrorResponse(connection, auction,
                                current->error + ": " + current->details);

    OpenRTB::BidResponse response;
    response.id = auction.id;

    response.ext = getResponseExt(connection, auction);

    // Create a spot for each of the bid responses
    for (unsigned spotNum = 0; spotNum < current->responses.size(); ++spotNum) {
        if (!current->hasValidResponse(spotNum))
            continue;

        setSeatBid(auction, spotNum, response);
    }

    if (response.seatbid.empty())
        return HttpResponse(204, "none", "");

    static Datacratic::DefaultDescription<OpenRTB::BidResponse> desc;
    std::ostringstream stream;
    StreamJsonPrintingContext context(stream);
    desc.printJsonTyped(&response, context);

    return HttpResponse(200, "application/json", stream.str());
}

Json::Value
OpenRTBExchangeConnector::
getResponseExt(const HttpAuctionHandler & connection,
               const Auction & auction) const
{
    return {};
}

HttpResponse
OpenRTBExchangeConnector::
getDroppedAuctionResponse(const HttpAuctionHandler & connection,
                          const std::string & reason) const
{
    return HttpResponse(204, "application/json", "{}");
}

HttpResponse
OpenRTBExchangeConnector::
getErrorResponse(const HttpAuctionHandler & connection,
                 const Auction & auction,
                 const std::string & errorMessage) const
{
    Json::Value response;
    response["error"] = errorMessage;
    return HttpResponse(400, response);
}

std::string
OpenRTBExchangeConnector::
getBidSourceConfiguration() const
{
    auto suffix = std::to_string(port());
    return ML::format("{\"type\":\"openrtb\",\"url\":\"%s\"}",
                      ML::fqdn_hostname(suffix) + ":" + suffix);
}

void
OpenRTBExchangeConnector::
setSeatBid(Auction const & auction,
           int spotNum,
           OpenRTB::BidResponse & response) const
{
    const Auction::Data * data = auction.getCurrentData();

    // Get the winning bid
    auto & resp = data->winningResponse(spotNum);

    int seatIndex = 0;
    if(response.seatbid.empty()) {
        response.seatbid.emplace_back();
    }

    OpenRTB::SeatBid & seatBid = response.seatbid.at(seatIndex);

    // Add a new bid to the array
    seatBid.bid.emplace_back();

    // Put in the variable parts
    auto & b = seatBid.bid.back();
    b.cid = Id(resp.agent);
    b.id = Id(auction.id, auction.request->imp[0].id);
    b.impid = auction.request->imp[spotNum].id;
    b.price.val = getAmountIn<CPM>(resp.price.maxPrice);
}

} // namespace RTBKIT

namespace {
    using namespace RTBKIT;

    struct Init {
        Init() {
            ExchangeConnector::registerFactory<OpenRTBExchangeConnector>();
        }
    } init;
}

<commit_msg>made changes based on mathieus recommendation to check the delimiter<commit_after>/* openrtb_exchange_connector.cc
   Eric Robert, 7 May 2013

   Implementation of the OpenRTB exchange connector.
*/

#include "openrtb_exchange_connector.h"
#include "rtbkit/common/testing/exchange_source.h"
#include "rtbkit/plugins/bid_request/openrtb_bid_request.h"
#include "rtbkit/plugins/bid_request/openrtb_bid_source.h"
#include "rtbkit/plugins/exchange/http_auction_handler.h"
#include "rtbkit/core/agent_configuration/agent_config.h"
#include "openrtb/openrtb_parsing.h"
#include "soa/types/json_printing.h"
#include <boost/any.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
#include "jml/utils/file_functions.h"
#include "jml/arch/info.h"
#include "jml/utils/rng.h"

using namespace Datacratic;

namespace Datacratic {

template<typename T, int I, typename S>
Json::Value jsonEncode(const ML::compact_vector<T, I, S> & vec)
{
    Json::Value result(Json::arrayValue);
    for (unsigned i = 0;  i < vec.size();  ++i)
        result[i] = jsonEncode(vec[i]);
    return result;
}

template<typename T, int I, typename S>
ML::compact_vector<T, I, S>
jsonDecode(const Json::Value & val, ML::compact_vector<T, I, S> *)
{
    ExcAssert(val.isArray());
    ML::compact_vector<T, I, S> res;
    res.reserve(val.size());
    for (unsigned i = 0;  i < val.size();  ++i)
        res.push_back(jsonDecode(val[i], (T*)0));
    return res;
}

} // namespace Datacratic

namespace OpenRTB {

template<typename T>
Json::Value jsonEncode(const OpenRTB::List<T> & vec)
{
    using Datacratic::jsonEncode;
    Json::Value result(Json::arrayValue);
    for (unsigned i = 0;  i < vec.size();  ++i)
        result[i] = jsonEncode(vec[i]);
    return result;
}

template<typename T>
OpenRTB::List<T>
jsonDecode(const Json::Value & val, OpenRTB::List<T> *)
{
    using Datacratic::jsonDecode;
    ExcAssert(val.isArray());
    OpenRTB::List<T> res;
    res.reserve(val.size());
    for (unsigned i = 0;  i < val.size();  ++i)
        res.push_back(jsonDecode(val[i], (T*)0));
    return res;
}

} // namespace OpenRTB

namespace RTBKIT {

BOOST_STATIC_ASSERT(hasFromJson<Datacratic::Id>::value == true);
BOOST_STATIC_ASSERT(hasFromJson<int>::value == false);

/*****************************************************************************/
/* OPENRTB EXCHANGE CONNECTOR                                                */
/*****************************************************************************/

OpenRTBExchangeConnector::
OpenRTBExchangeConnector(ServiceBase & owner, const std::string & name)
    : HttpExchangeConnector(name, owner)
{
}

OpenRTBExchangeConnector::
OpenRTBExchangeConnector(const std::string & name,
                         std::shared_ptr<ServiceProxies> proxies)
    : HttpExchangeConnector(name, proxies)
{
}

std::shared_ptr<BidRequest>
OpenRTBExchangeConnector::
parseBidRequest(HttpAuctionHandler & connection,
                const HttpHeader & header,
                const std::string & payload)
{
    std::shared_ptr<BidRequest> res;

    // Check for JSON content-type
    if (!header.contentType.empty()) {
        static const std::string delimiter = ";";

        std::string::size_type posDelim = header.contentType.find(delimiter);
        std::string content;

        if(posDelim == std::string::npos)
            content = header.contentType;
        else {
            std::string content = header.contentType.substr(0, posDelim);
            #if 0
            std::string charset = header.contentType.substr(posDelim, header.contentType.length());
            #endif
        }

        if(content != "application/json") {
            connection.sendErrorResponse("non-JSON request");
            return res;
        }

    }
    else {
        connection.sendErrorResponse("non-JSON request");
        return res;
    }

    // Check for the x-openrtb-version header
    auto it = header.headers.find("x-openrtb-version");
    if (it == header.headers.end()) {
        connection.sendErrorResponse("no OpenRTB version header supplied");
        return res;
    }

    // Check that it's version 2.1
    std::string openRtbVersion = it->second;
    if (openRtbVersion != "2.1") {
        connection.sendErrorResponse("expected OpenRTB version 2.1; got " + openRtbVersion);
        return res;
    }

    // Parse the bid request
    ML::Parse_Context context("Bid Request", payload.c_str(), payload.size());
    res.reset(OpenRtbBidRequestParser::parseBidRequest(context,
                                                       exchangeName(),
                                                       exchangeName()));
    return res;
}

double
OpenRTBExchangeConnector::
getTimeAvailableMs(HttpAuctionHandler & connection,
                   const HttpHeader & header,
                   const std::string & payload)
{
    // Scan the payload quickly for the tmax parameter.
    static const std::string toFind = "\"tmax\":";
    std::string::size_type pos = payload.find(toFind);
    if (pos == std::string::npos)
        return 30.0;

    int tmax = atoi(payload.c_str() + pos + toFind.length());
    return tmax;
}

HttpResponse
OpenRTBExchangeConnector::
getResponse(const HttpAuctionHandler & connection,
            const HttpHeader & requestHeader,
            const Auction & auction) const
{
    const Auction::Data * current = auction.getCurrentData();

    if (current->hasError())
        return getErrorResponse(connection, auction,
                                current->error + ": " + current->details);

    OpenRTB::BidResponse response;
    response.id = auction.id;

    response.ext = getResponseExt(connection, auction);

    // Create a spot for each of the bid responses
    for (unsigned spotNum = 0; spotNum < current->responses.size(); ++spotNum) {
        if (!current->hasValidResponse(spotNum))
            continue;

        setSeatBid(auction, spotNum, response);
    }

    if (response.seatbid.empty())
        return HttpResponse(204, "none", "");

    static Datacratic::DefaultDescription<OpenRTB::BidResponse> desc;
    std::ostringstream stream;
    StreamJsonPrintingContext context(stream);
    desc.printJsonTyped(&response, context);

    return HttpResponse(200, "application/json", stream.str());
}

Json::Value
OpenRTBExchangeConnector::
getResponseExt(const HttpAuctionHandler & connection,
               const Auction & auction) const
{
    return {};
}

HttpResponse
OpenRTBExchangeConnector::
getDroppedAuctionResponse(const HttpAuctionHandler & connection,
                          const std::string & reason) const
{
    return HttpResponse(204, "application/json", "{}");
}

HttpResponse
OpenRTBExchangeConnector::
getErrorResponse(const HttpAuctionHandler & connection,
                 const Auction & auction,
                 const std::string & errorMessage) const
{
    Json::Value response;
    response["error"] = errorMessage;
    return HttpResponse(400, response);
}

std::string
OpenRTBExchangeConnector::
getBidSourceConfiguration() const
{
    auto suffix = std::to_string(port());
    return ML::format("{\"type\":\"openrtb\",\"url\":\"%s\"}",
                      ML::fqdn_hostname(suffix) + ":" + suffix);
}

void
OpenRTBExchangeConnector::
setSeatBid(Auction const & auction,
           int spotNum,
           OpenRTB::BidResponse & response) const
{
    const Auction::Data * data = auction.getCurrentData();

    // Get the winning bid
    auto & resp = data->winningResponse(spotNum);

    int seatIndex = 0;
    if(response.seatbid.empty()) {
        response.seatbid.emplace_back();
    }

    OpenRTB::SeatBid & seatBid = response.seatbid.at(seatIndex);

    // Add a new bid to the array
    seatBid.bid.emplace_back();

    // Put in the variable parts
    auto & b = seatBid.bid.back();
    b.cid = Id(resp.agent);
    b.id = Id(auction.id, auction.request->imp[0].id);
    b.impid = auction.request->imp[spotNum].id;
    b.price.val = getAmountIn<CPM>(resp.price.maxPrice);
}

} // namespace RTBKIT

namespace {
    using namespace RTBKIT;

    struct Init {
        Init() {
            ExchangeConnector::registerFactory<OpenRTBExchangeConnector>();
        }
    } init;
}

<|endoftext|>


<commit_before>#include <boost/version.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
#include <mapnik/symbolizer.hpp>
#include <vector>
#include <algorithm>

#include "utils.hpp"

using namespace mapnik;

int main(int argc, char** argv)
{
    std::vector<std::string> args;
    for (int i=1;i<argc;++i)
    {
        args.push_back(argv[i]);
    }
    bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();

    try {
        marker_multi_policy_enum policy_in = MARKER_WHOLE_MULTI;
        BOOST_TEST_EQ(policy_in,MARKER_WHOLE_MULTI);
        markers_symbolizer sym;
        put(sym, keys::markers_multipolicy, policy_in);
        BOOST_TEST_EQ(sym.properties.count(keys::markers_multipolicy),1);
        marker_multi_policy_enum policy_out = get<mapnik::marker_multi_policy_enum>(sym, keys::markers_multipolicy);
        BOOST_TEST_EQ(policy_out,MARKER_WHOLE_MULTI);
    } catch (...) {
        BOOST_TEST(true);
    }

    if (!::boost::detail::test_errors()) {
        if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
        else std::clog << "C++ exceptions: \x1b[1;32m✓ \x1b[0m\n";
#if BOOST_VERSION >= 104600
        ::boost::detail::report_errors_remind().called_report_errors_function = true;
#endif
    } else {
        return ::boost::report_errors();
    }
}
<commit_msg>avoid signed comparison warning in symbolizer test<commit_after>#include <boost/version.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
#include <mapnik/symbolizer.hpp>
#include <vector>
#include <algorithm>

#include "utils.hpp"

using namespace mapnik;

int main(int argc, char** argv)
{
    std::vector<std::string> args;
    for (int i=1;i<argc;++i)
    {
        args.push_back(argv[i]);
    }
    bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();

    try {
        marker_multi_policy_enum policy_in = MARKER_WHOLE_MULTI;
        BOOST_TEST_EQ(policy_in,MARKER_WHOLE_MULTI);
        markers_symbolizer sym;
        put(sym, keys::markers_multipolicy, policy_in);
        BOOST_TEST_EQ(sym.properties.count(keys::markers_multipolicy),static_cast<unsigned long>(1));
        marker_multi_policy_enum policy_out = get<mapnik::marker_multi_policy_enum>(sym, keys::markers_multipolicy);
        BOOST_TEST_EQ(policy_out,MARKER_WHOLE_MULTI);
    } catch (...) {
        BOOST_TEST(true);
    }

    if (!::boost::detail::test_errors()) {
        if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
        else std::clog << "C++ exceptions: \x1b[1;32m✓ \x1b[0m\n";
#if BOOST_VERSION >= 104600
        ::boost::detail::report_errors_remind().called_report_errors_function = true;
#endif
    } else {
        return ::boost::report_errors();
    }
}
<|endoftext|>


<commit_before>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/mlir/tfrt/python_tests/python_test_attrs.h"

#include "mlir/IR/Attributes.h"  // from @llvm-project
#include "mlir/IR/BuiltinTypes.h"  // from @llvm-project
#include "mlir/IR/MLIRContext.h"  // from @llvm-project
#include "mlir/IR/Operation.h"  // from @llvm-project
#include "mlir/Support/LLVM.h"  // from @llvm-project
#include "mlir/Support/LogicalResult.h"  // from @llvm-project
// Include the auto-generated dialect defs.
#include "tensorflow/compiler/mlir/tfrt/python_tests/python_test_attrs.cc.inc"

namespace mlir {
namespace tfrt {

void PythonTestAttrsDialect::initialize() {}

::mlir::LogicalResult PythonTestAttrsDialect::verifyRegionArgAttribute(
    ::mlir::Operation* op, unsigned regionIndex, unsigned argIndex,
    ::mlir::NamedAttribute attribute) {
  const auto& arg = op->getRegion(regionIndex).getArguments()[argIndex];

  // Only verify at the tensor level. We are interested in the correct attribute
  // values when processing the Tensorflow dialect IR.
  auto arg_type = arg.getType().dyn_cast<RankedTensorType>();
  if (!arg_type) return success();

  if (attribute.getName() == GetStaticTypeAttrName()) {
    auto type_attr = attribute.getValue().dyn_cast<TypeAttr>();
    if (!type_attr) {
      return op->emitError()
             << GetStaticTypeAttrName()
             << " argument attribute of other type than TypeAttr";
    }

    auto attr_type = type_attr.getValue().dyn_cast<RankedTensorType>();
    if (!attr_type) {
      return op->emitError()
             << GetStaticTypeAttrName()
             << " argument type attribute is not a ranked tensor type";
    }
    if (attr_type.getNumDynamicDims() > 0) {
      return op->emitError() << GetStaticTypeAttrName()
                             << " argument type attribute is a ranked tensor "
                                "type with dynamic dimensions";
    }
    if (attr_type.getRank() != arg_type.getRank()) {
      return op->emitError()
             << GetStaticTypeAttrName()
             << " argument type attribute is a ranked tensor type with a "
                "different rank than the rank of the argument tensor";
    }
    if (attr_type.getElementType() != arg_type.getElementType()) {
      return op->emitError()
             << GetStaticTypeAttrName()
             << " argument type attribute is a ranked tensor type with a "
                "different element type than the element type of the argument "
                "tensor";
    }
    const auto& attr_shape = attr_type.getShape();
    const auto& arg_shape = arg_type.getShape();
    for (int64_t i = 0; i < attr_shape.size(); ++i) {
      if (!arg_type.isDynamicDim(i) && arg_shape[i] != attr_shape[i]) {
        return op->emitError()
               << GetStaticTypeAttrName()
               << " argument type attribute is a ranked tensor type with a "
                  "shape that doesn't match the static dimensions of the "
                  "argument tensor";
      }
    }
  } else if (attribute.getName() == GetShapeValueAttrName()) {
    auto dense_attr = attribute.getValue().dyn_cast<DenseIntElementsAttr>();
    if (!dense_attr) {
      return op->emitError()
             << GetShapeValueAttrName()
             << " argument attribute is not a dense int elements attribute";
    }

    if (dense_attr.getType() != arg_type) {
      return op->emitError() << GetShapeValueAttrName()
                             << " argument elements attribute has a different "
                                "type than the argument type";
    }

    // We expect a valid shape value, therefore check that the dimension values
    // are not negative.
    for (auto&& dim : dense_attr) {
      if (dim.isNegative()) {
        return op->emitError()
               << GetShapeValueAttrName()
               << " argument elements attribute has a negative dimension value";
      }
    }
  }
  return success();
}

}  // namespace tfrt
}  // namespace mlir
<commit_msg>Consider integer types of width at most 8 bit to be compatible.<commit_after>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/mlir/tfrt/python_tests/python_test_attrs.h"

#include <algorithm>

#include "mlir/IR/Attributes.h"  // from @llvm-project
#include "mlir/IR/BuiltinTypes.h"  // from @llvm-project
#include "mlir/IR/MLIRContext.h"  // from @llvm-project
#include "mlir/IR/Operation.h"  // from @llvm-project
#include "mlir/Support/LLVM.h"  // from @llvm-project
#include "mlir/Support/LogicalResult.h"  // from @llvm-project
// Include the auto-generated dialect defs.
#include "tensorflow/compiler/mlir/tfrt/python_tests/python_test_attrs.cc.inc"

namespace mlir {
namespace tfrt {

void PythonTestAttrsDialect::initialize() {}

::mlir::LogicalResult PythonTestAttrsDialect::verifyRegionArgAttribute(
    ::mlir::Operation* op, unsigned regionIndex, unsigned argIndex,
    ::mlir::NamedAttribute attribute) {
  const auto& arg = op->getRegion(regionIndex).getArguments()[argIndex];

  // Only verify at the tensor level. We are interested in the correct attribute
  // values when processing the Tensorflow dialect IR.
  auto arg_type = arg.getType().dyn_cast<RankedTensorType>();
  if (!arg_type) return success();

  if (attribute.getName() == GetStaticTypeAttrName()) {
    auto type_attr = attribute.getValue().dyn_cast<TypeAttr>();
    if (!type_attr) {
      return op->emitError()
             << GetStaticTypeAttrName()
             << " argument attribute of other type than TypeAttr";
    }

    auto attr_type = type_attr.getValue().dyn_cast<RankedTensorType>();
    if (!attr_type) {
      return op->emitError()
             << GetStaticTypeAttrName()
             << " argument type attribute is not a ranked tensor type";
    }
    if (attr_type.getNumDynamicDims() > 0) {
      return op->emitError() << GetStaticTypeAttrName()
                             << " argument type attribute is a ranked tensor "
                                "type with dynamic dimensions";
    }
    if (attr_type.getRank() != arg_type.getRank()) {
      return op->emitError()
             << GetStaticTypeAttrName()
             << " argument type attribute is a ranked tensor type with a "
                "different rank than the rank of the argument tensor";
    }
    auto compatible = [&](Type a, Type b) {
      if (a == b) {
        return true;
      }
      if (!a.isa<IntegerType>() || !b.isa<IntegerType>()) {
        return false;
      }
      auto width_a = a.dyn_cast<IntegerType>().getWidth();
      auto width_b = b.dyn_cast<IntegerType>().getWidth();
      return width_a == width_b || std::max(width_a, width_b) == 8;
    };
    if (!compatible(attr_type.getElementType(), arg_type.getElementType())) {
      return op->emitError()
             << GetStaticTypeAttrName()
             << " argument type attribute is a ranked tensor type with a "
                "different element type than the element type of the argument "
                "tensor";
    }
    const auto& attr_shape = attr_type.getShape();
    const auto& arg_shape = arg_type.getShape();
    for (int64_t i = 0; i < attr_shape.size(); ++i) {
      if (!arg_type.isDynamicDim(i) && arg_shape[i] != attr_shape[i]) {
        return op->emitError()
               << GetStaticTypeAttrName()
               << " argument type attribute is a ranked tensor type with a "
                  "shape that doesn't match the static dimensions of the "
                  "argument tensor";
      }
    }
  } else if (attribute.getName() == GetShapeValueAttrName()) {
    auto dense_attr = attribute.getValue().dyn_cast<DenseIntElementsAttr>();
    if (!dense_attr) {
      return op->emitError()
             << GetShapeValueAttrName()
             << " argument attribute is not a dense int elements attribute";
    }

    if (dense_attr.getType() != arg_type) {
      return op->emitError() << GetShapeValueAttrName()
                             << " argument elements attribute has a different "
                                "type than the argument type";
    }

    // We expect a valid shape value, therefore check that the dimension values
    // are not negative.
    for (auto&& dim : dense_attr) {
      if (dim.isNegative()) {
        return op->emitError()
               << GetShapeValueAttrName()
               << " argument elements attribute has a negative dimension value";
      }
    }
  }
  return success();
}

}  // namespace tfrt
}  // namespace mlir
<|endoftext|>


<commit_before>#include <gbBase/Assert.hpp>

#include <gbBase/Exception.hpp>

#include <catch.hpp>

namespace
{
// catch's exception checking does not seem to work
// with abstract exception types; let's roll our own!
template<typename T>
void checkExceptionType(void (*fun)())
{
    bool was_caught = false;
    try {
        fun();
    } catch(T&) {
        was_caught = true;
    } catch(...) {
        CHECK(("Incorrect exception type.", false));
    }
    CHECK(was_caught);
}
}

TEST_CASE("Assert")
{
    using namespace GHULBUS_BASE_NAMESPACE;
    SECTION("Default handler is failAbort")
    {
        CHECK(Assert::getAssertionHandler() == &Assert::failAbort);
    }

    SECTION("Getting and setting handler")
    {
        auto handler = [](Assert::HandlerParameters const& param) {};
        Assert::setAssertionHandler(handler);
        REQUIRE(Assert::getAssertionHandler() == handler);
        Assert::setAssertionHandler(&Assert::failAbort);
    }

    SECTION("Default user param is NULL")
    {
        CHECK(Assert::getHandlerParam() == nullptr);
    }

    SECTION("Getting and setting user param")
    {
        int token;
        Assert::setHandlerParam(&token);
        REQUIRE(Assert::getHandlerParam() == &token);
        Assert::setHandlerParam(nullptr);
    }

    SECTION("assertionFailed should invoke currently active handler")
    {
        auto handler = [](Assert::HandlerParameters const& param) {
            CHECK(param.file == std::string("file"));
            CHECK(param.line == 42);
            CHECK(param.function == std::string("func"));
            CHECK(param.condition == std::string("cond"));
            CHECK(param.message == std::string("msg"));
            *static_cast<bool*>(param.user_param) = true;
        };
        Assert::setAssertionHandler(handler);
        bool handlerWasCalled = false;
        Assert::assertionFailed(Assert::HandlerParameters{ "file", 42, "func", "cond", "msg", &handlerWasCalled });
        CHECK(handlerWasCalled);
        Assert::setAssertionHandler(&Assert::failAbort);
    }

    SECTION("Macro invokes assertion handler with user param")
    {
        auto handler = [](Assert::HandlerParameters const& param) {
            CHECK(param.message == std::string("hello from the test!"));
            *static_cast<bool*>(param.user_param) = true;
        };
        Assert::setAssertionHandler(handler);
        bool handlerWasCalled = false;
        Assert::setHandlerParam(&handlerWasCalled);
        GHULBUS_ASSERT_PRD_MESSAGE(false, "hello from the test!");
        CHECK(handlerWasCalled);
        Assert::setAssertionHandler(&Assert::failAbort);
    }

    SECTION("Throw Handler throws AssertFailed exception")
    {
        // the big gotcha of this test is that we throw across dll boundaries here.
        // on some platforms, this can mess up the rtti if the exception was not declared correctly.
        // technically, this is probably more a test of Exceptions::AssertFailed than GHULBUS_ASSERT...
        Assert::setAssertionHandler(&Assert::failThrow);
        auto doAssert = []() { GHULBUS_ASSERT_PRD(false); };
        checkExceptionType<Exceptions::AssertFailed>(doAssert);
        checkExceptionType<Exception>(doAssert);
        checkExceptionType<std::exception>(doAssert);
        Assert::setAssertionHandler(&Assert::failAbort);
    }

    SECTION("Assert with message should forward message to exception")
    {
        Assert::setAssertionHandler(&Assert::failThrow);
        bool was_caught = false;
        char const* test_msg = "Just an example error message for testing purposes";
        try {
            GHULBUS_ASSERT_PRD_MESSAGE(false, test_msg);
        } catch(Exceptions::AssertFailed& e) {
            auto const err_msg = boost::get_error_info<Exception_Info::description>(e);
            REQUIRE(err_msg);
            CHECK(*err_msg == std::string("false - ") + test_msg);
            was_caught = true;
        }
        CHECK(was_caught);
        Assert::setAssertionHandler(&Assert::failAbort);
    }

    SECTION("Precondition macro should behave the same as assert")
    {
        Assert::setAssertionHandler(&Assert::failThrow);
        auto doAssert = []() { GHULBUS_PRECONDITION_PRD(false); };
        checkExceptionType<Exceptions::AssertFailed>(doAssert);
        Assert::setAssertionHandler(&Assert::failAbort);
    }

    SECTION("Unreachable macro should trigger failing assertion")
    {
        Assert::setAssertionHandler(&Assert::failThrow);
        auto doAssert = []() { GHULBUS_UNREACHABLE(); };
        checkExceptionType<Exceptions::AssertFailed>(doAssert);
        Assert::setAssertionHandler(&Assert::failAbort);
    }
}
<commit_msg>fixed clang warning<commit_after>#include <gbBase/Assert.hpp>

#include <gbBase/Exception.hpp>

#include <catch.hpp>

namespace
{
// catch's exception checking does not seem to work
// with abstract exception types; let's roll our own!
template<typename T>
void checkExceptionType(void (*fun)())
{
    bool was_caught = false;
    try {
        fun();
    } catch(T&) {
        was_caught = true;
    } catch(...) {
        CHECK_FALSE("Incorrect exception type");
    }
    CHECK(was_caught);
}
}

TEST_CASE("Assert")
{
    using namespace GHULBUS_BASE_NAMESPACE;
    SECTION("Default handler is failAbort")
    {
        CHECK(Assert::getAssertionHandler() == &Assert::failAbort);
    }

    SECTION("Getting and setting handler")
    {
        auto handler = [](Assert::HandlerParameters const& param) {};
        Assert::setAssertionHandler(handler);
        REQUIRE(Assert::getAssertionHandler() == handler);
        Assert::setAssertionHandler(&Assert::failAbort);
    }

    SECTION("Default user param is NULL")
    {
        CHECK(Assert::getHandlerParam() == nullptr);
    }

    SECTION("Getting and setting user param")
    {
        int token;
        Assert::setHandlerParam(&token);
        REQUIRE(Assert::getHandlerParam() == &token);
        Assert::setHandlerParam(nullptr);
    }

    SECTION("assertionFailed should invoke currently active handler")
    {
        auto handler = [](Assert::HandlerParameters const& param) {
            CHECK(param.file == std::string("file"));
            CHECK(param.line == 42);
            CHECK(param.function == std::string("func"));
            CHECK(param.condition == std::string("cond"));
            CHECK(param.message == std::string("msg"));
            *static_cast<bool*>(param.user_param) = true;
        };
        Assert::setAssertionHandler(handler);
        bool handlerWasCalled = false;
        Assert::assertionFailed(Assert::HandlerParameters{ "file", 42, "func", "cond", "msg", &handlerWasCalled });
        CHECK(handlerWasCalled);
        Assert::setAssertionHandler(&Assert::failAbort);
    }

    SECTION("Macro invokes assertion handler with user param")
    {
        auto handler = [](Assert::HandlerParameters const& param) {
            CHECK(param.message == std::string("hello from the test!"));
            *static_cast<bool*>(param.user_param) = true;
        };
        Assert::setAssertionHandler(handler);
        bool handlerWasCalled = false;
        Assert::setHandlerParam(&handlerWasCalled);
        GHULBUS_ASSERT_PRD_MESSAGE(false, "hello from the test!");
        CHECK(handlerWasCalled);
        Assert::setAssertionHandler(&Assert::failAbort);
    }

    SECTION("Throw Handler throws AssertFailed exception")
    {
        // the big gotcha of this test is that we throw across dll boundaries here.
        // on some platforms, this can mess up the rtti if the exception was not declared correctly.
        // technically, this is probably more a test of Exceptions::AssertFailed than GHULBUS_ASSERT...
        Assert::setAssertionHandler(&Assert::failThrow);
        auto doAssert = []() { GHULBUS_ASSERT_PRD(false); };
        checkExceptionType<Exceptions::AssertFailed>(doAssert);
        checkExceptionType<Exception>(doAssert);
        checkExceptionType<std::exception>(doAssert);
        Assert::setAssertionHandler(&Assert::failAbort);
    }

    SECTION("Assert with message should forward message to exception")
    {
        Assert::setAssertionHandler(&Assert::failThrow);
        bool was_caught = false;
        char const* test_msg = "Just an example error message for testing purposes";
        try {
            GHULBUS_ASSERT_PRD_MESSAGE(false, test_msg);
        } catch(Exceptions::AssertFailed& e) {
            auto const err_msg = boost::get_error_info<Exception_Info::description>(e);
            REQUIRE(err_msg);
            CHECK(*err_msg == std::string("false - ") + test_msg);
            was_caught = true;
        }
        CHECK(was_caught);
        Assert::setAssertionHandler(&Assert::failAbort);
    }

    SECTION("Precondition macro should behave the same as assert")
    {
        Assert::setAssertionHandler(&Assert::failThrow);
        auto doAssert = []() { GHULBUS_PRECONDITION_PRD(false); };
        checkExceptionType<Exceptions::AssertFailed>(doAssert);
        Assert::setAssertionHandler(&Assert::failAbort);
    }

    SECTION("Unreachable macro should trigger failing assertion")
    {
        Assert::setAssertionHandler(&Assert::failThrow);
        auto doAssert = []() { GHULBUS_UNREACHABLE(); };
        checkExceptionType<Exceptions::AssertFailed>(doAssert);
        Assert::setAssertionHandler(&Assert::failAbort);
    }
}
<|endoftext|>


<commit_before>// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "quic/masque/masque_server_backend.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"

namespace quic {

namespace {

std::string GetRequestHandlerKey(
    const QuicSimpleServerBackend::RequestHandler* request_handler) {
  return absl::StrCat(request_handler->connection_id().ToString(), "_",
                      request_handler->stream_id(), "_",
                      request_handler->peer_host());
}

}  // namespace

MasqueServerBackend::MasqueServerBackend(MasqueMode masque_mode,
                                         const std::string& server_authority,
                                         const std::string& cache_directory)
    : masque_mode_(masque_mode), server_authority_(server_authority) {
  if (!cache_directory.empty()) {
    QuicMemoryCacheBackend::InitializeBackend(cache_directory);
  }
}

bool MasqueServerBackend::MaybeHandleMasqueRequest(
    const spdy::Http2HeaderBlock& request_headers,
    const std::string& request_body,
    QuicSimpleServerBackend::RequestHandler* request_handler) {
  auto path_pair = request_headers.find(":path");
  auto method_pair = request_headers.find(":method");
  auto scheme_pair = request_headers.find(":scheme");
  if (path_pair == request_headers.end() ||
      method_pair == request_headers.end() ||
      scheme_pair == request_headers.end()) {
    // This request is missing required headers.
    return false;
  }
  absl::string_view path = path_pair->second;
  absl::string_view scheme = scheme_pair->second;
  absl::string_view method = method_pair->second;
  std::string masque_path = "";
  if (masque_mode_ == MasqueMode::kLegacy) {
    if (scheme != "https" || method != "POST" || request_body.empty()) {
      // MASQUE requests MUST be a non-empty https POST.
      return false;
    }

    if (path.rfind("/.well-known/masque/", 0) != 0) {
      // This request is not a MASQUE path.
      return false;
    }
    masque_path = path.substr(sizeof("/.well-known/masque/") - 1);
  } else {
    if (method != "CONNECT-UDP") {
      // Unexpected method.
      return false;
    }
  }

  if (!server_authority_.empty()) {
    auto authority_pair = request_headers.find(":authority");
    if (authority_pair == request_headers.end()) {
      // Cannot enforce missing authority.
      return false;
    }
    absl::string_view authority = authority_pair->second;
    if (server_authority_ != authority) {
      // This request does not match server_authority.
      return false;
    }
  }

  auto backend_client_pair =
      backend_clients_.find(request_handler->connection_id());
  if (backend_client_pair == backend_clients_.end()) {
    QUIC_LOG(ERROR) << "Could not find backend client for "
                    << GetRequestHandlerKey(request_handler) << " "
                    << masque_path << request_headers.DebugString();
    return false;
  }

  BackendClient* backend_client = backend_client_pair->second;

  std::unique_ptr<QuicBackendResponse> response =
      backend_client->HandleMasqueRequest(masque_path, request_headers,
                                          request_body, request_handler);
  if (response == nullptr) {
    QUIC_LOG(ERROR) << "Backend client did not process request for "
                    << GetRequestHandlerKey(request_handler) << " "
                    << masque_path << request_headers.DebugString();
    return false;
  }

  QUIC_DLOG(INFO) << "Sending MASQUE response for "
                  << GetRequestHandlerKey(request_handler) << " " << masque_path
                  << request_headers.DebugString();

  request_handler->OnResponseBackendComplete(response.get(), {});
  active_response_map_[GetRequestHandlerKey(request_handler)] =
      std::move(response);

  return true;
}

void MasqueServerBackend::FetchResponseFromBackend(
    const spdy::Http2HeaderBlock& request_headers,
    const std::string& request_body,
    QuicSimpleServerBackend::RequestHandler* request_handler) {
  if (MaybeHandleMasqueRequest(request_headers, request_body,
                               request_handler)) {
    // Request was handled as a MASQUE request.
    return;
  }
  QUIC_DLOG(INFO) << "Fetching non-MASQUE response for "
                  << GetRequestHandlerKey(request_handler)
                  << request_headers.DebugString();
  QuicMemoryCacheBackend::FetchResponseFromBackend(
      request_headers, request_body, request_handler);
}

void MasqueServerBackend::CloseBackendResponseStream(
    QuicSimpleServerBackend::RequestHandler* request_handler) {
  QUIC_DLOG(INFO) << "Closing response stream for "
                  << GetRequestHandlerKey(request_handler);
  active_response_map_.erase(GetRequestHandlerKey(request_handler));
  QuicMemoryCacheBackend::CloseBackendResponseStream(request_handler);
}

void MasqueServerBackend::RegisterBackendClient(QuicConnectionId connection_id,
                                                BackendClient* backend_client) {
  QUIC_BUG_IF(backend_clients_.find(connection_id) != backend_clients_.end())
      << connection_id << " already in backend clients map";
  backend_clients_[connection_id] = backend_client;
  QUIC_DLOG(INFO) << "Registering backend client for " << connection_id;
}

void MasqueServerBackend::RemoveBackendClient(QuicConnectionId connection_id) {
  backend_clients_.erase(connection_id);
  QUIC_DLOG(INFO) << "Removing backend client for " << connection_id;
}

}  // namespace quic
<commit_msg>Make absl::string_view to std::string conversion explicit in Masque.<commit_after>// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "quic/masque/masque_server_backend.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"

namespace quic {

namespace {

std::string GetRequestHandlerKey(
    const QuicSimpleServerBackend::RequestHandler* request_handler) {
  return absl::StrCat(request_handler->connection_id().ToString(), "_",
                      request_handler->stream_id(), "_",
                      request_handler->peer_host());
}

}  // namespace

MasqueServerBackend::MasqueServerBackend(MasqueMode masque_mode,
                                         const std::string& server_authority,
                                         const std::string& cache_directory)
    : masque_mode_(masque_mode), server_authority_(server_authority) {
  if (!cache_directory.empty()) {
    QuicMemoryCacheBackend::InitializeBackend(cache_directory);
  }
}

bool MasqueServerBackend::MaybeHandleMasqueRequest(
    const spdy::Http2HeaderBlock& request_headers,
    const std::string& request_body,
    QuicSimpleServerBackend::RequestHandler* request_handler) {
  auto path_pair = request_headers.find(":path");
  auto method_pair = request_headers.find(":method");
  auto scheme_pair = request_headers.find(":scheme");
  if (path_pair == request_headers.end() ||
      method_pair == request_headers.end() ||
      scheme_pair == request_headers.end()) {
    // This request is missing required headers.
    return false;
  }
  absl::string_view path = path_pair->second;
  absl::string_view scheme = scheme_pair->second;
  absl::string_view method = method_pair->second;
  std::string masque_path = "";
  if (masque_mode_ == MasqueMode::kLegacy) {
    if (scheme != "https" || method != "POST" || request_body.empty()) {
      // MASQUE requests MUST be a non-empty https POST.
      return false;
    }

    if (path.rfind("/.well-known/masque/", 0) != 0) {
      // This request is not a MASQUE path.
      return false;
    }
    masque_path = std::string(path.substr(sizeof("/.well-known/masque/") - 1));
  } else {
    if (method != "CONNECT-UDP") {
      // Unexpected method.
      return false;
    }
  }

  if (!server_authority_.empty()) {
    auto authority_pair = request_headers.find(":authority");
    if (authority_pair == request_headers.end()) {
      // Cannot enforce missing authority.
      return false;
    }
    absl::string_view authority = authority_pair->second;
    if (server_authority_ != authority) {
      // This request does not match server_authority.
      return false;
    }
  }

  auto backend_client_pair =
      backend_clients_.find(request_handler->connection_id());
  if (backend_client_pair == backend_clients_.end()) {
    QUIC_LOG(ERROR) << "Could not find backend client for "
                    << GetRequestHandlerKey(request_handler) << " "
                    << masque_path << request_headers.DebugString();
    return false;
  }

  BackendClient* backend_client = backend_client_pair->second;

  std::unique_ptr<QuicBackendResponse> response =
      backend_client->HandleMasqueRequest(masque_path, request_headers,
                                          request_body, request_handler);
  if (response == nullptr) {
    QUIC_LOG(ERROR) << "Backend client did not process request for "
                    << GetRequestHandlerKey(request_handler) << " "
                    << masque_path << request_headers.DebugString();
    return false;
  }

  QUIC_DLOG(INFO) << "Sending MASQUE response for "
                  << GetRequestHandlerKey(request_handler) << " " << masque_path
                  << request_headers.DebugString();

  request_handler->OnResponseBackendComplete(response.get(), {});
  active_response_map_[GetRequestHandlerKey(request_handler)] =
      std::move(response);

  return true;
}

void MasqueServerBackend::FetchResponseFromBackend(
    const spdy::Http2HeaderBlock& request_headers,
    const std::string& request_body,
    QuicSimpleServerBackend::RequestHandler* request_handler) {
  if (MaybeHandleMasqueRequest(request_headers, request_body,
                               request_handler)) {
    // Request was handled as a MASQUE request.
    return;
  }
  QUIC_DLOG(INFO) << "Fetching non-MASQUE response for "
                  << GetRequestHandlerKey(request_handler)
                  << request_headers.DebugString();
  QuicMemoryCacheBackend::FetchResponseFromBackend(
      request_headers, request_body, request_handler);
}

void MasqueServerBackend::CloseBackendResponseStream(
    QuicSimpleServerBackend::RequestHandler* request_handler) {
  QUIC_DLOG(INFO) << "Closing response stream for "
                  << GetRequestHandlerKey(request_handler);
  active_response_map_.erase(GetRequestHandlerKey(request_handler));
  QuicMemoryCacheBackend::CloseBackendResponseStream(request_handler);
}

void MasqueServerBackend::RegisterBackendClient(QuicConnectionId connection_id,
                                                BackendClient* backend_client) {
  QUIC_BUG_IF(backend_clients_.find(connection_id) != backend_clients_.end())
      << connection_id << " already in backend clients map";
  backend_clients_[connection_id] = backend_client;
  QUIC_DLOG(INFO) << "Registering backend client for " << connection_id;
}

void MasqueServerBackend::RemoveBackendClient(QuicConnectionId connection_id) {
  backend_clients_.erase(connection_id);
  QUIC_DLOG(INFO) << "Removing backend client for " << connection_id;
}

}  // namespace quic
<|endoftext|>


<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "quiche/quic/tools/quic_toy_server.h"

#include <utility>
#include <vector>

#include "quiche/quic/core/quic_versions.h"
#include "quiche/quic/platform/api/quic_default_proof_providers.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
#include "quiche/quic/tools/quic_memory_cache_backend.h"
#include "quiche/common/platform/api/quiche_command_line_flags.h"

DEFINE_QUICHE_COMMAND_LINE_FLAG(int32_t, port, 6121,
                                "The port the quic server will listen on.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(
    std::string, quic_response_cache_dir, "",
    "Specifies the directory used during QuicHttpResponseCache "
    "construction to seed the cache. Cache directory can be "
    "generated using `wget -p --save-headers <url>`");

DEFINE_QUICHE_COMMAND_LINE_FLAG(
    bool, generate_dynamic_responses, false,
    "If true, then URLs which have a numeric path will send a dynamically "
    "generated response of that many bytes.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(bool, quic_ietf_draft, false,
                                "Only enable IETF draft versions. This also "
                                "enables required internal QUIC flags.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(
    std::string, quic_versions, "",
    "QUIC versions to enable, e.g. \"h3-25,h3-27\". If not set, then all "
    "available versions are enabled.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(bool, enable_webtransport, false,
                                "If true, WebTransport support is enabled.");

namespace quic {

std::unique_ptr<quic::QuicSimpleServerBackend>
QuicToyServer::MemoryCacheBackendFactory::CreateBackend() {
  auto memory_cache_backend = std::make_unique<QuicMemoryCacheBackend>();
  if (quiche::GetQuicheCommandLineFlag(FLAGS_generate_dynamic_responses)) {
    memory_cache_backend->GenerateDynamicResponses();
  }
  if (!quiche::GetQuicheCommandLineFlag(FLAGS_quic_response_cache_dir)
           .empty()) {
    memory_cache_backend->InitializeBackend(
        quiche::GetQuicheCommandLineFlag(FLAGS_quic_response_cache_dir));
  }
  if (quiche::GetQuicheCommandLineFlag(FLAGS_enable_webtransport)) {
    memory_cache_backend->EnableWebTransport();
  }
  return memory_cache_backend;
}

QuicToyServer::QuicToyServer(BackendFactory* backend_factory,
                             ServerFactory* server_factory)
    : backend_factory_(backend_factory), server_factory_(server_factory) {}

int QuicToyServer::Start() {
  ParsedQuicVersionVector supported_versions;
  if (quiche::GetQuicheCommandLineFlag(FLAGS_quic_ietf_draft)) {
    QuicVersionInitializeSupportForIetfDraft();
    for (const ParsedQuicVersion& version : AllSupportedVersions()) {
      // Add all versions that supports IETF QUIC.
      if (version.HasIetfQuicFrames() &&
          version.handshake_protocol == quic::PROTOCOL_TLS1_3) {
        supported_versions.push_back(version);
      }
    }
  } else {
    supported_versions = AllSupportedVersions();
  }
  std::string versions_string =
      quiche::GetQuicheCommandLineFlag(FLAGS_quic_versions);
  if (!versions_string.empty()) {
    supported_versions = ParseQuicVersionVectorString(versions_string);
  }
  if (supported_versions.empty()) {
    return 1;
  }
  for (const auto& version : supported_versions) {
    QuicEnableVersion(version);
  }
  auto proof_source = quic::CreateDefaultProofSource();
  auto backend = backend_factory_->CreateBackend();
  auto server = server_factory_->CreateServer(
      backend.get(), std::move(proof_source), supported_versions);

  if (!server->CreateUDPSocketAndListen(quic::QuicSocketAddress(
          quic::QuicIpAddress::Any6(),
          quiche::GetQuicheCommandLineFlag(FLAGS_port)))) {
    return 1;
  }

  server->HandleEventsForever();
  return 0;
}

}  // namespace quic
<commit_msg>Re-implement QUIC toy server CONNECT flags<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "quiche/quic/tools/quic_toy_server.h"

#include <utility>
#include <vector>

#include "absl/container/flat_hash_set.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "quiche/quic/core/quic_server_id.h"
#include "quiche/quic/core/quic_versions.h"
#include "quiche/quic/platform/api/quic_default_proof_providers.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
#include "quiche/quic/tools/connect_server_backend.h"
#include "quiche/quic/tools/quic_memory_cache_backend.h"
#include "quiche/common/platform/api/quiche_command_line_flags.h"
#include "quiche/common/platform/api/quiche_logging.h"

DEFINE_QUICHE_COMMAND_LINE_FLAG(int32_t, port, 6121,
                                "The port the quic server will listen on.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(
    std::string, quic_response_cache_dir, "",
    "Specifies the directory used during QuicHttpResponseCache "
    "construction to seed the cache. Cache directory can be "
    "generated using `wget -p --save-headers <url>`");

DEFINE_QUICHE_COMMAND_LINE_FLAG(
    bool, generate_dynamic_responses, false,
    "If true, then URLs which have a numeric path will send a dynamically "
    "generated response of that many bytes.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(bool, quic_ietf_draft, false,
                                "Only enable IETF draft versions. This also "
                                "enables required internal QUIC flags.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(
    std::string, quic_versions, "",
    "QUIC versions to enable, e.g. \"h3-25,h3-27\". If not set, then all "
    "available versions are enabled.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(bool, enable_webtransport, false,
                                "If true, WebTransport support is enabled.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(
    std::string, connect_proxy_destinations, "",
    "Specifies a comma-separated list of destinations (\"hostname:port\") to "
    "which the quic server will allow tunneling via CONNECT.");

namespace quic {

std::unique_ptr<quic::QuicSimpleServerBackend>
QuicToyServer::MemoryCacheBackendFactory::CreateBackend() {
  auto memory_cache_backend = std::make_unique<QuicMemoryCacheBackend>();
  if (quiche::GetQuicheCommandLineFlag(FLAGS_generate_dynamic_responses)) {
    memory_cache_backend->GenerateDynamicResponses();
  }
  if (!quiche::GetQuicheCommandLineFlag(FLAGS_quic_response_cache_dir)
           .empty()) {
    memory_cache_backend->InitializeBackend(
        quiche::GetQuicheCommandLineFlag(FLAGS_quic_response_cache_dir));
  }
  if (quiche::GetQuicheCommandLineFlag(FLAGS_enable_webtransport)) {
    memory_cache_backend->EnableWebTransport();
  }

  if (!quiche::GetQuicheCommandLineFlag(FLAGS_connect_proxy_destinations)
           .empty()) {
    absl::flat_hash_set<QuicServerId> connect_proxy_destinations;
    for (absl::string_view destination : absl::StrSplit(
             quiche::GetQuicheCommandLineFlag(FLAGS_connect_proxy_destinations),
             ',', absl::SkipEmpty())) {
      absl::optional<QuicServerId> destination_server_id =
          QuicServerId::ParseFromHostPortString(destination);
      QUICHE_CHECK(destination_server_id.has_value());
      connect_proxy_destinations.insert(
          std::move(destination_server_id).value());
    }
    QUICHE_CHECK(!connect_proxy_destinations.empty());

    return std::make_unique<ConnectServerBackend>(
        std::move(memory_cache_backend), std::move(connect_proxy_destinations));
  }

  return memory_cache_backend;
}

QuicToyServer::QuicToyServer(BackendFactory* backend_factory,
                             ServerFactory* server_factory)
    : backend_factory_(backend_factory), server_factory_(server_factory) {}

int QuicToyServer::Start() {
  ParsedQuicVersionVector supported_versions;
  if (quiche::GetQuicheCommandLineFlag(FLAGS_quic_ietf_draft)) {
    QuicVersionInitializeSupportForIetfDraft();
    for (const ParsedQuicVersion& version : AllSupportedVersions()) {
      // Add all versions that supports IETF QUIC.
      if (version.HasIetfQuicFrames() &&
          version.handshake_protocol == quic::PROTOCOL_TLS1_3) {
        supported_versions.push_back(version);
      }
    }
  } else {
    supported_versions = AllSupportedVersions();
  }
  std::string versions_string =
      quiche::GetQuicheCommandLineFlag(FLAGS_quic_versions);
  if (!versions_string.empty()) {
    supported_versions = ParseQuicVersionVectorString(versions_string);
  }
  if (supported_versions.empty()) {
    return 1;
  }
  for (const auto& version : supported_versions) {
    QuicEnableVersion(version);
  }
  auto proof_source = quic::CreateDefaultProofSource();
  auto backend = backend_factory_->CreateBackend();
  auto server = server_factory_->CreateServer(
      backend.get(), std::move(proof_source), supported_versions);

  if (!server->CreateUDPSocketAndListen(quic::QuicSocketAddress(
          quic::QuicIpAddress::Any6(),
          quiche::GetQuicheCommandLineFlag(FLAGS_port)))) {
    return 1;
  }

  server->HandleEventsForever();
  return 0;
}

}  // namespace quic
<|endoftext|>