<commit_before>/*
 *
 * Copyright 2015, 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.
 *
 */

#include <atomic>
#include <chrono>
#include <future>  // for async()
#include <iostream>
#include <memory>
#include <random>
#include <string>

#include "helper.h"
#include "route_guide.grpc_cb.pb.h"

using grpc_cb::Channel;
using grpc_cb::ChannelSptr;
using grpc_cb::Status;
using routeguide::Point;
using routeguide::Feature;
using routeguide::Rectangle;
using routeguide::RouteSummary;
using routeguide::RouteNote;
using routeguide::RouteGuide::Stub;

const float kCoordFactor = 10000000.0;
static unsigned seed = (unsigned)std::chrono::system_clock::now().time_since_epoch().count();
static std::default_random_engine generator(seed);

Point MakePoint(long latitude, long longitude) {
  Point p;
  p.set_latitude(latitude);
  p.set_longitude(longitude);
  return p;
}

routeguide::Rectangle MakeRect(const Point& lo, const Point& hi) {
  routeguide::Rectangle rect;
  *rect.mutable_lo() = lo;
  *rect.mutable_hi() = hi;
  return rect;
}

routeguide::Rectangle MakeRect(long lo_latitude, long lo_longitude,
                   long hi_latitude, long hi_longitude) {
  return MakeRect(MakePoint(lo_latitude, lo_longitude),
                  MakePoint(hi_latitude, hi_longitude));
}

Feature MakeFeature(const std::string& name,
                    long latitude, long longitude) {
  Feature f;
  f.set_name(name);
  f.mutable_location()->CopyFrom(MakePoint(latitude, longitude));
  return f;
}

RouteNote MakeRouteNote(const std::string& message,
                        long latitude, long longitude) {
  RouteNote n;
  n.set_message(message);
  n.mutable_location()->CopyFrom(MakePoint(latitude, longitude));
  return n;
}

void PrintFeature(const Feature& feature) {
  if (!feature.has_location()) {
    std::cout << "Server returns incomplete feature." << std::endl;
    return;
  }
  if (feature.name().empty()) {
    std::cout << "Found no feature at "
        << feature.location().latitude()/kCoordFactor << ", "
        << feature.location().longitude()/kCoordFactor << std::endl;
  }
  else {
    std::cout << "Found feature called " << feature.name()  << " at "
        << feature.location().latitude()/kCoordFactor << ", "
        << feature.location().longitude()/kCoordFactor << std::endl;
  }
}  // PrintFeature()

void PrintServerNote(const RouteNote& server_note) {
  std::cout << "Got message " << server_note.message()
            << " at " << server_note.location().latitude() << ", "
            << server_note.location().longitude() << std::endl;
}

void RandomSleep() {
  std::uniform_int_distribution<int> delay_distribution(500, 1500);
  std::this_thread::sleep_for(std::chrono::milliseconds(
      delay_distribution(generator)));
}

void RunWriteRouteNote(Stub::RouteChat_SyncReaderWriter sync_reader_writer) {
  std::vector<RouteNote> notes{
    MakeRouteNote("First message", 0, 0),
    MakeRouteNote("Second message", 0, 1),
    MakeRouteNote("Third message", 1, 0),
    MakeRouteNote("Fourth message", 0, 0)};
  for (const RouteNote& note : notes) {
    std::cout << "Sending message " << note.message()
              << " at " << note.location().latitude() << ", "
              << note.location().longitude() << std::endl;
    sync_reader_writer.Write(note);
    // RandomSleep();
  }
  sync_reader_writer.CloseWriting();
}

class RouteGuideClient {
 public:
  RouteGuideClient(std::shared_ptr<Channel> channel, const std::string& db)
      : stub_(new Stub(channel)) {
    routeguide::ParseDb(db, &feature_list_);
    assert(!feature_list_.empty());
  }

  void BlockingGetFeature() {
    Point point;
    Feature feature;
    point = MakePoint(409146138, -746188906);
    BlockingGetOneFeature(point, &feature);
    point = MakePoint(0, 0);
    BlockingGetOneFeature(point, &feature);
  }

  void BlockingListFeatures() {
    routeguide::Rectangle rect = MakeRect(
        400000000, -750000000, 420000000, -730000000);
    Feature feature;

    std::cout << "Looking for features between 40, -75 and 42, -73"
        << std::endl;

    auto sync_reader(stub_->SyncListFeatures(rect));
    while (sync_reader.ReadOne(&feature)) {
      std::cout << "Found feature called "
                << feature.name() << " at "
                << feature.location().latitude()/kCoordFactor << ", "
                << feature.location().longitude()/kCoordFactor << std::endl;
    }
    Status status = sync_reader.RecvStatus();
    if (status.ok()) {
      std::cout << "ListFeatures rpc succeeded." << std::endl;
    } else {
      std::cout << "ListFeatures rpc failed." << std::endl;
    }
  }

  void BlockingRecordRoute() {
    Point point;
    const int kPoints = 10;
    std::uniform_int_distribution<int> feature_distribution(
        0, feature_list_.size() - 1);

    auto sync_writer(stub_->SyncRecordRoute());
    for (int i = 0; i < kPoints; i++) {
      const Feature& f = feature_list_[feature_distribution(generator)];
      std::cout << "Visiting point "
                << f.location().latitude()/kCoordFactor << ", "
                << f.location().longitude()/kCoordFactor << std::endl;
      if (!sync_writer.Write(f.location())) {
        // Broken stream.
        break;
      }
      RandomSleep();
    }
    RouteSummary stats;
    // Recv reponse and status.
    Status status = sync_writer.Close(&stats);  // Todo: timeout
    if (status.ok()) {
      std::cout << "Finished trip with " << stats.point_count() << " points\n"
                << "Passed " << stats.feature_count() << " features\n"
                << "Traveled " << stats.distance() << " meters\n"
                << "It took " << stats.elapsed_time() << " seconds"
                << std::endl;
    } else {
      std::cout << "RecordRoute rpc failed." << std::endl;
    }
  }

  // Todo: Callback on client stream response and status.

  void BlockingRouteChat() {
    auto sync_reader_writer(stub_->SyncRouteChat());
    auto f = std::async(std::launch::async, [sync_reader_writer]() {
        RunWriteRouteNote(sync_reader_writer);
    });

    RouteNote server_note;
    while (sync_reader_writer.ReadOne(&server_note))
        PrintServerNote(server_note);

    f.wait();
    // Todo: Close() should auto close writing.
    Status status = sync_reader_writer.RecvStatus();
    if (!status.ok()) {
      std::cout << "RouteChat rpc failed." << std::endl;
    }
  }

 private:
  bool BlockingGetOneFeature(const Point& point, Feature* feature) {
    Status status = stub_->BlockingGetFeature(point, feature);
    if (!status.ok()) {
      std::cout << "GetFeature rpc failed." << std::endl;
      return false;
    }
    PrintFeature(*feature);
    return feature->has_location();
  }

  std::unique_ptr<Stub> stub_;
  std::vector<Feature> feature_list_;
};

void GetFeatureAsync(const ChannelSptr& channel) {
  Stub stub(channel);

  // Ignore error status.
  stub.AsyncGetFeature(MakePoint(0, 0),
                       [](const Feature& feature) { PrintFeature(feature); });

  // Ignore response.
  stub.AsyncGetFeature(MakePoint(0, 0));

  Point point1 = MakePoint(409146138, -746188906);
  stub.AsyncGetFeature(point1,
      [&stub](const Feature& feature) {
        PrintFeature(feature);
        stub.Shutdown();
      },
      [&stub](const Status& err) {
        std::cout << "AsyncGetFeature rpc failed. "
            << err.GetDetails() << std::endl;
        stub.Shutdown();
      });  // AsyncGetFeature()
  stub.BlockingRun();  // until stub.Shutdown()
}

void ListFeaturesAsync(const ChannelSptr& channel) {
  Stub stub(channel);
  routeguide::Rectangle rect = MakeRect(
      400000000, -750000000, 420000000, -730000000);
  std::cout << "Looking for features between 40, -75 and 42, -73" << std::endl;

  stub.AsyncListFeatures(rect,
    [](const Feature& feature) {
      std::cout << "Got feature " << feature.name() << " at "
          << feature.location().latitude()/kCoordFactor << ", "
          << feature.location().longitude()/kCoordFactor << std::endl;
    },
    [&stub](const Status& status) {
      std::cout << "End status: (" << status.GetCode() << ") "
          << status.GetDetails() << std::endl;
      stub.Shutdown();  // To break BlockingRun().
    });
  stub.BlockingRun();  // until stub.Shutdown()
}

void RecordRouteAsync(const ChannelSptr& channel,
                      const std::string& db) {
  assert(!db.empty());
  std::vector<Feature> feature_list;
  routeguide::ParseDb(db, &feature_list);
  assert(!feature_list.empty());

  Point point;
  const int kPoints = 10;
  std::uniform_int_distribution<int> feature_distribution(
      0, feature_list.size() - 1);

  Stub stub(channel);
  auto f = std::async(std::launch::async, [&stub]() { stub.BlockingRun(); });

  // ClientAsyncWriter<Point, RouteSummary> async_writer;
  auto async_writer = stub.AsyncRecordRoute();
  for (int i = 0; i < kPoints; i++) {
    const Feature& f = feature_list[feature_distribution(generator)];
    std::cout << "Visiting point "
              << f.location().latitude()/kCoordFactor << ", "
              << f.location().longitude()/kCoordFactor << std::endl;
    if (!async_writer.Write(f.location())) {
      // Broken stream.
      break;
    }
    RandomSleep();
  }
  // Recv reponse and status.
  async_writer.Close([](const Status& status, const RouteSummary& resp) {
    if (!status.ok()) {
      std::cout << "RecordRoute rpc failed." << std::endl;
      return;
    }
    std::cout << "Finished trip with " << resp.point_count() << " points\n"
              << "Passed " << resp.feature_count() << " features\n"
              << "Traveled " << resp.distance() << " meters\n"
              << "It took " << resp.elapsed_time() << " seconds" << std::endl;
  });

  // Todo: timeout

  stub.Shutdown();
}  // RecordRouteAsync()

void AsyncWriteRouteNotes(Stub::RouteChat_AsyncReaderWriter async_reader_writer) {
  std::vector<RouteNote> notes{
    MakeRouteNote("First message", 0, 0),
    MakeRouteNote("Second message", 0, 1),
    MakeRouteNote("Third message", 1, 0),
    MakeRouteNote("Fourth message", 0, 0)};
  for (const RouteNote& note : notes) {
    std::cout << "Sending message " << note.message()
              << " at " << note.location().latitude() << ", "
              << note.location().longitude() << std::endl;
    async_reader_writer.Write(note);
    // RandomSleep();
  }
  async_reader_writer.CloseWriting();  // Optional.
}

void RouteChatAsync(const ChannelSptr& channel) {
  Stub stub(channel);
  std::atomic_bool bReaderDone = false;
  auto async_reader_writer(
      stub.AsyncRouteChat([&bReaderDone](const Status& status) {
        if (!status.ok()) {
          std::cout << "RouteChat rpc failed. " << status.GetDetails()
                    << std::endl;
        }
        bReaderDone = true;
      }));

  async_reader_writer.ReadEach(
      [](const RouteNote& note) { PrintServerNote(note); });

  AsyncWriteRouteNotes(async_reader_writer);
  auto f = std::async(std::launch::async, [&stub]() {
    stub.BlockingRun();
  });

  while (!bReaderDone)
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
  stub.Shutdown();  // To break BlockingRun().
}  // RouteChatAsync()

void TestRpcTimeout(const ChannelSptr& channel) {
  Stub stub(channel);
  stub.SetCallTimeoutMs(INT64_MIN);
  Point point = MakePoint(0, 0);
  Feature feature;
  Status status = stub.BlockingGetFeature(point, &feature);
  assert(status.GetCode() == GRPC_STATUS_DEADLINE_EXCEEDED);
}

int main(int argc, char** argv) {
  // Expect only arg: --db_path=path/to/route_guide_db.json.
  std::string db = routeguide::GetDbFileContent(argc, argv);
  assert(!db.empty());
  ChannelSptr channel(new Channel("localhost:50051"));
  RouteGuideClient guide(channel, db);

  TestRpcTimeout(channel);

  std::cout << "---- BlockingGetFeature --------------" << std::endl;
  guide.BlockingGetFeature();
  std::cout << "---- BlockingListFeatures --------------" << std::endl;
  guide.BlockingListFeatures();
  std::cout << "---- BlockingRecordRoute --------------" << std::endl;
  guide.BlockingRecordRoute();
  std::cout << "---- BlockingRouteChat --------------" << std::endl;
  guide.BlockingRouteChat();

  std::cout << "---- GetFeatureAsync ----" << std::endl;
  GetFeatureAsync(channel);
  std::cout << "---- ListFeaturesAsync ----" << std::endl;
  ListFeaturesAsync(channel);
  std::cout << "---- RecordRouteAsnyc ----" << std::endl;
  RecordRouteAsync(channel, db);
  std::cout << "---- RouteChatAsync ---" << std::endl;
  RouteChatAsync(channel);

  return 0;
}
<commit_msg>Change RouteChatAsync() example.<commit_after>/*
 *
 * Copyright 2015, 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.
 *
 */

#include <atomic>
#include <chrono>
#include <future>  // for async()
#include <iostream>
#include <memory>
#include <random>
#include <string>

#include "helper.h"
#include "route_guide.grpc_cb.pb.h"

using grpc_cb::Channel;
using grpc_cb::ChannelSptr;
using grpc_cb::Status;
using routeguide::Point;
using routeguide::Feature;
using routeguide::Rectangle;
using routeguide::RouteSummary;
using routeguide::RouteNote;
using routeguide::RouteGuide::Stub;

const float kCoordFactor = 10000000.0;
static unsigned seed = (unsigned)std::chrono::system_clock::now().time_since_epoch().count();
static std::default_random_engine generator(seed);

Point MakePoint(long latitude, long longitude) {
  Point p;
  p.set_latitude(latitude);
  p.set_longitude(longitude);
  return p;
}

routeguide::Rectangle MakeRect(const Point& lo, const Point& hi) {
  routeguide::Rectangle rect;
  *rect.mutable_lo() = lo;
  *rect.mutable_hi() = hi;
  return rect;
}

routeguide::Rectangle MakeRect(long lo_latitude, long lo_longitude,
                   long hi_latitude, long hi_longitude) {
  return MakeRect(MakePoint(lo_latitude, lo_longitude),
                  MakePoint(hi_latitude, hi_longitude));
}

Feature MakeFeature(const std::string& name,
                    long latitude, long longitude) {
  Feature f;
  f.set_name(name);
  f.mutable_location()->CopyFrom(MakePoint(latitude, longitude));
  return f;
}

RouteNote MakeRouteNote(const std::string& message,
                        long latitude, long longitude) {
  RouteNote n;
  n.set_message(message);
  n.mutable_location()->CopyFrom(MakePoint(latitude, longitude));
  return n;
}

void PrintFeature(const Feature& feature) {
  if (!feature.has_location()) {
    std::cout << "Server returns incomplete feature." << std::endl;
    return;
  }
  if (feature.name().empty()) {
    std::cout << "Found no feature at "
        << feature.location().latitude()/kCoordFactor << ", "
        << feature.location().longitude()/kCoordFactor << std::endl;
  }
  else {
    std::cout << "Found feature called " << feature.name()  << " at "
        << feature.location().latitude()/kCoordFactor << ", "
        << feature.location().longitude()/kCoordFactor << std::endl;
  }
}  // PrintFeature()

void PrintServerNote(const RouteNote& server_note) {
  std::cout << "Got message " << server_note.message()
            << " at " << server_note.location().latitude() << ", "
            << server_note.location().longitude() << std::endl;
}

void RandomSleep() {
  std::uniform_int_distribution<int> delay_distribution(500, 1500);
  std::this_thread::sleep_for(std::chrono::milliseconds(
      delay_distribution(generator)));
}

void RunWriteRouteNote(Stub::RouteChat_SyncReaderWriter sync_reader_writer) {
  std::vector<RouteNote> notes{
    MakeRouteNote("First message", 0, 0),
    MakeRouteNote("Second message", 0, 1),
    MakeRouteNote("Third message", 1, 0),
    MakeRouteNote("Fourth message", 0, 0)};
  for (const RouteNote& note : notes) {
    std::cout << "Sending message " << note.message()
              << " at " << note.location().latitude() << ", "
              << note.location().longitude() << std::endl;
    sync_reader_writer.Write(note);
    // RandomSleep();
  }
  sync_reader_writer.CloseWriting();
}

class RouteGuideClient {
 public:
  RouteGuideClient(std::shared_ptr<Channel> channel, const std::string& db)
      : stub_(new Stub(channel)) {
    routeguide::ParseDb(db, &feature_list_);
    assert(!feature_list_.empty());
  }

  void BlockingGetFeature() {
    Point point;
    Feature feature;
    point = MakePoint(409146138, -746188906);
    BlockingGetOneFeature(point, &feature);
    point = MakePoint(0, 0);
    BlockingGetOneFeature(point, &feature);
  }

  void BlockingListFeatures() {
    routeguide::Rectangle rect = MakeRect(
        400000000, -750000000, 420000000, -730000000);
    Feature feature;

    std::cout << "Looking for features between 40, -75 and 42, -73"
        << std::endl;

    auto sync_reader(stub_->SyncListFeatures(rect));
    while (sync_reader.ReadOne(&feature)) {
      std::cout << "Found feature called "
                << feature.name() << " at "
                << feature.location().latitude()/kCoordFactor << ", "
                << feature.location().longitude()/kCoordFactor << std::endl;
    }
    Status status = sync_reader.RecvStatus();
    if (status.ok()) {
      std::cout << "ListFeatures rpc succeeded." << std::endl;
    } else {
      std::cout << "ListFeatures rpc failed." << std::endl;
    }
  }

  void BlockingRecordRoute() {
    Point point;
    const int kPoints = 10;
    std::uniform_int_distribution<int> feature_distribution(
        0, feature_list_.size() - 1);

    auto sync_writer(stub_->SyncRecordRoute());
    for (int i = 0; i < kPoints; i++) {
      const Feature& f = feature_list_[feature_distribution(generator)];
      std::cout << "Visiting point "
                << f.location().latitude()/kCoordFactor << ", "
                << f.location().longitude()/kCoordFactor << std::endl;
      if (!sync_writer.Write(f.location())) {
        // Broken stream.
        break;
      }
      RandomSleep();
    }
    RouteSummary stats;
    // Recv reponse and status.
    Status status = sync_writer.Close(&stats);  // Todo: timeout
    if (status.ok()) {
      std::cout << "Finished trip with " << stats.point_count() << " points\n"
                << "Passed " << stats.feature_count() << " features\n"
                << "Traveled " << stats.distance() << " meters\n"
                << "It took " << stats.elapsed_time() << " seconds"
                << std::endl;
    } else {
      std::cout << "RecordRoute rpc failed." << std::endl;
    }
  }

  // Todo: Callback on client stream response and status.

  void BlockingRouteChat() {
    auto sync_reader_writer(stub_->SyncRouteChat());
    auto f = std::async(std::launch::async, [sync_reader_writer]() {
        RunWriteRouteNote(sync_reader_writer);
    });

    RouteNote server_note;
    while (sync_reader_writer.ReadOne(&server_note))
        PrintServerNote(server_note);

    f.wait();
    // Todo: Close() should auto close writing.
    Status status = sync_reader_writer.RecvStatus();
    if (!status.ok()) {
      std::cout << "RouteChat rpc failed." << std::endl;
    }
  }

 private:
  bool BlockingGetOneFeature(const Point& point, Feature* feature) {
    Status status = stub_->BlockingGetFeature(point, feature);
    if (!status.ok()) {
      std::cout << "GetFeature rpc failed." << std::endl;
      return false;
    }
    PrintFeature(*feature);
    return feature->has_location();
  }

  std::unique_ptr<Stub> stub_;
  std::vector<Feature> feature_list_;
};

void GetFeatureAsync(const ChannelSptr& channel) {
  Stub stub(channel);

  // Ignore error status.
  stub.AsyncGetFeature(MakePoint(0, 0),
                       [](const Feature& feature) { PrintFeature(feature); });

  // Ignore response.
  stub.AsyncGetFeature(MakePoint(0, 0));

  Point point1 = MakePoint(409146138, -746188906);
  stub.AsyncGetFeature(point1,
      [&stub](const Feature& feature) {
        PrintFeature(feature);
        stub.Shutdown();
      },
      [&stub](const Status& err) {
        std::cout << "AsyncGetFeature rpc failed. "
            << err.GetDetails() << std::endl;
        stub.Shutdown();
      });  // AsyncGetFeature()
  stub.BlockingRun();  // until stub.Shutdown()
}

void ListFeaturesAsync(const ChannelSptr& channel) {
  Stub stub(channel);
  routeguide::Rectangle rect = MakeRect(
      400000000, -750000000, 420000000, -730000000);
  std::cout << "Looking for features between 40, -75 and 42, -73" << std::endl;

  stub.AsyncListFeatures(rect,
    [](const Feature& feature) {
      std::cout << "Got feature " << feature.name() << " at "
          << feature.location().latitude()/kCoordFactor << ", "
          << feature.location().longitude()/kCoordFactor << std::endl;
    },
    [&stub](const Status& status) {
      std::cout << "End status: (" << status.GetCode() << ") "
          << status.GetDetails() << std::endl;
      stub.Shutdown();  // To break BlockingRun().
    });
  stub.BlockingRun();  // until stub.Shutdown()
}

void RecordRouteAsync(const ChannelSptr& channel,
                      const std::string& db) {
  assert(!db.empty());
  std::vector<Feature> feature_list;
  routeguide::ParseDb(db, &feature_list);
  assert(!feature_list.empty());

  Point point;
  const int kPoints = 10;
  std::uniform_int_distribution<int> feature_distribution(
      0, feature_list.size() - 1);

  Stub stub(channel);
  auto f = std::async(std::launch::async, [&stub]() { stub.BlockingRun(); });

  // ClientAsyncWriter<Point, RouteSummary> async_writer;
  auto async_writer = stub.AsyncRecordRoute();
  for (int i = 0; i < kPoints; i++) {
    const Feature& f = feature_list[feature_distribution(generator)];
    std::cout << "Visiting point "
              << f.location().latitude()/kCoordFactor << ", "
              << f.location().longitude()/kCoordFactor << std::endl;
    if (!async_writer.Write(f.location())) {
      // Broken stream.
      break;
    }
    RandomSleep();
  }
  // Recv reponse and status.
  async_writer.Close([](const Status& status, const RouteSummary& resp) {
    if (!status.ok()) {
      std::cout << "RecordRoute rpc failed." << std::endl;
      return;
    }
    std::cout << "Finished trip with " << resp.point_count() << " points\n"
              << "Passed " << resp.feature_count() << " features\n"
              << "Traveled " << resp.distance() << " meters\n"
              << "It took " << resp.elapsed_time() << " seconds" << std::endl;
  });

  // Todo: timeout

  stub.Shutdown();
}  // RecordRouteAsync()

void AsyncWriteRouteNotes(Stub::RouteChat_AsyncReaderWriter async_reader_writer) {
  std::vector<RouteNote> notes{
    MakeRouteNote("First message", 0, 0),
    MakeRouteNote("Second message", 0, 1),
    MakeRouteNote("Third message", 1, 0),
    MakeRouteNote("Fourth message", 0, 0)};
  for (const RouteNote& note : notes) {
    std::cout << "Sending message " << note.message()
              << " at " << note.location().latitude() << ", "
              << note.location().longitude() << std::endl;
    async_reader_writer.Write(note);
    RandomSleep();
  }
  async_reader_writer.CloseWriting();  // Optional.
}

void RouteChatAsync(const ChannelSptr& channel) {
  Stub stub(channel);
  std::atomic_bool bReaderDone = false;
  auto async_reader_writer(
      stub.AsyncRouteChat([&bReaderDone](const Status& status) {
        if (!status.ok()) {
          std::cout << "RouteChat rpc failed. " << status.GetDetails()
                    << std::endl;
        }
        bReaderDone = true;
      }));

  async_reader_writer.ReadEach(
      [](const RouteNote& note) { PrintServerNote(note); });

  auto f_write = std::async(std::launch::async, AsyncWriteRouteNotes, async_reader_writer);
  auto f_run = std::async(std::launch::async, [&stub]() {
    stub.BlockingRun();
  });

  while (!bReaderDone)
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
  stub.Shutdown();  // To break BlockingRun().
}  // RouteChatAsync()

void TestRpcTimeout(const ChannelSptr& channel) {
  Stub stub(channel);
  stub.SetCallTimeoutMs(INT64_MIN);
  Point point = MakePoint(0, 0);
  Feature feature;
  Status status = stub.BlockingGetFeature(point, &feature);
  assert(status.GetCode() == GRPC_STATUS_DEADLINE_EXCEEDED);
}

int main(int argc, char** argv) {
  // Expect only arg: --db_path=path/to/route_guide_db.json.
  std::string db = routeguide::GetDbFileContent(argc, argv);
  assert(!db.empty());
  ChannelSptr channel(new Channel("localhost:50051"));
  RouteGuideClient guide(channel, db);

  TestRpcTimeout(channel);

  std::cout << "---- BlockingGetFeature --------------" << std::endl;
  guide.BlockingGetFeature();
  std::cout << "---- BlockingListFeatures --------------" << std::endl;
  guide.BlockingListFeatures();
  std::cout << "---- BlockingRecordRoute --------------" << std::endl;
  guide.BlockingRecordRoute();
  std::cout << "---- BlockingRouteChat --------------" << std::endl;
  guide.BlockingRouteChat();

  std::cout << "---- GetFeatureAsync ----" << std::endl;
  GetFeatureAsync(channel);
  std::cout << "---- ListFeaturesAsync ----" << std::endl;
  ListFeaturesAsync(channel);
  std::cout << "---- RecordRouteAsnyc ----" << std::endl;
  RecordRouteAsync(channel, db);
  std::cout << "---- RouteChatAsync ---" << std::endl;
  RouteChatAsync(channel);

  return 0;
}
<|endoftext|>


<commit_before>/* OpenSceneGraph example, osgvertexattributes.
*
*  Permission is hereby granted, free of charge, to any person obtaining a copy
*  of this software and associated documentation files (the "Software"), to deal
*  in the Software without restriction, including without limitation the rights
*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the Software is
*  furnished to do so, subject to the following conditions:
*
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
*  THE SOFTWARE.
*/

#include <osgUtil/ShaderGen>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>

class ConvertToVertexAttibArrays : public osg::NodeVisitor
{
    public:

        typedef std::pair<unsigned int, std::string> AttributeAlias;

        ConvertToVertexAttibArrays():
            osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
        {
            _manualVertexAliasing = false;

            // mappings taken from http://www.opengl.org/registry/specs/NV/vertex_program.txt
            _vertexAlias = AttributeAlias(0, "osg_Vertex");
            _normalAlias = AttributeAlias(2, "osg_Normal");
            _colorAlias = AttributeAlias(3, "osg_Color");
            _secondaryColorAlias = AttributeAlias(4, "osg_SecondaryColor");
            _fogCoordAlias = AttributeAlias(5, "osg_FogCoord");
            _texCoordAlias[0] = AttributeAlias(8, "osg_MultiTexCoord0");
            _texCoordAlias[1] = AttributeAlias(9, "osg_MultiTexCoord1");
            _texCoordAlias[2] = AttributeAlias(10, "osg_MultiTexCoord2");
            _texCoordAlias[3] = AttributeAlias(11, "osg_MultiTexCoord3");
            _texCoordAlias[4] = AttributeAlias(12, "osg_MultiTexCoord4");
            _texCoordAlias[5] = AttributeAlias(13, "osg_MultiTexCoord5");
            _texCoordAlias[6] = AttributeAlias(14, "osg_MultiTexCoord6");
            _texCoordAlias[7] = AttributeAlias(15, "osg_MultiTexCoord7");
        }

        void bindAttribute(osg::Program& program, const AttributeAlias& alias)
        {
                program.addBindAttribLocation(alias.second, alias.first);
        }

        void replaceAndBindAttrib(osg::Program& program, std::string& source, const std::string& originalStr, const AttributeAlias& alias, const std::string& declarationPrefix)
        {
            if (replace(source, originalStr, alias.second))
            {
                source.insert(0, declarationPrefix + alias.second + std::string(";\n"));
                if (_manualVertexAliasing) bindAttribute(program, alias);
            }
        }

        void replaceBuiltInUniform(std::string& source, const std::string& originalStr, const std::string& newStr, const std::string& declarationPrefix)
        {
            if (replace(source, originalStr, newStr))
            {
                source.insert(0, declarationPrefix + newStr + std::string(";\n"));
            }
        }

        void convertVertexShader(osg::Program& program, osg::Shader& shader)
        {
            std::string source = shader.getShaderSource();

            // replace ftransform as it only works with built-ins
            replace(source, "ftransform()", "gl_ModelViewProjectionMatrix * gl_Vertex");

#if 1
            replaceAndBindAttrib(program, source, "gl_Normal", _normalAlias, "attribute vec3 ");
            replaceAndBindAttrib(program, source, "gl_Vertex", _vertexAlias, "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_Color", _colorAlias, "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_SecondaryColor", _secondaryColorAlias, "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_FogCoord", _fogCoordAlias, "attribute float ");

            replaceAndBindAttrib(program, source, "gl_MultiTexCoord0", _texCoordAlias[0], "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_MultiTexCoord1", _texCoordAlias[1], "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_MultiTexCoord2", _texCoordAlias[2], "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_MultiTexCoord3", _texCoordAlias[3], "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_MultiTexCoord4", _texCoordAlias[4], "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_MultiTexCoord5", _texCoordAlias[5], "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_MultiTexCoord6", _texCoordAlias[6], "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_MultiTexCoord7", _texCoordAlias[7], "attribute vec4 ");
#endif

#if 1
            // replace built in uniform
            replaceBuiltInUniform(source, "gl_ModelViewMatrix", "osg_ModeViewMatrix", "uniform mat4 ");
            replaceBuiltInUniform(source, "gl_ModelViewProjectionMatrix", "osg_ModelViewProjectionMatrix", "uniform mat4 ");
            replaceBuiltInUniform(source, "gl_ProjectionMatrix", "osg_ProjectionMatrix", "uniform mat4 ");
#endif
            shader.setShaderSource(source);
        }

        void convertFragmentShader(osg::Program& program, osg::Shader& shader)
        {
        }

        virtual void reset()
        {
            _visited.clear();
        }

        void apply(osg::Node& node)
        {
            if (_visited.count(&node)!=0) return;
            _visited.insert(&node);

            if (node.getStateSet()) apply(*(node.getStateSet()));
            traverse(node);
        }

        void apply(osg::Geode& geode)
        {
            if (_visited.count(&geode)!=0) return;
            _visited.insert(&geode);

            if (geode.getStateSet()) apply(*(geode.getStateSet()));

            for(unsigned int i=0; i<geode.getNumDrawables(); ++i)
            {
                if (geode.getDrawable(i)->getStateSet()) apply(*(geode.getDrawable(i)->getStateSet()));

                osg::Geometry* geom = geode.getDrawable(i)->asGeometry();
                if (geom) apply(*geom);
            }
        }

        bool replace(std::string& str, const std::string& original_phrase, const std::string& new_phrase)
        {
            bool replacedStr = false;
            std::string::size_type pos = 0;
            while((pos=str.find(original_phrase, pos))!=std::string::npos)
            {
                std::string::size_type endOfPhrasePos = pos+original_phrase.size();
                if (endOfPhrasePos<str.size())
                {
                    char c = str[endOfPhrasePos];
                    if ((c>='0' && c<='9') ||
                        (c>='a' && c<='z') ||
                        (c>='A' && c<='Z'))
                    {
                        pos = endOfPhrasePos;
                        continue;
                    }
                }

                replacedStr = true;
                str.replace(pos, original_phrase.size(), new_phrase);
            }
            return replacedStr;
        }

        void apply(osg::Program& program, osg::Shader& shader)
        {
             if (_visited.count(&shader)!=0) return;
            _visited.insert(&shader);

            osg::notify(osg::NOTICE)<<"Shader "<<shader.getTypename()<<" ----before-----------"<<std::endl;
            osg::notify(osg::NOTICE)<<shader.getShaderSource()<<std::endl;

            if (shader.getType()==osg::Shader::VERTEX) convertVertexShader(program, shader);
            else if (shader.getType()==osg::Shader::FRAGMENT) convertFragmentShader(program, shader);

            osg::notify(osg::NOTICE)<<"--after-----------"<<std::endl;
            osg::notify(osg::NOTICE)<<shader.getShaderSource()<<std::endl;
            osg::notify(osg::NOTICE)<<"---------------------"<<std::endl;
        }

        void apply(osg::StateSet& stateset)
        {
             if (_visited.count(&stateset)!=0) return;
            _visited.insert(&stateset);

            return;

            osg::notify(osg::NOTICE)<<"Found stateset "<<&stateset<<std::endl;
            osg::Program* program = dynamic_cast<osg::Program*>(stateset.getAttribute(osg::StateAttribute::PROGRAM));
            if (program)
            {
                osg::notify(osg::NOTICE)<<"   Found Program "<<program<<std::endl;
                for(unsigned int i=0; i<program->getNumShaders(); ++i)
                {
                    apply(*program, *(program->getShader(i)));
                }

            }
       }

        void apply(osg::Geometry& geom)
        {
            geom.setUseDisplayList(false);

            if (!_manualVertexAliasing) return;

            osg::notify(osg::NOTICE)<<"Found geometry "<<&geom<<std::endl;
            if (geom.getVertexArray())
            {
                setVertexAttrib(geom, _vertexAlias, geom.getVertexArray(), false, osg::Geometry::BIND_PER_VERTEX);
                geom.setVertexArray(0);
            }

            if (geom.getNormalArray())
            {
                setVertexAttrib(geom, _normalAlias, geom.getNormalArray(), true, geom.getNormalBinding());
                geom.setNormalArray(0);
            }

            if (geom.getColorArray())
            {
                setVertexAttrib(geom, _colorAlias, geom.getColorArray(), false, geom.getColorBinding());
                geom.setColorArray(0);
            }

            if (geom.getSecondaryColorArray())
            {
                setVertexAttrib(geom, _secondaryColorAlias, geom.getSecondaryColorArray(), false, geom.getSecondaryColorBinding());
                geom.setSecondaryColorArray(0);
            }

            if (geom.getFogCoordArray())
            {
                // should we normalize the FogCoord array? Don't think so...
                setVertexAttrib(geom, _fogCoordAlias, geom.getFogCoordArray(), false, geom.getFogCoordBinding());
                geom.setFogCoordArray(0);
            }

            unsigned int maxNumTexCoords = geom.getNumTexCoordArrays();
            if (maxNumTexCoords>8)
            {
                osg::notify(osg::NOTICE)<<"Warning: Ignoring "<<maxNumTexCoords-8<<" texture coordinate arrays, only 8 are currently supported in vertex attribute conversion code."<<std::endl;
                maxNumTexCoords = 8;
            }
            for(unsigned int i=0; i<maxNumTexCoords; ++i)
            {
                if (geom.getTexCoordArray(i))
                {
                    setVertexAttrib(geom, _texCoordAlias[i], geom.getTexCoordArray(i), false, osg::Geometry::BIND_PER_VERTEX);
                    geom.setTexCoordArray(i,0);
                }
                else
                {
                    osg::notify(osg::NOTICE)<<"Found empty TexCoordArray("<<i<<")"<<std::endl;
                }
            }
        }

        void setVertexAttrib(osg::Geometry& geom, const AttributeAlias& alias, osg::Array* array, bool normalize, osg::Geometry::AttributeBinding binding)
        {
            unsigned int index = alias.first;
            const std::string& name = alias.second;
            array->setName(name);
            geom.setVertexAttribArray(index, array);
            geom.setVertexAttribNormalize(index, normalize);
            geom.setVertexAttribBinding(index, binding);

            osg::notify(osg::NOTICE)<<"   vertex attrib("<<name<<", index="<<index<<", normalize="<<normalize<<" binding="<<binding<<")"<<std::endl;
        }

        typedef std::set<osg::Object*> Visited;
        Visited         _visited;

        bool           _manualVertexAliasing;
        AttributeAlias _vertexAlias;
        AttributeAlias _normalAlias;
        AttributeAlias _colorAlias;
        AttributeAlias _secondaryColorAlias;
        AttributeAlias _fogCoordAlias;
        AttributeAlias _texCoordAlias[8];
};

int main(int argc, char *argv[])
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // construct the viewer.
    osgViewer::Viewer viewer(arguments);

    std::string outputFileName;
    while (arguments.read("-o",outputFileName)) {}

    bool runShaderGen = true;
    while (arguments.read("--shader-gen")) { runShaderGen = true; }
    while (arguments.read("--no-shader-gen")) { runShaderGen = false; }

    bool runConvertToVertexAttributes = true;
    while (arguments.read("--vertex-attrib")) { runConvertToVertexAttributes = true; }
    while (arguments.read("--no-vertex-attrib")) { runConvertToVertexAttributes = false; }

    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
    if (!loadedModel.get())
    {
        osg::notify(osg::NOTICE)<<"No model loaded, please specify a model filename."<<std::endl;
        return 1;
    }

    if (runShaderGen)
    {
        // convert fixed function pipeline to shaders
        osgUtil::ShaderGenVisitor sgv;
        loadedModel->accept(sgv);
    }

    if (runConvertToVertexAttributes)
    {
        // find any conventional vertex, colour, normal and tex coords arrays and convert to vertex attributes
        ConvertToVertexAttibArrays ctvaa;
        loadedModel->accept(ctvaa);
    }

    if (!outputFileName.empty())
    {
        osgDB::writeNodeFile(*loadedModel, outputFileName);
        return 0;
    }

    // add a viewport to the viewer and attach the scene graph.
    viewer.setSceneData(loadedModel.get());

    viewer.setCameraManipulator(new osgGA::TrackballManipulator());

    // add the stats handler
    viewer.addEventHandler(new osgViewer::StatsHandler);

    viewer.realize();

    if (runConvertToVertexAttributes)
    {
        // switch on the uniforms that track the modelview and projection matrices
        osgViewer::Viewer::Windows windows;
        viewer.getWindows(windows);
        for(osgViewer::Viewer::Windows::iterator itr = windows.begin();
            itr != windows.end();
            ++itr)
        {
            (*itr)->getState()->setUseModelViewAndProjectionUniforms(true);
            (*itr)->getState()->setUseVertexAttributeAliasing(true);
        }
    }

    return viewer.run();
}
<commit_msg>Added --simple option and associated set up of a very simple geometry and shader scene graph<commit_after>/* OpenSceneGraph example, osgvertexattributes.
*
*  Permission is hereby granted, free of charge, to any person obtaining a copy
*  of this software and associated documentation files (the "Software"), to deal
*  in the Software without restriction, including without limitation the rights
*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the Software is
*  furnished to do so, subject to the following conditions:
*
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
*  THE SOFTWARE.
*/

#include <osgUtil/ShaderGen>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>

class ConvertToVertexAttibArrays : public osg::NodeVisitor
{
    public:

        typedef std::pair<unsigned int, std::string> AttributeAlias;

        ConvertToVertexAttibArrays():
            osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
        {
            _manualVertexAliasing = false;

            // mappings taken from http://www.opengl.org/registry/specs/NV/vertex_program.txt
            _vertexAlias = AttributeAlias(0, "osg_Vertex");
            _normalAlias = AttributeAlias(2, "osg_Normal");
            _colorAlias = AttributeAlias(3, "osg_Color");
            _secondaryColorAlias = AttributeAlias(4, "osg_SecondaryColor");
            _fogCoordAlias = AttributeAlias(5, "osg_FogCoord");
            _texCoordAlias[0] = AttributeAlias(8, "osg_MultiTexCoord0");
            _texCoordAlias[1] = AttributeAlias(9, "osg_MultiTexCoord1");
            _texCoordAlias[2] = AttributeAlias(10, "osg_MultiTexCoord2");
            _texCoordAlias[3] = AttributeAlias(11, "osg_MultiTexCoord3");
            _texCoordAlias[4] = AttributeAlias(12, "osg_MultiTexCoord4");
            _texCoordAlias[5] = AttributeAlias(13, "osg_MultiTexCoord5");
            _texCoordAlias[6] = AttributeAlias(14, "osg_MultiTexCoord6");
            _texCoordAlias[7] = AttributeAlias(15, "osg_MultiTexCoord7");
        }

        void bindAttribute(osg::Program& program, const AttributeAlias& alias)
        {
                program.addBindAttribLocation(alias.second, alias.first);
        }

        void replaceAndBindAttrib(osg::Program& program, std::string& source, const std::string& originalStr, const AttributeAlias& alias, const std::string& declarationPrefix)
        {
            if (replace(source, originalStr, alias.second))
            {
                source.insert(0, declarationPrefix + alias.second + std::string(";\n"));
                if (_manualVertexAliasing) bindAttribute(program, alias);
            }
        }

        void replaceBuiltInUniform(std::string& source, const std::string& originalStr, const std::string& newStr, const std::string& declarationPrefix)
        {
            if (replace(source, originalStr, newStr))
            {
                source.insert(0, declarationPrefix + newStr + std::string(";\n"));
            }
        }

        void convertVertexShader(osg::Program& program, osg::Shader& shader)
        {
            std::string source = shader.getShaderSource();

            // replace ftransform as it only works with built-ins
            replace(source, "ftransform()", "gl_ModelViewProjectionMatrix * gl_Vertex");

#if 1
            replaceAndBindAttrib(program, source, "gl_Normal", _normalAlias, "attribute vec3 ");
            replaceAndBindAttrib(program, source, "gl_Vertex", _vertexAlias, "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_Color", _colorAlias, "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_SecondaryColor", _secondaryColorAlias, "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_FogCoord", _fogCoordAlias, "attribute float ");

            replaceAndBindAttrib(program, source, "gl_MultiTexCoord0", _texCoordAlias[0], "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_MultiTexCoord1", _texCoordAlias[1], "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_MultiTexCoord2", _texCoordAlias[2], "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_MultiTexCoord3", _texCoordAlias[3], "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_MultiTexCoord4", _texCoordAlias[4], "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_MultiTexCoord5", _texCoordAlias[5], "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_MultiTexCoord6", _texCoordAlias[6], "attribute vec4 ");
            replaceAndBindAttrib(program, source, "gl_MultiTexCoord7", _texCoordAlias[7], "attribute vec4 ");
#endif

#if 1
            // replace built in uniform
            replaceBuiltInUniform(source, "gl_ModelViewMatrix", "osg_ModeViewMatrix", "uniform mat4 ");
            replaceBuiltInUniform(source, "gl_ModelViewProjectionMatrix", "osg_ModelViewProjectionMatrix", "uniform mat4 ");
            replaceBuiltInUniform(source, "gl_ProjectionMatrix", "osg_ProjectionMatrix", "uniform mat4 ");
#endif
            shader.setShaderSource(source);
        }

        void convertFragmentShader(osg::Program& program, osg::Shader& shader)
        {
        }

        virtual void reset()
        {
            _visited.clear();
        }

        void apply(osg::Node& node)
        {
            if (_visited.count(&node)!=0) return;
            _visited.insert(&node);

            if (node.getStateSet()) apply(*(node.getStateSet()));
            traverse(node);
        }

        void apply(osg::Geode& geode)
        {
            if (_visited.count(&geode)!=0) return;
            _visited.insert(&geode);

            if (geode.getStateSet()) apply(*(geode.getStateSet()));

            for(unsigned int i=0; i<geode.getNumDrawables(); ++i)
            {
                if (geode.getDrawable(i)->getStateSet()) apply(*(geode.getDrawable(i)->getStateSet()));

                osg::Geometry* geom = geode.getDrawable(i)->asGeometry();
                if (geom) apply(*geom);
            }
        }

        bool replace(std::string& str, const std::string& original_phrase, const std::string& new_phrase)
        {
            bool replacedStr = false;
            std::string::size_type pos = 0;
            while((pos=str.find(original_phrase, pos))!=std::string::npos)
            {
                std::string::size_type endOfPhrasePos = pos+original_phrase.size();
                if (endOfPhrasePos<str.size())
                {
                    char c = str[endOfPhrasePos];
                    if ((c>='0' && c<='9') ||
                        (c>='a' && c<='z') ||
                        (c>='A' && c<='Z'))
                    {
                        pos = endOfPhrasePos;
                        continue;
                    }
                }

                replacedStr = true;
                str.replace(pos, original_phrase.size(), new_phrase);
            }
            return replacedStr;
        }

        void apply(osg::Program& program, osg::Shader& shader)
        {
             if (_visited.count(&shader)!=0) return;
            _visited.insert(&shader);

            osg::notify(osg::NOTICE)<<"Shader "<<shader.getTypename()<<" ----before-----------"<<std::endl;
            osg::notify(osg::NOTICE)<<shader.getShaderSource()<<std::endl;

            if (shader.getType()==osg::Shader::VERTEX) convertVertexShader(program, shader);
            else if (shader.getType()==osg::Shader::FRAGMENT) convertFragmentShader(program, shader);

            osg::notify(osg::NOTICE)<<"--after-----------"<<std::endl;
            osg::notify(osg::NOTICE)<<shader.getShaderSource()<<std::endl;
            osg::notify(osg::NOTICE)<<"---------------------"<<std::endl;
        }

        void apply(osg::StateSet& stateset)
        {
             if (_visited.count(&stateset)!=0) return;
            _visited.insert(&stateset);

            return;

            osg::notify(osg::NOTICE)<<"Found stateset "<<&stateset<<std::endl;
            osg::Program* program = dynamic_cast<osg::Program*>(stateset.getAttribute(osg::StateAttribute::PROGRAM));
            if (program)
            {
                osg::notify(osg::NOTICE)<<"   Found Program "<<program<<std::endl;
                for(unsigned int i=0; i<program->getNumShaders(); ++i)
                {
                    apply(*program, *(program->getShader(i)));
                }

            }
       }

        void apply(osg::Geometry& geom)
        {
            geom.setUseDisplayList(false);

            if (!_manualVertexAliasing) return;

            osg::notify(osg::NOTICE)<<"Found geometry "<<&geom<<std::endl;
            if (geom.getVertexArray())
            {
                setVertexAttrib(geom, _vertexAlias, geom.getVertexArray(), false, osg::Geometry::BIND_PER_VERTEX);
                geom.setVertexArray(0);
            }

            if (geom.getNormalArray())
            {
                setVertexAttrib(geom, _normalAlias, geom.getNormalArray(), true, geom.getNormalBinding());
                geom.setNormalArray(0);
            }

            if (geom.getColorArray())
            {
                setVertexAttrib(geom, _colorAlias, geom.getColorArray(), false, geom.getColorBinding());
                geom.setColorArray(0);
            }

            if (geom.getSecondaryColorArray())
            {
                setVertexAttrib(geom, _secondaryColorAlias, geom.getSecondaryColorArray(), false, geom.getSecondaryColorBinding());
                geom.setSecondaryColorArray(0);
            }

            if (geom.getFogCoordArray())
            {
                // should we normalize the FogCoord array? Don't think so...
                setVertexAttrib(geom, _fogCoordAlias, geom.getFogCoordArray(), false, geom.getFogCoordBinding());
                geom.setFogCoordArray(0);
            }

            unsigned int maxNumTexCoords = geom.getNumTexCoordArrays();
            if (maxNumTexCoords>8)
            {
                osg::notify(osg::NOTICE)<<"Warning: Ignoring "<<maxNumTexCoords-8<<" texture coordinate arrays, only 8 are currently supported in vertex attribute conversion code."<<std::endl;
                maxNumTexCoords = 8;
            }
            for(unsigned int i=0; i<maxNumTexCoords; ++i)
            {
                if (geom.getTexCoordArray(i))
                {
                    setVertexAttrib(geom, _texCoordAlias[i], geom.getTexCoordArray(i), false, osg::Geometry::BIND_PER_VERTEX);
                    geom.setTexCoordArray(i,0);
                }
                else
                {
                    osg::notify(osg::NOTICE)<<"Found empty TexCoordArray("<<i<<")"<<std::endl;
                }
            }
        }

        void setVertexAttrib(osg::Geometry& geom, const AttributeAlias& alias, osg::Array* array, bool normalize, osg::Geometry::AttributeBinding binding)
        {
            unsigned int index = alias.first;
            const std::string& name = alias.second;
            array->setName(name);
            geom.setVertexAttribArray(index, array);
            geom.setVertexAttribNormalize(index, normalize);
            geom.setVertexAttribBinding(index, binding);

            osg::notify(osg::NOTICE)<<"   vertex attrib("<<name<<", index="<<index<<", normalize="<<normalize<<" binding="<<binding<<")"<<std::endl;
        }

        typedef std::set<osg::Object*> Visited;
        Visited         _visited;

        bool           _manualVertexAliasing;
        AttributeAlias _vertexAlias;
        AttributeAlias _normalAlias;
        AttributeAlias _colorAlias;
        AttributeAlias _secondaryColorAlias;
        AttributeAlias _fogCoordAlias;
        AttributeAlias _texCoordAlias[8];
};

osg::Node* createSimpleTestModel()
{
    osg::Group* group = new osg::Group;

    osg::Geode* geode = new osg::Geode;
    group->addChild(geode);

    osg::Geometry* geometry = new osg::Geometry;
    geode->addDrawable(geometry);

    osg::Vec3Array* vertices = new osg::Vec3Array;
    vertices->push_back(osg::Vec3(0.0,0.0,0.0));
    vertices->push_back(osg::Vec3(0.0,0.0,1.0));
    vertices->push_back(osg::Vec3(1.0,0.0,0.0));
    vertices->push_back(osg::Vec3(1.0,0.0,1.0));
    geometry->setVertexArray(vertices);

    geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP, 0, 4));

    char vertexShaderSource[] =
       "void main(void)\n"
       "{\n"
       "    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
       "}\n";

    char fragmentShaderSource[] =
        "void main(void)\n"
        "{\n"
        "    gl_FragColor = vec4(1.0,1.0,0.0,1.0); \n"
        "}\n";

    osg::Program* program = new osg::Program;
    program->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShaderSource));
    program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource));

    geometry->getOrCreateStateSet()->setAttribute(program);

    return group;
}

int main(int argc, char *argv[])
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // construct the viewer.
    osgViewer::Viewer viewer(arguments);

    std::string outputFileName;
    while (arguments.read("-o",outputFileName)) {}

    osg::ref_ptr<osg::Node> loadedModel;

    bool runConvertToVertexAttributes = true;
    if (arguments.read("--simple") || arguments.read("--s"))
    {
        loadedModel = createSimpleTestModel();
    }
    else
    {
        bool runShaderGen = true;
        while (arguments.read("--shader-gen")) { runShaderGen = true; }
        while (arguments.read("--no-shader-gen")) { runShaderGen = false; }

        while (arguments.read("--vertex-attrib")) { runConvertToVertexAttributes = true; }
        while (arguments.read("--no-vertex-attrib")) { runConvertToVertexAttributes = false; }

        loadedModel = osgDB::readNodeFiles(arguments);
        if (!loadedModel.get())
        {
            osg::notify(osg::NOTICE)<<"No model loaded, please specify a model filename."<<std::endl;
            return 1;
        }

        if (runShaderGen)
        {
            // convert fixed function pipeline to shaders
            osgUtil::ShaderGenVisitor sgv;
            loadedModel->accept(sgv);
        }

        if (runConvertToVertexAttributes)
        {
            // find any conventional vertex, colour, normal and tex coords arrays and convert to vertex attributes
            ConvertToVertexAttibArrays ctvaa;
            loadedModel->accept(ctvaa);
        }
    }

    if (!loadedModel) return 1;

    if (!outputFileName.empty())
    {
        osgDB::writeNodeFile(*loadedModel, outputFileName);
        return 0;
    }

    // add a viewport to the viewer and attach the scene graph.
    viewer.setSceneData(loadedModel.get());

    viewer.setCameraManipulator(new osgGA::TrackballManipulator());

    // add the stats handler
    viewer.addEventHandler(new osgViewer::StatsHandler);

    viewer.realize();

    if (runConvertToVertexAttributes)
    {
        // switch on the uniforms that track the modelview and projection matrices
        osgViewer::Viewer::Windows windows;
        viewer.getWindows(windows);
        for(osgViewer::Viewer::Windows::iterator itr = windows.begin();
            itr != windows.end();
            ++itr)
        {
            (*itr)->getState()->setUseModelViewAndProjectionUniforms(true);
            (*itr)->getState()->setUseVertexAttributeAliasing(true);
        }
    }

    return viewer.run();
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <iterator>

#include "gtest/gtest.h"

#include "sdd/conf/default_configurations.hh"
#include "sdd/dd/context.hh"
#include "sdd/dd/path_generator.hh"
#include "sdd/dd/definition.hh"
#include "sdd/manager.hh"

#include "tests/configuration.hh"

/*------------------------------------------------------------------------------------------------*/

template <typename C>
struct path_generator_test
  : public testing::Test
{
  typedef C configuration_type;

  sdd::manager<C> m;

  const sdd::SDD<C> zero;
  const sdd::SDD<C> one;

  path_generator_test()
    : m(sdd::init(small_conf<C>()))
    , zero(sdd::zero<C>())
    , one(sdd::one<C>())
  {}
};

/*------------------------------------------------------------------------------------------------*/

TYPED_TEST_CASE(path_generator_test, configurations);
#include "tests/macros.hh"

/*------------------------------------------------------------------------------------------------*/

TYPED_TEST(path_generator_test, terminal_zero)
{
  // an empty path is returned
  auto gen = zero.paths();
  ASSERT_EQ(0u, std::begin(gen)->size());
  ASSERT_EQ(1u, std::distance(std::begin(gen), std::end(gen)));
}

/*------------------------------------------------------------------------------------------------*/

TYPED_TEST(path_generator_test, terminal_one)
{
  // an empty path is returned
  auto gen = one.paths();
  ASSERT_EQ(0u, std::begin(gen)->size());
  ASSERT_EQ(1u, std::distance(std::begin(gen), std::end(gen)));
}

/*------------------------------------------------------------------------------------------------*/

TYPED_TEST(path_generator_test, flat)
{
  {
    const auto x = SDD('a', {0,1}, SDD('b', {0,1}, one)) + SDD('a', {2,3}, SDD('b', {2,3}, one));
    auto gen = x.paths();
    std::vector<sdd::path<conf>> v(std::begin(gen), std::end(gen));
    std::sort(v.begin(), v.end());
    ASSERT_EQ(2u, v.size());
    std::vector<sdd::path<conf>> r {sdd::path<conf>{{0,1}, {0,1}}, sdd::path<conf>{{2,3}, {2,3}}};
    std::sort(r.begin(), r.end());

    ASSERT_EQ(r, v);
  }
  {
    const auto x = SDD(2, {0}, SDD(1, {0}, SDD(0, {0}, one)))
                 + SDD(2, {1}, SDD(1, {1}, SDD(0, {0}, one)))
                 + SDD(2, {2}, SDD(1, {2}, SDD(0, {2}, one)));
    auto gen = x.paths();
    std::vector<sdd::path<conf>> v(std::begin(gen), std::end(gen));
    std::sort(v.begin(), v.end());

    ASSERT_EQ(3u, v.size());
    std::vector<sdd::path<conf>> r { sdd::path<conf>{{0}, {0}, {0}}
                                   , sdd::path<conf>{{1}, {1}, {0}}
                                   , sdd::path<conf>{{2}, {2}, {2}}
                                   };
    std::sort(r.begin(), r.end());

    ASSERT_EQ(r, v);
  }
}

/*------------------------------------------------------------------------------------------------*/

TYPED_TEST(path_generator_test, hierarchical)
{
  {
    const auto x = SDD('1', {0}, SDD('0', {0}, one)) + SDD('1', {1}, SDD('0', {1}, one));
    const auto z = SDD(10, x, SDD(11, x, one));
    auto gen = z.paths();
    std::vector<sdd::path<conf>> v(std::begin(gen), std::end(gen));
    std::sort(v.begin(), v.end());

    ASSERT_EQ(4u, v.size());
    std::vector<sdd::path<conf>> r { sdd::path<conf>{{0}, {0}, {0}, {0}}
                                   , sdd::path<conf>{{0}, {0}, {1}, {1}}
                                   , sdd::path<conf>{{1}, {1}, {1}, {1}}
                                   , sdd::path<conf>{{1}, {1}, {0}, {0}}
                                   };
    std::sort(r.begin(), r.end());
    ASSERT_EQ(r, v);
  }
  {
    const auto x1 = SDD('1', {0}, SDD('0', {0}, one)) + SDD('1', {1}, SDD('0', {1}, one));
    const auto x2 = SDD('1', {2}, SDD('0', {2}, one)) + SDD('1', {3}, SDD('0', {3}, one));
    const auto z = SDD(10, x1, SDD(11, x1, one)) + SDD(10, x2, SDD(11, x2, one));
    auto gen = z.paths();
    std::vector<sdd::path<conf>> v(std::begin(gen), std::end(gen));
    std::sort(v.begin(), v.end());

    ASSERT_EQ(8u, v.size());
    std::vector<sdd::path<conf>> r { sdd::path<conf>{{0}, {0}, {0}, {0}}
                                   , sdd::path<conf>{{0}, {0}, {1}, {1}}
                                   , sdd::path<conf>{{1}, {1}, {1}, {1}}
                                   , sdd::path<conf>{{1}, {1}, {0}, {0}}
                                   , sdd::path<conf>{{2}, {2}, {2}, {2}}
                                   , sdd::path<conf>{{2}, {2}, {3}, {3}}
                                   , sdd::path<conf>{{3}, {3}, {2}, {2}}
                                   , sdd::path<conf>{{3}, {3}, {3}, {3}}
                                   };
    std::sort(r.begin(), r.end());
    ASSERT_EQ(r, v);
  }
  {
    const auto x = SDD('1', {0}, SDD('0', {0}, one)) + SDD('1', {1}, SDD('0', {1}, one));
    const auto z = SDD(100, SDD(10, x, one), SDD(11, x, one));
    auto gen = z.paths();
    std::vector<sdd::path<conf>> v(std::begin(gen), std::end(gen));

    ASSERT_EQ(4u, v.size());
    std::vector<sdd::path<conf>> r { sdd::path<conf>{{0}, {0}, {0}, {0}}
                                   , sdd::path<conf>{{0}, {0}, {1}, {1}}
                                   , sdd::path<conf>{{1}, {1}, {1}, {1}}
                                   , sdd::path<conf>{{1}, {1}, {0}, {0}}
                                   };
    std::sort(r.begin(), r.end());
    ASSERT_EQ(r, v);
  }
}

/*------------------------------------------------------------------------------------------------*/
<commit_msg>Fix path generator test<commit_after>#include <algorithm>
#include <iterator>

#include "gtest/gtest.h"

#include "sdd/conf/default_configurations.hh"
#include "sdd/dd/context.hh"
#include "sdd/dd/path_generator.hh"
#include "sdd/dd/definition.hh"
#include "sdd/manager.hh"

#include "tests/configuration.hh"

/*------------------------------------------------------------------------------------------------*/

template <typename C>
struct path_generator_test
  : public testing::Test
{
  typedef C configuration_type;

  sdd::manager<C> m;

  const sdd::SDD<C> zero;
  const sdd::SDD<C> one;

  path_generator_test()
    : m(sdd::init(small_conf<C>()))
    , zero(sdd::zero<C>())
    , one(sdd::one<C>())
  {}
};

/*------------------------------------------------------------------------------------------------*/

TYPED_TEST_CASE(path_generator_test, configurations);
#include "tests/macros.hh"

/*------------------------------------------------------------------------------------------------*/

TYPED_TEST(path_generator_test, terminal_zero)
{
  // an empty path is returned
  auto gen = zero.paths();
  ASSERT_EQ(0u, std::begin(gen)->size());
  ASSERT_EQ(1u, std::distance(std::begin(gen), std::end(gen)));
}

/*------------------------------------------------------------------------------------------------*/

TYPED_TEST(path_generator_test, terminal_one)
{
  // an empty path is returned
  auto gen = one.paths();
  ASSERT_EQ(0u, std::begin(gen)->size());
  ASSERT_EQ(1u, std::distance(std::begin(gen), std::end(gen)));
}

/*------------------------------------------------------------------------------------------------*/

TYPED_TEST(path_generator_test, flat)
{
  {
    const auto x = SDD('a', {0,1}, SDD('b', {0,1}, one)) + SDD('a', {2,3}, SDD('b', {2,3}, one));
    auto gen = x.paths();
    std::vector<sdd::path<conf>> v(std::begin(gen), std::end(gen));
    std::sort(v.begin(), v.end());
    ASSERT_EQ(2u, v.size());
    std::vector<sdd::path<conf>> r {sdd::path<conf>{{0,1}, {0,1}}, sdd::path<conf>{{2,3}, {2,3}}};
    std::sort(r.begin(), r.end());

    ASSERT_EQ(r, v);
  }
  {
    const auto x = SDD(2, {0}, SDD(1, {0}, SDD(0, {0}, one)))
                 + SDD(2, {1}, SDD(1, {1}, SDD(0, {0}, one)))
                 + SDD(2, {2}, SDD(1, {2}, SDD(0, {2}, one)));
    auto gen = x.paths();
    std::vector<sdd::path<conf>> v(std::begin(gen), std::end(gen));
    std::sort(v.begin(), v.end());

    ASSERT_EQ(3u, v.size());
    std::vector<sdd::path<conf>> r { sdd::path<conf>{{0}, {0}, {0}}
                                   , sdd::path<conf>{{1}, {1}, {0}}
                                   , sdd::path<conf>{{2}, {2}, {2}}
                                   };
    std::sort(r.begin(), r.end());

    ASSERT_EQ(r, v);
  }
}

/*------------------------------------------------------------------------------------------------*/

TYPED_TEST(path_generator_test, hierarchical)
{
  {
    const auto x = SDD('1', {0}, SDD('0', {0}, one)) + SDD('1', {1}, SDD('0', {1}, one));
    const auto z = SDD(10, x, SDD(11, x, one));
    auto gen = z.paths();
    std::vector<sdd::path<conf>> v(std::begin(gen), std::end(gen));
    std::sort(v.begin(), v.end());

    ASSERT_EQ(4u, v.size());
    std::vector<sdd::path<conf>> r { sdd::path<conf>{{0}, {0}, {0}, {0}}
                                   , sdd::path<conf>{{0}, {0}, {1}, {1}}
                                   , sdd::path<conf>{{1}, {1}, {1}, {1}}
                                   , sdd::path<conf>{{1}, {1}, {0}, {0}}
                                   };
    std::sort(r.begin(), r.end());
    ASSERT_EQ(r, v);
  }
  {
    const auto x1 = SDD('1', {0}, SDD('0', {0}, one)) + SDD('1', {1}, SDD('0', {1}, one));
    const auto x2 = SDD('1', {2}, SDD('0', {2}, one)) + SDD('1', {3}, SDD('0', {3}, one));
    const auto z = SDD(10, x1, SDD(11, x1, one)) + SDD(10, x2, SDD(11, x2, one));
    auto gen = z.paths();
    std::vector<sdd::path<conf>> v(std::begin(gen), std::end(gen));
    std::sort(v.begin(), v.end());

    ASSERT_EQ(8u, v.size());
    std::vector<sdd::path<conf>> r { sdd::path<conf>{{0}, {0}, {0}, {0}}
                                   , sdd::path<conf>{{0}, {0}, {1}, {1}}
                                   , sdd::path<conf>{{1}, {1}, {1}, {1}}
                                   , sdd::path<conf>{{1}, {1}, {0}, {0}}
                                   , sdd::path<conf>{{2}, {2}, {2}, {2}}
                                   , sdd::path<conf>{{2}, {2}, {3}, {3}}
                                   , sdd::path<conf>{{3}, {3}, {2}, {2}}
                                   , sdd::path<conf>{{3}, {3}, {3}, {3}}
                                   };
    std::sort(r.begin(), r.end());
    ASSERT_EQ(r, v);
  }
  {
    const auto x = SDD('1', {0}, SDD('0', {0}, one)) + SDD('1', {1}, SDD('0', {1}, one));
    const auto z = SDD(100, SDD(10, x, one), SDD(11, x, one));
    auto gen = z.paths();
    std::vector<sdd::path<conf>> v(std::begin(gen), std::end(gen));
    std::sort(v.begin(), v.end());

    ASSERT_EQ(4u, v.size());
    std::vector<sdd::path<conf>> r { sdd::path<conf>{{0}, {0}, {0}, {0}}
                                   , sdd::path<conf>{{0}, {0}, {1}, {1}}
                                   , sdd::path<conf>{{1}, {1}, {1}, {1}}
                                   , sdd::path<conf>{{1}, {1}, {0}, {0}}
                                   };
    std::sort(r.begin(), r.end());
    ASSERT_EQ(r, v);
  }
}

/*------------------------------------------------------------------------------------------------*/
<|endoftext|>


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

#ifndef EXTENSIONS_SOURCE_PROPCTRLR_PROPEVENTTRANSLATION_HXX
#define EXTENSIONS_SOURCE_PROPCTRLR_PROPEVENTTRANSLATION_HXX

/** === begin UNO includes === **/
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYCHANGELISTENER_HPP_
#include <com/sun/star/beans/XPropertyChangeListener.hpp>
#endif
/** === end UNO includes === **/

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif

//........................................................................
namespace pcr
{
//........................................................................

    //====================================================================
    //= PropertyEventTranslation
    //====================================================================
    typedef ::cppu::WeakImplHelper1 <   ::com::sun::star::beans::XPropertyChangeListener
                                    >   PropertyEventTranslation_Base;

    class PropertyEventTranslation : public PropertyEventTranslation_Base
    {
        ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >
                m_xDelegator;
        ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >
                m_xTranslatedEventSource;

    public:
        /** constructs the object
            @throws NullPointerException
                if <arg>_rxDelegator</arg> is <NULL/>
        */
        PropertyEventTranslation(
            const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxDelegator,
            const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxTranslatedEventSource
        );

        inline const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >&
            getDelegator() const { return m_xDelegator; }

    protected:
        // XPropertyChangeListener
        virtual void SAL_CALL propertyChange( const ::com::sun::star::beans::PropertyChangeEvent& evt ) throw (::com::sun::star::uno::RuntimeException);
        // XEventListener
        virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);

    private:
        PropertyEventTranslation();                                             // never implemented
        PropertyEventTranslation( const PropertyEventTranslation& );            // never implemented
        PropertyEventTranslation& operator=( const PropertyEventTranslation& ); // never implemented
    };

//........................................................................
} // namespace pcr
//........................................................................

#endif // EXTENSIONS_SOURCE_PROPCTRLR_PROPEVENTTRANSLATION_HXX

<commit_msg>INTEGRATION: CWS changefileheader (1.2.380); FILE MERGED 2008/04/01 15:15:20 thb 1.2.380.3: #i85898# Stripping all external header guards 2008/04/01 12:29:53 thb 1.2.380.2: #i85898# Stripping all external header guards 2008/03/31 12:31:54 rt 1.2.380.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: propeventtranslation.hxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef EXTENSIONS_SOURCE_PROPCTRLR_PROPEVENTTRANSLATION_HXX
#define EXTENSIONS_SOURCE_PROPCTRLR_PROPEVENTTRANSLATION_HXX

/** === begin UNO includes === **/
#include <com/sun/star/beans/XPropertyChangeListener.hpp>
/** === end UNO includes === **/
#include <cppuhelper/implbase1.hxx>

//........................................................................
namespace pcr
{
//........................................................................

    //====================================================================
    //= PropertyEventTranslation
    //====================================================================
    typedef ::cppu::WeakImplHelper1 <   ::com::sun::star::beans::XPropertyChangeListener
                                    >   PropertyEventTranslation_Base;

    class PropertyEventTranslation : public PropertyEventTranslation_Base
    {
        ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >
                m_xDelegator;
        ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >
                m_xTranslatedEventSource;

    public:
        /** constructs the object
            @throws NullPointerException
                if <arg>_rxDelegator</arg> is <NULL/>
        */
        PropertyEventTranslation(
            const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxDelegator,
            const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxTranslatedEventSource
        );

        inline const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >&
            getDelegator() const { return m_xDelegator; }

    protected:
        // XPropertyChangeListener
        virtual void SAL_CALL propertyChange( const ::com::sun::star::beans::PropertyChangeEvent& evt ) throw (::com::sun::star::uno::RuntimeException);
        // XEventListener
        virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);

    private:
        PropertyEventTranslation();                                             // never implemented
        PropertyEventTranslation( const PropertyEventTranslation& );            // never implemented
        PropertyEventTranslation& operator=( const PropertyEventTranslation& ); // never implemented
    };

//........................................................................
} // namespace pcr
//........................................................................

#endif // EXTENSIONS_SOURCE_PROPCTRLR_PROPEVENTTRANSLATION_HXX

<|endoftext|>


<commit_before>#ifndef __NBA_MEMPOOL_HH__
#define __NBA_MEMPOOL_HH__

#include <stdint.h>
#include <assert.h>

#define __ALIGN(x,a) (((x)+(a)-1)&~((a)-1))

namespace nba
{

class MemoryPool
{
public:
    MemoryPool() : max_size_(0), curpos_(0)
    {}

    virtual ~MemoryPool() {}

    virtual bool init(size_t max_size) = 0;

    int _alloc(size_t size, size_t *start_offset)
    {
        if (curpos_ + size > max_size_)
            return -1;
        /* IMPORTANT: We need to return the position before adding the new size. */
        if (start_offset != nullptr)
            *start_offset = curpos_;
        curpos_ += size;
        curpos_ = __ALIGN(curpos_, 64);
        return 0;
    }

    // The device implementer's should provide his own alloc() method.

    void reset()
    {
        curpos_ = 0;
    }

    size_t get_alloc_size()
    {
        return curpos_;
    }

    virtual void *get_base_ptr() = 0;

protected:
    size_t max_size_;
    size_t curpos_;
};

}

#undef __ALIGN

#endif

// vim: ts=8 sts=4 sw=4 et
<commit_msg>Minor code clean up for lib/memorypool.<commit_after>#ifndef __NBA_MEMPOOL_HH__
#define __NBA_MEMPOOL_HH__

#include <cstdint>
#include <cassert>
#include <cerrno>

#define __ALIGN(x,a) (((x)+(a)-1)&~((a)-1))

namespace nba
{

/**
 * This abstract memory pool class provides a bump allocator
 * in the memroy region defined by its subclasses.
 */
class MemoryPool
{
public:
    MemoryPool() : max_size_(0), curpos_(0)
    {}

    virtual ~MemoryPool() {}

    virtual bool init(size_t max_size) = 0;

    int _alloc(size_t size, size_t *start_offset)
    {
        if (curpos_ + size > max_size_)
            return -ENOMEM;
        /* IMPORTANT: We need to return the position before adding the new size. */
        if (start_offset != nullptr)
            *start_offset = curpos_;
        curpos_ += size;
        curpos_ = __ALIGN(curpos_, 64);
        return 0;
    }

    // The device implementer's should provide his own alloc() method.

    void reset()
    {
        curpos_ = 0;
    }

    size_t get_alloc_size()
    {
        return curpos_;
    }

    virtual void *get_base_ptr() = 0;

protected:
    size_t max_size_;
    size_t curpos_;
};

}

#undef __ALIGN

#endif

// vim: ts=8 sts=4 sw=4 et
<|endoftext|>


<commit_before>#include <catch/catch.hpp>

#include <world/core.h>

using namespace world;

TEST_CASE("Perlin - General test case", "[perlin]") {
    Perlin perlin;
    arma::mat reference(100, 100, arma::fill::zeros);
    arma::mat subject(100, 100, arma::fill::zeros);

    REQUIRE(arma::accu(arma::abs(subject - reference)) < 1e-3);

    SECTION("generating perlin noise changes the matrix") {
        perlin.generatePerlinNoise2D(subject, {1, 0.5, false, 0, 4., 0, 0});
        REQUIRE(arma::accu(arma::abs(subject - reference)) > 1e-3);
    }

    SECTION("two patterns generated in a row are the same") {
        perlin.generatePerlinNoise2D(subject, {1, 0.5, false, 0, 4., 0, 0});
        perlin.generatePerlinNoise2D(reference, {1, 0.5, false, 0, 4., 0, 0});
        REQUIRE(arma::accu(arma::abs(subject - reference)) < 1e-3);
    }
}

TEST_CASE("Perlin - Random values modifier") {
    Perlin perlin;
    arma::mat noise(100, 100);

    SECTION("sides must be 0") {
        const double eps = std::numeric_limits<double>::epsilon();
        perlin.generatePerlinNoise2D(noise, {1, 0.5, false, 0, 4., 0, 0},
            [&](double x, double y, double val) {
            if (x < eps || 1 - x < eps ||
                y < eps || 1 - y < eps) {
                return .0;
            }

            return val;
        });

        // Sum all the sides : must be ~0
        bool success = true;
        std::stringstream errors;

        for (int x = 0; x < 100; x++) {
            for (int y = 0; y < 100; y++) {
                if (x == 0 || y == 0 || x == 99 || y == 99) {
                    if (noise(x, y) != Approx(0.0)) {
                        success = false;
                        errors << noise(x, y) << " should be 0" << std::endl;
                    }
                }
            }
        }

        // But the noise should not be 0
        INFO(errors.str());
        CHECK(success);
        CHECK(arma::accu(arma::abs(noise)) > 98 * 98 * eps);
    }
}

TEST_CASE("Perlin - Benchmarks", "[!benchmark]") {
	arma::mat noise(1024, 1024);

	Perlin perlin;
	PerlinInfo info{
		12, 0.4, false, 0, 4, 0, 0
	};

	BENCHMARK("1024*1024 perlin with 4 frequency at octave 0, and 13 octaves") {
		perlin.generatePerlinNoise2D(noise, info);
	}

	arma::mat noise2(4096, 4096);
	info.octaves = 3;
	info.frequency *= 4;

	BENCHMARK("4096*4096 perlin with 16 frequency at octave 0, and 4 octaves") {
		perlin.generatePerlinNoise2D(noise2, info);
	}
}<commit_msg>Format test_perlin<commit_after>#include <catch/catch.hpp>

#include <world/core.h>

using namespace world;

TEST_CASE("Perlin - General test case", "[perlin]") {
    Perlin perlin;
    arma::mat reference(100, 100, arma::fill::zeros);
    arma::mat subject(100, 100, arma::fill::zeros);

    REQUIRE(arma::accu(arma::abs(subject - reference)) < 1e-3);

    SECTION("generating perlin noise changes the matrix") {
        perlin.generatePerlinNoise2D(subject, {1, 0.5, false, 0, 4., 0, 0});
        REQUIRE(arma::accu(arma::abs(subject - reference)) > 1e-3);
    }

    SECTION("two patterns generated in a row are the same") {
        perlin.generatePerlinNoise2D(subject, {1, 0.5, false, 0, 4., 0, 0});
        perlin.generatePerlinNoise2D(reference, {1, 0.5, false, 0, 4., 0, 0});
        REQUIRE(arma::accu(arma::abs(subject - reference)) < 1e-3);
    }
}

TEST_CASE("Perlin - Random values modifier") {
    Perlin perlin;
    arma::mat noise(100, 100);

    SECTION("sides must be 0") {
        const double eps = std::numeric_limits<double>::epsilon();
        perlin.generatePerlinNoise2D(noise, {1, 0.5, false, 0, 4., 0, 0},
                                     [&](double x, double y, double val) {
                                         if (x < eps || 1 - x < eps ||
                                             y < eps || 1 - y < eps) {
                                             return .0;
                                         }

                                         return val;
                                     });

        // Sum all the sides : must be ~0
        bool success = true;
        std::stringstream errors;

        for (int x = 0; x < 100; x++) {
            for (int y = 0; y < 100; y++) {
                if (x == 0 || y == 0 || x == 99 || y == 99) {
                    if (noise(x, y) != Approx(0.0)) {
                        success = false;
                        errors << noise(x, y) << " should be 0" << std::endl;
                    }
                }
            }
        }

        // But the noise should not be 0
        INFO(errors.str());
        CHECK(success);
        CHECK(arma::accu(arma::abs(noise)) > 98 * 98 * eps);
    }
}

TEST_CASE("Perlin - Benchmarks", "[!benchmark]") {
    arma::mat noise(1024, 1024);

    Perlin perlin;
    PerlinInfo info{12, 0.4, false, 0, 4, 0, 0};

    BENCHMARK("1024*1024 perlin with 4 frequency at octave 0, and 13 octaves") {
        perlin.generatePerlinNoise2D(noise, info);
    }

    arma::mat noise2(4096, 4096);
    info.octaves = 3;
    info.frequency *= 4;

    BENCHMARK("4096*4096 perlin with 16 frequency at octave 0, and 4 octaves") {
        perlin.generatePerlinNoise2D(noise2, info);
    }
}<|endoftext|>


<commit_before>/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
 *
 * 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 "jrt.h"
#include "mem-allocator.h"

extern "C"
{
  extern void srand (unsigned int __seed);
  extern int rand (void);
  extern long int time (long int *__timer);
  extern int printf (__const char *__restrict __format, ...);
  extern void *memset (void *__s, int __c, size_t __n);
}

// Heap size is 32K
#define test_heap_size (32 * 1024)

// Iterations count
#define test_iters (64 * 1024)

// Subiterations count
#define test_sub_iters 32

// Threshold size of block to allocate
#define test_threshold_block_size 8192

uint8_t *ptrs[test_sub_iters];
size_t sizes[test_sub_iters];

static void
test_heap_give_some_memory_back (mem_try_give_memory_back_severity_t severity)
{
  int p;

  if (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_LOW)
  {
    p = 8;
  }
  else if (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_MEDIUM)
  {
    p = 4;
  }
  else if (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_HIGH)
  {
    p = 2;
  }
  else
  {
    JERRY_ASSERT (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_CRITICAL);

    p = 1;
  }

  for (int i = 0; i < test_sub_iters; i++)
  {
    if (rand () % p == 0)
    {
      if (ptrs[i] != NULL)
      {
        for (size_t k = 0; k < sizes[i]; k++)
        {
          JERRY_ASSERT (ptrs[i][k] == 0);
        }

        mem_heap_free_block (ptrs[i]);
        ptrs[i] = NULL;
      }
    }
  }
} /* test_heap_give_some_memory_back */

int
main (int __attr_unused___ argc,
      char __attr_unused___ **argv)
{
  uint8_t test_native_heap[test_heap_size];

  mem_heap_init (test_native_heap, sizeof (test_native_heap));

  srand ((unsigned int) time (NULL));
  int k = rand ();
  printf ("seed=%d\n", k);
  srand ((unsigned int) k);

  mem_register_a_try_give_memory_back_callback (test_heap_give_some_memory_back);

  mem_heap_print (true, false, true);

  for (uint32_t i = 0; i < test_iters; i++)
  {
    for (uint32_t j = 0; j < test_sub_iters; j++)
    {
      size_t size = (size_t) rand () % test_threshold_block_size;
      ptrs[j] = (uint8_t*) mem_heap_alloc_block (size,
                                                 (rand () % 2) ?
                                                 MEM_HEAP_ALLOC_SHORT_TERM : MEM_HEAP_ALLOC_SHORT_TERM);
      sizes[j] = size;

      JERRY_ASSERT (size == 0 || ptrs[j] != NULL);
      memset (ptrs[j], 0, sizes[j]);

      JERRY_ASSERT (ptrs[j] == NULL
                    || mem_heap_get_block_start (ptrs[j] + (size_t) rand () % sizes [j]) == ptrs[j]);
    }

    // mem_heap_print (true);

    for (uint32_t j = 0; j < test_sub_iters; j++)
    {
      if (ptrs[j] != NULL)
      {
        for (size_t k = 0; k < sizes[j]; k++)
        {
          JERRY_ASSERT(ptrs[j][k] == 0);
        }

        JERRY_ASSERT (sizes [j] == 0
                      || mem_heap_get_block_start (ptrs[j] + (size_t) rand () % sizes [j]) == ptrs[j]);

        mem_heap_free_block (ptrs[j]);

        ptrs[j] = NULL;
      }
    }
  }

  mem_heap_print (true, false, true);

  return 0;
} /* main */
<commit_msg>Adding missing long-term allocation requests to heap unit test.<commit_after>/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
 *
 * 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 "jrt.h"
#include "mem-allocator.h"

extern "C"
{
  extern void srand (unsigned int __seed);
  extern int rand (void);
  extern long int time (long int *__timer);
  extern int printf (__const char *__restrict __format, ...);
  extern void *memset (void *__s, int __c, size_t __n);
}

// Heap size is 32K
#define test_heap_size (32 * 1024)

// Iterations count
#define test_iters (64 * 1024)

// Subiterations count
#define test_sub_iters 32

// Threshold size of block to allocate
#define test_threshold_block_size 8192

uint8_t *ptrs[test_sub_iters];
size_t sizes[test_sub_iters];

static void
test_heap_give_some_memory_back (mem_try_give_memory_back_severity_t severity)
{
  int p;

  if (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_LOW)
  {
    p = 8;
  }
  else if (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_MEDIUM)
  {
    p = 4;
  }
  else if (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_HIGH)
  {
    p = 2;
  }
  else
  {
    JERRY_ASSERT (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_CRITICAL);

    p = 1;
  }

  for (int i = 0; i < test_sub_iters; i++)
  {
    if (rand () % p == 0)
    {
      if (ptrs[i] != NULL)
      {
        for (size_t k = 0; k < sizes[i]; k++)
        {
          JERRY_ASSERT (ptrs[i][k] == 0);
        }

        mem_heap_free_block (ptrs[i]);
        ptrs[i] = NULL;
      }
    }
  }
} /* test_heap_give_some_memory_back */

int
main (int __attr_unused___ argc,
      char __attr_unused___ **argv)
{
  uint8_t test_native_heap[test_heap_size];

  mem_heap_init (test_native_heap, sizeof (test_native_heap));

  srand ((unsigned int) time (NULL));
  int k = rand ();
  printf ("seed=%d\n", k);
  srand ((unsigned int) k);

  mem_register_a_try_give_memory_back_callback (test_heap_give_some_memory_back);

  mem_heap_print (true, false, true);

  for (uint32_t i = 0; i < test_iters; i++)
  {
    for (uint32_t j = 0; j < test_sub_iters; j++)
    {
      size_t size = (size_t) rand () % test_threshold_block_size;
      ptrs[j] = (uint8_t*) mem_heap_alloc_block (size,
                                                 (rand () % 2) ?
                                                 MEM_HEAP_ALLOC_LONG_TERM : MEM_HEAP_ALLOC_SHORT_TERM);
      sizes[j] = size;

      JERRY_ASSERT (size == 0 || ptrs[j] != NULL);
      memset (ptrs[j], 0, sizes[j]);

      JERRY_ASSERT (ptrs[j] == NULL
                    || mem_heap_get_block_start (ptrs[j] + (size_t) rand () % sizes [j]) == ptrs[j]);
    }

    // mem_heap_print (true);

    for (uint32_t j = 0; j < test_sub_iters; j++)
    {
      if (ptrs[j] != NULL)
      {
        for (size_t k = 0; k < sizes[j]; k++)
        {
          JERRY_ASSERT(ptrs[j][k] == 0);
        }

        JERRY_ASSERT (sizes [j] == 0
                      || mem_heap_get_block_start (ptrs[j] + (size_t) rand () % sizes [j]) == ptrs[j]);

        mem_heap_free_block (ptrs[j]);

        ptrs[j] = NULL;
      }
    }
  }

  mem_heap_print (true, false, true);

  return 0;
} /* main */
<|endoftext|>