<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 "test/core/util/test_config.h"

#include <thread>

#include "test/core/util/port.h"
#include "test/cpp/util/echo.grpc.pb.h"
#include "src/core/support/env.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/server_credentials.h>
#include <grpc++/status.h>
#include <gtest/gtest.h>
#include <grpc/grpc.h>
#include <grpc/support/sync.h>

using grpc::cpp::test::util::EchoRequest;
using grpc::cpp::test::util::EchoResponse;

namespace grpc {
namespace testing {

class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
 public:
  explicit TestServiceImpl(gpr_event* ev) : ev_(ev) {}

  Status Echo(ServerContext* context, const EchoRequest* request,
              EchoResponse* response) GRPC_OVERRIDE {
    gpr_event_set(ev_, (void*)1);
    while (!context->IsCancelled()) {
    }
    return Status::OK;
  }

 private:
  gpr_event* ev_;
};

class ShutdownTest : public ::testing::Test {
 public:
  ShutdownTest() : shutdown_(false), service_(&ev_) { gpr_event_init(&ev_); }

  void SetUp() GRPC_OVERRIDE {
    port_ = grpc_pick_unused_port_or_die();
    server_ = SetUpServer(port_);
  }

  std::unique_ptr<Server> SetUpServer(const int port) {
    grpc::string server_address = "localhost:" + to_string(port);

    ServerBuilder builder;
    builder.AddListeningPort(server_address, InsecureServerCredentials());
    builder.RegisterService(&service_);
    std::unique_ptr<Server> server = builder.BuildAndStart();
    return server;
  }

  void TearDown() GRPC_OVERRIDE { GPR_ASSERT(shutdown_); }

  void ResetStub() {
    string target = "dns:localhost:" + to_string(port_);
    channel_ = CreateChannel(target, InsecureCredentials(), ChannelArguments());
    stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel_));
  }

  string to_string(const int number) {
    std::stringstream strs;
    strs << number;
    return strs.str();
  }

  void SendRequest() {
    EchoRequest request;
    EchoResponse response;
    request.set_message("Hello");
    ClientContext context;
    GPR_ASSERT(!shutdown_);
    Status s = stub_->Echo(&context, request, &response);
    GPR_ASSERT(shutdown_);
  }

 protected:
  std::shared_ptr<ChannelInterface> channel_;
  std::unique_ptr<grpc::cpp::test::util::TestService::Stub> stub_;
  std::unique_ptr<Server> server_;
  bool shutdown_;
  int port_;
  gpr_event ev_;
  TestServiceImpl service_;
};

// Tests zookeeper state change between two RPCs
// TODO(ctiller): leaked objects in this test
TEST_F(ShutdownTest, ShutdownTest) {
  ResetStub();

  // send the request in a background thread
  std::thread thr(std::bind(&ShutdownTest::SendRequest, this));

  // wait for the server to get the event
  gpr_event_wait(&ev_, gpr_inf_future(GPR_CLOCK_MONOTONIC));

  shutdown_ = true;

  // shutdown should trigger cancellation causing everything to shutdown
  auto deadline =
      std::chrono::system_clock::now() + std::chrono::microseconds(100);
  server_->Shutdown(deadline);
  EXPECT_GE(std::chrono::system_clock::now(), deadline);

  thr.join();
}

}  // namespace testing
}  // namespace grpc

int main(int argc, char** argv) {
  grpc_test_init(argc, argv);
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>fix shutdown_test<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 "test/core/util/test_config.h"

#include <thread>

#include "test/core/util/port.h"
#include "test/cpp/util/echo.grpc.pb.h"
#include "src/core/support/env.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/channel.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/server_credentials.h>
#include <grpc++/status.h>
#include <gtest/gtest.h>
#include <grpc/grpc.h>
#include <grpc/support/sync.h>

using grpc::cpp::test::util::EchoRequest;
using grpc::cpp::test::util::EchoResponse;

namespace grpc {
namespace testing {

class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
 public:
  explicit TestServiceImpl(gpr_event* ev) : ev_(ev) {}

  Status Echo(ServerContext* context, const EchoRequest* request,
              EchoResponse* response) GRPC_OVERRIDE {
    gpr_event_set(ev_, (void*)1);
    while (!context->IsCancelled()) {
    }
    return Status::OK;
  }

 private:
  gpr_event* ev_;
};

class ShutdownTest : public ::testing::Test {
 public:
  ShutdownTest() : shutdown_(false), service_(&ev_) { gpr_event_init(&ev_); }

  void SetUp() GRPC_OVERRIDE {
    port_ = grpc_pick_unused_port_or_die();
    server_ = SetUpServer(port_);
  }

  std::unique_ptr<Server> SetUpServer(const int port) {
    grpc::string server_address = "localhost:" + to_string(port);

    ServerBuilder builder;
    builder.AddListeningPort(server_address, InsecureServerCredentials());
    builder.RegisterService(&service_);
    std::unique_ptr<Server> server = builder.BuildAndStart();
    return server;
  }

  void TearDown() GRPC_OVERRIDE { GPR_ASSERT(shutdown_); }

  void ResetStub() {
    string target = "dns:localhost:" + to_string(port_);
    channel_ = CreateChannel(target, InsecureCredentials(), ChannelArguments());
    stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel_));
  }

  string to_string(const int number) {
    std::stringstream strs;
    strs << number;
    return strs.str();
  }

  void SendRequest() {
    EchoRequest request;
    EchoResponse response;
    request.set_message("Hello");
    ClientContext context;
    GPR_ASSERT(!shutdown_);
    Status s = stub_->Echo(&context, request, &response);
    GPR_ASSERT(shutdown_);
  }

 protected:
  std::shared_ptr<Channel> channel_;
  std::unique_ptr<grpc::cpp::test::util::TestService::Stub> stub_;
  std::unique_ptr<Server> server_;
  bool shutdown_;
  int port_;
  gpr_event ev_;
  TestServiceImpl service_;
};

// Tests zookeeper state change between two RPCs
// TODO(ctiller): leaked objects in this test
TEST_F(ShutdownTest, ShutdownTest) {
  ResetStub();

  // send the request in a background thread
  std::thread thr(std::bind(&ShutdownTest::SendRequest, this));

  // wait for the server to get the event
  gpr_event_wait(&ev_, gpr_inf_future(GPR_CLOCK_MONOTONIC));

  shutdown_ = true;

  // shutdown should trigger cancellation causing everything to shutdown
  auto deadline =
      std::chrono::system_clock::now() + std::chrono::microseconds(100);
  server_->Shutdown(deadline);
  EXPECT_GE(std::chrono::system_clock::now(), deadline);

  thr.join();
}

}  // namespace testing
}  // namespace grpc

int main(int argc, char** argv) {
  grpc_test_init(argc, argv);
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#include <cstring>
#include <string>
#include <turbo/ipc/posix/pipe.hpp>
#include <turbo/filesystem/path.hpp>
#include <turbo/process/status.hpp>
#include <turbo/process/posix/spawn.hpp>
#include <gtest/gtest.h>

namespace tf = turbo::filesystem;
namespace tip = turbo::ipc::posix;
namespace tpp = turbo::process::posix;
namespace tps = turbo::process::status;

tpp::child spawn_child(const char* exe, char* const args[], char* const env[])
{
    tpp::child&& child = tpp::spawn(exe, args, env, 2 << 16);
    const char* expected = "READY\n";
    char signal[256];
    child.err.read_all(signal, strlen(expected));
    if (strncmp(expected, signal, sizeof(signal)) != 0)
    {
	std::cerr << "ERROR: ready signal not received; instead received: " << signal << std::endl;
    }
    return std::move(child);
}

TEST(spawn_test, stdstream_check)
{
    tf::path exe = tps::current_exe_path().parent_path() /= "spawn_child";
    tpp::child&& child = spawn_child(exe.c_str(), {}, {});

    char input[] = "FOO\n";
    child.in.write_all(input, strlen(input));

    const char* expected = "FOOBAR\n";
    char output[256];
    child.out.read_all(output, strlen(expected));
    EXPECT_EQ(strncmp(expected, output, sizeof(output)), 0) << "Unexpected message from stdout: " << output;
}
<commit_msg>restrict buffer sizes to the exact expected message size<commit_after>#include <cstring>
#include <string>
#include <turbo/ipc/posix/pipe.hpp>
#include <turbo/filesystem/path.hpp>
#include <turbo/process/status.hpp>
#include <turbo/process/posix/spawn.hpp>
#include <gtest/gtest.h>

namespace tf = turbo::filesystem;
namespace tip = turbo::ipc::posix;
namespace tpp = turbo::process::posix;
namespace tps = turbo::process::status;

tpp::child spawn_child(const char* exe, char* const args[], char* const env[])
{
    tpp::child&& child = tpp::spawn(exe, args, env, 2 << 16);
    const char* expected = "READY\n";
    char signal[7];
    child.err.read_all(signal, strlen(expected));
    if (strncmp(expected, signal, sizeof(signal)) != 0)
    {
	std::cerr << "ERROR: ready signal not received; instead received: " << signal << std::endl;
    }
    return std::move(child);
}

TEST(spawn_test, stdstream_check)
{
    tf::path exe = tps::current_exe_path().parent_path() /= "spawn_child";
    tpp::child&& child = spawn_child(exe.c_str(), {}, {});

    char input[] = "FOO\n";
    child.in.write_all(input, strlen(input));

    const char* expected = "FOOBAR\n";
    char output[8];
    child.out.read_all(output, strlen(expected));
    EXPECT_EQ(strncmp(expected, output, sizeof(output)), 0) << "Unexpected message from stdout: " << output;
}
<|endoftext|>


<commit_before>//===-- MachineLICM.cpp - Machine Loop Invariant Code Motion Pass ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass performs loop invariant code motion on machine instructions. We
// attempt to remove as much code from the body of a loop as possible.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "machine-licm"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"

using namespace llvm;

namespace {
  // Hidden options to help debugging
  cl::opt<bool>
  PerformLICM("machine-licm",
              cl::init(false), cl::Hidden,
              cl::desc("Perform loop-invariant code motion on machine code"));
}

STATISTIC(NumHoisted, "Number of machine instructions hoisted out of loops");

namespace {
  class VISIBILITY_HIDDEN MachineLICM : public MachineFunctionPass {
    const TargetInstrInfo *TII;
    MachineFunction       *CurMF; // Current MachineFunction

    // Various analyses that we use...
    MachineLoopInfo      *LI;   // Current MachineLoopInfo
    MachineDominatorTree *DT;   // Machine dominator tree for the current Loop

    // State that is updated as we process loops
    bool         Changed;       // True if a loop is changed.
    MachineLoop *CurLoop;       // The current loop we are working on.

    // Map the def of a virtual register to the machine instruction.
    IndexedMap<const MachineInstr*, VirtReg2IndexFunctor> VRegDefs;
  public:
    static char ID; // Pass identification, replacement for typeid
    MachineLICM() : MachineFunctionPass((intptr_t)&ID) {}

    virtual bool runOnMachineFunction(MachineFunction &MF);

    /// FIXME: Loop preheaders?
    ///
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
      AU.addRequired<MachineLoopInfo>();
      AU.addRequired<MachineDominatorTree>();
    }
  private:
    /// VisitAllLoops - Visit all of the loops in depth first order and try to
    /// hoist invariant instructions from them.
    ///
    void VisitAllLoops(MachineLoop *L) {
      const std::vector<MachineLoop*> &SubLoops = L->getSubLoops();

      for (MachineLoop::iterator
             I = SubLoops.begin(), E = SubLoops.end(); I != E; ++I) {
        MachineLoop *ML = *I;

        // Traverse the body of the loop in depth first order on the dominator
        // tree so that we are guaranteed to see definitions before we see uses.
        VisitAllLoops(ML);
        HoistRegion(DT->getNode(ML->getHeader()));
      }

      HoistRegion(DT->getNode(L->getHeader()));
    }

    /// MapVirtualRegisterDefs - Create a map of which machine instruction
    /// defines a virtual register.
    ///
    void MapVirtualRegisterDefs();

    /// IsInSubLoop - A little predicate that returns true if the specified
    /// basic block is in a subloop of the current one, not the current one
    /// itself.
    ///
    bool IsInSubLoop(MachineBasicBlock *BB) {
      assert(CurLoop->contains(BB) && "Only valid if BB is IN the loop");
      return LI->getLoopFor(BB) != CurLoop;
    }

    /// IsLoopInvariantInst - Returns true if the instruction is loop
    /// invariant. I.e., all virtual register operands are defined outside of
    /// the loop, physical registers aren't accessed (explicitly or implicitly),
    /// and the instruction is hoistable.
    ///
    bool IsLoopInvariantInst(MachineInstr &I);

    /// FindPredecessors - Get all of the predecessors of the loop that are not
    /// back-edges.
    ///
    void FindPredecessors(std::vector<MachineBasicBlock*> &Preds) {
      const MachineBasicBlock *Header = CurLoop->getHeader();

      for (MachineBasicBlock::const_pred_iterator
             I = Header->pred_begin(), E = Header->pred_end(); I != E; ++I)
        if (!CurLoop->contains(*I))
          Preds.push_back(*I);
    }

    /// MoveInstToEndOfBlock - Moves the machine instruction to the bottom of
    /// the predecessor basic block (but before the terminator instructions).
    ///
    void MoveInstToEndOfBlock(MachineBasicBlock *MBB, MachineInstr *MI) {
      DEBUG({
          DOUT << "Hoisting " << *MI;
          if (MBB->getBasicBlock())
            DOUT << " to MachineBasicBlock "
                 << MBB->getBasicBlock()->getName();
          DOUT << "\n";
        });
      MachineBasicBlock::iterator Iter = MBB->getFirstTerminator();
      MBB->insert(Iter, MI);
      ++NumHoisted;
    }

    /// HoistRegion - Walk the specified region of the CFG (defined by all
    /// blocks dominated by the specified block, and that are in the current
    /// loop) in depth first order w.r.t the DominatorTree. This allows us to
    /// visit definitions before uses, allowing us to hoist a loop body in one
    /// pass without iteration.
    ///
    void HoistRegion(MachineDomTreeNode *N);

    /// Hoist - When an instruction is found to only use loop invariant operands
    /// that is safe to hoist, this instruction is called to do the dirty work.
    ///
    void Hoist(MachineInstr &MI);
  };

  char MachineLICM::ID = 0;
  RegisterPass<MachineLICM> X("machine-licm",
                              "Machine Loop Invariant Code Motion");
} // end anonymous namespace

FunctionPass *llvm::createMachineLICMPass() { return new MachineLICM(); }

/// Hoist expressions out of the specified loop. Note, alias info for inner loop
/// is not preserved so it is not a good idea to run LICM multiple times on one
/// loop.
///
bool MachineLICM::runOnMachineFunction(MachineFunction &MF) {
  if (!PerformLICM) return false; // For debugging.

  DOUT << "******** Machine LICM ********\n";

  Changed = false;
  CurMF = &MF;
  TII = CurMF->getTarget().getInstrInfo();

  // Get our Loop information...
  LI = &getAnalysis<MachineLoopInfo>();
  DT = &getAnalysis<MachineDominatorTree>();

  MapVirtualRegisterDefs();

  for (MachineLoopInfo::iterator
         I = LI->begin(), E = LI->end(); I != E; ++I) {
    CurLoop = *I;

    // Visit all of the instructions of the loop. We want to visit the subloops
    // first, though, so that we can hoist their invariants first into their
    // containing loop before we process that loop.
    VisitAllLoops(CurLoop);
  }

  return Changed;
}

/// MapVirtualRegisterDefs - Create a map of which machine instruction defines a
/// virtual register.
///
void MachineLICM::MapVirtualRegisterDefs() {
  for (MachineFunction::const_iterator
         I = CurMF->begin(), E = CurMF->end(); I != E; ++I) {
    const MachineBasicBlock &MBB = *I;

    for (MachineBasicBlock::const_iterator
           II = MBB.begin(), IE = MBB.end(); II != IE; ++II) {
      const MachineInstr &MI = *II;

      for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
        const MachineOperand &MO = MI.getOperand(i);

        if (MO.isRegister() && MO.isDef() &&
            MRegisterInfo::isVirtualRegister(MO.getReg())) {
          VRegDefs.grow(MO.getReg());
          VRegDefs[MO.getReg()] = &MI;
        }
      }
    }
  }
}

/// HoistRegion - Walk the specified region of the CFG (defined by all blocks
/// dominated by the specified block, and that are in the current loop) in depth
/// first order w.r.t the DominatorTree. This allows us to visit definitions
/// before uses, allowing us to hoist a loop body in one pass without iteration.
///
void MachineLICM::HoistRegion(MachineDomTreeNode *N) {
  assert(N != 0 && "Null dominator tree node?");
  MachineBasicBlock *BB = N->getBlock();

  // If this subregion is not in the top level loop at all, exit.
  if (!CurLoop->contains(BB)) return;

  // Only need to process the contents of this block if it is not part of a
  // subloop (which would already have been processed).
  if (!IsInSubLoop(BB))
    for (MachineBasicBlock::iterator
           I = BB->begin(), E = BB->end(); I != E; ) {
      MachineInstr &MI = *I++;

      // Try hoisting the instruction out of the loop. We can only do this if
      // all of the operands of the instruction are loop invariant and if it is
      // safe to hoist the instruction.
      Hoist(MI);
    }

  const std::vector<MachineDomTreeNode*> &Children = N->getChildren();

  for (unsigned I = 0, E = Children.size(); I != E; ++I)
    HoistRegion(Children[I]);
}

/// IsLoopInvariantInst - Returns true if the instruction is loop
/// invariant. I.e., all virtual register operands are defined outside of the
/// loop, physical registers aren't accessed explicitly, and there are no side
/// effects that aren't captured by the operands or other flags.
///
bool MachineLICM::IsLoopInvariantInst(MachineInstr &I) {
  DEBUG({
      DOUT << "--- Checking if we can hoist " << I;
      if (I.getInstrDescriptor()->ImplicitUses) {
        DOUT << "  * Instruction has implicit uses:\n";

        const TargetMachine &TM = CurMF->getTarget();
        const MRegisterInfo *MRI = TM.getRegisterInfo();
        const unsigned *ImpUses = I.getInstrDescriptor()->ImplicitUses;

        for (; *ImpUses; ++ImpUses)
          DOUT << "      -> " << MRI->getName(*ImpUses) << "\n";
      }

      if (I.getInstrDescriptor()->ImplicitDefs) {
        DOUT << "  * Instruction has implicit defines:\n";

        const TargetMachine &TM = CurMF->getTarget();
        const MRegisterInfo *MRI = TM.getRegisterInfo();
        const unsigned *ImpDefs = I.getInstrDescriptor()->ImplicitDefs;

        for (; *ImpDefs; ++ImpDefs)
          DOUT << "      -> " << MRI->getName(*ImpDefs) << "\n";
      }

      if (TII->hasUnmodelledSideEffects(&I))
        DOUT << "  * Instruction has side effects.\n";
    });

  // The instruction is loop invariant if all of its operands are loop-invariant
  for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = I.getOperand(i);

    if (!(MO.isRegister() && MO.getReg() && MO.isUse()))
      continue;

    unsigned Reg = MO.getReg();

    // Don't hoist instructions that access physical registers.
    if (!MRegisterInfo::isVirtualRegister(Reg))
      return false;

    assert(VRegDefs[Reg] && "Machine instr not mapped for this vreg?");

    // If the loop contains the definition of an operand, then the instruction
    // isn't loop invariant.
    if (CurLoop->contains(VRegDefs[Reg]->getParent()))
      return false;
  }

  // Don't hoist something that has unmodelled side effects.
  if (TII->hasUnmodelledSideEffects(&I)) return false;

  // If we got this far, the instruction is loop invariant!
  return true;
}

/// Hoist - When an instruction is found to only use loop invariant operands
/// that is safe to hoist, this instruction is called to do the dirty work.
///
void MachineLICM::Hoist(MachineInstr &MI) {
  if (!IsLoopInvariantInst(MI)) return;

  std::vector<MachineBasicBlock*> Preds;

  // Non-back-edge predecessors.
  FindPredecessors(Preds);

  // Either we don't have any predecessors(?!) or we have more than one, which
  // is forbidden.
  if (Preds.empty() || Preds.size() != 1) return;

  // Check that the predecessor is qualified to take the hoisted
  // instruction. I.e., there is only one edge from the predecessor, and it's to
  // the loop header.
  MachineBasicBlock *MBB = Preds.front();

  // FIXME: We are assuming at first that the basic block coming into this loop
  // has only one successor. This isn't the case in general because we haven't
  // broken critical edges or added preheaders.
  if (MBB->succ_size() != 1) return;
  assert(*MBB->succ_begin() == CurLoop->getHeader() &&
         "The predecessor doesn't feed directly into the loop header!");

  // Now move the instructions to the predecessor.
  MachineInstr *NewMI = MI.clone();
  MoveInstToEndOfBlock(MBB, NewMI);

  // Update VRegDefs.
  for (unsigned i = 0, e = NewMI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = NewMI->getOperand(i);

    if (MO.isRegister() && MO.isDef() &&
        MRegisterInfo::isVirtualRegister(MO.getReg())) {
      VRegDefs.grow(MO.getReg());
      VRegDefs[MO.getReg()] = NewMI;
    }
  }

  // Hoisting was successful! Remove bothersome instruction now.
  MI.getParent()->remove(&MI);
  Changed = true;
}
<commit_msg>Use the new architecture to get the containing machine basic block for a machine instruction. Also, use "splice" to move the new instruction instead of remove/insert (where it was leaking memory anyway).<commit_after>//===-- MachineLICM.cpp - Machine Loop Invariant Code Motion Pass ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass performs loop invariant code motion on machine instructions. We
// attempt to remove as much code from the body of a loop as possible.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "machine-licm"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"

using namespace llvm;

namespace {
  // Hidden options to help debugging
  cl::opt<bool>
  PerformLICM("machine-licm",
              cl::init(false), cl::Hidden,
              cl::desc("Perform loop-invariant code motion on machine code"));
}

STATISTIC(NumHoisted, "Number of machine instructions hoisted out of loops");

namespace {
  class VISIBILITY_HIDDEN MachineLICM : public MachineFunctionPass {
    const TargetMachine   *TM;
    const TargetInstrInfo *TII;
    MachineFunction       *CurMF; // Current MachineFunction

    // Various analyses that we use...
    MachineLoopInfo      *LI;   // Current MachineLoopInfo
    MachineDominatorTree *DT;   // Machine dominator tree for the current Loop
    MachineRegisterInfo  *RegInfo; // Machine register information

    // State that is updated as we process loops
    bool         Changed;       // True if a loop is changed.
    MachineLoop *CurLoop;       // The current loop we are working on.

    // Map the def of a virtual register to the machine instruction.
    IndexedMap<const MachineInstr*, VirtReg2IndexFunctor> VRegDefs;
  public:
    static char ID; // Pass identification, replacement for typeid
    MachineLICM() : MachineFunctionPass((intptr_t)&ID) {}

    virtual bool runOnMachineFunction(MachineFunction &MF);

    /// FIXME: Loop preheaders?
    ///
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
      AU.addRequired<MachineLoopInfo>();
      AU.addRequired<MachineDominatorTree>();
    }
  private:
    /// VisitAllLoops - Visit all of the loops in depth first order and try to
    /// hoist invariant instructions from them.
    ///
    void VisitAllLoops(MachineLoop *L) {
      const std::vector<MachineLoop*> &SubLoops = L->getSubLoops();

      for (MachineLoop::iterator
             I = SubLoops.begin(), E = SubLoops.end(); I != E; ++I) {
        MachineLoop *ML = *I;

        // Traverse the body of the loop in depth first order on the dominator
        // tree so that we are guaranteed to see definitions before we see uses.
        VisitAllLoops(ML);
        HoistRegion(DT->getNode(ML->getHeader()));
      }

      HoistRegion(DT->getNode(L->getHeader()));
    }

    /// MapVirtualRegisterDefs - Create a map of which machine instruction
    /// defines a virtual register.
    ///
    void MapVirtualRegisterDefs();

    /// IsInSubLoop - A little predicate that returns true if the specified
    /// basic block is in a subloop of the current one, not the current one
    /// itself.
    ///
    bool IsInSubLoop(MachineBasicBlock *BB) {
      assert(CurLoop->contains(BB) && "Only valid if BB is IN the loop");
      return LI->getLoopFor(BB) != CurLoop;
    }

    /// IsLoopInvariantInst - Returns true if the instruction is loop
    /// invariant. I.e., all virtual register operands are defined outside of
    /// the loop, physical registers aren't accessed (explicitly or implicitly),
    /// and the instruction is hoistable.
    ///
    bool IsLoopInvariantInst(MachineInstr &I);

    /// FindPredecessors - Get all of the predecessors of the loop that are not
    /// back-edges.
    ///
    void FindPredecessors(std::vector<MachineBasicBlock*> &Preds) {
      const MachineBasicBlock *Header = CurLoop->getHeader();

      for (MachineBasicBlock::const_pred_iterator
             I = Header->pred_begin(), E = Header->pred_end(); I != E; ++I)
        if (!CurLoop->contains(*I))
          Preds.push_back(*I);
    }

    /// MoveInstToEndOfBlock - Moves the machine instruction to the bottom of
    /// the predecessor basic block (but before the terminator instructions).
    ///
    void MoveInstToEndOfBlock(MachineBasicBlock *ToMBB,
                              MachineBasicBlock *FromMBB,
                              MachineInstr *MI) {
      DEBUG({
          DOUT << "Hoisting " << *MI;
          if (ToMBB->getBasicBlock())
            DOUT << " to MachineBasicBlock "
                 << ToMBB->getBasicBlock()->getName();
          DOUT << "\n";
        });

      MachineBasicBlock::iterator WhereIter = ToMBB->getFirstTerminator();
      MachineBasicBlock::iterator To, From = FromMBB->begin();

      while (&*From != MI)
        ++From;

      assert(From != FromMBB->end() && "Didn't find instr in BB!");

      To = From;
      ToMBB->splice(WhereIter, FromMBB, From, ++To);
      ++NumHoisted;
    }

    /// HoistRegion - Walk the specified region of the CFG (defined by all
    /// blocks dominated by the specified block, and that are in the current
    /// loop) in depth first order w.r.t the DominatorTree. This allows us to
    /// visit definitions before uses, allowing us to hoist a loop body in one
    /// pass without iteration.
    ///
    void HoistRegion(MachineDomTreeNode *N);

    /// Hoist - When an instruction is found to only use loop invariant operands
    /// that is safe to hoist, this instruction is called to do the dirty work.
    ///
    void Hoist(MachineInstr &MI);
  };

  char MachineLICM::ID = 0;
  RegisterPass<MachineLICM> X("machine-licm",
                              "Machine Loop Invariant Code Motion");
} // end anonymous namespace

FunctionPass *llvm::createMachineLICMPass() { return new MachineLICM(); }

/// Hoist expressions out of the specified loop. Note, alias info for inner loop
/// is not preserved so it is not a good idea to run LICM multiple times on one
/// loop.
///
bool MachineLICM::runOnMachineFunction(MachineFunction &MF) {
  if (!PerformLICM) return false; // For debugging.

  DOUT << "******** Machine LICM ********\n";

  Changed = false;
  CurMF = &MF;
  TM = &CurMF->getTarget();
  TII = TM->getInstrInfo();
  RegInfo = new MachineRegisterInfo(*TM->getRegisterInfo());

  // Get our Loop information...
  LI = &getAnalysis<MachineLoopInfo>();
  DT = &getAnalysis<MachineDominatorTree>();

  MapVirtualRegisterDefs();

  for (MachineLoopInfo::iterator
         I = LI->begin(), E = LI->end(); I != E; ++I) {
    CurLoop = *I;

    // Visit all of the instructions of the loop. We want to visit the subloops
    // first, though, so that we can hoist their invariants first into their
    // containing loop before we process that loop.
    VisitAllLoops(CurLoop);
  }

  delete RegInfo;
  return Changed;
}

/// MapVirtualRegisterDefs - Create a map of which machine instruction defines a
/// virtual register.
///
void MachineLICM::MapVirtualRegisterDefs() {
  for (MachineFunction::const_iterator
         I = CurMF->begin(), E = CurMF->end(); I != E; ++I) {
    const MachineBasicBlock &MBB = *I;

    for (MachineBasicBlock::const_iterator
           II = MBB.begin(), IE = MBB.end(); II != IE; ++II) {
      const MachineInstr &MI = *II;

      for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
        const MachineOperand &MO = MI.getOperand(i);

        if (MO.isRegister() && MO.isDef() &&
            MRegisterInfo::isVirtualRegister(MO.getReg())) {
          VRegDefs.grow(MO.getReg());
          VRegDefs[MO.getReg()] = &MI;
        }
      }
    }
  }
}

/// HoistRegion - Walk the specified region of the CFG (defined by all blocks
/// dominated by the specified block, and that are in the current loop) in depth
/// first order w.r.t the DominatorTree. This allows us to visit definitions
/// before uses, allowing us to hoist a loop body in one pass without iteration.
///
void MachineLICM::HoistRegion(MachineDomTreeNode *N) {
  assert(N != 0 && "Null dominator tree node?");
  MachineBasicBlock *BB = N->getBlock();

  // If this subregion is not in the top level loop at all, exit.
  if (!CurLoop->contains(BB)) return;

  // Only need to process the contents of this block if it is not part of a
  // subloop (which would already have been processed).
  if (!IsInSubLoop(BB))
    for (MachineBasicBlock::iterator
           I = BB->begin(), E = BB->end(); I != E; ) {
      MachineInstr &MI = *I++;

      // Try hoisting the instruction out of the loop. We can only do this if
      // all of the operands of the instruction are loop invariant and if it is
      // safe to hoist the instruction.
      Hoist(MI);
    }

  const std::vector<MachineDomTreeNode*> &Children = N->getChildren();

  for (unsigned I = 0, E = Children.size(); I != E; ++I)
    HoistRegion(Children[I]);
}

/// IsLoopInvariantInst - Returns true if the instruction is loop
/// invariant. I.e., all virtual register operands are defined outside of the
/// loop, physical registers aren't accessed explicitly, and there are no side
/// effects that aren't captured by the operands or other flags.
///
bool MachineLICM::IsLoopInvariantInst(MachineInstr &I) {
  DEBUG({
      DOUT << "--- Checking if we can hoist " << I;
      if (I.getInstrDescriptor()->ImplicitUses) {
        DOUT << "  * Instruction has implicit uses:\n";

        const MRegisterInfo *MRI = TM->getRegisterInfo();
        const unsigned *ImpUses = I.getInstrDescriptor()->ImplicitUses;

        for (; *ImpUses; ++ImpUses)
          DOUT << "      -> " << MRI->getName(*ImpUses) << "\n";
      }

      if (I.getInstrDescriptor()->ImplicitDefs) {
        DOUT << "  * Instruction has implicit defines:\n";

        const MRegisterInfo *MRI = TM->getRegisterInfo();
        const unsigned *ImpDefs = I.getInstrDescriptor()->ImplicitDefs;

        for (; *ImpDefs; ++ImpDefs)
          DOUT << "      -> " << MRI->getName(*ImpDefs) << "\n";
      }

      if (TII->hasUnmodelledSideEffects(&I))
        DOUT << "  * Instruction has side effects.\n";
    });

  // The instruction is loop invariant if all of its operands are loop-invariant
  for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = I.getOperand(i);

    if (!(MO.isRegister() && MO.getReg() && MO.isUse()))
      continue;

    unsigned Reg = MO.getReg();

    // Don't hoist instructions that access physical registers.
    if (!MRegisterInfo::isVirtualRegister(Reg))
      return false;

    assert(RegInfo->getVRegDef(Reg)&&"Machine instr not mapped for this vreg?");

    // If the loop contains the definition of an operand, then the instruction
    // isn't loop invariant.
    if (CurLoop->contains(RegInfo->getVRegDef(Reg)->getParent()))
      return false;
  }

  // Don't hoist something that has unmodelled side effects.
  if (TII->hasUnmodelledSideEffects(&I)) return false;

  // If we got this far, the instruction is loop invariant!
  return true;
}

/// Hoist - When an instruction is found to only use loop invariant operands
/// that is safe to hoist, this instruction is called to do the dirty work.
///
void MachineLICM::Hoist(MachineInstr &MI) {
  if (!IsLoopInvariantInst(MI)) return;

  std::vector<MachineBasicBlock*> Preds;

  // Non-back-edge predecessors.
  FindPredecessors(Preds);

  // Either we don't have any predecessors(?!) or we have more than one, which
  // is forbidden.
  if (Preds.empty() || Preds.size() != 1) return;

  // Check that the predecessor is qualified to take the hoisted
  // instruction. I.e., there is only one edge from the predecessor, and it's to
  // the loop header.
  MachineBasicBlock *MBB = Preds.front();

  // FIXME: We are assuming at first that the basic block coming into this loop
  // has only one successor. This isn't the case in general because we haven't
  // broken critical edges or added preheaders.
  if (MBB->succ_size() != 1) return;
  assert(*MBB->succ_begin() == CurLoop->getHeader() &&
         "The predecessor doesn't feed directly into the loop header!");

  // Now move the instructions to the predecessor.
  MoveInstToEndOfBlock(MBB, MI.getParent(), &MI);
  Changed = true;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 OpenALPR Technology, Inc.
 * Open source Automated License Plate Recognition [http://www.openalpr.com]
 *
 * This file is part of OpenALPR.
 *
 * OpenALPR is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License
 * version 3 as published by the Free Software Foundation
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <iostream>
#include <stdio.h>
#include <sys/stat.h>

#include "postprocess/regexrule.h"
#include "licenseplatecandidate.h"
#include "utility.h"
#include "support/filesystem.h"
#include "ocr.h"

using namespace std;
using namespace cv;
using namespace alpr;

// Given a directory full of lp images (named [statecode]#.png) crop out the alphanumeric characters.
// These will be used to train the OCR

#ifdef __APPLE__
const int LEFT_ARROW_KEY = 2;
const int RIGHT_ARROW_KEY = 3;

const int DOWN_ARROW_KEY = 1;
const int UP_ARROW_KEY= 0;

#elif WIN32
const int LEFT_ARROW_KEY = 2424832;
const int RIGHT_ARROW_KEY = 2555904;

const int DOWN_ARROW_KEY = 2621440;
const int UP_ARROW_KEY = 2490368;

const int ENTER_KEY_ONE = 13;
const int ENTER_KEY_TWO = 10;
#else
const int LEFT_ARROW_KEY = 1113937;
const int RIGHT_ARROW_KEY = 1113939;

const int DOWN_ARROW_KEY = 1113940;
const int UP_ARROW_KEY= 1113938;

const int ENTER_KEY_ONE = 1048586;
const int ENTER_KEY_TWO = 1048586;
#endif

const string SPACE = " ";
const int SPACE_KEY = 32;
const int ESCAPE_KEY = 27;

const int DASHBOARD_COLUMNS = 3;

void showDashboard(vector<Mat> images, vector<bool> selectedImages, int selectedIndex);
vector<string> showCharSelection(Mat image, vector<Rect> charRegions, string state);

int main( int argc, const char** argv )
{
  string country;
  string inDir;
  string outDir;
  Mat frame;

  //Check if user specify image to process
  if(argc == 4)
  {
    country = argv[1];
    inDir = argv[2];
    outDir = argv[3];
  }
  else
  {
    printf("Use:\n\t%s country indirectory outdirectory\n",argv[0]);
    printf("Ex: \n\t%s eu ./pics/ ./out\n",argv[0]);
    return 0;
  }

  if (DirectoryExists(outDir.c_str()) == false)
  {
    printf("Output dir does not exist\n");
    return 0;
  }

  cout << "Usage: " << endl;
  cout << "\tn		-- Next plate" << endl;
  cout << "\tp		-- Previous plate" << endl;
  cout << "\tW		-- Select image and save characters according to OCR results, then go to next image" << endl;
  cout << "\ts		-- Save characters" << endl;
  cout << "\t<- and ->	-- Cycle between images" << endl;
  cout << "\tEnt/space	-- Select plate" << endl;
  cout << endl;
  cout << "Within a plate" << endl;
  cout << "\t<- and ->		-- Cycle between characters" << endl;
  cout << "\t[0-9A-Z]		-- Identify a character (saves the image)" << endl;
  cout << "\tESC/Ent/Space	-- Back to plate selection" << endl;

  Config config(country);
  config.debugGeneral = false;
  config.debugCharAnalysis = false;
  config.debugCharSegmenter = false;
  OCR ocr(&config);

  if (DirectoryExists(inDir.c_str()))
  {
    vector<string> files = getFilesInDir(inDir.c_str());

    sort( files.begin(), files.end(), stringCompare );

    for (int i = 0; i< files.size(); i++)
    {
      if (hasEnding(files[i], ".png") || hasEnding(files[i], ".jpg"))
      {
        string fullpath = inDir + "/" + files[i];
        cout << fullpath << endl;
        frame = imread( fullpath.c_str() );
        if(frame.data == NULL)
        {
          cout << "Unable to read license plate: " << fullpath << endl;
          continue;
        }
        resize(frame, frame, Size(config.ocrImageWidthPx, config.ocrImageHeightPx));

        imshow ("Original", frame);

	PipelineData pipeline_data(frame, Rect(0, 0, frame.cols, frame.rows), &config);
	cvtColor(frame, frame, CV_BGR2GRAY);
	pipeline_data.crop_gray = Mat(frame, Rect(0, 0, frame.cols, frame.rows));
        char statecode[3];
        statecode[0] = files[i][0];
        statecode[1] = files[i][1];
        statecode[2] = '\0';
        string statecodestr(statecode);

        CharacterAnalysis regionizer(&pipeline_data);

        if (pipeline_data.plate_inverted)
          bitwise_not(pipeline_data.crop_gray, pipeline_data.crop_gray);

        CharacterSegmenter charSegmenter(&pipeline_data);

        //ocr.cleanCharRegions(charSegmenter.thresholds, charSegmenter.characters);

        ocr.performOCR(&pipeline_data);
        ocr.postProcessor.analyze(statecodestr, 25);
        cout << "OCR results: " << ocr.postProcessor.bestChars << endl;

        vector<bool> selectedBoxes(pipeline_data.thresholds.size());
        for (int z = 0; z < pipeline_data.thresholds.size(); z++)
          selectedBoxes[z] = false;

        int curDashboardSelection = 0;

        vector<string> humanInputs(pipeline_data.charRegionsFlat.size());

        for (int z = 0; z < pipeline_data.charRegionsFlat.size(); z++)
          humanInputs[z] = SPACE;

        showDashboard(pipeline_data.thresholds, selectedBoxes, 0);

        int waitkey = waitKey(50);

        while ((char) waitkey != 'n' && (char) waitkey != 'p')	 // Next image
        {
          if (waitkey == LEFT_ARROW_KEY) // left arrow key
          {
            if (curDashboardSelection > 0)
              curDashboardSelection--;
            showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
          }
          else if (waitkey == RIGHT_ARROW_KEY) // right arrow key
          {
            if (curDashboardSelection < pipeline_data.thresholds.size() - 1)
              curDashboardSelection++;
            showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
          }
          else if (waitkey == DOWN_ARROW_KEY)
          {
            if (curDashboardSelection + DASHBOARD_COLUMNS <= pipeline_data.thresholds.size() - 1)
              curDashboardSelection += DASHBOARD_COLUMNS;
            showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
          }
          else if (waitkey == UP_ARROW_KEY)
          {
            if (curDashboardSelection - DASHBOARD_COLUMNS >= 0)
              curDashboardSelection -= DASHBOARD_COLUMNS;
            showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
          }
          else if (waitkey == ENTER_KEY_ONE || waitkey == ENTER_KEY_TWO)
          {
	    if (pipeline_data.charRegionsFlat.size() > 0)
	    {
	      vector<string> tempdata = showCharSelection(pipeline_data.thresholds[curDashboardSelection], pipeline_data.charRegionsFlat, statecodestr);
	      for (int c = 0; c < pipeline_data.charRegionsFlat.size(); c++)
		humanInputs[c] = tempdata[c];
	    }
	    else
	    {
	      cout << "No character regions available in this image" << endl;
	    }
          }
          else if ((char) waitkey == SPACE_KEY)
          {
            selectedBoxes[curDashboardSelection] = !selectedBoxes[curDashboardSelection];
            showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
          }
          else if ((char) waitkey == 's' || (char) waitkey == 'S' )
          {

            bool somethingSelected = false;
            bool chardataTagged = false;
            for (int c = 0; c < pipeline_data.thresholds.size(); c++)
            {
              if (selectedBoxes[c])
              {
                somethingSelected = true;
                break;
              }
            }
            for (int c = 0; c < pipeline_data.charRegionsFlat.size(); c++)
            {
              if (humanInputs[c] != SPACE)
              {
                chardataTagged = true;
                break;
              }
            }
            // Save
            if (somethingSelected && chardataTagged)
            {
              for (int c = 0; c < pipeline_data.charRegionsFlat.size(); c++)
              {
                if (humanInputs[c] == SPACE)
                  continue;

                for (int t = 0; t < pipeline_data.thresholds.size(); t++)
                {
                  if (selectedBoxes[t] == false)
                    continue;

                  stringstream filename;

                  // Ensure that crop rect does not extend beyond extent of image.
                  cv::Rect char_region = expandRect(pipeline_data.charRegionsFlat[c], 0, 0,
                          pipeline_data.thresholds[t].cols,
                          pipeline_data.thresholds[t].rows);

                  Mat cropped = pipeline_data.thresholds[t](char_region);
                  filename << outDir << "/" << humanInputs[c] << "-" << t << "-" << files[i];
                  imwrite(filename.str(), cropped);
                  cout << "Writing char image: " << filename.str() << endl;
                }
              }
            }
            else if (somethingSelected == false)
              cout << "Did not select any boxes" << endl;
            else if (chardataTagged == false)
              cout << "You have not tagged any characters" << endl;

            if ((char) waitkey == 'W')
            {
              waitkey = 'n';
              continue;
            }
          }

          waitkey = waitKey(50);
		  //std::cout << "key: " << (int) waitkey << std::endl;
        }

        if ((char) waitkey == 'p')
          i = i - 2;
        if (i < -1)
          i = -1;
      }
    }
  }
}

void showDashboard(vector<Mat> images, vector<bool> selectedImages, int selectedIndex)
{
  vector<Mat> vecCopy;

  if (selectedIndex < 0)
    selectedIndex = 0;
  if (selectedIndex >= images.size())
    selectedIndex = images.size() -1;

  for (int i = 0; i < images.size(); i++)
  {
    Mat imgCopy(images[i].size(), images[i].type());
    images[i].copyTo(imgCopy);
    cvtColor(imgCopy, imgCopy, CV_GRAY2BGR);
    if (i == selectedIndex)
    {
      rectangle(imgCopy, Point(1,1), Point(imgCopy.size().width - 1, imgCopy.size().height -1), Scalar(0, 255, 0), 1);
    }
    if (selectedImages[i])
    {
      rectangle(imgCopy, Point(2,2), Point(imgCopy.size().width - 2, imgCopy.size().height -2), Scalar(255, 0, 0), 1);
    }

    vecCopy.push_back(imgCopy);
  }

  Mat dashboard = drawImageDashboard(vecCopy, vecCopy[0].type(), DASHBOARD_COLUMNS);

  imshow("Selection dashboard", dashboard);
}

vector<string> showCharSelection(Mat image, vector<Rect> charRegions, string state)
{
  int curCharIdx = 0;

  vector<string> humanInputs(charRegions.size());
  for (int i = 0; i < charRegions.size(); i++)
    humanInputs[i] = SPACE;

  RegexRule regex_rule("", "[\\pL\\pN]", "", "");

  int16_t waitkey = waitKey(50);
  while (waitkey != ENTER_KEY_ONE && waitkey != ENTER_KEY_TWO && waitkey != ESCAPE_KEY)
  {
    Mat imgCopy(image.size(), image.type());
    image.copyTo(imgCopy);
    cvtColor(imgCopy, imgCopy, CV_GRAY2BGR);

    rectangle(imgCopy, charRegions[curCharIdx], Scalar(0, 255, 0), 1);

    imshow("Character selector", imgCopy);

    if ((char) waitkey == LEFT_ARROW_KEY)
      curCharIdx--;
    else if ((char) waitkey == RIGHT_ARROW_KEY)
      curCharIdx++;
    else if (waitkey == SPACE_KEY)
    {
      humanInputs[curCharIdx] = " ";
      curCharIdx++;
    }
    else if (waitkey > 0 && regex_rule.match(utf8chr(waitkey))) // Verify that it's an actual character
    {
      // Save the character to disk
      humanInputs[curCharIdx] = utf8chr(waitkey);
      curCharIdx++;

      if (curCharIdx >= charRegions.size())
      {
        waitkey = (int16_t) ENTER_KEY_ONE;
        break;
      }
    }

    if (curCharIdx < 0)
      curCharIdx = 0;
    if (curCharIdx >= charRegions.size())
      curCharIdx = charRegions.size() -1;

    waitkey = waitKey(50);
  }

  if (waitkey == ENTER_KEY_ONE || waitkey == ENTER_KEY_TWO)
  {
    // Save all the inputs
    for (int i = 0; i < charRegions.size(); i++)
    {
      if (humanInputs[i] != SPACE)
        cout << "Tagged " << state << " char code: '" << humanInputs[i] << "' at char position: " << i << endl;
    }
  }

  destroyWindow("Character selector");

  return humanInputs;
}
<commit_msg>Fixing the build issue in OSX<commit_after>/*
 * Copyright (c) 2015 OpenALPR Technology, Inc.
 * Open source Automated License Plate Recognition [http://www.openalpr.com]
 *
 * This file is part of OpenALPR.
 *
 * OpenALPR is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License
 * version 3 as published by the Free Software Foundation
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <iostream>
#include <stdio.h>
#include <sys/stat.h>

#include "postprocess/regexrule.h"
#include "licenseplatecandidate.h"
#include "utility.h"
#include "support/filesystem.h"
#include "ocr.h"

using namespace std;
using namespace cv;
using namespace alpr;

// Given a directory full of lp images (named [statecode]#.png) crop out the alphanumeric characters.
// These will be used to train the OCR

#ifdef __APPLE__
const int LEFT_ARROW_KEY = 2;
const int RIGHT_ARROW_KEY = 3;

const int DOWN_ARROW_KEY = 1;
const int UP_ARROW_KEY= 0;

const int ENTER_KEY_ONE = 13;
const int ENTER_KEY_TWO = 10;

#elif WIN32
const int LEFT_ARROW_KEY = 2424832;
const int RIGHT_ARROW_KEY = 2555904;

const int DOWN_ARROW_KEY = 2621440;
const int UP_ARROW_KEY = 2490368;

const int ENTER_KEY_ONE = 13;
const int ENTER_KEY_TWO = 10;
#else
const int LEFT_ARROW_KEY = 1113937;
const int RIGHT_ARROW_KEY = 1113939;

const int DOWN_ARROW_KEY = 1113940;
const int UP_ARROW_KEY= 1113938;

const int ENTER_KEY_ONE = 1048586;
const int ENTER_KEY_TWO = 1048586;
#endif

const string SPACE = " ";
const int SPACE_KEY = 32;
const int ESCAPE_KEY = 27;

const int DASHBOARD_COLUMNS = 3;

void showDashboard(vector<Mat> images, vector<bool> selectedImages, int selectedIndex);
vector<string> showCharSelection(Mat image, vector<Rect> charRegions, string state);

int main( int argc, const char** argv )
{
  string country;
  string inDir;
  string outDir;
  Mat frame;

  //Check if user specify image to process
  if(argc == 4)
  {
    country = argv[1];
    inDir = argv[2];
    outDir = argv[3];
  }
  else
  {
    printf("Use:\n\t%s country indirectory outdirectory\n",argv[0]);
    printf("Ex: \n\t%s eu ./pics/ ./out\n",argv[0]);
    return 0;
  }

  if (DirectoryExists(outDir.c_str()) == false)
  {
    printf("Output dir does not exist\n");
    return 0;
  }

  cout << "Usage: " << endl;
  cout << "\tn		-- Next plate" << endl;
  cout << "\tp		-- Previous plate" << endl;
  cout << "\tW		-- Select image and save characters according to OCR results, then go to next image" << endl;
  cout << "\ts		-- Save characters" << endl;
  cout << "\t<- and ->	-- Cycle between images" << endl;
  cout << "\tEnt/space	-- Select plate" << endl;
  cout << endl;
  cout << "Within a plate" << endl;
  cout << "\t<- and ->		-- Cycle between characters" << endl;
  cout << "\t[0-9A-Z]		-- Identify a character (saves the image)" << endl;
  cout << "\tESC/Ent/Space	-- Back to plate selection" << endl;

  Config config(country);
  config.debugGeneral = false;
  config.debugCharAnalysis = false;
  config.debugCharSegmenter = false;
  OCR ocr(&config);

  if (DirectoryExists(inDir.c_str()))
  {
    vector<string> files = getFilesInDir(inDir.c_str());

    sort( files.begin(), files.end(), stringCompare );

    for (int i = 0; i< files.size(); i++)
    {
      if (hasEnding(files[i], ".png") || hasEnding(files[i], ".jpg"))
      {
        string fullpath = inDir + "/" + files[i];
        cout << fullpath << endl;
        frame = imread( fullpath.c_str() );
        if(frame.data == NULL)
        {
          cout << "Unable to read license plate: " << fullpath << endl;
          continue;
        }
        resize(frame, frame, Size(config.ocrImageWidthPx, config.ocrImageHeightPx));

        imshow ("Original", frame);

	PipelineData pipeline_data(frame, Rect(0, 0, frame.cols, frame.rows), &config);
	cvtColor(frame, frame, CV_BGR2GRAY);
	pipeline_data.crop_gray = Mat(frame, Rect(0, 0, frame.cols, frame.rows));
        char statecode[3];
        statecode[0] = files[i][0];
        statecode[1] = files[i][1];
        statecode[2] = '\0';
        string statecodestr(statecode);

        CharacterAnalysis regionizer(&pipeline_data);

        if (pipeline_data.plate_inverted)
          bitwise_not(pipeline_data.crop_gray, pipeline_data.crop_gray);

        CharacterSegmenter charSegmenter(&pipeline_data);

        //ocr.cleanCharRegions(charSegmenter.thresholds, charSegmenter.characters);

        ocr.performOCR(&pipeline_data);
        ocr.postProcessor.analyze(statecodestr, 25);
        cout << "OCR results: " << ocr.postProcessor.bestChars << endl;

        vector<bool> selectedBoxes(pipeline_data.thresholds.size());
        for (int z = 0; z < pipeline_data.thresholds.size(); z++)
          selectedBoxes[z] = false;

        int curDashboardSelection = 0;

        vector<string> humanInputs(pipeline_data.charRegionsFlat.size());

        for (int z = 0; z < pipeline_data.charRegionsFlat.size(); z++)
          humanInputs[z] = SPACE;

        showDashboard(pipeline_data.thresholds, selectedBoxes, 0);

        int waitkey = waitKey(50);

        while ((char) waitkey != 'n' && (char) waitkey != 'p')	 // Next image
        {
          if (waitkey == LEFT_ARROW_KEY) // left arrow key
          {
            if (curDashboardSelection > 0)
              curDashboardSelection--;
            showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
          }
          else if (waitkey == RIGHT_ARROW_KEY) // right arrow key
          {
            if (curDashboardSelection < pipeline_data.thresholds.size() - 1)
              curDashboardSelection++;
            showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
          }
          else if (waitkey == DOWN_ARROW_KEY)
          {
            if (curDashboardSelection + DASHBOARD_COLUMNS <= pipeline_data.thresholds.size() - 1)
              curDashboardSelection += DASHBOARD_COLUMNS;
            showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
          }
          else if (waitkey == UP_ARROW_KEY)
          {
            if (curDashboardSelection - DASHBOARD_COLUMNS >= 0)
              curDashboardSelection -= DASHBOARD_COLUMNS;
            showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
          }
          else if (waitkey == ENTER_KEY_ONE || waitkey == ENTER_KEY_TWO)
          {
	    if (pipeline_data.charRegionsFlat.size() > 0)
	    {
	      vector<string> tempdata = showCharSelection(pipeline_data.thresholds[curDashboardSelection], pipeline_data.charRegionsFlat, statecodestr);
	      for (int c = 0; c < pipeline_data.charRegionsFlat.size(); c++)
		humanInputs[c] = tempdata[c];
	    }
	    else
	    {
	      cout << "No character regions available in this image" << endl;
	    }
          }
          else if ((char) waitkey == SPACE_KEY)
          {
            selectedBoxes[curDashboardSelection] = !selectedBoxes[curDashboardSelection];
            showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
          }
          else if ((char) waitkey == 's' || (char) waitkey == 'S' )
          {

            bool somethingSelected = false;
            bool chardataTagged = false;
            for (int c = 0; c < pipeline_data.thresholds.size(); c++)
            {
              if (selectedBoxes[c])
              {
                somethingSelected = true;
                break;
              }
            }
            for (int c = 0; c < pipeline_data.charRegionsFlat.size(); c++)
            {
              if (humanInputs[c] != SPACE)
              {
                chardataTagged = true;
                break;
              }
            }
            // Save
            if (somethingSelected && chardataTagged)
            {
              for (int c = 0; c < pipeline_data.charRegionsFlat.size(); c++)
              {
                if (humanInputs[c] == SPACE)
                  continue;

                for (int t = 0; t < pipeline_data.thresholds.size(); t++)
                {
                  if (selectedBoxes[t] == false)
                    continue;

                  stringstream filename;

                  // Ensure that crop rect does not extend beyond extent of image.
                  cv::Rect char_region = expandRect(pipeline_data.charRegionsFlat[c], 0, 0,
                          pipeline_data.thresholds[t].cols,
                          pipeline_data.thresholds[t].rows);

                  Mat cropped = pipeline_data.thresholds[t](char_region);
                  filename << outDir << "/" << humanInputs[c] << "-" << t << "-" << files[i];
                  imwrite(filename.str(), cropped);
                  cout << "Writing char image: " << filename.str() << endl;
                }
              }
            }
            else if (somethingSelected == false)
              cout << "Did not select any boxes" << endl;
            else if (chardataTagged == false)
              cout << "You have not tagged any characters" << endl;

            if ((char) waitkey == 'W')
            {
              waitkey = 'n';
              continue;
            }
          }

          waitkey = waitKey(50);
		  //std::cout << "key: " << (int) waitkey << std::endl;
        }

        if ((char) waitkey == 'p')
          i = i - 2;
        if (i < -1)
          i = -1;
      }
    }
  }
}

void showDashboard(vector<Mat> images, vector<bool> selectedImages, int selectedIndex)
{
  vector<Mat> vecCopy;

  if (selectedIndex < 0)
    selectedIndex = 0;
  if (selectedIndex >= images.size())
    selectedIndex = images.size() -1;

  for (int i = 0; i < images.size(); i++)
  {
    Mat imgCopy(images[i].size(), images[i].type());
    images[i].copyTo(imgCopy);
    cvtColor(imgCopy, imgCopy, CV_GRAY2BGR);
    if (i == selectedIndex)
    {
      rectangle(imgCopy, Point(1,1), Point(imgCopy.size().width - 1, imgCopy.size().height -1), Scalar(0, 255, 0), 1);
    }
    if (selectedImages[i])
    {
      rectangle(imgCopy, Point(2,2), Point(imgCopy.size().width - 2, imgCopy.size().height -2), Scalar(255, 0, 0), 1);
    }

    vecCopy.push_back(imgCopy);
  }

  Mat dashboard = drawImageDashboard(vecCopy, vecCopy[0].type(), DASHBOARD_COLUMNS);

  imshow("Selection dashboard", dashboard);
}

vector<string> showCharSelection(Mat image, vector<Rect> charRegions, string state)
{
  int curCharIdx = 0;

  vector<string> humanInputs(charRegions.size());
  for (int i = 0; i < charRegions.size(); i++)
    humanInputs[i] = SPACE;

  RegexRule regex_rule("", "[\\pL\\pN]", "", "");

  int16_t waitkey = waitKey(50);
  while (waitkey != ENTER_KEY_ONE && waitkey != ENTER_KEY_TWO && waitkey != ESCAPE_KEY)
  {
    Mat imgCopy(image.size(), image.type());
    image.copyTo(imgCopy);
    cvtColor(imgCopy, imgCopy, CV_GRAY2BGR);

    rectangle(imgCopy, charRegions[curCharIdx], Scalar(0, 255, 0), 1);

    imshow("Character selector", imgCopy);

    if ((char) waitkey == LEFT_ARROW_KEY)
      curCharIdx--;
    else if ((char) waitkey == RIGHT_ARROW_KEY)
      curCharIdx++;
    else if (waitkey == SPACE_KEY)
    {
      humanInputs[curCharIdx] = " ";
      curCharIdx++;
    }
    else if (waitkey > 0 && regex_rule.match(utf8chr(waitkey))) // Verify that it's an actual character
    {
      // Save the character to disk
      humanInputs[curCharIdx] = utf8chr(waitkey);
      curCharIdx++;

      if (curCharIdx >= charRegions.size())
      {
        waitkey = (int16_t) ENTER_KEY_ONE;
        break;
      }
    }

    if (curCharIdx < 0)
      curCharIdx = 0;
    if (curCharIdx >= charRegions.size())
      curCharIdx = charRegions.size() -1;

    waitkey = waitKey(50);
  }

  if (waitkey == ENTER_KEY_ONE || waitkey == ENTER_KEY_TWO)
  {
    // Save all the inputs
    for (int i = 0; i < charRegions.size(); i++)
    {
      if (humanInputs[i] != SPACE)
        cout << "Tagged " << state << " char code: '" << humanInputs[i] << "' at char position: " << i << endl;
    }
  }

  destroyWindow("Character selector");

  return humanInputs;
}
<|endoftext|>


<commit_before>/*
 -----------------------------------------------------------------------------
 This source file is part of OGRE
 (Object-oriented Graphics Rendering Engine)
 For the latest info, see http://www.ogre3d.org/

 Copyright (c) 2000-2013 Torus Knot Software Ltd

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

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

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

// Sadly we needed to add this #if to solve a NACL compiler bug...
#if (OGRE_PLATFORM == OGRE_PLATFORM_NACL)
#include "ppapi/utility/completion_callback_factory.h"
#endif

using namespace Ogre;

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#include "OgreString.h"
#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
#include "SampleBrowser_OSX.h"
#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
#include "SampleBrowser_iOS.h"
#elif OGRE_PLATFORM == OGRE_PLATFORM_NACL
#include "SampleBrowser_NaCl.h"
#elif OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
#include "SampleBrowser_Android.h"
#include "SampleBrowser.h"

SampleBrowser* OgreAndroidBridge::mBrowser = NULL;
AndroidInputInjector* OgreAndroidBridge::mInputInjector = NULL;
AndroidMultiTouch* OgreAndroidBridge::mTouch = NULL;
AndroidKeyboard* OgreAndroidBridge::mKeyboard = NULL;
RenderWindow* OgreAndroidBridge::mRenderWnd = NULL;
Root* OgreAndroidBridge::mRoot = NULL;
bool OgreAndroidBridge::mInit = false;

#   ifdef OGRE_STATIC_LIB
StaticPluginLoader* OgreAndroidBridge::mStaticPluginLoader = NULL;
#   endif

#endif

#if OGRE_PLATFORM != OGRE_PLATFORM_NACL

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR cmdLine, INT) {
    int argc = __argc;
    char** argv = __argv;
#elif OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
void android_main(struct android_app* state) {
#else
int main(int argc, char *argv[]) {
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	int retVal = UIApplicationMain(argc, argv, @"UIApplication", @"AppDelegate");
	[pool release];
	return retVal;
#elif (OGRE_PLATFORM == OGRE_PLATFORM_APPLE) && __LP64__
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    mAppDelegate = [[AppDelegate alloc] init];
    [[NSApplication sharedApplication] setDelegate:mAppDelegate];
	int retVal = NSApplicationMain(argc, (const char **) argv);

	[pool release];

	return retVal;
#elif OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
    // Make sure glue isn't stripped.
    app_dummy();

    OgreAndroidBridge::init(state);
    OgreAndroidBridge::go(state);
#else

	try
	{
        bool nograb = false;
        if (argc >= 2 && String(argv[1]) == "nograb")
            nograb = true;

        int startUpSampleIdx = -1;
        if (argc >= 3)
        {
            startUpSampleIdx = StringConverter::parseInt(String(argv[2]), -1);
        }
        else if (argc >= 2)
        {
            // first parameter can be either nograb or index. in the former case, we'll just
            // get -1, which is fine.
            startUpSampleIdx = StringConverter::parseInt(String(argv[1]), -1);
        }
		OgreBites::SampleBrowser brows (nograb, startUpSampleIdx);
		brows.go();
	}
	catch (Exception& e)
	{
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
		MessageBoxA(NULL, e.getFullDescription().c_str(), "An exception has occurred!", MB_ICONERROR | MB_TASKMODAL);
#else
		std::cerr << "An exception has occurred: " << e.getFullDescription().c_str() << std::endl;
#endif
	}
	return 0;
#endif
}

#endif
<commit_msg>For real this time, I'm done breaking the sample browser build.<commit_after>/*
 -----------------------------------------------------------------------------
 This source file is part of OGRE
 (Object-oriented Graphics Rendering Engine)
 For the latest info, see http://www.ogre3d.org/

 Copyright (c) 2000-2013 Torus Knot Software Ltd

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

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

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

// Sadly we needed to add this #if to solve a NACL compiler bug...
#if (OGRE_PLATFORM == OGRE_PLATFORM_NACL)
#include "ppapi/utility/completion_callback_factory.h"
#endif

#if !defined(OGRE_STATIC_LIB) && (OGRE_PLATFORM != OGRE_PLATFORM_APPLE && __LP64__)
#include "SampleBrowser.h"
#endif

using namespace Ogre;

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#include "OgreString.h"
#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
#include "SampleBrowser_OSX.h"
#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
#include "SampleBrowser_iOS.h"
#elif OGRE_PLATFORM == OGRE_PLATFORM_NACL
#include "SampleBrowser_NaCl.h"
#elif OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
#include "SampleBrowser_Android.h"

SampleBrowser* OgreAndroidBridge::mBrowser = NULL;
AndroidInputInjector* OgreAndroidBridge::mInputInjector = NULL;
AndroidMultiTouch* OgreAndroidBridge::mTouch = NULL;
AndroidKeyboard* OgreAndroidBridge::mKeyboard = NULL;
RenderWindow* OgreAndroidBridge::mRenderWnd = NULL;
Root* OgreAndroidBridge::mRoot = NULL;
bool OgreAndroidBridge::mInit = false;

#   ifdef OGRE_STATIC_LIB
StaticPluginLoader* OgreAndroidBridge::mStaticPluginLoader = NULL;
#   endif

#endif

#if OGRE_PLATFORM != OGRE_PLATFORM_NACL

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR cmdLine, INT) {
    int argc = __argc;
    char** argv = __argv;
#elif OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
void android_main(struct android_app* state) {
#else
int main(int argc, char *argv[]) {
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	int retVal = UIApplicationMain(argc, argv, @"UIApplication", @"AppDelegate");
	[pool release];
	return retVal;
#elif (OGRE_PLATFORM == OGRE_PLATFORM_APPLE) && __LP64__
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    mAppDelegate = [[AppDelegate alloc] init];
    [[NSApplication sharedApplication] setDelegate:mAppDelegate];
	int retVal = NSApplicationMain(argc, (const char **) argv);

	[pool release];

	return retVal;
#elif OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
    // Make sure glue isn't stripped.
    app_dummy();

    OgreAndroidBridge::init(state);
    OgreAndroidBridge::go(state);
#else

	try
	{
        bool nograb = false;
        if (argc >= 2 && String(argv[1]) == "nograb")
            nograb = true;

        int startUpSampleIdx = -1;
        if (argc >= 3)
        {
            startUpSampleIdx = StringConverter::parseInt(String(argv[2]), -1);
        }
        else if (argc >= 2)
        {
            // first parameter can be either nograb or index. in the former case, we'll just
            // get -1, which is fine.
            startUpSampleIdx = StringConverter::parseInt(String(argv[1]), -1);
        }
		OgreBites::SampleBrowser brows (nograb, startUpSampleIdx);
		brows.go();
	}
	catch (Exception& e)
	{
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
		MessageBoxA(NULL, e.getFullDescription().c_str(), "An exception has occurred!", MB_ICONERROR | MB_TASKMODAL);
#else
		std::cerr << "An exception has occurred: " << e.getFullDescription().c_str() << std::endl;
#endif
	}
	return 0;
#endif
}

#endif
<|endoftext|>


<commit_before>#include "ResNinePatch.hpp"
#include "../App.hpp"
#include "../util/util.hpp"

using namespace morda;

namespace{

class ResSubImage : public ResImage, public ResImage::QuadTexture{
	friend class ResImage;

	std::shared_ptr<ResImage::QuadTexture> tex;

	std::array<Vec2r, 4> texCoords;

	Vec2r dim_v;

public:
	//rect is a rectangle on the texture, Y axis up.
	ResSubImage(decltype(tex) tex, Vec2r texDim, const Rectr& rect) :
			tex(std::move(tex)),
			dim_v(rect.d)
	{
		Rectr r(rect);
		r.p.y = texDim.y - r.p.y - r.d.y;
		this->texCoords[0] = texDim.compDiv(r.leftTop());
		this->texCoords[1] = texDim.compDiv(r.rightTop());
		this->texCoords[2] = texDim.compDiv(r.rightBottom());
		this->texCoords[3] = texDim.compDiv(r.p);
	}

	ResSubImage(const ResSubImage& orig) = delete;
	ResSubImage& operator=(const ResSubImage& orig) = delete;

	Vec2r dim(real dpi) const noexcept override{
		return this->dim_v;
	}

	virtual std::shared_ptr<const ResImage::QuadTexture> get(Vec2r forDim)const override{
		return this->sharedFromThis(this);
	}

	void render(const Matr4r& matrix, PosTexShader& s, const std::array<kolme::Vec2f, 4>& texCoords) const override{
		ASSERT(this->tex)
		this->tex->render(matrix, s, texCoords);
	}
};

}

std::shared_ptr<ResNinePatch> ResNinePatch::load(const stob::Node& chain, const papki::File& fi){

	//TODO: remove?
	if(chain.thisOrNext("tex").node()){
		auto tex = morda::App::inst().resMan.load<ResTexture>(chain.side("tex").up().value());

		auto rect = makeRectrFromSTOB(&chain.side("rect").up());

		auto borders = makeRectrFromSTOB(&chain.side("borders").up());

		return utki::makeShared<ResNinePatch>(
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.p, borders.p)), //lt
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.p.x + borders.p.x, rect.p.y, rect.d.x - borders.p.x - borders.d.x, borders.p.y)), //t
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.right() - borders.d.x, rect.p.y, borders.d.x, borders.p.y)), //rt
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.p.x, rect.p.y + borders.p.y, borders.p.x, rect.d.y - borders.p.y - borders.d.y)), //l
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.p.x + borders.p.x, rect.p.y + borders.p.y, rect.d.x - borders.p.x - borders.d.x, rect.d.y - borders.p.y - borders.d.y)), //m
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.right() - borders.d.x, rect.p.y + borders.p.y, borders.d.x, rect.d.y - borders.p.y - borders.d.y)), //r
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.p.x, rect.top() - borders.d.y, borders.p.x, borders.d.y)), //lb
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.p.x + borders.p.x, rect.top() - borders.d.y, rect.d.x - borders.p.x - borders.d.x, borders.d.y)), //b
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.right() - borders.d.x, rect.top() - borders.d.y, borders.d.x, borders.d.y)) //br
			);
	}

	auto borders = makeSidesrFromSTOB(&chain.side("borders").up());

	auto file = chain.side("file").up().asString();
	fi.setPath(file);
	auto image = ResImage::load(fi);

	return utki::makeShared<ResNinePatch>(image, borders);
}

ResNinePatch::ImageMatrix_t ResNinePatch::get(Sidesr borders) const {
	if(!this->image){
		return ImageMatrix_t({{{this->lt, this->t, this->rt}, {this->l, this->m, this->r} , {this->lb, this->b, this->rb}}});
	}

	//TODO: add caching by requested borders

	real mul = 1;
	auto req = borders.begin();
	for(auto orig = this->borders.begin(); orig != this->borders.end(); ++orig, ++req){
		if(*orig <= 0 || *req <= 0){
			continue;
		}

		if(*req > (*orig) * mul){
			mul = *req / *orig;
		}
	}

	auto dim = this->image->dim() * mul;

	auto quadTex = this->image->get(dim);

	//TODO:
	return ImageMatrix_t();
}
<commit_msg>stuff<commit_after>#include "ResNinePatch.hpp"
#include "../App.hpp"
#include "../util/util.hpp"

using namespace morda;

namespace{

class ResSubImage : public ResImage, public ResImage::QuadTexture{
	friend class ResImage;

	std::shared_ptr<ResImage::QuadTexture> tex;

	std::array<Vec2r, 4> texCoords;

	Vec2r dim_v;

public:
	//rect is a rectangle on the texture, Y axis up.
	ResSubImage(decltype(tex) tex, Vec2r texDim, const Rectr& rect) :
			tex(std::move(tex)),
			dim_v(rect.d)
	{
		Rectr r(rect);
		r.p.y = texDim.y - r.p.y - r.d.y;
		this->texCoords[0] = texDim.compDiv(r.leftTop());
		this->texCoords[1] = texDim.compDiv(r.rightTop());
		this->texCoords[2] = texDim.compDiv(r.rightBottom());
		this->texCoords[3] = texDim.compDiv(r.p);
	}

	ResSubImage(const ResSubImage& orig) = delete;
	ResSubImage& operator=(const ResSubImage& orig) = delete;

	Vec2r dim(real dpi) const noexcept override{
		return this->dim_v;
	}

	virtual std::shared_ptr<const ResImage::QuadTexture> get(Vec2r forDim)const override{
		return this->sharedFromThis(this);
	}

	void render(const Matr4r& matrix, PosTexShader& s, const std::array<kolme::Vec2f, 4>& texCoords) const override{
		ASSERT(this->tex)
		this->tex->render(matrix, s, texCoords);
	}
};

}

std::shared_ptr<ResNinePatch> ResNinePatch::load(const stob::Node& chain, const papki::File& fi){

	//TODO: remove?
	if(chain.thisOrNext("tex").node()){
		auto tex = morda::App::inst().resMan.load<ResTexture>(chain.side("tex").up().value());

		auto rect = makeRectrFromSTOB(&chain.side("rect").up());

		auto borders = makeRectrFromSTOB(&chain.side("borders").up());

		return utki::makeShared<ResNinePatch>(
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.p, borders.p)), //lt
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.p.x + borders.p.x, rect.p.y, rect.d.x - borders.p.x - borders.d.x, borders.p.y)), //t
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.right() - borders.d.x, rect.p.y, borders.d.x, borders.p.y)), //rt
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.p.x, rect.p.y + borders.p.y, borders.p.x, rect.d.y - borders.p.y - borders.d.y)), //l
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.p.x + borders.p.x, rect.p.y + borders.p.y, rect.d.x - borders.p.x - borders.d.x, rect.d.y - borders.p.y - borders.d.y)), //m
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.right() - borders.d.x, rect.p.y + borders.p.y, borders.d.x, rect.d.y - borders.p.y - borders.d.y)), //r
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.p.x, rect.top() - borders.d.y, borders.p.x, borders.d.y)), //lb
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.p.x + borders.p.x, rect.top() - borders.d.y, rect.d.x - borders.p.x - borders.d.x, borders.d.y)), //b
				utki::makeShared<ResAtlasImage>(tex, Rectr(rect.right() - borders.d.x, rect.top() - borders.d.y, borders.d.x, borders.d.y)) //br
			);
	}

	auto borders = makeSidesrFromSTOB(&chain.side("borders").up());

	auto file = chain.side("file").up().asString();
	fi.setPath(file);
	auto image = ResImage::load(fi);

	return utki::makeShared<ResNinePatch>(image, borders);
}

ResNinePatch::ImageMatrix_t ResNinePatch::get(Sidesr borders) const {
	if(!this->image){
		return ImageMatrix_t({{{{this->lt, this->t, this->rt}}, {{this->l, this->m, this->r}} , {{this->lb, this->b, this->rb}}}});
	}

	//TODO: add caching by requested borders

	real mul = 1;
	auto req = borders.begin();
	for(auto orig = this->borders.begin(); orig != this->borders.end(); ++orig, ++req){
		if(*orig <= 0 || *req <= 0){
			continue;
		}

		if(*req > (*orig) * mul){
			mul = *req / *orig;
		}
	}

	auto dim = this->image->dim() * mul;

	auto quadTex = this->image->get(dim);

	//TODO:
	return ImageMatrix_t();
}
<|endoftext|>


<commit_before>//
// Created by FyS on 30/05/17.
//

#include <spdlog/spdlog.h>
#include <TokenGenerator.hh>
#include <TcpConnection.hh>
#include <FySMessage.pb.h>
#include "SessionManager.hh"

fys::network::SessionManager::SessionManager(const uint size) : _connections(size), _connectionsToken(size)
{}

uint fys::network::SessionManager::addConnection(const fys::network::TcpConnection::ptr &newConnection) {
    uint i = 0;

    for (; i < _connections.size(); ++i) {
        if (!_connections.at(i)) {
            connectionHandle(newConnection, i);
            return i;
        }
    }
    _connections.resize(_connections.size() + 1000, nullptr);
    _connectionsToken.resize(_connections.size() + 1000);
    connectionHandle(newConnection, i);
    return i;
}

void fys::network::SessionManager::connectionHandle(const fys::network::TcpConnection::ptr &newConnection, const uint i) {
    Token newToken = fys::utils::TokenGenerator::getInstance()->generateByte();

    this->_connections.at(i) = newConnection;
    this->_connectionsToken.at(i) = newToken;
    newConnection->setSessionIndex(i);
    newConnection->setCustomShutdownHandler([this, i, token = std::move(newToken)]() { this->disconnectUser(i, token); });
}

void fys::network::SessionManager::disconnectUser(const uint idxSession, const fys::network::Token &token) {
    if (idxSession < _connectionsToken.size()) {
        if (std::equal(_connectionsToken.at(idxSession).begin(), _connectionsToken.at(idxSession).end(), token.begin())) {
            spdlog::get("c")->debug("Disconnect user {} from Session manager ({}) and token {}", idxSession, _name, std::string(token.begin(), token.end()));
            _connections.at(idxSession) = nullptr;
            _connectionsToken.at(idxSession) = {};
            return;
        }
    }
    spdlog::get("c")->error("Couldn't find the specified user's token to disconnect on session manager {}", _name);
}

const std::string fys::network::SessionManager::getConnectionToken(const uint indexInSession) const noexcept {
    if (indexInSession < _connectionsToken.size())
        return std::string(_connectionsToken.at(indexInSession).begin(), _connectionsToken.at(indexInSession).end());
    return "";
}

void fys::network::SessionManager::sendResponse(const uint indexInSession, fys::pb::FySResponseMessage &&msg) const noexcept {
    if (indexInSession < _connections.size())
        _connections.at(indexInSession)->send(std::move(msg));
}

void fys::network::SessionManager::send(const uint indexInSession, fys::pb::FySMessage &&msg) const noexcept {
    if (indexInSession < _connections.size())
        _connections.at(indexInSession)->send(std::move(msg));
}

std::pair<std::string, ushort> fys::network::SessionManager::getConnectionData(const uint idxInSession) const noexcept {
    if (idxInSession >= _connections.size() || !_connections.at(idxInSession))
        return std::make_pair(std::string(""), static_cast<ushort>(0));
    return std::make_pair(_connections.at(idxInSession)->getIpAddress(), _connections.at(idxInSession)->getPort());
}

void fys::network::SessionManager::setName(std::string &&name) {
    _name = std::move(name);
}
<commit_msg>[FYS] [gateway]: - change resizing of SessionManager<commit_after>//
// Created by FyS on 30/05/17.
//

#include <spdlog/spdlog.h>
#include <TokenGenerator.hh>
#include <TcpConnection.hh>
#include <FySMessage.pb.h>
#include "SessionManager.hh"

fys::network::SessionManager::SessionManager(const uint size) : _connections(size), _connectionsToken(size)
{}

uint fys::network::SessionManager::addConnection(const fys::network::TcpConnection::ptr &newConnection) {
    uint i = 0;

    for (; i < _connections.size(); ++i) {
        if (!_connections.at(i)) {
            connectionHandle(newConnection, i);
            return i;
        }
    }
    _connections.resize(_connections.size() + 100, nullptr);
    _connectionsToken.resize(_connections.size() + 100);
    connectionHandle(newConnection, i);
    return i;
}

void fys::network::SessionManager::connectionHandle(const fys::network::TcpConnection::ptr &newConnection, const uint i) {
    Token newToken = fys::utils::TokenGenerator::getInstance()->generateByte();

    this->_connections.at(i) = newConnection;
    this->_connectionsToken.at(i) = newToken;
    newConnection->setSessionIndex(i);
    newConnection->setCustomShutdownHandler([this, i, token = std::move(newToken)]() { this->disconnectUser(i, token); });
}

void fys::network::SessionManager::disconnectUser(const uint idxSession, const fys::network::Token &token) {
    if (idxSession < _connectionsToken.size()) {
        if (std::equal(_connectionsToken.at(idxSession).begin(), _connectionsToken.at(idxSession).end(), token.begin())) {
            spdlog::get("c")->debug("Disconnect user {} from Session manager ({}) and token {}", idxSession, _name, std::string(token.begin(), token.end()));
            _connections.at(idxSession) = nullptr;
            _connectionsToken.at(idxSession) = {};
            return;
        }
    }
    spdlog::get("c")->error("Couldn't find the specified user's token to disconnect on session manager {}", _name);
}

const std::string fys::network::SessionManager::getConnectionToken(const uint indexInSession) const noexcept {
    if (indexInSession < _connectionsToken.size())
        return std::string(_connectionsToken.at(indexInSession).begin(), _connectionsToken.at(indexInSession).end());
    return "";
}

void fys::network::SessionManager::sendResponse(const uint indexInSession, fys::pb::FySResponseMessage &&msg) const noexcept {
    if (indexInSession < _connections.size())
        _connections.at(indexInSession)->send(std::move(msg));
}

void fys::network::SessionManager::send(const uint indexInSession, fys::pb::FySMessage &&msg) const noexcept {
    if (indexInSession < _connections.size())
        _connections.at(indexInSession)->send(std::move(msg));
}

std::pair<std::string, ushort> fys::network::SessionManager::getConnectionData(const uint idxInSession) const noexcept {
    if (idxInSession >= _connections.size() || !_connections.at(idxInSession))
        return std::make_pair(std::string(""), static_cast<ushort>(0));
    return std::make_pair(_connections.at(idxInSession)->getIpAddress(), _connections.at(idxInSession)->getPort());
}

void fys::network::SessionManager::setName(std::string &&name) {
    _name = std::move(name);
}
<|endoftext|>


<commit_before>#include <stdlib.h>

#include "ZWaveModule.h"
#include "azure_c_shared_utility/threadapi.h"
#include "azure_c_shared_utility/xlogging.h"
#include "azure_c_shared_utility/crt_abstractions.h"
#include "messageproperties.h"
#include "message.h"
#include "module.h"
#include "broker.h"

#include <parson.h>

typedef struct ZWAVEDEVICE_DATA_TAG
{
	BROKER_HANDLE       broker;
	THREAD_HANDLE       simulatedDeviceThread;
	const char *        fakeMacAddress;
	unsigned int        messagePeriod;
	unsigned int        simulatedDeviceRunning : 1;
} ZWAVEDEVICE_DATA;

typedef struct ZWAVEDEVICE_CONFIG_TAG
{
	STRING_HANDLE IoTHubName;		//Sergei's comments
	STRING_HANDLE IoTHubSuffix;		//Sergei's comments
	char *              macAddress;
	unsigned int        messagePeriod;
} ZWAVEDEVICE_CONFIG;

#define SUFFIX "IoTHubSuffix"		//Sergei's comments
#define HUBNAME "IoTHubName"		//Sergei's comments

static void * ZwaveDevice_ParseConfigurationFromJson(const char* configuration)
{
	ZWAVEDEVICE_CONFIG * result;
	if (configuration == NULL)
	{
		LogError("invalid module args.");
		result = NULL;
	}
	else
	{
		JSON_Value* json = json_parse_string((const char*)configuration);
		if (json == NULL)
		{
			LogError("unable to json_parse_string");
			result = NULL;
		}
		else
		{
			JSON_Object* root = json_value_get_object(json);
			if (root == NULL)
			{
				LogError("unable to json_value_get_object");
				result = NULL;
			}
			else
			{
				ZWAVEDEVICE_CONFIG config;
				const char* macAddress = json_object_get_string(root, "macAddress");
				if (macAddress == NULL)
				{
					LogError("unable to json_object_get_string");
					result = NULL;
				}
				else
				{
					int period = (int)json_object_get_number(root, "messagePeriod");
					if (period <= 0)
					{
						LogError("Invalid period time specified");
						result = NULL;
					}
					else
					{
						if (mallocAndStrcpy_s(&(config.macAddress), macAddress) != 0)
						{
							result = NULL;
						}
						else
						{
							config.messagePeriod = period;
							result = (ZWAVEDEVICE_CONFIG*)malloc(sizeof(ZWAVEDEVICE_CONFIG));
							if (result == NULL) {
								free(config.macAddress);
								LogError("allocation of configuration failed");
							}
							else
							{
								*result = config;
							}
						}
					}
				}
			}
			json_value_free(json);
		}
	}
	return result;
}
/*Sergei's comments*/
static void ZwaveDevice_FreeConfiguration(void* configuration)
{
	/*Codes_SRS_IOTHUBMODULE_05_014: [ If `configuration` is NULL then `IotHub_FreeConfiguration` shall do nothing. ]*/
	if (configuration != NULL)
	{
		ZWAVEDEVICE_CONFIG* config = (ZWAVEDEVICE_CONFIG*)configuration;

		/*Codes_SRS_IOTHUBMODULE_05_015: [ `IotHub_FreeConfiguration` shall free the strings referenced by the `IoTHubName` and `IoTHubSuffix` data members, and then free the `IOTHUB_CONFIG` structure itself. ]*/
		free((void*)config->IoTHubName);
		free((void*)config->IoTHubSuffix);
		free(config);
	}
}

/*Sergei's comments*/
//static MODULE_HANDLE ZwaveDevice_Create(BROKER_HANDLE broker, const void* configuration)
//{
//
//	ZWAVEDEVICE_CONFIG *result;
//	const ZWAVEDEVICE_CONFIG* config = configuration;
//
//	/*Codes_SRS_IOTHUBMODULE_02_001: [ If `broker` is `NULL` then `IotHub_Create` shall fail and return `NULL`. ]*/
//	/*Codes_SRS_IOTHUBMODULE_02_002: [ If `configuration` is `NULL` then `IotHub_Create` shall fail and return `NULL`. ]*/
//	/*Codes_SRS_IOTHUBMODULE_02_003: [ If `configuration->IoTHubName` is `NULL` then `IotHub_Create` shall and return `NULL`. ]*/
//	/*Codes_SRS_IOTHUBMODULE_02_004: [ If `configuration->IoTHubSuffix` is `NULL` then `IotHub_Create` shall fail and return `NULL`. ]*/
//	if (
//		(broker == NULL) ||
//		(configuration == NULL)
//		)
//	{
//		LogError("invalid arg broker=%p, configuration=%p", broker, configuration);
//		result = NULL;
//	}
//	else if (
//		(config->IoTHubName == NULL) ||
//		(config->IoTHubSuffix == NULL) ||
//		(config->transportProvider == NULL)
//		)
//	{
//		LogError("invalid configuration IoTHubName=%s IoTHubSuffix=%s transportProvider=%p",
//			(config != NULL) ? config->IoTHubName : "<null>",
//			(config != NULL) ? config->IoTHubSuffix : "<null>",
//			(config != NULL) ? config->transportProvider : 0);
//		result = NULL;
//	}
//	else
//	{
//		result = malloc(sizeof(IOTHUB_HANDLE_DATA));
//		/*Codes_SRS_IOTHUBMODULE_02_027: [ When `IotHub_Create` encounters an internal failure it shall fail and return `NULL`. ]*/
//		if (result == NULL)
//		{
//			LogError("malloc returned NULL");
//			/*return as is*/
//		}
//		else
//		{
//			/*Codes_SRS_IOTHUBMODULE_02_006: [ `IotHub_Create` shall create an empty `VECTOR` containing pointers to `PERSONALITY`s. ]*/
//			result->personalities = VECTOR_create(sizeof(PERSONALITY_PTR));
//			if (result->personalities == NULL)
//			{
//				/*Codes_SRS_IOTHUBMODULE_02_007: [ If creating the personality vector fails then `IotHub_Create` shall fail and return `NULL`. ]*/
//				free(result);
//				result = NULL;
//				LogError("VECTOR_create returned NULL");
//			}
//			else
//			{
//				result->transportProvider = config->transportProvider;
//				if (result->transportProvider == HTTP_Protocol ||
//					result->transportProvider == AMQP_Protocol)
//				{
//					/*Codes_SRS_IOTHUBMODULE_17_001: [ If `configuration->transportProvider` is `HTTP_Protocol` or `AMQP_Protocol`, `IotHub_Create` shall create a shared transport by calling `IoTHubTransport_Create`. ]*/
//					result->transportHandle = IoTHubTransport_Create(config->transportProvider, config->IoTHubName, config->IoTHubSuffix);
//					if (result->transportHandle == NULL)
//					{
//						/*Codes_SRS_IOTHUBMODULE_17_002: [ If creating the shared transport fails, `IotHub_Create` shall fail and return `NULL`. ]*/
//						VECTOR_destroy(result->personalities);
//						free(result);
//						result = NULL;
//						LogError("VECTOR_create returned NULL");
//					}
//				}
//				else
//				{
//					result->transportHandle = NULL;
//				}
//
//				if (result != NULL)
//				{
//					/*Codes_SRS_IOTHUBMODULE_02_028: [ `IotHub_Create` shall create a copy of `configuration->IoTHubName`. ]*/
//					/*Codes_SRS_IOTHUBMODULE_02_029: [ `IotHub_Create` shall create a copy of `configuration->IoTHubSuffix`. ]*/
//					if ((result->IoTHubName = STRING_construct(config->IoTHubName)) == NULL)
//					{
//						LogError("STRING_construct returned NULL");
//						IoTHubTransport_Destroy(result->transportHandle);
//						VECTOR_destroy(result->personalities);
//						free(result);
//						result = NULL;
//					}
//					else if ((result->IoTHubSuffix = STRING_construct(config->IoTHubSuffix)) == NULL)
//					{
//						LogError("STRING_construct returned NULL");
//						STRING_delete(result->IoTHubName);
//						IoTHubTransport_Destroy(result->transportHandle);
//						VECTOR_destroy(result->personalities);
//						free(result);
//						result = NULL;
//					}
//					else
//					{
//						/*Codes_SRS_IOTHUBMODULE_17_004: [ `IotHub_Create` shall store the broker. ]*/
//						result->broker = broker;
//						/*Codes_SRS_IOTHUBMODULE_02_008: [ Otherwise, `IotHub_Create` shall return a non-`NULL` handle. ]*/
//					}
//				}
//			}
//		}
//	}
//	return result;
//}

/*
*    Required for all modules:  the public API and the designated implementation functions.
*/
static const MODULE_API_1 ZwaveDevice_APIS_all =
{
	{ MODULE_API_VERSION_1 },

	ZwaveDevice_ParseConfigurationFromJson,
	ZwaveDevice_FreeConfiguration,
	//ZwaveDevice_Create //,
	//ZwaveDevice_Destroy,
	//ZwaveDevice_Receive,
	//ZwaveDevice_Start
};

#ifdef BUILD_MODULE_TYPE_STATIC
MODULE_EXPORT const MODULE_API* MODULE_STATIC_GETAPI(ZWAVE_DEVICE_MODULE)(MODULE_API_VERSION gateway_api_version)
#else
MODULE_EXPORT const MODULE_API* Module_GetApi(MODULE_API_VERSION gateway_api_version)
#endif
{
	(void)gateway_api_version;
	return (const MODULE_API *)&ZwaveDevice_APIS_all;
}
<commit_msg>Add module ZwaveDevice_Create<commit_after>#include <stdlib.h>

#include "ZWaveModule.h"
#include "azure_c_shared_utility/threadapi.h"
#include "azure_c_shared_utility/xlogging.h"
#include "azure_c_shared_utility/crt_abstractions.h"
#include "messageproperties.h"
#include "message.h"
#include "module.h"
#include "broker.h"

#include <parson.h>

typedef struct ZWAVEDEVICE_DATA_TAG
{
	BROKER_HANDLE       broker;
	THREAD_HANDLE       simulatedDeviceThread;
	const char *        fakeMacAddress;
	unsigned int        messagePeriod;
	unsigned int        simulatedDeviceRunning : 1;
} ZWAVEDEVICE_DATA;

typedef struct ZWAVEDEVICE_CONFIG_TAG
{
	char *              macAddress;
	unsigned int        messagePeriod;
} ZWAVEDEVICE_CONFIG;

/*Sergei's add module*/
static MODULE_HANDLE ZwaveDevice_Create(BROKER_HANDLE broker, const void* configuration)
{
	ZWAVEDEVICE_DATA * result;
	ZWAVEDEVICE_CONFIG * config = (ZWAVEDEVICE_CONFIG *)configuration;
	if (broker == NULL || config == NULL)
	{
		LogError("invalid SIMULATED DEVICE module args.");
		result = NULL;
	}
	else
	{
		/* allocate module data struct */
		result = (ZWAVEDEVICE_DATA*)malloc(sizeof(ZWAVEDEVICE_DATA));
		if (result == NULL)
		{
			LogError("couldn't allocate memory for BLE Module");
		}
		else
		{
			/* save the message broker */
			result->broker = broker;
			/* set module is running to true */
			result->simulatedDeviceRunning = 1;
			/* save fake MacAddress */
			char * newFakeAddress;
			int status = mallocAndStrcpy_s(&newFakeAddress, config->macAddress);

			if (status != 0)
			{
				LogError("MacAddress did not copy");
			}
			else
			{
				result->fakeMacAddress = newFakeAddress;
				result->messagePeriod = config->messagePeriod;
				result->simulatedDeviceThread = NULL;

			}

		}
	}
	return result;
}

static void* ZwaveDevice_ParseConfigurationFromJson(const char* configuration)
{
	ZWAVEDEVICE_CONFIG * result;
	if (configuration == NULL)
	{
		LogError("invalid module args.");
		result = NULL;
	}
	else
	{
		JSON_Value* json = json_parse_string((const char*)configuration);
		if (json == NULL)
		{
			LogError("unable to json_parse_string");
			result = NULL;
		}
		else
		{
			JSON_Object* root = json_value_get_object(json);
			if (root == NULL)
			{
				LogError("unable to json_value_get_object");
				result = NULL;
			}
			else
			{
				ZWAVEDEVICE_CONFIG config;
				const char* macAddress = json_object_get_string(root, "macAddress");
				if (macAddress == NULL)
				{
					LogError("unable to json_object_get_string");
					result = NULL;
				}
				else
				{
					int period = (int)json_object_get_number(root, "messagePeriod");
					if (period <= 0)
					{
						LogError("Invalid period time specified");
						result = NULL;
					}
					else
					{
						if (mallocAndStrcpy_s(&(config.macAddress), macAddress) != 0)
						{
							result = NULL;
						}
						else
						{
							config.messagePeriod = period;
							result = (ZWAVEDEVICE_CONFIG*)malloc(sizeof(ZWAVEDEVICE_CONFIG));
							if (result == NULL) {
								free(config.macAddress);
								LogError("allocation of configuration failed");
							}
							else
							{
								*result = config;
							}
						}
					}
				}
			}
			json_value_free(json);
		}
	}
	return result;
}

/*Sergei's add module*/
void ZwaveDevice_FreeConfiguration(void * configuration)
{
	if (configuration != NULL)
	{
		ZWAVEDEVICE_CONFIG * config = (ZWAVEDEVICE_CONFIG *)configuration;
		free(config->macAddress);
		free(config);
	}
}

/*
*    Required for all modules:  the public API and the designated implementation functions.
*/
static const MODULE_API_1 ZwaveDevice_APIS_all =
{
	{ MODULE_API_VERSION_1 },

	ZwaveDevice_ParseConfigurationFromJson,
	ZwaveDevice_FreeConfiguration,
	ZwaveDevice_Create //,
	//ZwaveDevice_Destroy,
	//ZwaveDevice_Receive,
	//ZwaveDevice_Start
};

#ifdef BUILD_MODULE_TYPE_STATIC
MODULE_EXPORT const MODULE_API* MODULE_STATIC_GETAPI(ZWAVE_DEVICE_MODULE)(MODULE_API_VERSION gateway_api_version)
#else
MODULE_EXPORT const MODULE_API* Module_GetApi(MODULE_API_VERSION gateway_api_version)
#endif
{
	(void)gateway_api_version;
	return (const MODULE_API *)&ZwaveDevice_APIS_all;
}
<|endoftext|>