<commit_before>#ifndef STDC11_HH
#define STDC11_HH

#include <string>
#include <sstream>
#include <math.h>
#include <cassert>
#include <memory>
#include <iomanip>
#include <type_traits>
#include <limits>

/* **
 * This file is juste a set of convenient standard methods from std11 such
 * as smart pointer and other stuff.
 */

#define sign_form(T) typename std::make_signed<T>::type
#define sign_form_(T) std::make_signed<T>::type

namespace std
{

  template< typename T >
  inline T convert(const std::string& str)
  {
    std::istringstream iss(str);
    T obj;

    iss >> std::ws >> obj >> std::ws;

    if(!iss.eof())
      throw "dammit!";

    return obj;
  }
  const double PI = 3.14159265;

  template<typename T>
  bool is_signed_cast_safe(T a)
  {
    static_assert(std::numeric_limits<T>::is_modulo, "type must be 2 complement");
    static_assert(!std::numeric_limits<T>::is_signed, "type must be unsigned");

    typedef typename std::make_signed<T>::type signed_T;
    typedef typename std::make_unsigned<T>::type unsigned_T;

    return a < (unsigned_T) std::numeric_limits<signed_T>::max() ;
    //&& a < (unsigned)std::numeric_limits<typename std::make_signed<T>::type>::max();
  }

  template<typename C, typename T>
  bool is_cast_lossless(T a)
  {
    if(std::numeric_limits<C>::digits >= std::numeric_limits<T>::digits)
      return true;

    static_assert(std::numeric_limits<C>::is_modulo, "type must be 2 complement");

    return a <= static_cast<T>(std::numeric_limits<C>::max()) &&
           a >= static_cast<T>(std::numeric_limits<C>::min());
  }

  template <bool B, typename T1, typename T2>
  struct IF;
  template <typename T1, typename T2>
  struct IF<false,T1,T2>
  {
    typedef T2 res;
  };
  template <typename T1, typename T2>
  struct IF<true,T1,T2>
  {
    typedef T1 res;
  };

  template <typename T>
  std::string to_string (T num)
  {
    std::ostringstream ss;
    ss << std::setprecision(3) << num;
    return ss.str();
  }

  template<typename T>
  T round(T v)
  {
    return ::round(v);
  }

  template<typename T,typename ContainerT>
  void tokenize(const std::string &str,
                ContainerT &tokens,
                const std::string &delimiters = " ",
                bool trimEmpty = false)
  {
    std::string::size_type pos, lastPos = 0;
    while(true)
    {
      pos = str.find_first_of(delimiters, lastPos);
      if(pos == std::string::npos)
      {
        if(lastPos != str.length())
          tokens.push_back(std::string(str.data()+lastPos,
                                       (sizeof(T))*(str.length()-lastPos) ));
          break;
      }
      else
        if(pos != lastPos || !trimEmpty)
          tokens.push_back(std::string(str.data()+lastPos,
                                       (sizeof(T))*(pos-lastPos) ));
      lastPos = pos + 1;
    }
  }

}

#endif

<commit_msg>Add approximation equality<commit_after>#ifndef STDC11_HH
#define STDC11_HH

#include <string>
#include <sstream>
#include <math.h>
#include <cassert>
#include <memory>
#include <iomanip>
#include <type_traits>
#include <limits>
#include <cmath>

/* **
 * This file is juste a set of convenient standard methods from std11 such
 * as smart pointer and other stuff.
 */

#define sign_form(T) typename std::make_signed<T>::type
#define sign_form_(T) std::make_signed<T>::type

namespace std
{
  template<bool exclude=true, typename T>
  bool approx_equal(T a, T b, T epsilon=std::numeric_limits<T>::epsilon())
  {
    if(std::numeric_limits<T>::is_integer)
      if(exclude)
        return std::abs(a-b) < epsilon;
      else
        return std::abs(a-b) <= epsilon;
    else
      if(exclude)
        return std::fabs(a-b) < epsilon;
      else
        return std::fabs(a-b) <= epsilon;
  }

  template< typename T >
  inline T convert(const std::string& str)
  {
    std::istringstream iss(str);
    T obj;

    iss >> std::ws >> obj >> std::ws;

    if(!iss.eof())
      throw "dammit!";

    return obj;
  }
  const double PI = 3.14159265;

  template<typename T>
  bool is_signed_cast_safe(T a)
  {
    static_assert(std::numeric_limits<T>::is_modulo, "type must be 2 complement");
    static_assert(!std::numeric_limits<T>::is_signed, "type must be unsigned");

    typedef typename std::make_signed<T>::type signed_T;
    typedef typename std::make_unsigned<T>::type unsigned_T;

    return a < (unsigned_T) std::numeric_limits<signed_T>::max() ;
    //&& a < (unsigned)std::numeric_limits<typename std::make_signed<T>::type>::max();
  }

  template<typename C, typename T>
  bool is_cast_lossless(T a)
  {
    if(std::numeric_limits<C>::digits >= std::numeric_limits<T>::digits)
      return true;

    static_assert(std::numeric_limits<C>::is_modulo, "type must be 2 complement");

    return a <= static_cast<T>(std::numeric_limits<C>::max()) &&
           a >= static_cast<T>(std::numeric_limits<C>::min());
  }

  template <bool B, typename T1, typename T2>
  struct IF;
  template <typename T1, typename T2>
  struct IF<false,T1,T2>
  {
    typedef T2 res;
  };
  template <typename T1, typename T2>
  struct IF<true,T1,T2>
  {
    typedef T1 res;
  };

  template <typename T>
  std::string to_string (T num)
  {
    std::ostringstream ss;
    ss << std::setprecision(3) << num;
    return ss.str();
  }

  template<typename T>
  T round(T v)
  {
    return ::round(v);
  }

  template<typename T,typename ContainerT>
  void tokenize(const std::string &str,
                ContainerT &tokens,
                const std::string &delimiters = " ",
                bool trimEmpty = false)
  {
    std::string::size_type pos, lastPos = 0;
    while(true)
    {
      pos = str.find_first_of(delimiters, lastPos);
      if(pos == std::string::npos)
      {
        if(lastPos != str.length())
          tokens.push_back(std::string(str.data()+lastPos,
                                       (sizeof(T))*(str.length()-lastPos) ));
          break;
      }
      else
        if(pos != lastPos || !trimEmpty)
          tokens.push_back(std::string(str.data()+lastPos,
                                       (sizeof(T))*(pos-lastPos) ));
      lastPos = pos + 1;
    }
  }

}

#endif

<|endoftext|>


<commit_before>//===-- LoopUnswitch.cpp - Hoist loop-invariant conditionals in loop ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass transforms loops that contain branches on loop-invariant conditions
// to have multiple loops.  For example, it turns the left into the right code:
//
//  for (...)                  if (lic)
//    A                          for (...)
//    if (lic)                     A; B; C
//      B                      else
//    C                          for (...)
//                                 A; C
//
// This can increase the size of the code exponentially (doubling it every time
// a loop is unswitched) so we only unswitch if the resultant code will be
// smaller than a threshold.
//
// This pass expects LICM to be run before it to hoist invariant conditions out
// of the loop, to make the unswitching opportunity obvious.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "loop-unswitch"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
#include <algorithm>
#include <iostream>
#include <set>
using namespace llvm;

namespace {
  Statistic<> NumUnswitched("loop-unswitch", "Number of loops unswitched");

  class LoopUnswitch : public FunctionPass {
    LoopInfo *LI;  // Loop information
  public:
    virtual bool runOnFunction(Function &F);
    bool visitLoop(Loop *L);

    /// This transformation requires natural loop information & requires that
    /// loop preheaders be inserted into the CFG...
    ///
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequiredID(LoopSimplifyID);
      AU.addRequired<LoopInfo>();
      AU.addPreserved<LoopInfo>();
    }

  private:
    void VersionLoop(Value *LIC, Loop *L);
    BasicBlock *SplitBlock(BasicBlock *BB, bool SplitAtTop);
    void RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC, bool Val);
  };
  RegisterOpt<LoopUnswitch> X("loop-unswitch", "Unswitch loops");
}

FunctionPass *llvm::createLoopUnswitchPass() { return new LoopUnswitch(); }

bool LoopUnswitch::runOnFunction(Function &F) {
  bool Changed = false;
  LI = &getAnalysis<LoopInfo>();

  // Transform all the top-level loops.  Copy the loop list so that the child
  // can update the loop tree if it needs to delete the loop.
  std::vector<Loop*> SubLoops(LI->begin(), LI->end());
  for (unsigned i = 0, e = SubLoops.size(); i != e; ++i)
    Changed |= visitLoop(SubLoops[i]);

  return Changed;
}

/// InsertPHINodesForUsesOutsideLoop - If this instruction is used outside of
/// the specified loop, insert a PHI node in the appropriate exit block to merge
/// the values in the two different loop versions.
///
/// Most values are not used outside of the loop they are defined in, so be
/// efficient for this case.
///
static bool LoopValuesUsedOutsideLoop(Loop *L) {
  // We will be doing lots of "loop contains block" queries.  Loop::contains is
  // linear time, use a set to speed this up.
  std::set<BasicBlock*> LoopBlocks;

  for (Loop::block_iterator BB = L->block_begin(), E = L->block_end();
       BB != E; ++BB)
    LoopBlocks.insert(*BB);

  for (Loop::block_iterator BB = L->block_begin(), E = L->block_end();
       BB != E; ++BB) {
    for (BasicBlock::iterator I = (*BB)->begin(), E = (*BB)->end(); I != E; ++I)
      for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E;
           ++UI) {
        BasicBlock *UserBB = cast<Instruction>(*UI)->getParent();
        if (!LoopBlocks.count(UserBB))
          return true;
      }
  }
  return false;
}

bool LoopUnswitch::visitLoop(Loop *L) {
  bool Changed = false;

  // Recurse through all subloops before we process this loop.  Copy the loop
  // list so that the child can update the loop tree if it needs to delete the
  // loop.
  std::vector<Loop*> SubLoops(L->begin(), L->end());
  for (unsigned i = 0, e = SubLoops.size(); i != e; ++i)
    Changed |= visitLoop(SubLoops[i]);

  // Loop over all of the basic blocks in the loop.  If we find an interior
  // block that is branching on a loop-invariant condition, we can unswitch this
  // loop.
  for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
       I != E; ++I) {
    TerminatorInst *TI = (*I)->getTerminator();
    if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
      if (!isa<Constant>(SI) && L->isLoopInvariant(SI->getCondition()))
        DEBUG(std::cerr << "TODO: Implement unswitching 'switch' loop %"
              << L->getHeader()->getName() << ", cost = "
              << L->getBlocks().size() << "\n" << **I);
      continue;
    }

    BranchInst *BI = dyn_cast<BranchInst>(TI);
    if (!BI) continue;

    // If this isn't branching on an invariant condition, we can't unswitch it.
    if (!BI->isConditional() || isa<Constant>(BI->getCondition()) ||
        !L->isLoopInvariant(BI->getCondition()))
      continue;

    // Check to see if it would be profitable to unswitch this loop.
    if (L->getBlocks().size() > 10) {
      // FIXME: this should estimate growth by the amount of code shared by the
      // resultant unswitched loops.  This should have no code growth:
      //    for () { if (iv) {...} }
      // as one copy of the loop will be empty.
      //
      DEBUG(std::cerr << "NOT unswitching loop %"
            << L->getHeader()->getName() << ", cost too high: "
            << L->getBlocks().size() << "\n");
      continue;
    }

    // If this loop has live-out values, we can't unswitch it. We need something
    // like loop-closed SSA form in order to know how to insert PHI nodes for
    // these values.
    if (LoopValuesUsedOutsideLoop(L)) {
      DEBUG(std::cerr << "NOT unswitching loop %"
                      << L->getHeader()->getName()
                      << ", a loop value is used outside loop!\n");
      continue;
    }

    //std::cerr << "BEFORE:\n"; LI->dump();
    VersionLoop(BI->getCondition(), L);
    //std::cerr << "AFTER:\n"; LI->dump();

    // FIXME: Why return here?  What if we have:
    // "for () { if (iv1) { if (iv2) { } } }" ?
    return true;
  }

  return Changed;
}

/// SplitBlock - Split the specified basic block into two pieces.  If SplitAtTop
/// is false, this splits the block so the second half only has an unconditional
/// branch.  If SplitAtTop is true, it makes it so the first half of the block
/// only has an unconditional branch in it.
///
/// This method updates the LoopInfo for this function to correctly reflect the
/// CFG changes made.
BasicBlock *LoopUnswitch::SplitBlock(BasicBlock *BB, bool SplitAtTop) {
  BasicBlock::iterator SplitPoint;
  if (!SplitAtTop)
    SplitPoint = BB->getTerminator();
  else {
    SplitPoint = BB->begin();
    while (isa<PHINode>(SplitPoint)) ++SplitPoint;
  }

  BasicBlock *New = BB->splitBasicBlock(SplitPoint, BB->getName()+".tail");
  // New now lives in whichever loop that BB used to.
  if (Loop *L = LI->getLoopFor(BB))
    L->addBasicBlockToLoop(New, *LI);
  return SplitAtTop ? BB : New;
}

// RemapInstruction - Convert the instruction operands from referencing the
// current values into those specified by ValueMap.
//
static inline void RemapInstruction(Instruction *I,
                                    std::map<const Value *, Value*> &ValueMap) {
  for (unsigned op = 0, E = I->getNumOperands(); op != E; ++op) {
    Value *Op = I->getOperand(op);
    std::map<const Value *, Value*>::iterator It = ValueMap.find(Op);
    if (It != ValueMap.end()) Op = It->second;
    I->setOperand(op, Op);
  }
}

/// CloneLoop - Recursively clone the specified loop and all of its children,
/// mapping the blocks with the specified map.
static Loop *CloneLoop(Loop *L, Loop *PL, std::map<const Value*, Value*> &VM,
                       LoopInfo *LI) {
  Loop *New = new Loop();

  if (PL)
    PL->addChildLoop(New);
  else
    LI->addTopLevelLoop(New);

  // Add all of the blocks in L to the new loop.
  for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
       I != E; ++I)
    if (LI->getLoopFor(*I) == L)
      New->addBasicBlockToLoop(cast<BasicBlock>(VM[*I]), *LI);

  // Add all of the subloops to the new loop.
  for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I)
    CloneLoop(*I, New, VM, LI);

  return New;
}

/// VersionLoop - We determined that the loop is profitable to unswitch and
/// contains a branch on a loop invariant condition.  Split it into loop
/// versions and test the condition outside of either loop.
void LoopUnswitch::VersionLoop(Value *LIC, Loop *L) {
  Function *F = L->getHeader()->getParent();

  DEBUG(std::cerr << "loop-unswitch: Unswitching loop %"
        << L->getHeader()->getName() << " [" << L->getBlocks().size()
        << " blocks] in Function " << F->getName()
        << " on cond:" << *LIC << "\n");

  std::vector<BasicBlock*> LoopBlocks;

  // First step, split the preheader and exit blocks, and add these blocks to
  // the LoopBlocks list.
  BasicBlock *OrigPreheader = L->getLoopPreheader();
  LoopBlocks.push_back(SplitBlock(OrigPreheader, false));

  // We want the loop to come after the preheader, but before the exit blocks.
  LoopBlocks.insert(LoopBlocks.end(), L->block_begin(), L->block_end());

  std::vector<BasicBlock*> ExitBlocks;
  L->getExitBlocks(ExitBlocks);
  std::sort(ExitBlocks.begin(), ExitBlocks.end());
  ExitBlocks.erase(std::unique(ExitBlocks.begin(), ExitBlocks.end()),
                   ExitBlocks.end());
  for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i)
    LoopBlocks.push_back(ExitBlocks[i] = SplitBlock(ExitBlocks[i], true));

  // Next step, clone all of the basic blocks that make up the loop (including
  // the loop preheader and exit blocks), keeping track of the mapping between
  // the instructions and blocks.
  std::vector<BasicBlock*> NewBlocks;
  NewBlocks.reserve(LoopBlocks.size());
  std::map<const Value*, Value*> ValueMap;
  for (unsigned i = 0, e = LoopBlocks.size(); i != e; ++i) {
    NewBlocks.push_back(CloneBasicBlock(LoopBlocks[i], ValueMap, ".us", F));
    ValueMap[LoopBlocks[i]] = NewBlocks.back();  // Keep the BB mapping.
  }

  // Splice the newly inserted blocks into the function right before the
  // original preheader.
  F->getBasicBlockList().splice(LoopBlocks[0], F->getBasicBlockList(),
                                NewBlocks[0], F->end());

  // Now we create the new Loop object for the versioned loop.
  Loop *NewLoop = CloneLoop(L, L->getParentLoop(), ValueMap, LI);
  if (Loop *Parent = L->getParentLoop()) {
    // Make sure to add the cloned preheader and exit blocks to the parent loop
    // as well.
    Parent->addBasicBlockToLoop(NewBlocks[0], *LI);
    for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i)
      Parent->addBasicBlockToLoop(cast<BasicBlock>(ValueMap[ExitBlocks[i]]),
                                  *LI);
  }

  // Rewrite the code to refer to itself.
  for (unsigned i = 0, e = NewBlocks.size(); i != e; ++i)
    for (BasicBlock::iterator I = NewBlocks[i]->begin(),
           E = NewBlocks[i]->end(); I != E; ++I)
      RemapInstruction(I, ValueMap);

  // Rewrite the original preheader to select between versions of the loop.
  assert(isa<BranchInst>(OrigPreheader->getTerminator()) &&
         cast<BranchInst>(OrigPreheader->getTerminator())->isUnconditional() &&
         OrigPreheader->getTerminator()->getSuccessor(0) == LoopBlocks[0] &&
         "Preheader splitting did not work correctly!");
  // Remove the unconditional branch to LoopBlocks[0].
  OrigPreheader->getInstList().pop_back();

  // Insert a conditional branch on LIC to the two preheaders.  The original
  // code is the true version and the new code is the false version.
  new BranchInst(LoopBlocks[0], NewBlocks[0], LIC, OrigPreheader);

  // Now we rewrite the original code to know that the condition is true and the
  // new code to know that the condition is false.
  RewriteLoopBodyWithConditionConstant(L, LIC, true);
  RewriteLoopBodyWithConditionConstant(NewLoop, LIC, false);
  ++NumUnswitched;

  // Try to unswitch each of our new loops now!
  visitLoop(L);
  visitLoop(NewLoop);
}

// RewriteLoopBodyWithConditionConstant - We know that the boolean value LIC has
// the value specified by Val in the specified loop.  Rewrite any uses of LIC or
// of properties correlated to it.
void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
                                                        bool Val) {
  // FIXME: Support correlated properties, like:
  //  for (...)
  //    if (li1 < li2)
  //      ...
  //    if (li1 > li2)
  //      ...
  ConstantBool *BoolVal = ConstantBool::get(Val);

  std::vector<User*> Users(LIC->use_begin(), LIC->use_end());
  for (unsigned i = 0, e = Users.size(); i != e; ++i)
    if (Instruction *U = dyn_cast<Instruction>(Users[i]))
      if (L->contains(U->getParent()))
        U->replaceUsesOfWith(LIC, BoolVal);
}
<commit_msg>Make the threshold a parameter<commit_after>//===-- LoopUnswitch.cpp - Hoist loop-invariant conditionals in loop ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass transforms loops that contain branches on loop-invariant conditions
// to have multiple loops.  For example, it turns the left into the right code:
//
//  for (...)                  if (lic)
//    A                          for (...)
//    if (lic)                     A; B; C
//      B                      else
//    C                          for (...)
//                                 A; C
//
// This can increase the size of the code exponentially (doubling it every time
// a loop is unswitched) so we only unswitch if the resultant code will be
// smaller than a threshold.
//
// This pass expects LICM to be run before it to hoist invariant conditions out
// of the loop, to make the unswitching opportunity obvious.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "loop-unswitch"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/CommandLine.h"
#include <algorithm>
#include <iostream>
#include <set>
using namespace llvm;

namespace {
  Statistic<> NumUnswitched("loop-unswitch", "Number of loops unswitched");
  cl::opt<unsigned>
  Threshold("loop-unswitch-threshold", cl::desc("Max loop size to unswitch"),
            cl::init(10), cl::Hidden);

  class LoopUnswitch : public FunctionPass {
    LoopInfo *LI;  // Loop information
  public:
    virtual bool runOnFunction(Function &F);
    bool visitLoop(Loop *L);

    /// This transformation requires natural loop information & requires that
    /// loop preheaders be inserted into the CFG...
    ///
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequiredID(LoopSimplifyID);
      AU.addRequired<LoopInfo>();
      AU.addPreserved<LoopInfo>();
    }

  private:
    void VersionLoop(Value *LIC, Loop *L);
    BasicBlock *SplitBlock(BasicBlock *BB, bool SplitAtTop);
    void RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC, bool Val);
  };
  RegisterOpt<LoopUnswitch> X("loop-unswitch", "Unswitch loops");
}

FunctionPass *llvm::createLoopUnswitchPass() { return new LoopUnswitch(); }

bool LoopUnswitch::runOnFunction(Function &F) {
  bool Changed = false;
  LI = &getAnalysis<LoopInfo>();

  // Transform all the top-level loops.  Copy the loop list so that the child
  // can update the loop tree if it needs to delete the loop.
  std::vector<Loop*> SubLoops(LI->begin(), LI->end());
  for (unsigned i = 0, e = SubLoops.size(); i != e; ++i)
    Changed |= visitLoop(SubLoops[i]);

  return Changed;
}

/// InsertPHINodesForUsesOutsideLoop - If this instruction is used outside of
/// the specified loop, insert a PHI node in the appropriate exit block to merge
/// the values in the two different loop versions.
///
/// Most values are not used outside of the loop they are defined in, so be
/// efficient for this case.
///
static bool LoopValuesUsedOutsideLoop(Loop *L) {
  // We will be doing lots of "loop contains block" queries.  Loop::contains is
  // linear time, use a set to speed this up.
  std::set<BasicBlock*> LoopBlocks;

  for (Loop::block_iterator BB = L->block_begin(), E = L->block_end();
       BB != E; ++BB)
    LoopBlocks.insert(*BB);

  for (Loop::block_iterator BB = L->block_begin(), E = L->block_end();
       BB != E; ++BB) {
    for (BasicBlock::iterator I = (*BB)->begin(), E = (*BB)->end(); I != E; ++I)
      for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E;
           ++UI) {
        BasicBlock *UserBB = cast<Instruction>(*UI)->getParent();
        if (!LoopBlocks.count(UserBB))
          return true;
      }
  }
  return false;
}

bool LoopUnswitch::visitLoop(Loop *L) {
  bool Changed = false;

  // Recurse through all subloops before we process this loop.  Copy the loop
  // list so that the child can update the loop tree if it needs to delete the
  // loop.
  std::vector<Loop*> SubLoops(L->begin(), L->end());
  for (unsigned i = 0, e = SubLoops.size(); i != e; ++i)
    Changed |= visitLoop(SubLoops[i]);

  // Loop over all of the basic blocks in the loop.  If we find an interior
  // block that is branching on a loop-invariant condition, we can unswitch this
  // loop.
  for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
       I != E; ++I) {
    TerminatorInst *TI = (*I)->getTerminator();
    if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
      if (!isa<Constant>(SI) && L->isLoopInvariant(SI->getCondition()))
        DEBUG(std::cerr << "TODO: Implement unswitching 'switch' loop %"
              << L->getHeader()->getName() << ", cost = "
              << L->getBlocks().size() << "\n" << **I);
      continue;
    }

    BranchInst *BI = dyn_cast<BranchInst>(TI);
    if (!BI) continue;

    // If this isn't branching on an invariant condition, we can't unswitch it.
    if (!BI->isConditional() || isa<Constant>(BI->getCondition()) ||
        !L->isLoopInvariant(BI->getCondition()))
      continue;

    // Check to see if it would be profitable to unswitch this loop.
    if (L->getBlocks().size() > Threshold) {
      // FIXME: this should estimate growth by the amount of code shared by the
      // resultant unswitched loops.  This should have no code growth:
      //    for () { if (iv) {...} }
      // as one copy of the loop will be empty.
      //
      DEBUG(std::cerr << "NOT unswitching loop %"
            << L->getHeader()->getName() << ", cost too high: "
            << L->getBlocks().size() << "\n");
      continue;
    }

    // If this loop has live-out values, we can't unswitch it. We need something
    // like loop-closed SSA form in order to know how to insert PHI nodes for
    // these values.
    if (LoopValuesUsedOutsideLoop(L)) {
      DEBUG(std::cerr << "NOT unswitching loop %"
                      << L->getHeader()->getName()
                      << ", a loop value is used outside loop!\n");
      continue;
    }

    //std::cerr << "BEFORE:\n"; LI->dump();
    VersionLoop(BI->getCondition(), L);
    //std::cerr << "AFTER:\n"; LI->dump();

    // FIXME: Why return here?  What if we have:
    // "for () { if (iv1) { if (iv2) { } } }" ?
    return true;
  }

  return Changed;
}

/// SplitBlock - Split the specified basic block into two pieces.  If SplitAtTop
/// is false, this splits the block so the second half only has an unconditional
/// branch.  If SplitAtTop is true, it makes it so the first half of the block
/// only has an unconditional branch in it.
///
/// This method updates the LoopInfo for this function to correctly reflect the
/// CFG changes made.
BasicBlock *LoopUnswitch::SplitBlock(BasicBlock *BB, bool SplitAtTop) {
  BasicBlock::iterator SplitPoint;
  if (!SplitAtTop)
    SplitPoint = BB->getTerminator();
  else {
    SplitPoint = BB->begin();
    while (isa<PHINode>(SplitPoint)) ++SplitPoint;
  }

  BasicBlock *New = BB->splitBasicBlock(SplitPoint, BB->getName()+".tail");
  // New now lives in whichever loop that BB used to.
  if (Loop *L = LI->getLoopFor(BB))
    L->addBasicBlockToLoop(New, *LI);
  return SplitAtTop ? BB : New;
}

// RemapInstruction - Convert the instruction operands from referencing the
// current values into those specified by ValueMap.
//
static inline void RemapInstruction(Instruction *I,
                                    std::map<const Value *, Value*> &ValueMap) {
  for (unsigned op = 0, E = I->getNumOperands(); op != E; ++op) {
    Value *Op = I->getOperand(op);
    std::map<const Value *, Value*>::iterator It = ValueMap.find(Op);
    if (It != ValueMap.end()) Op = It->second;
    I->setOperand(op, Op);
  }
}

/// CloneLoop - Recursively clone the specified loop and all of its children,
/// mapping the blocks with the specified map.
static Loop *CloneLoop(Loop *L, Loop *PL, std::map<const Value*, Value*> &VM,
                       LoopInfo *LI) {
  Loop *New = new Loop();

  if (PL)
    PL->addChildLoop(New);
  else
    LI->addTopLevelLoop(New);

  // Add all of the blocks in L to the new loop.
  for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
       I != E; ++I)
    if (LI->getLoopFor(*I) == L)
      New->addBasicBlockToLoop(cast<BasicBlock>(VM[*I]), *LI);

  // Add all of the subloops to the new loop.
  for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I)
    CloneLoop(*I, New, VM, LI);

  return New;
}

/// VersionLoop - We determined that the loop is profitable to unswitch and
/// contains a branch on a loop invariant condition.  Split it into loop
/// versions and test the condition outside of either loop.
void LoopUnswitch::VersionLoop(Value *LIC, Loop *L) {
  Function *F = L->getHeader()->getParent();

  DEBUG(std::cerr << "loop-unswitch: Unswitching loop %"
        << L->getHeader()->getName() << " [" << L->getBlocks().size()
        << " blocks] in Function " << F->getName()
        << " on cond:" << *LIC << "\n");

  std::vector<BasicBlock*> LoopBlocks;

  // First step, split the preheader and exit blocks, and add these blocks to
  // the LoopBlocks list.
  BasicBlock *OrigPreheader = L->getLoopPreheader();
  LoopBlocks.push_back(SplitBlock(OrigPreheader, false));

  // We want the loop to come after the preheader, but before the exit blocks.
  LoopBlocks.insert(LoopBlocks.end(), L->block_begin(), L->block_end());

  std::vector<BasicBlock*> ExitBlocks;
  L->getExitBlocks(ExitBlocks);
  std::sort(ExitBlocks.begin(), ExitBlocks.end());
  ExitBlocks.erase(std::unique(ExitBlocks.begin(), ExitBlocks.end()),
                   ExitBlocks.end());
  for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i)
    LoopBlocks.push_back(ExitBlocks[i] = SplitBlock(ExitBlocks[i], true));

  // Next step, clone all of the basic blocks that make up the loop (including
  // the loop preheader and exit blocks), keeping track of the mapping between
  // the instructions and blocks.
  std::vector<BasicBlock*> NewBlocks;
  NewBlocks.reserve(LoopBlocks.size());
  std::map<const Value*, Value*> ValueMap;
  for (unsigned i = 0, e = LoopBlocks.size(); i != e; ++i) {
    NewBlocks.push_back(CloneBasicBlock(LoopBlocks[i], ValueMap, ".us", F));
    ValueMap[LoopBlocks[i]] = NewBlocks.back();  // Keep the BB mapping.
  }

  // Splice the newly inserted blocks into the function right before the
  // original preheader.
  F->getBasicBlockList().splice(LoopBlocks[0], F->getBasicBlockList(),
                                NewBlocks[0], F->end());

  // Now we create the new Loop object for the versioned loop.
  Loop *NewLoop = CloneLoop(L, L->getParentLoop(), ValueMap, LI);
  if (Loop *Parent = L->getParentLoop()) {
    // Make sure to add the cloned preheader and exit blocks to the parent loop
    // as well.
    Parent->addBasicBlockToLoop(NewBlocks[0], *LI);
    for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i)
      Parent->addBasicBlockToLoop(cast<BasicBlock>(ValueMap[ExitBlocks[i]]),
                                  *LI);
  }

  // Rewrite the code to refer to itself.
  for (unsigned i = 0, e = NewBlocks.size(); i != e; ++i)
    for (BasicBlock::iterator I = NewBlocks[i]->begin(),
           E = NewBlocks[i]->end(); I != E; ++I)
      RemapInstruction(I, ValueMap);

  // Rewrite the original preheader to select between versions of the loop.
  assert(isa<BranchInst>(OrigPreheader->getTerminator()) &&
         cast<BranchInst>(OrigPreheader->getTerminator())->isUnconditional() &&
         OrigPreheader->getTerminator()->getSuccessor(0) == LoopBlocks[0] &&
         "Preheader splitting did not work correctly!");
  // Remove the unconditional branch to LoopBlocks[0].
  OrigPreheader->getInstList().pop_back();

  // Insert a conditional branch on LIC to the two preheaders.  The original
  // code is the true version and the new code is the false version.
  new BranchInst(LoopBlocks[0], NewBlocks[0], LIC, OrigPreheader);

  // Now we rewrite the original code to know that the condition is true and the
  // new code to know that the condition is false.
  RewriteLoopBodyWithConditionConstant(L, LIC, true);
  RewriteLoopBodyWithConditionConstant(NewLoop, LIC, false);
  ++NumUnswitched;

  // Try to unswitch each of our new loops now!
  visitLoop(L);
  visitLoop(NewLoop);
}

// RewriteLoopBodyWithConditionConstant - We know that the boolean value LIC has
// the value specified by Val in the specified loop.  Rewrite any uses of LIC or
// of properties correlated to it.
void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
                                                        bool Val) {
  // FIXME: Support correlated properties, like:
  //  for (...)
  //    if (li1 < li2)
  //      ...
  //    if (li1 > li2)
  //      ...
  ConstantBool *BoolVal = ConstantBool::get(Val);

  std::vector<User*> Users(LIC->use_begin(), LIC->use_end());
  for (unsigned i = 0, e = Users.size(); i != e; ++i)
    if (Instruction *U = dyn_cast<Instruction>(Users[i]))
      if (L->contains(U->getParent()))
        U->replaceUsesOfWith(LIC, BoolVal);
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkTetra.hh
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
// .NAME vtkTetra - a 3D cell that represents a tetrahedron
// .SECTION Description
// vtkTetra is a concrete implementation of vtkCell to represent a 3D
// tetrahedron.

#ifndef __vtkTetra_h
#define __vtkTetra_h

#include "vtkCell.hh"

class vtkTetra : public vtkCell
{
public:
  vtkTetra() {};
  vtkTetra(const vtkTetra& t);
  char *GetClassName() {return "vtkTetra";};

  // cell methods
  vtkCell *MakeObject() {return new vtkTetra(*this);};
  int GetCellType() {return VTK_TETRA;};
  int GetCellDimension() {return 3;};
  int GetNumberOfEdges() {return 6;};
  int GetNumberOfFaces() {return 4;};
  vtkCell *GetEdge(int edgeId);
  vtkCell *GetFace(int faceId);

  int CellBoundary(int subId, float pcoords[3], vtkIdList& pts);
  void Contour(float value, vtkFloatScalars *cellScalars,
               vtkFloatPoints *points, vtkCellArray *verts,
               vtkCellArray *lines, vtkCellArray *polys, vtkFloatScalars *s);
  int EvaluatePosition(float x[3], float closestPoint[3],
                       int& subId, float pcoords[3],
                       float& dist2, float *weights);
  void EvaluateLocation(int& subId, float pcoords[3], float x[3],
                        float *weights);
  int IntersectWithLine(float p1[3], float p2[3], float tol, float& t,
                        float x[3], float pcoords[3], int& subId);
  int Triangulate(int index, vtkFloatPoints &pts);
  void Derivatives(int subId, float pcoords[3], float *values,
                   int dim, float *derivs);

  // tetrahedron specific
  void TetraCenter(float p1[3], float p2[3], float p3[3], float p4[3], float center[3]);
  float Circumsphere(float  p1[3], float p2[3], float p3[3], float p4[3], float center[3]);
  int BarycentricCoords(float x[3], float  x1[3], float x2[3], float x3[3],
                        float x4[3], float bcoords[4]);

};

#endif

<commit_msg>ENH: Added derivative calculation.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkTetra.hh
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
// .NAME vtkTetra - a 3D cell that represents a tetrahedron
// .SECTION Description
// vtkTetra is a concrete implementation of vtkCell to represent a 3D
// tetrahedron.

#ifndef __vtkTetra_h
#define __vtkTetra_h

#include "vtkCell.hh"

class vtkTetra : public vtkCell
{
public:
  vtkTetra() {};
  vtkTetra(const vtkTetra& t);
  char *GetClassName() {return "vtkTetra";};

  // cell methods
  vtkCell *MakeObject() {return new vtkTetra(*this);};
  int GetCellType() {return VTK_TETRA;};
  int GetCellDimension() {return 3;};
  int GetNumberOfEdges() {return 6;};
  int GetNumberOfFaces() {return 4;};
  vtkCell *GetEdge(int edgeId);
  vtkCell *GetFace(int faceId);

  int CellBoundary(int subId, float pcoords[3], vtkIdList& pts);
  void Contour(float value, vtkFloatScalars *cellScalars,
               vtkFloatPoints *points, vtkCellArray *verts,
               vtkCellArray *lines, vtkCellArray *polys, vtkFloatScalars *s);
  int EvaluatePosition(float x[3], float closestPoint[3],
                       int& subId, float pcoords[3],
                       float& dist2, float *weights);
  void EvaluateLocation(int& subId, float pcoords[3], float x[3],
                        float *weights);
  int IntersectWithLine(float p1[3], float p2[3], float tol, float& t,
                        float x[3], float pcoords[3], int& subId);
  int Triangulate(int index, vtkFloatPoints &pts);
  void Derivatives(int subId, float pcoords[3], float *values,
                   int dim, float *derivs);

  // tetrahedron specific
  void TetraCenter(float p1[3], float p2[3], float p3[3], float p4[3], float center[3]);
  float Circumsphere(float  p1[3], float p2[3], float p3[3], float p4[3], float center[3]);
  int BarycentricCoords(float x[3], float  x1[3], float x2[3], float x3[3],
                        float x4[3], float bcoords[4]);

  void InterpolationFunctions(float pcoords[3], float weights[4]);
  void InterpolationDerivs(float derivs[12]);
  void JacobianInverse(double **inverse, float derivs[12]);

};

#endif

<|endoftext|>


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

#include <precomp.h>
#include "hfi_module.hxx"

// NOT FULLY DEFINED SERVICES
#include <ary/idl/i_ce.hxx>
#include <ary/idl/i_module.hxx>
#include <ary/idl/ik_module.hxx>
#include <ary_i/codeinf2.hxx>
#include <toolkit/hf_docentry.hxx>
#include <toolkit/hf_linachain.hxx>
#include <toolkit/hf_navi_sub.hxx>
#include <toolkit/hf_title.hxx>
#include "hfi_doc.hxx"
#include "hfi_navibar.hxx"
#include "hfi_tag.hxx"
#include "hfi_typetext.hxx"
#include "hi_linkhelper.hxx"

extern const String
    C_sCePrefix_Module("module");

namespace
{

const String
    C_sList_NestedModules("Nested Modules");
const String
    C_sList_NestedModules_Label("NestedModules");
const String
    C_sList_Services("Services");
const String
    C_sList_Singletons("Singletons");
const String
    C_sList_Interfaces("Interfaces");
const String
    C_sList_Structs("Structs");
const String
    C_sList_Exceptions("Exceptions");
const String
    C_sList_Enums("Enums");
const String
    C_sList_Typedefs("Typedefs");
const String
    C_sList_ConstGroups("Constant Groups");
const String
    C_sList_ConstGroups_Label("ConstantGroups");

enum E_SubListIndices
{   // In case of changes, also adapt make_Navibar() !!
    sli_NestedModules = 0,
    sli_Services = 1,
    sli_Singletons = 2,
    sli_Interfaces = 3,
    sli_Structs = 4,
    sli_Exceptions = 5,
    sli_Enums = 6,
    sli_Typedefs = 7,
    sli_ConstGroups = 8
};

} //anonymous namespace

HF_IdlModule::HF_IdlModule( Environment &         io_rEnv,
                            Xml::Element &        o_rOut )
    :   HtmlFactory_Idl(io_rEnv, &o_rOut)
{
}

HF_IdlModule::~HF_IdlModule()
{
}

typedef ary::idl::ifc_module::attr  ModuleAttr;

void
HF_IdlModule::Produce_byData( const client & i_ce ) const
{
    Dyn<HF_NaviSubRow>
        pNaviSubRow( &make_Navibar(i_ce) );

    HF_TitleTable
        aTitle(CurOut());
    HF_LinkedNameChain
        aNameChain(aTitle.Add_Row());

    if ( Env().CurPosition().Depth() > 0 )
    {
        aNameChain.Produce_CompleteChain_forModule(Env().CurPosition(), nameChainLinker);

        StreamLock
            sl(200);
        aTitle.Produce_Title( sl()
                                << C_sCePrefix_Module
                                  << " "
                                << i_ce.LocalName()
                                << c_str );
    }
    else
    {
        aTitle.Produce_Title( "Global Module" );
    }

    write_Docu(aTitle.Add_Row(), i_ce);
    CurOut() << new Html::HorizontalLine();

    // Write children lists:
    ce_ptr_list aNestedModules;
    ce_ptr_list aServices;
    ce_ptr_list aInterfaces;
    ce_ptr_list aStructs;
    ce_ptr_list aExceptions;
    ce_ptr_list aEnums;
    ce_ptr_list aTypedefs;
    ce_ptr_list aConstantGroups;
    ce_ptr_list aSingletons;

    ModuleAttr::Get_AllChildrenSeparated(
                                aNestedModules,
                                aServices,
                                aInterfaces,
                                aStructs,
                                aExceptions,
                                aEnums,
                                aTypedefs,
                                aConstantGroups,
                                aSingletons,
                                Env().Data().Ces(),
                                i_ce );

    // Has this to be in the order of enum E_SubListIndices ???
    if (produce_ChildList(C_sList_NestedModules, C_sList_NestedModules_Label, aNestedModules ))
        pNaviSubRow->SwitchOn(sli_NestedModules);
    if (produce_ChildList(C_sList_Services, C_sList_Services, aServices))
        pNaviSubRow->SwitchOn(sli_Services);
    if (produce_ChildList(C_sList_Singletons, C_sList_Singletons, aSingletons))
        pNaviSubRow->SwitchOn(sli_Singletons);
    if (produce_ChildList(C_sList_Interfaces, C_sList_Interfaces, aInterfaces))
        pNaviSubRow->SwitchOn(sli_Interfaces);
    if (produce_ChildList(C_sList_Structs, C_sList_Structs, aStructs))
        pNaviSubRow->SwitchOn(sli_Structs);
    if (produce_ChildList(C_sList_Exceptions, C_sList_Exceptions, aExceptions))
        pNaviSubRow->SwitchOn(sli_Exceptions);
    if (produce_ChildList(C_sList_Enums, C_sList_Enums, aEnums))
        pNaviSubRow->SwitchOn(sli_Enums);
    if (produce_ChildList(C_sList_Typedefs, C_sList_Typedefs, aTypedefs))
        pNaviSubRow->SwitchOn(sli_Typedefs);
    if (produce_ChildList(C_sList_ConstGroups, C_sList_ConstGroups_Label, aConstantGroups))
        pNaviSubRow->SwitchOn(sli_ConstGroups);
    pNaviSubRow->Produce_Row();
}

DYN HF_NaviSubRow &
HF_IdlModule::make_Navibar( const client & i_ce ) const
{
    HF_IdlNavigationBar
        aNaviBar(Env(), CurOut());
    aNaviBar.Produce_ModuleMainRow(i_ce);

    DYN HF_NaviSubRow &
        ret = aNaviBar.Add_SubRow();

    // Has to be in the order of E_SubListIndices:
    ret.AddItem(C_sList_NestedModules, C_sList_NestedModules_Label, false);
    ret.AddItem(C_sList_Services, C_sList_Services, false);
    ret.AddItem(C_sList_Singletons, C_sList_Singletons, false);
    ret.AddItem(C_sList_Interfaces, C_sList_Interfaces, false);
    ret.AddItem(C_sList_Structs, C_sList_Structs, false);
    ret.AddItem(C_sList_Exceptions, C_sList_Exceptions, false);
    ret.AddItem(C_sList_Enums, C_sList_Enums, false);
    ret.AddItem(C_sList_Typedefs, C_sList_Typedefs, false);
    ret.AddItem(C_sList_ConstGroups, C_sList_ConstGroups_Label, false);

    CurOut() << new Html::HorizontalLine();
    return ret;
}

bool
HF_IdlModule::produce_ChildList( const String &      i_sName,
                                 const String &      i_sLabel,
                                 const ce_ptr_list & i_list ) const
{
    if ( i_list.size() == 0 )
        return false;

    HF_SubTitleTable
        aTable( CurOut(),
                i_sLabel,
                i_sName,
                2 );

    ce_ptr_list::const_iterator
        itEnd = i_list.end();
    for ( ce_ptr_list::const_iterator it = i_list.begin();
          it != itEnd;
          ++it )
    {
        Xml::Element &
            rRow = aTable.Add_Row();
        produce_Link(rRow, *it);
        produce_LinkDoc(rRow, *it);
    }   // end for

    return true;
}

void
HF_IdlModule::produce_Link( Xml::Element &      o_row,
                            const client *      i_ce ) const
{
    csv_assert(i_ce != 0);
    Xml::Element &
        rCell = o_row
                >> *new Html::TableCell
                    << new Html::ClassAttr(C_sCellStyle_SummaryLeft);

    if (i_ce->ClassId() != ary::idl::Module::class_id)
    {
        HF_IdlTypeText
            aText(Env(), rCell, true);
        aText.Produce_byData(i_ce->CeId());
    }
    else
    {
        StreamLock slBuf(100);
         rCell
            >> *new Html::Link( slBuf() << i_ce->LocalName()
                                        << "/module-ix.html"
                                        << c_str )
                << i_ce->LocalName();
    }
}

void
HF_IdlModule::produce_LinkDoc( Xml::Element &      o_row,
                               const client *      i_ce ) const
{
    csv_assert(i_ce != 0);

    // We need the cell in any case, because, the rendering may be hurt else.
    Xml::Element &
        rCell = o_row
                    >> *new Html::TableCell
                        << new Html::ClassAttr(C_sCellStyle_SummaryRight);

    const client &
        rCe = *i_ce;
    const ce_info *
        pShort = rCe.Docu();
    if ( pShort == 0 )
        return;

    if (pShort->IsDeprecated())
    {
        rCell << "[ DEPRECATED ]" << new Html::LineBreak;
    }
    if (pShort->IsOptional())
    {
        rCell << "[ OPTIONAL ]" << new Html::LineBreak;
    }

    HF_IdlDocuTextDisplay
        aShortDisplay(Env(), &rCell, *i_ce);
    pShort->Short().DisplayAt(aShortDisplay);
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.4.6); FILE MERGED 2006/09/01 17:15:34 kaib 1.4.6.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: hfi_module.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 16:47:16 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_autodoc.hxx"

#include <precomp.h>
#include "hfi_module.hxx"

// NOT FULLY DEFINED SERVICES
#include <ary/idl/i_ce.hxx>
#include <ary/idl/i_module.hxx>
#include <ary/idl/ik_module.hxx>
#include <ary_i/codeinf2.hxx>
#include <toolkit/hf_docentry.hxx>
#include <toolkit/hf_linachain.hxx>
#include <toolkit/hf_navi_sub.hxx>
#include <toolkit/hf_title.hxx>
#include "hfi_doc.hxx"
#include "hfi_navibar.hxx"
#include "hfi_tag.hxx"
#include "hfi_typetext.hxx"
#include "hi_linkhelper.hxx"

extern const String
    C_sCePrefix_Module("module");

namespace
{

const String
    C_sList_NestedModules("Nested Modules");
const String
    C_sList_NestedModules_Label("NestedModules");
const String
    C_sList_Services("Services");
const String
    C_sList_Singletons("Singletons");
const String
    C_sList_Interfaces("Interfaces");
const String
    C_sList_Structs("Structs");
const String
    C_sList_Exceptions("Exceptions");
const String
    C_sList_Enums("Enums");
const String
    C_sList_Typedefs("Typedefs");
const String
    C_sList_ConstGroups("Constant Groups");
const String
    C_sList_ConstGroups_Label("ConstantGroups");

enum E_SubListIndices
{   // In case of changes, also adapt make_Navibar() !!
    sli_NestedModules = 0,
    sli_Services = 1,
    sli_Singletons = 2,
    sli_Interfaces = 3,
    sli_Structs = 4,
    sli_Exceptions = 5,
    sli_Enums = 6,
    sli_Typedefs = 7,
    sli_ConstGroups = 8
};

} //anonymous namespace

HF_IdlModule::HF_IdlModule( Environment &         io_rEnv,
                            Xml::Element &        o_rOut )
    :   HtmlFactory_Idl(io_rEnv, &o_rOut)
{
}

HF_IdlModule::~HF_IdlModule()
{
}

typedef ary::idl::ifc_module::attr  ModuleAttr;

void
HF_IdlModule::Produce_byData( const client & i_ce ) const
{
    Dyn<HF_NaviSubRow>
        pNaviSubRow( &make_Navibar(i_ce) );

    HF_TitleTable
        aTitle(CurOut());
    HF_LinkedNameChain
        aNameChain(aTitle.Add_Row());

    if ( Env().CurPosition().Depth() > 0 )
    {
        aNameChain.Produce_CompleteChain_forModule(Env().CurPosition(), nameChainLinker);

        StreamLock
            sl(200);
        aTitle.Produce_Title( sl()
                                << C_sCePrefix_Module
                                  << " "
                                << i_ce.LocalName()
                                << c_str );
    }
    else
    {
        aTitle.Produce_Title( "Global Module" );
    }

    write_Docu(aTitle.Add_Row(), i_ce);
    CurOut() << new Html::HorizontalLine();

    // Write children lists:
    ce_ptr_list aNestedModules;
    ce_ptr_list aServices;
    ce_ptr_list aInterfaces;
    ce_ptr_list aStructs;
    ce_ptr_list aExceptions;
    ce_ptr_list aEnums;
    ce_ptr_list aTypedefs;
    ce_ptr_list aConstantGroups;
    ce_ptr_list aSingletons;

    ModuleAttr::Get_AllChildrenSeparated(
                                aNestedModules,
                                aServices,
                                aInterfaces,
                                aStructs,
                                aExceptions,
                                aEnums,
                                aTypedefs,
                                aConstantGroups,
                                aSingletons,
                                Env().Data().Ces(),
                                i_ce );

    // Has this to be in the order of enum E_SubListIndices ???
    if (produce_ChildList(C_sList_NestedModules, C_sList_NestedModules_Label, aNestedModules ))
        pNaviSubRow->SwitchOn(sli_NestedModules);
    if (produce_ChildList(C_sList_Services, C_sList_Services, aServices))
        pNaviSubRow->SwitchOn(sli_Services);
    if (produce_ChildList(C_sList_Singletons, C_sList_Singletons, aSingletons))
        pNaviSubRow->SwitchOn(sli_Singletons);
    if (produce_ChildList(C_sList_Interfaces, C_sList_Interfaces, aInterfaces))
        pNaviSubRow->SwitchOn(sli_Interfaces);
    if (produce_ChildList(C_sList_Structs, C_sList_Structs, aStructs))
        pNaviSubRow->SwitchOn(sli_Structs);
    if (produce_ChildList(C_sList_Exceptions, C_sList_Exceptions, aExceptions))
        pNaviSubRow->SwitchOn(sli_Exceptions);
    if (produce_ChildList(C_sList_Enums, C_sList_Enums, aEnums))
        pNaviSubRow->SwitchOn(sli_Enums);
    if (produce_ChildList(C_sList_Typedefs, C_sList_Typedefs, aTypedefs))
        pNaviSubRow->SwitchOn(sli_Typedefs);
    if (produce_ChildList(C_sList_ConstGroups, C_sList_ConstGroups_Label, aConstantGroups))
        pNaviSubRow->SwitchOn(sli_ConstGroups);
    pNaviSubRow->Produce_Row();
}

DYN HF_NaviSubRow &
HF_IdlModule::make_Navibar( const client & i_ce ) const
{
    HF_IdlNavigationBar
        aNaviBar(Env(), CurOut());
    aNaviBar.Produce_ModuleMainRow(i_ce);

    DYN HF_NaviSubRow &
        ret = aNaviBar.Add_SubRow();

    // Has to be in the order of E_SubListIndices:
    ret.AddItem(C_sList_NestedModules, C_sList_NestedModules_Label, false);
    ret.AddItem(C_sList_Services, C_sList_Services, false);
    ret.AddItem(C_sList_Singletons, C_sList_Singletons, false);
    ret.AddItem(C_sList_Interfaces, C_sList_Interfaces, false);
    ret.AddItem(C_sList_Structs, C_sList_Structs, false);
    ret.AddItem(C_sList_Exceptions, C_sList_Exceptions, false);
    ret.AddItem(C_sList_Enums, C_sList_Enums, false);
    ret.AddItem(C_sList_Typedefs, C_sList_Typedefs, false);
    ret.AddItem(C_sList_ConstGroups, C_sList_ConstGroups_Label, false);

    CurOut() << new Html::HorizontalLine();
    return ret;
}

bool
HF_IdlModule::produce_ChildList( const String &      i_sName,
                                 const String &      i_sLabel,
                                 const ce_ptr_list & i_list ) const
{
    if ( i_list.size() == 0 )
        return false;

    HF_SubTitleTable
        aTable( CurOut(),
                i_sLabel,
                i_sName,
                2 );

    ce_ptr_list::const_iterator
        itEnd = i_list.end();
    for ( ce_ptr_list::const_iterator it = i_list.begin();
          it != itEnd;
          ++it )
    {
        Xml::Element &
            rRow = aTable.Add_Row();
        produce_Link(rRow, *it);
        produce_LinkDoc(rRow, *it);
    }   // end for

    return true;
}

void
HF_IdlModule::produce_Link( Xml::Element &      o_row,
                            const client *      i_ce ) const
{
    csv_assert(i_ce != 0);
    Xml::Element &
        rCell = o_row
                >> *new Html::TableCell
                    << new Html::ClassAttr(C_sCellStyle_SummaryLeft);

    if (i_ce->ClassId() != ary::idl::Module::class_id)
    {
        HF_IdlTypeText
            aText(Env(), rCell, true);
        aText.Produce_byData(i_ce->CeId());
    }
    else
    {
        StreamLock slBuf(100);
         rCell
            >> *new Html::Link( slBuf() << i_ce->LocalName()
                                        << "/module-ix.html"
                                        << c_str )
                << i_ce->LocalName();
    }
}

void
HF_IdlModule::produce_LinkDoc( Xml::Element &      o_row,
                               const client *      i_ce ) const
{
    csv_assert(i_ce != 0);

    // We need the cell in any case, because, the rendering may be hurt else.
    Xml::Element &
        rCell = o_row
                    >> *new Html::TableCell
                        << new Html::ClassAttr(C_sCellStyle_SummaryRight);

    const client &
        rCe = *i_ce;
    const ce_info *
        pShort = rCe.Docu();
    if ( pShort == 0 )
        return;

    if (pShort->IsDeprecated())
    {
        rCell << "[ DEPRECATED ]" << new Html::LineBreak;
    }
    if (pShort->IsOptional())
    {
        rCell << "[ OPTIONAL ]" << new Html::LineBreak;
    }

    HF_IdlDocuTextDisplay
        aShortDisplay(Env(), &rCell, *i_ce);
    pShort->Short().DisplayAt(aShortDisplay);
}
<|endoftext|>


<commit_before>//===- Main.cpp - Top-Level TableGen implementation -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// TableGen is a tool which can be used to build up a description of something,
// then invoke one or more "tablegen backends" to emit information about the
// description in some predefined format.  In practice, this is used by the LLVM
// code generators to automate generation of a code generator through a
// high-level description of the target.
//
//===----------------------------------------------------------------------===//

#include "llvm/TableGen/Main.h"
#include "TGParser.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include <algorithm>
#include <cstdio>
#include <system_error>
using namespace llvm;

static cl::opt<std::string>
OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
               cl::init("-"));

static cl::opt<std::string>
DependFilename("d",
               cl::desc("Dependency filename"),
               cl::value_desc("filename"),
               cl::init(""));

static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));

static cl::list<std::string>
IncludeDirs("I", cl::desc("Directory of include files"),
            cl::value_desc("directory"), cl::Prefix);

static cl::list<std::string>
MacroNames("D", cl::desc("Name of the macro to be defined"),
            cl::value_desc("macro name"), cl::Prefix);

static int reportError(const char *ProgName, Twine Msg) {
  errs() << ProgName << ": " << Msg;
  errs().flush();
  return 1;
}

/// Create a dependency file for `-d` option.
///
/// This functionality is really only for the benefit of the build system.
/// It is similar to GCC's `-M*` family of options.
static int createDependencyFile(const TGParser &Parser, const char *argv0) {
  if (OutputFilename == "-")
    return reportError(argv0, "the option -d must be used together with -o\n");

  std::error_code EC;
  ToolOutputFile DepOut(DependFilename, EC, sys::fs::OF_Text);
  if (EC)
    return reportError(argv0, "error opening " + DependFilename + ":" +
                                  EC.message() + "\n");
  DepOut.os() << OutputFilename << ":";
  for (const auto &Dep : Parser.getDependencies()) {
    DepOut.os() << ' ' << Dep.first;
  }
  DepOut.os() << "\n";
  DepOut.keep();
  return 0;
}

int llvm::TableGenMain(char *argv0, TableGenMainFn *MainFn) {
  RecordKeeper Records;

  // Parse the input file.
  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
      MemoryBuffer::getFileOrSTDIN(InputFilename);
  if (std::error_code EC = FileOrErr.getError())
    return reportError(argv0, "Could not open input file '" + InputFilename +
                                  "': " + EC.message() + "\n");

  // Tell SrcMgr about this buffer, which is what TGParser will pick up.
  SrcMgr.AddNewSourceBuffer(std::move(*FileOrErr), SMLoc());

  // Record the location of the include directory so that the lexer can find
  // it later.
  SrcMgr.setIncludeDirs(IncludeDirs);

  TGParser Parser(SrcMgr, MacroNames, Records);

  if (Parser.ParseFile())
    return 1;

  // Write output to memory.
  std::string OutString;
  raw_string_ostream Out(OutString);
  if (MainFn(Out, Records))
    return 1;

  // Always write the depfile, even if the main output hasn't changed.
  // If it's missing, Ninja considers the output dirty.  If this was below
  // the early exit below and someone deleted the .inc.d file but not the .inc
  // file, tablegen would never write the depfile.
  if (!DependFilename.empty()) {
    if (int Ret = createDependencyFile(Parser, argv0))
      return Ret;
  }

  // Only updates the real output file if there are any differences.
  // This prevents recompilation of all the files depending on it if there
  // aren't any.
  if (auto ExistingOrErr = MemoryBuffer::getFile(OutputFilename))
    if (std::move(ExistingOrErr.get())->getBuffer() == Out.str())
      return 0;

  std::error_code EC;
  ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_Text);
  if (EC)
    return reportError(argv0, "error opening " + OutputFilename + ":" +
                                  EC.message() + "\n");
  OutFile.os() << Out.str();

  if (ErrorsPrinted > 0)
    return reportError(argv0, Twine(ErrorsPrinted) + " errors.\n");

  // Declare success.
  OutFile.keep();
  return 0;
}
<commit_msg>[TableGen] Skip CRLF conversion when writing output<commit_after>//===- Main.cpp - Top-Level TableGen implementation -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// TableGen is a tool which can be used to build up a description of something,
// then invoke one or more "tablegen backends" to emit information about the
// description in some predefined format.  In practice, this is used by the LLVM
// code generators to automate generation of a code generator through a
// high-level description of the target.
//
//===----------------------------------------------------------------------===//

#include "llvm/TableGen/Main.h"
#include "TGParser.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include <algorithm>
#include <cstdio>
#include <system_error>
using namespace llvm;

static cl::opt<std::string>
OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
               cl::init("-"));

static cl::opt<std::string>
DependFilename("d",
               cl::desc("Dependency filename"),
               cl::value_desc("filename"),
               cl::init(""));

static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));

static cl::list<std::string>
IncludeDirs("I", cl::desc("Directory of include files"),
            cl::value_desc("directory"), cl::Prefix);

static cl::list<std::string>
MacroNames("D", cl::desc("Name of the macro to be defined"),
            cl::value_desc("macro name"), cl::Prefix);

static int reportError(const char *ProgName, Twine Msg) {
  errs() << ProgName << ": " << Msg;
  errs().flush();
  return 1;
}

/// Create a dependency file for `-d` option.
///
/// This functionality is really only for the benefit of the build system.
/// It is similar to GCC's `-M*` family of options.
static int createDependencyFile(const TGParser &Parser, const char *argv0) {
  if (OutputFilename == "-")
    return reportError(argv0, "the option -d must be used together with -o\n");

  std::error_code EC;
  ToolOutputFile DepOut(DependFilename, EC, sys::fs::OF_None);
  if (EC)
    return reportError(argv0, "error opening " + DependFilename + ":" +
                                  EC.message() + "\n");
  DepOut.os() << OutputFilename << ":";
  for (const auto &Dep : Parser.getDependencies()) {
    DepOut.os() << ' ' << Dep.first;
  }
  DepOut.os() << "\n";
  DepOut.keep();
  return 0;
}

int llvm::TableGenMain(char *argv0, TableGenMainFn *MainFn) {
  RecordKeeper Records;

  // Parse the input file.
  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
      MemoryBuffer::getFileOrSTDIN(InputFilename);
  if (std::error_code EC = FileOrErr.getError())
    return reportError(argv0, "Could not open input file '" + InputFilename +
                                  "': " + EC.message() + "\n");

  // Tell SrcMgr about this buffer, which is what TGParser will pick up.
  SrcMgr.AddNewSourceBuffer(std::move(*FileOrErr), SMLoc());

  // Record the location of the include directory so that the lexer can find
  // it later.
  SrcMgr.setIncludeDirs(IncludeDirs);

  TGParser Parser(SrcMgr, MacroNames, Records);

  if (Parser.ParseFile())
    return 1;

  // Write output to memory.
  std::string OutString;
  raw_string_ostream Out(OutString);
  if (MainFn(Out, Records))
    return 1;

  // Always write the depfile, even if the main output hasn't changed.
  // If it's missing, Ninja considers the output dirty.  If this was below
  // the early exit below and someone deleted the .inc.d file but not the .inc
  // file, tablegen would never write the depfile.
  if (!DependFilename.empty()) {
    if (int Ret = createDependencyFile(Parser, argv0))
      return Ret;
  }

  // Only updates the real output file if there are any differences.
  // This prevents recompilation of all the files depending on it if there
  // aren't any.
  if (auto ExistingOrErr = MemoryBuffer::getFile(OutputFilename))
    if (std::move(ExistingOrErr.get())->getBuffer() == Out.str())
      return 0;

  std::error_code EC;
  ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_None);
  if (EC)
    return reportError(argv0, "error opening " + OutputFilename + ":" +
                                  EC.message() + "\n");
  OutFile.os() << Out.str();

  if (ErrorsPrinted > 0)
    return reportError(argv0, Twine(ErrorsPrinted) + " errors.\n");

  // Declare success.
  OutFile.keep();
  return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/common/native_mate_converters/net_converter.h"

#include <string>

#include "atom/common/node_includes.h"
#include "native_mate/dictionary.h"
#include "net/cert/x509_certificate.h"
#include "net/url_request/url_request.h"

namespace mate {

// static
v8::Local<v8::Value> Converter<const net::URLRequest*>::ToV8(
    v8::Isolate* isolate, const net::URLRequest* val) {
  mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
  dict.Set("method", val->method());
  dict.Set("url", val->url().spec());
  dict.Set("referrer", val->referrer());
  return mate::ConvertToV8(isolate, dict);
}

// static
v8::Local<v8::Value> Converter<const net::AuthChallengeInfo*>::ToV8(
    v8::Isolate* isolate, const net::AuthChallengeInfo* val) {
  mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
  dict.Set("isProxy", val->is_proxy);
  dict.Set("scheme", val->scheme);
  dict.Set("host", val->challenger.host());
  dict.Set("port", static_cast<uint32_t>(val->challenger.port()));
  dict.Set("realm", val->realm);
  return mate::ConvertToV8(isolate, dict);
}

// static
v8::Local<v8::Value> Converter<scoped_refptr<net::X509Certificate>>::ToV8(
    v8::Isolate* isolate, const scoped_refptr<net::X509Certificate>& val) {
  mate::Dictionary dict(isolate, v8::Object::New(isolate));
  std::string encoded_data;
  net::X509Certificate::GetPEMEncoded(
      val->os_cert_handle(), &encoded_data);
  auto buffer = node::Buffer::Copy(isolate,
                                   encoded_data.data(),
                                   encoded_data.size()).ToLocalChecked();
  dict.Set("data", buffer);
  dict.Set("issuerName", val->issuer().GetDisplayName());
  return dict.GetHandle();
}

}  // namespace mate
<commit_msg>protocol: provide upload data when available<commit_after>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/common/native_mate_converters/net_converter.h"

#include <string>
#include <vector>

#include "atom/common/node_includes.h"
#include "native_mate/dictionary.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/base/upload_element_reader.h"
#include "net/base/upload_file_element_reader.h"
#include "net/cert/x509_certificate.h"
#include "net/url_request/url_request.h"

namespace mate {

// static
v8::Local<v8::Value> Converter<const net::URLRequest*>::ToV8(
    v8::Isolate* isolate, const net::URLRequest* val) {
  mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
  dict.Set("method", val->method());
  dict.Set("url", val->url().spec());
  dict.Set("referrer", val->referrer());
  const net::UploadDataStream* upload_data = val->get_upload();
  if (upload_data) {
    const ScopedVector<net::UploadElementReader>* readers =
        upload_data->GetElementReaders();
    std::vector<mate::Dictionary> upload_data_list;
    upload_data_list.reserve(readers->size());
    for (const auto& reader : *readers) {
      auto upload_data_dict = mate::Dictionary::CreateEmpty(isolate);
      if (reader->AsBytesReader()) {
        const net::UploadBytesElementReader* bytes_reader =
            reader->AsBytesReader();
        auto bytes =
            node::Buffer::Copy(isolate, bytes_reader->bytes(),
                               bytes_reader->length()).ToLocalChecked();
        upload_data_dict.Set("bytes", bytes);
      } else if (reader->AsFileReader()) {
        const net::UploadFileElementReader* file_reader =
            reader->AsFileReader();
        upload_data_dict.Set("file", file_reader->path().AsUTF8Unsafe());
      }
      upload_data_list.push_back(upload_data_dict);
    }
    dict.Set("uploadData", upload_data_list);
  }
  return mate::ConvertToV8(isolate, dict);
}

// static
v8::Local<v8::Value> Converter<const net::AuthChallengeInfo*>::ToV8(
    v8::Isolate* isolate, const net::AuthChallengeInfo* val) {
  mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
  dict.Set("isProxy", val->is_proxy);
  dict.Set("scheme", val->scheme);
  dict.Set("host", val->challenger.host());
  dict.Set("port", static_cast<uint32_t>(val->challenger.port()));
  dict.Set("realm", val->realm);
  return mate::ConvertToV8(isolate, dict);
}

// static
v8::Local<v8::Value> Converter<scoped_refptr<net::X509Certificate>>::ToV8(
    v8::Isolate* isolate, const scoped_refptr<net::X509Certificate>& val) {
  mate::Dictionary dict(isolate, v8::Object::New(isolate));
  std::string encoded_data;
  net::X509Certificate::GetPEMEncoded(
      val->os_cert_handle(), &encoded_data);
  auto buffer = node::Buffer::Copy(isolate,
                                   encoded_data.data(),
                                   encoded_data.size()).ToLocalChecked();
  dict.Set("data", buffer);
  dict.Set("issuerName", val->issuer().GetDisplayName());
  return dict.GetHandle();
}

}  // namespace mate
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mthemedaemonprotocol.h"
#include <QHash>
#include <QtEndian>

using namespace M::MThemeDaemonProtocol;

const QString M::MThemeDaemonProtocol::ServerAddress = "m.mthemedaemon";
static const int SOCKET_DELAY_MS = 15000;

PacketData::~PacketData()
{}

PixmapIdentifier::~PixmapIdentifier()
{}

Number::~Number()
{}

String::~String()
{}

StringBool::~StringBool()
{}

PixmapHandle::~PixmapHandle()
{}

ClientList::~ClientList()
{}

ThemeChangeInfo::~ThemeChangeInfo()
{}

MostUsedPixmaps::~MostUsedPixmaps()
{}

RequestedPixmap::~RequestedPixmap()
{}

Packet::Packet(PacketType type, quint64 seq, PacketData *data)
:
    m_seq  (seq),
    m_data (data),
    m_type (type)
{}

Packet::~Packet()
{}

void Packet::setData(PacketData *data)
{
    m_data = QSharedPointer<PacketData>(data);
}

QDataStream &operator<<(QDataStream &stream, const Packet &packet)
{
    Q_ASSERT(packet.type() != Packet::Unknown);

    QByteArray serializedPackageData;
    QDataStream serializedPackageDataStream(&serializedPackageData, QIODevice::WriteOnly);
    writePacketData(serializedPackageDataStream, packet);
    stream.writeBytes(serializedPackageData.constData(), serializedPackageData.length());

    return stream;
}

void writePacketData(QDataStream &stream, const M::MThemeDaemonProtocol::Packet &packet)
{
    stream << quint32(packet.type());
    stream << packet.sequenceNumber();

    switch (packet.type()) {
    // NULL as data
    case Packet::RequestClearPixmapDirectoriesPacket:
    case Packet::QueryThemeDaemonStatusPacket:
        break;

    // string as data
    case Packet::ErrorPacket:
    case Packet::RequestRegistrationPacket: {
        stream << static_cast<const String *>(packet.data())->string;
    } break;

    // two string lists as data
    case Packet::ThemeChangedPacket: {
        const ThemeChangeInfo* info = static_cast<const ThemeChangeInfo*>(packet.data());
        stream << info->themeInheritance << info->themeLibraryNames;
    } break;

    case Packet::ProtocolVersionPacket:
    case Packet::ThemeChangeAppliedPacket: {
        stream << static_cast<const Number *>(packet.data())->value;
    } break;

    // stringbool as data
    case Packet::RequestNewPixmapDirectoryPacket: {
        const StringBool *sb = static_cast<const StringBool *>(packet.data());
        stream << sb->string << sb->b;
    } break;

    // pixmap identifier as data
    case Packet::PixmapUsedPacket:
    case Packet::ReleasePixmapPacket: {
        const PixmapIdentifier *id = static_cast<const PixmapIdentifier *>(packet.data());
        stream << *id;
    } break;

    case Packet::RequestPixmapPacket: {
        const RequestedPixmap *pixmap = static_cast<const RequestedPixmap *>(packet.data());
        stream << pixmap->priority;
        stream << pixmap->id;
    } break;

    // pixmap handle as data
    case Packet::PixmapUpdatedPacket: {
        const PixmapHandle *h = static_cast<const PixmapHandle *>(packet.data());
        stream << *h;
    } break;

    case Packet::MostUsedPixmapsPacket: {
        const MostUsedPixmaps *mostUsedPixmaps = static_cast<const MostUsedPixmaps *>(packet.data());

        stream << mostUsedPixmaps->addedHandles;
        stream << mostUsedPixmaps->removedIdentifiers;
    } break;

    // client list as data
    case Packet::ThemeDaemonStatusPacket: {
        const ClientList *cl = static_cast<const ClientList *>(packet.data());
        quint32 clientCount = cl->clients.count();
        stream << clientCount;
        for (uint i = 0; i < clientCount; ++i)
        {
            const ClientInfo &info = cl->clients.at(i);
            stream << info.name;
            quint32 pixmapCount = info.pixmaps.count();
            stream << pixmapCount;
            for (quint32 j = 0; j < pixmapCount; ++j) {
                stream << info.pixmaps.at(j);
            }
            quint32 requestedPixmapCount = info.requestedPixmaps.count();
            stream << requestedPixmapCount;
            for (quint32 j = 0; j < requestedPixmapCount; ++j) {
                stream << info.requestedPixmaps.at(j);
            }
            quint32 releasedPixmapCount = info.releasedPixmaps.count();
            stream << releasedPixmapCount;
            for (quint32 j = 0; j < releasedPixmapCount; ++j) {
                stream << info.releasedPixmaps.at(j);
            }
        }
    } break;

    default:
        // print out warning
        break;
    }
}

static bool waitForAvailableBytes(QDataStream &stream, quint32 count)
{
    while (stream.device()->bytesAvailable() < count) {
        if (!stream.device()->waitForReadyRead(SOCKET_DELAY_MS)) {
            return false;
        }
    }
    return true;
}

QDataStream &operator>>(QDataStream &stream, Packet &packet)
{
    Q_ASSERT(!packet.data());

    if (!waitForAvailableBytes(stream, sizeof(quint32))) {
        return stream;
    }
    quint32 length;
    stream >> length;
    if (!waitForAvailableBytes(stream, length)) {
        return stream;
    }

    char *raw = new char[length];
    stream.readRawData(raw, length);
    QByteArray serializedPackageData = QByteArray::fromRawData(raw, length);
    QDataStream serializedPackageDataStream(serializedPackageData);
    readPacketData(serializedPackageDataStream, packet);

    delete raw;

    return stream;
}

void readPacketData(QDataStream &stream, M::MThemeDaemonProtocol::Packet &packet)
{
    quint32 type = 0;
    quint64 seq  = 0;

    stream >> type >> seq;

    packet.setType(Packet::PacketType(type));
    packet.setSequenceNumber(seq);

    switch (packet.type()) {

    // NULL as data
    case Packet::RequestClearPixmapDirectoriesPacket:
    case Packet::QueryThemeDaemonStatusPacket:
        break;

    // string as data
    case Packet::ErrorPacket:
    case Packet::RequestRegistrationPacket: {
        QString string;
        stream >> string;
        packet.setData(new String(string));
    } break;

    // two string lists as data
    case Packet::ThemeChangedPacket: {
        QStringList themeInheritance, themeLibraryNames;
        stream >> themeInheritance >> themeLibraryNames;
        packet.setData(new ThemeChangeInfo(themeInheritance, themeLibraryNames));
    } break;

    case Packet::ProtocolVersionPacket:
    case Packet::ThemeChangeAppliedPacket: {
        qint32  priority;
        stream >> priority;
        packet.setData(new Number(priority));
    } break;

    // stringbool as data
    case Packet::RequestNewPixmapDirectoryPacket: {
        QString string;
        stream >> string;
        bool b = false;
        stream >> b;
        packet.setData(new StringBool(string, b));
    } break;

    // pixmap identifier as data
    case Packet::PixmapUsedPacket:
    case Packet::ReleasePixmapPacket: {
        PixmapIdentifier id;
        stream >> id;
        packet.setData(new PixmapIdentifier(id));
    } break;

    case Packet::RequestPixmapPacket: {
        qint32 priority;
        stream >> priority;
        PixmapIdentifier id;
        stream >> id;
        packet.setData(new RequestedPixmap(id, priority));
    } break;

    // pixmap handle as data
    case Packet::PixmapUpdatedPacket: {
        PixmapHandle h;
        stream >> h;
        packet.setData(new PixmapHandle(h));
    } break;

    case Packet::MostUsedPixmapsPacket: {
        QList<PixmapHandle> addedHandles;
        stream >> addedHandles;

        QList<PixmapIdentifier> removedIdentifiers;
        stream >> removedIdentifiers;

        packet.setData(new MostUsedPixmaps(addedHandles, removedIdentifiers));
    } break;

    // client list as data
    case Packet::ThemeDaemonStatusPacket: {
        QList<ClientInfo> clients;
        quint32 clientCount = 0;
        stream >> clientCount;
        while (clientCount) {
            ClientInfo info;
            stream >> info.name;
            quint32 pixmapCount = 0;
            stream >> pixmapCount;
            while (pixmapCount) {
                PixmapIdentifier id;
                stream >> id;
                info.pixmaps.append(id);
                --pixmapCount;
            }
            quint32 requestedPixmapCount = 0;
            stream >> requestedPixmapCount;
            while (requestedPixmapCount) {
                PixmapIdentifier id;
                stream >> id;
                info.requestedPixmaps.append(id);
                --requestedPixmapCount;
            }
            quint32 releasedPixmapCount = 0;
            stream >> releasedPixmapCount;
            while (releasedPixmapCount) {
                PixmapIdentifier id;
                stream >> id;
                info.releasedPixmaps.append(id);
                --releasedPixmapCount;
            }

            clients.append(info);
            --clientCount;
        }
        packet.setData(new ClientList(clients));
    } break;

    default:
        // print out warning
        break;
    }
}

QDataStream &operator<<(QDataStream &stream, const M::MThemeDaemonProtocol::PixmapHandle &handle)
{
    stream << handle.identifier;
    stream << quint64(quintptr(handle.pixmapHandle.xHandle));
    stream << quint64(quintptr(handle.pixmapHandle.eglHandle));
    stream << handle.pixmapHandle.shmHandle;
    stream << handle.pixmapHandle.size;
    stream << (quint64)handle.pixmapHandle.format;
    stream << handle.pixmapHandle.numBytes;
    stream << (bool)handle.pixmapHandle.directMap;
    return stream;
}

QDataStream &operator>>(QDataStream &stream, M::MThemeDaemonProtocol::PixmapHandle &handle)
{
    stream >> handle.identifier;

    quint64 h;
    stream >> h;
    handle.pixmapHandle.xHandle = (Qt::HANDLE) quintptr(h);
    stream >> h;
    handle.pixmapHandle.eglHandle = (Qt::HANDLE) quintptr(h);
    stream >> handle.pixmapHandle.shmHandle;
    stream >> handle.pixmapHandle.size;
    stream >> h;
    handle.pixmapHandle.format = QImage::Format(h);
    stream >> handle.pixmapHandle.numBytes;
    stream >> handle.pixmapHandle.directMap;
    return stream;
}

QDataStream &operator<<(QDataStream &stream, const M::MThemeDaemonProtocol::PixmapIdentifier &id)
{
    stream << id.imageId;
    stream << id.size;
    return stream;
}

QDataStream &operator>>(QDataStream &stream, M::MThemeDaemonProtocol::PixmapIdentifier &id)
{
    QString imageId;
    stream >> imageId;
    QSize size;
    stream >> size;
    id.imageId = imageId;
    id.size = size;
    return stream;
}

uint M::MThemeDaemonProtocol::qHash(const PixmapIdentifier &id)
{
    using ::qHash;

    const uint idHash     = qHash(id.imageId);
    const uint widthHash  = qHash(id.size.width());
    const uint heightHash = qHash(id.size.height());

    // Twiddle the bits a little, taking a cue from Qt's own qHash() overloads
    return idHash ^ (widthHash << 8) ^ (widthHash >> 24) ^ (heightHash << 24) ^ (heightHash >> 8);
}
<commit_msg>Changes: remove bogus Q_ASSERT<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mthemedaemonprotocol.h"
#include <QHash>
#include <QtEndian>

using namespace M::MThemeDaemonProtocol;

const QString M::MThemeDaemonProtocol::ServerAddress = "m.mthemedaemon";
static const int SOCKET_DELAY_MS = 15000;

PacketData::~PacketData()
{}

PixmapIdentifier::~PixmapIdentifier()
{}

Number::~Number()
{}

String::~String()
{}

StringBool::~StringBool()
{}

PixmapHandle::~PixmapHandle()
{}

ClientList::~ClientList()
{}

ThemeChangeInfo::~ThemeChangeInfo()
{}

MostUsedPixmaps::~MostUsedPixmaps()
{}

RequestedPixmap::~RequestedPixmap()
{}

Packet::Packet(PacketType type, quint64 seq, PacketData *data)
:
    m_seq  (seq),
    m_data (data),
    m_type (type)
{}

Packet::~Packet()
{}

void Packet::setData(PacketData *data)
{
    m_data = QSharedPointer<PacketData>(data);
}

QDataStream &operator<<(QDataStream &stream, const Packet &packet)
{
    Q_ASSERT(packet.type() != Packet::Unknown);

    QByteArray serializedPackageData;
    QDataStream serializedPackageDataStream(&serializedPackageData, QIODevice::WriteOnly);
    writePacketData(serializedPackageDataStream, packet);
    stream.writeBytes(serializedPackageData.constData(), serializedPackageData.length());

    return stream;
}

void writePacketData(QDataStream &stream, const M::MThemeDaemonProtocol::Packet &packet)
{
    stream << quint32(packet.type());
    stream << packet.sequenceNumber();

    switch (packet.type()) {
    // NULL as data
    case Packet::RequestClearPixmapDirectoriesPacket:
    case Packet::QueryThemeDaemonStatusPacket:
        break;

    // string as data
    case Packet::ErrorPacket:
    case Packet::RequestRegistrationPacket: {
        stream << static_cast<const String *>(packet.data())->string;
    } break;

    // two string lists as data
    case Packet::ThemeChangedPacket: {
        const ThemeChangeInfo* info = static_cast<const ThemeChangeInfo*>(packet.data());
        stream << info->themeInheritance << info->themeLibraryNames;
    } break;

    case Packet::ProtocolVersionPacket:
    case Packet::ThemeChangeAppliedPacket: {
        stream << static_cast<const Number *>(packet.data())->value;
    } break;

    // stringbool as data
    case Packet::RequestNewPixmapDirectoryPacket: {
        const StringBool *sb = static_cast<const StringBool *>(packet.data());
        stream << sb->string << sb->b;
    } break;

    // pixmap identifier as data
    case Packet::PixmapUsedPacket:
    case Packet::ReleasePixmapPacket: {
        const PixmapIdentifier *id = static_cast<const PixmapIdentifier *>(packet.data());
        stream << *id;
    } break;

    case Packet::RequestPixmapPacket: {
        const RequestedPixmap *pixmap = static_cast<const RequestedPixmap *>(packet.data());
        stream << pixmap->priority;
        stream << pixmap->id;
    } break;

    // pixmap handle as data
    case Packet::PixmapUpdatedPacket: {
        const PixmapHandle *h = static_cast<const PixmapHandle *>(packet.data());
        stream << *h;
    } break;

    case Packet::MostUsedPixmapsPacket: {
        const MostUsedPixmaps *mostUsedPixmaps = static_cast<const MostUsedPixmaps *>(packet.data());

        stream << mostUsedPixmaps->addedHandles;
        stream << mostUsedPixmaps->removedIdentifiers;
    } break;

    // client list as data
    case Packet::ThemeDaemonStatusPacket: {
        const ClientList *cl = static_cast<const ClientList *>(packet.data());
        quint32 clientCount = cl->clients.count();
        stream << clientCount;
        for (uint i = 0; i < clientCount; ++i)
        {
            const ClientInfo &info = cl->clients.at(i);
            stream << info.name;
            quint32 pixmapCount = info.pixmaps.count();
            stream << pixmapCount;
            for (quint32 j = 0; j < pixmapCount; ++j) {
                stream << info.pixmaps.at(j);
            }
            quint32 requestedPixmapCount = info.requestedPixmaps.count();
            stream << requestedPixmapCount;
            for (quint32 j = 0; j < requestedPixmapCount; ++j) {
                stream << info.requestedPixmaps.at(j);
            }
            quint32 releasedPixmapCount = info.releasedPixmaps.count();
            stream << releasedPixmapCount;
            for (quint32 j = 0; j < releasedPixmapCount; ++j) {
                stream << info.releasedPixmaps.at(j);
            }
        }
    } break;

    default:
        // print out warning
        break;
    }
}

static bool waitForAvailableBytes(QDataStream &stream, quint32 count)
{
    while (stream.device()->bytesAvailable() < count) {
        if (!stream.device()->waitForReadyRead(SOCKET_DELAY_MS)) {
            return false;
        }
    }
    return true;
}

QDataStream &operator>>(QDataStream &stream, Packet &packet)
{
    if (!waitForAvailableBytes(stream, sizeof(quint32))) {
        return stream;
    }
    quint32 length;
    stream >> length;
    if (!waitForAvailableBytes(stream, length)) {
        return stream;
    }

    char *raw = new char[length];
    stream.readRawData(raw, length);
    QByteArray serializedPackageData = QByteArray::fromRawData(raw, length);
    QDataStream serializedPackageDataStream(serializedPackageData);
    readPacketData(serializedPackageDataStream, packet);

    delete raw;

    return stream;
}

void readPacketData(QDataStream &stream, M::MThemeDaemonProtocol::Packet &packet)
{
    quint32 type = 0;
    quint64 seq  = 0;

    stream >> type >> seq;

    packet.setType(Packet::PacketType(type));
    packet.setSequenceNumber(seq);

    switch (packet.type()) {

    // NULL as data
    case Packet::RequestClearPixmapDirectoriesPacket:
    case Packet::QueryThemeDaemonStatusPacket:
        break;

    // string as data
    case Packet::ErrorPacket:
    case Packet::RequestRegistrationPacket: {
        QString string;
        stream >> string;
        packet.setData(new String(string));
    } break;

    // two string lists as data
    case Packet::ThemeChangedPacket: {
        QStringList themeInheritance, themeLibraryNames;
        stream >> themeInheritance >> themeLibraryNames;
        packet.setData(new ThemeChangeInfo(themeInheritance, themeLibraryNames));
    } break;

    case Packet::ProtocolVersionPacket:
    case Packet::ThemeChangeAppliedPacket: {
        qint32  priority;
        stream >> priority;
        packet.setData(new Number(priority));
    } break;

    // stringbool as data
    case Packet::RequestNewPixmapDirectoryPacket: {
        QString string;
        stream >> string;
        bool b = false;
        stream >> b;
        packet.setData(new StringBool(string, b));
    } break;

    // pixmap identifier as data
    case Packet::PixmapUsedPacket:
    case Packet::ReleasePixmapPacket: {
        PixmapIdentifier id;
        stream >> id;
        packet.setData(new PixmapIdentifier(id));
    } break;

    case Packet::RequestPixmapPacket: {
        qint32 priority;
        stream >> priority;
        PixmapIdentifier id;
        stream >> id;
        packet.setData(new RequestedPixmap(id, priority));
    } break;

    // pixmap handle as data
    case Packet::PixmapUpdatedPacket: {
        PixmapHandle h;
        stream >> h;
        packet.setData(new PixmapHandle(h));
    } break;

    case Packet::MostUsedPixmapsPacket: {
        QList<PixmapHandle> addedHandles;
        stream >> addedHandles;

        QList<PixmapIdentifier> removedIdentifiers;
        stream >> removedIdentifiers;

        packet.setData(new MostUsedPixmaps(addedHandles, removedIdentifiers));
    } break;

    // client list as data
    case Packet::ThemeDaemonStatusPacket: {
        QList<ClientInfo> clients;
        quint32 clientCount = 0;
        stream >> clientCount;
        while (clientCount) {
            ClientInfo info;
            stream >> info.name;
            quint32 pixmapCount = 0;
            stream >> pixmapCount;
            while (pixmapCount) {
                PixmapIdentifier id;
                stream >> id;
                info.pixmaps.append(id);
                --pixmapCount;
            }
            quint32 requestedPixmapCount = 0;
            stream >> requestedPixmapCount;
            while (requestedPixmapCount) {
                PixmapIdentifier id;
                stream >> id;
                info.requestedPixmaps.append(id);
                --requestedPixmapCount;
            }
            quint32 releasedPixmapCount = 0;
            stream >> releasedPixmapCount;
            while (releasedPixmapCount) {
                PixmapIdentifier id;
                stream >> id;
                info.releasedPixmaps.append(id);
                --releasedPixmapCount;
            }

            clients.append(info);
            --clientCount;
        }
        packet.setData(new ClientList(clients));
    } break;

    default:
        // print out warning
        break;
    }
}

QDataStream &operator<<(QDataStream &stream, const M::MThemeDaemonProtocol::PixmapHandle &handle)
{
    stream << handle.identifier;
    stream << quint64(quintptr(handle.pixmapHandle.xHandle));
    stream << quint64(quintptr(handle.pixmapHandle.eglHandle));
    stream << handle.pixmapHandle.shmHandle;
    stream << handle.pixmapHandle.size;
    stream << (quint64)handle.pixmapHandle.format;
    stream << handle.pixmapHandle.numBytes;
    stream << (bool)handle.pixmapHandle.directMap;
    return stream;
}

QDataStream &operator>>(QDataStream &stream, M::MThemeDaemonProtocol::PixmapHandle &handle)
{
    stream >> handle.identifier;

    quint64 h;
    stream >> h;
    handle.pixmapHandle.xHandle = (Qt::HANDLE) quintptr(h);
    stream >> h;
    handle.pixmapHandle.eglHandle = (Qt::HANDLE) quintptr(h);
    stream >> handle.pixmapHandle.shmHandle;
    stream >> handle.pixmapHandle.size;
    stream >> h;
    handle.pixmapHandle.format = QImage::Format(h);
    stream >> handle.pixmapHandle.numBytes;
    stream >> handle.pixmapHandle.directMap;
    return stream;
}

QDataStream &operator<<(QDataStream &stream, const M::MThemeDaemonProtocol::PixmapIdentifier &id)
{
    stream << id.imageId;
    stream << id.size;
    return stream;
}

QDataStream &operator>>(QDataStream &stream, M::MThemeDaemonProtocol::PixmapIdentifier &id)
{
    QString imageId;
    stream >> imageId;
    QSize size;
    stream >> size;
    id.imageId = imageId;
    id.size = size;
    return stream;
}

uint M::MThemeDaemonProtocol::qHash(const PixmapIdentifier &id)
{
    using ::qHash;

    const uint idHash     = qHash(id.imageId);
    const uint widthHash  = qHash(id.size.width());
    const uint heightHash = qHash(id.size.height());

    // Twiddle the bits a little, taking a cue from Qt's own qHash() overloads
    return idHash ^ (widthHash << 8) ^ (widthHash >> 24) ^ (heightHash << 24) ^ (heightHash >> 8);
}
<|endoftext|>