<commit_before>//==- Deserialize.cpp - Generic Object Serialization to Bitcode --*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the internal methods used for object serialization.
//
//===----------------------------------------------------------------------===//

#include "llvm/Bitcode/Deserialize.h"

#ifdef DEBUG_BACKPATCH
#include "llvm/Support/Streams.h"
#endif

using namespace llvm;

Deserializer::Deserializer(BitstreamReader& stream)
  : Stream(stream), RecIdx(0), FreeList(NULL), AbbrevNo(0), RecordCode(0) {

    StreamStart = Stream.GetCurrentBitNo();
}

Deserializer::~Deserializer() {
  assert (RecIdx >= Record.size() &&
          "Still scanning bitcode record when deserialization completed.");

#ifdef DEBUG_BACKPATCH
  for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I)
    assert (I->first.hasFinalPtr() &&
            "Some pointers were not backpatched.");
#endif
}

bool Deserializer::inRecord() {
  if (Record.size() > 0) {
    if (RecIdx >= Record.size()) {
      RecIdx = 0;
      Record.clear();
      AbbrevNo = 0;
      return false;
    }
    else
      return true;
  }

  return false;
}

bool Deserializer::AdvanceStream() {
  assert (!inRecord() &&
          "Cannot advance stream.  Still processing a record.");

  if (AbbrevNo == bitc::ENTER_SUBBLOCK ||
      AbbrevNo >= bitc::UNABBREV_RECORD)
    return true;

  while (!Stream.AtEndOfStream()) {

    uint64_t Pos = Stream.GetCurrentBitNo();
    AbbrevNo = Stream.ReadCode();

    switch (AbbrevNo) {
      case bitc::ENTER_SUBBLOCK: {
        unsigned id = Stream.ReadSubBlockID();

        // Determine the extent of the block.  This is useful for jumping around
        // the stream.  This is hack: we read the header of the block, save
        // the length, and then revert the bitstream to a location just before
        // the block is entered.
        uint64_t BPos = Stream.GetCurrentBitNo();
        Stream.ReadVBR(bitc::CodeLenWidth); // Skip the code size.
        Stream.SkipToWord();
        unsigned NumWords = Stream.Read(bitc::BlockSizeWidth);
        Stream.JumpToBit(BPos);

        BlockStack.push_back(Location(Pos,id,NumWords));
        break;
      }

      case bitc::END_BLOCK: {
        bool x = Stream.ReadBlockEnd();
        assert(!x && "Error at block end.");
        BlockStack.pop_back();
        continue;
      }

      case bitc::DEFINE_ABBREV:
        Stream.ReadAbbrevRecord();
        continue;

      default:
        break;
    }

    return true;
  }

  return false;
}

void Deserializer::ReadRecord() {

  while (AdvanceStream() && AbbrevNo == bitc::ENTER_SUBBLOCK) {
    assert (!BlockStack.empty());
    Stream.EnterSubBlock(BlockStack.back().BlockID);
    AbbrevNo = 0;
  }

  if (Stream.AtEndOfStream())
    return;

  assert (Record.empty());
  assert (AbbrevNo >= bitc::UNABBREV_RECORD);
  RecordCode = Stream.ReadRecord(AbbrevNo,Record);
  assert (Record.size() > 0);
}

void Deserializer::SkipBlock() {
  assert (!inRecord());

  if (AtEnd())
    return;

  AdvanceStream();

  assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
  BlockStack.pop_back();
  Stream.SkipBlock();

  AbbrevNo = 0;
  AdvanceStream();
}

bool Deserializer::SkipToBlock(unsigned BlockID) {
  assert (!inRecord());

  AdvanceStream();
  assert (AbbrevNo == bitc::ENTER_SUBBLOCK);

  unsigned BlockLevel = BlockStack.size();

  while (!AtEnd() &&
         BlockLevel == BlockStack.size() &&
         getCurrentBlockID() != BlockID)
    SkipBlock();

  return !(AtEnd() || BlockLevel != BlockStack.size());
}

Deserializer::Location Deserializer::getCurrentBlockLocation() {
  if (!inRecord())
    AdvanceStream();

  return BlockStack.back();
}

bool Deserializer::JumpTo(const Location& Loc) {

  assert (!inRecord());

  AdvanceStream();

  assert (!BlockStack.empty() || AtEnd());

  uint64_t LastBPos = StreamStart;

  while (!BlockStack.empty()) {

    LastBPos = BlockStack.back().BitNo;

    // Determine of the current block contains the location of the block
    // we are looking for.
    if (BlockStack.back().contains(Loc)) {
      // We found the enclosing block.  We must first POP it off to
      // destroy any accumulated context within the block scope.  We then
      // jump to the position of the block and enter it.
      Stream.JumpToBit(LastBPos);

      if (BlockStack.size() == Stream.BlockScope.size())
        Stream.PopBlockScope();

      BlockStack.pop_back();

      AbbrevNo = 0;
      AdvanceStream();
      assert (AbbrevNo == bitc::ENTER_SUBBLOCK);

      Stream.EnterSubBlock(BlockStack.back().BlockID);
      break;
    }

    // This block does not contain the block we are looking for.  Pop it.
    if (BlockStack.size() == Stream.BlockScope.size())
      Stream.PopBlockScope();

    BlockStack.pop_back();

  }

  // Check if we have popped our way to the outermost scope.  If so,
  // we need to adjust our position.
  if (BlockStack.empty()) {
    assert (Stream.BlockScope.empty());

    Stream.JumpToBit(Loc.BitNo < LastBPos ? StreamStart : LastBPos);
    AbbrevNo = 0;
    AdvanceStream();
  }

  assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
  assert (!BlockStack.empty());

  while (!AtEnd() && BlockStack.back() != Loc) {
    if (BlockStack.back().contains(Loc)) {
      Stream.EnterSubBlock(BlockStack.back().BlockID);
      AbbrevNo = 0;
      AdvanceStream();
      continue;
    }
    else
      SkipBlock();
  }

  if (AtEnd())
    return false;

  assert (BlockStack.back() == Loc);

  return true;
}

void Deserializer::Rewind() {
  while (!Stream.BlockScope.empty())
    Stream.PopBlockScope();

  while (!BlockStack.empty())
    BlockStack.pop_back();

  Stream.JumpToBit(StreamStart);
  AbbrevNo = 0;
}

unsigned Deserializer::getCurrentBlockID() {
  if (!inRecord())
    AdvanceStream();

  return BlockStack.back().BlockID;
}

unsigned Deserializer::getRecordCode() {
  if (!inRecord()) {
    AdvanceStream();
    assert (AbbrevNo >= bitc::UNABBREV_RECORD);
    ReadRecord();
  }

  return RecordCode;
}

bool Deserializer::FinishedBlock(Location BlockLoc) {
  if (!inRecord())
    AdvanceStream();

  for (llvm::SmallVector<Location,8>::reverse_iterator
        I=BlockStack.rbegin(), E=BlockStack.rend(); I!=E; ++I)
      if (*I == BlockLoc)
        return false;

  return true;
}

unsigned Deserializer::getAbbrevNo() {
  if (!inRecord())
    AdvanceStream();

  return AbbrevNo;
}

bool Deserializer::AtEnd() {
  if (inRecord())
    return false;

  if (!AdvanceStream())
    return true;

  return false;
}

uint64_t Deserializer::ReadInt() {
  // FIXME: Any error recovery/handling with incomplete or bad files?
  if (!inRecord())
    ReadRecord();

  return Record[RecIdx++];
}

int64_t Deserializer::ReadSInt() {
  uint64_t x = ReadInt();
  int64_t magnitude = x >> 1;
  return x & 0x1 ? -magnitude : magnitude;
}

char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
  if (cstr == NULL)
    MaxLen = 0; // Zero this just in case someone does something funny.

  unsigned len = ReadInt();

  assert (MaxLen == 0 || (len + (isNullTerm ? 1 : 0)) <= MaxLen);

  if (!cstr)
    cstr = new char[len + (isNullTerm ? 1 : 0)];

  assert (cstr != NULL);

  for (unsigned i = 0; i < len; ++i)
    cstr[i] = (char) ReadInt();

  if (isNullTerm)
    cstr[len] = '\0';

  return cstr;
}

void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm,
                            unsigned Idx) {

  unsigned len = ReadInt();

  // If Idx is beyond the current before size, reduce Idx to refer to the
  // element after the last element.
  if (Idx > buff.size())
    Idx = buff.size();

  buff.reserve(len+Idx);
  buff.resize(Idx);

  for (unsigned i = 0; i < len; ++i)
    buff.push_back((char) ReadInt());

  if (isNullTerm)
    buff.push_back('\0');
}

void Deserializer::RegisterPtr(const SerializedPtrID& PtrId,
                               const void* Ptr) {

  MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));

  assert (!HasFinalPtr(E) && "Pointer already registered.");

#ifdef DEBUG_BACKPATCH
  llvm::cerr << "RegisterPtr: " << PtrId << " => " << Ptr << "\n";
#endif

  SetPtr(E,Ptr);
}

void Deserializer::ReadUIntPtr(uintptr_t& PtrRef,
                               const SerializedPtrID& PtrId,
                               bool AllowBackpatch) {
  if (PtrId == 0) {
    PtrRef = 0;
    return;
  }

  MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));

  if (HasFinalPtr(E)) {
    PtrRef = GetFinalPtr(E);

#ifdef DEBUG_BACKPATCH
    llvm::cerr << "ReadUintPtr: " << PtrId
               << " <-- " <<  (void*) GetFinalPtr(E) << '\n';
#endif
  }
  else {
    assert (AllowBackpatch &&
            "Client forbids backpatching for this pointer.");

#ifdef DEBUG_BACKPATCH
    llvm::cerr << "ReadUintPtr: " << PtrId << " (NO PTR YET)\n";
#endif

    // Register backpatch.  Check the freelist for a BPNode.
    BPNode* N;

    if (FreeList) {
      N = FreeList;
      FreeList = FreeList->Next;
    }
    else // No available BPNode.  Allocate one.
      N = (BPNode*) Allocator.Allocate<BPNode>();

    new (N) BPNode(GetBPNode(E),PtrRef);
    SetBPNode(E,N);
  }
}

uintptr_t Deserializer::ReadInternalRefPtr() {
  SerializedPtrID PtrId = ReadPtrID();

  assert (PtrId != 0 && "References cannot refer the NULL address.");

  MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));

  assert (HasFinalPtr(E) &&
          "Cannot backpatch references.  Object must be already deserialized.");

  return GetFinalPtr(E);
}

void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
  BPNode* Last = NULL;

  for (BPNode* N = Head; N != NULL; N=N->Next) {
    Last = N;
    N->PtrRef |= reinterpret_cast<uintptr_t>(P);
  }

  if (Last) {
    Last->Next = FreeList;
    FreeList = Head;
  }

  Ptr = const_cast<void*>(P);
}

#define INT_READ(TYPE)\
void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
  X = (TYPE) D.ReadInt(); }

INT_READ(bool)
INT_READ(unsigned char)
INT_READ(unsigned short)
INT_READ(unsigned int)
INT_READ(unsigned long)

#define SINT_READ(TYPE)\
void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
  X = (TYPE) D.ReadSInt(); }

INT_READ(signed char)
INT_READ(signed short)
INT_READ(signed int)
INT_READ(signed long)
<commit_msg>revert r61368.<commit_after>//==- Deserialize.cpp - Generic Object Serialization to Bitcode --*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the internal methods used for object serialization.
//
//===----------------------------------------------------------------------===//

#include "llvm/Bitcode/Deserialize.h"

#ifdef DEBUG_BACKPATCH
#include "llvm/Support/Streams.h"
#endif

using namespace llvm;

Deserializer::Deserializer(BitstreamReader& stream)
  : Stream(stream), RecIdx(0), FreeList(NULL), AbbrevNo(0), RecordCode(0) {

    StreamStart = Stream.GetCurrentBitNo();
}

Deserializer::~Deserializer() {
  assert (RecIdx >= Record.size() &&
          "Still scanning bitcode record when deserialization completed.");

#ifdef DEBUG_BACKPATCH
  for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I)
    assert (I->first.hasFinalPtr() &&
            "Some pointers were not backpatched.");
#endif
}

bool Deserializer::inRecord() {
  if (Record.size() > 0) {
    if (RecIdx >= Record.size()) {
      RecIdx = 0;
      Record.clear();
      AbbrevNo = 0;
      return false;
    }
    else
      return true;
  }

  return false;
}

bool Deserializer::AdvanceStream() {
  assert (!inRecord() &&
          "Cannot advance stream.  Still processing a record.");

  if (AbbrevNo == bitc::ENTER_SUBBLOCK ||
      AbbrevNo >= bitc::UNABBREV_RECORD)
    return true;

  while (!Stream.AtEndOfStream()) {

    uint64_t Pos = Stream.GetCurrentBitNo();
    AbbrevNo = Stream.ReadCode();

    switch (AbbrevNo) {
      case bitc::ENTER_SUBBLOCK: {
        unsigned id = Stream.ReadSubBlockID();

        // Determine the extent of the block.  This is useful for jumping around
        // the stream.  This is hack: we read the header of the block, save
        // the length, and then revert the bitstream to a location just before
        // the block is entered.
        uint64_t BPos = Stream.GetCurrentBitNo();
        Stream.ReadVBR(bitc::CodeLenWidth); // Skip the code size.
        Stream.SkipToWord();
        unsigned NumWords = Stream.Read(bitc::BlockSizeWidth);
        Stream.JumpToBit(BPos);

        BlockStack.push_back(Location(Pos,id,NumWords));
        break;
      }

      case bitc::END_BLOCK: {
        bool x = Stream.ReadBlockEnd();
        assert(!x && "Error at block end."); x=x;
        BlockStack.pop_back();
        continue;
      }

      case bitc::DEFINE_ABBREV:
        Stream.ReadAbbrevRecord();
        continue;

      default:
        break;
    }

    return true;
  }

  return false;
}

void Deserializer::ReadRecord() {

  while (AdvanceStream() && AbbrevNo == bitc::ENTER_SUBBLOCK) {
    assert (!BlockStack.empty());
    Stream.EnterSubBlock(BlockStack.back().BlockID);
    AbbrevNo = 0;
  }

  if (Stream.AtEndOfStream())
    return;

  assert (Record.empty());
  assert (AbbrevNo >= bitc::UNABBREV_RECORD);
  RecordCode = Stream.ReadRecord(AbbrevNo,Record);
  assert (Record.size() > 0);
}

void Deserializer::SkipBlock() {
  assert (!inRecord());

  if (AtEnd())
    return;

  AdvanceStream();

  assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
  BlockStack.pop_back();
  Stream.SkipBlock();

  AbbrevNo = 0;
  AdvanceStream();
}

bool Deserializer::SkipToBlock(unsigned BlockID) {
  assert (!inRecord());

  AdvanceStream();
  assert (AbbrevNo == bitc::ENTER_SUBBLOCK);

  unsigned BlockLevel = BlockStack.size();

  while (!AtEnd() &&
         BlockLevel == BlockStack.size() &&
         getCurrentBlockID() != BlockID)
    SkipBlock();

  return !(AtEnd() || BlockLevel != BlockStack.size());
}

Deserializer::Location Deserializer::getCurrentBlockLocation() {
  if (!inRecord())
    AdvanceStream();

  return BlockStack.back();
}

bool Deserializer::JumpTo(const Location& Loc) {

  assert (!inRecord());

  AdvanceStream();

  assert (!BlockStack.empty() || AtEnd());

  uint64_t LastBPos = StreamStart;

  while (!BlockStack.empty()) {

    LastBPos = BlockStack.back().BitNo;

    // Determine of the current block contains the location of the block
    // we are looking for.
    if (BlockStack.back().contains(Loc)) {
      // We found the enclosing block.  We must first POP it off to
      // destroy any accumulated context within the block scope.  We then
      // jump to the position of the block and enter it.
      Stream.JumpToBit(LastBPos);

      if (BlockStack.size() == Stream.BlockScope.size())
        Stream.PopBlockScope();

      BlockStack.pop_back();

      AbbrevNo = 0;
      AdvanceStream();
      assert (AbbrevNo == bitc::ENTER_SUBBLOCK);

      Stream.EnterSubBlock(BlockStack.back().BlockID);
      break;
    }

    // This block does not contain the block we are looking for.  Pop it.
    if (BlockStack.size() == Stream.BlockScope.size())
      Stream.PopBlockScope();

    BlockStack.pop_back();

  }

  // Check if we have popped our way to the outermost scope.  If so,
  // we need to adjust our position.
  if (BlockStack.empty()) {
    assert (Stream.BlockScope.empty());

    Stream.JumpToBit(Loc.BitNo < LastBPos ? StreamStart : LastBPos);
    AbbrevNo = 0;
    AdvanceStream();
  }

  assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
  assert (!BlockStack.empty());

  while (!AtEnd() && BlockStack.back() != Loc) {
    if (BlockStack.back().contains(Loc)) {
      Stream.EnterSubBlock(BlockStack.back().BlockID);
      AbbrevNo = 0;
      AdvanceStream();
      continue;
    }
    else
      SkipBlock();
  }

  if (AtEnd())
    return false;

  assert (BlockStack.back() == Loc);

  return true;
}

void Deserializer::Rewind() {
  while (!Stream.BlockScope.empty())
    Stream.PopBlockScope();

  while (!BlockStack.empty())
    BlockStack.pop_back();

  Stream.JumpToBit(StreamStart);
  AbbrevNo = 0;
}

unsigned Deserializer::getCurrentBlockID() {
  if (!inRecord())
    AdvanceStream();

  return BlockStack.back().BlockID;
}

unsigned Deserializer::getRecordCode() {
  if (!inRecord()) {
    AdvanceStream();
    assert (AbbrevNo >= bitc::UNABBREV_RECORD);
    ReadRecord();
  }

  return RecordCode;
}

bool Deserializer::FinishedBlock(Location BlockLoc) {
  if (!inRecord())
    AdvanceStream();

  for (llvm::SmallVector<Location,8>::reverse_iterator
        I=BlockStack.rbegin(), E=BlockStack.rend(); I!=E; ++I)
      if (*I == BlockLoc)
        return false;

  return true;
}

unsigned Deserializer::getAbbrevNo() {
  if (!inRecord())
    AdvanceStream();

  return AbbrevNo;
}

bool Deserializer::AtEnd() {
  if (inRecord())
    return false;

  if (!AdvanceStream())
    return true;

  return false;
}

uint64_t Deserializer::ReadInt() {
  // FIXME: Any error recovery/handling with incomplete or bad files?
  if (!inRecord())
    ReadRecord();

  return Record[RecIdx++];
}

int64_t Deserializer::ReadSInt() {
  uint64_t x = ReadInt();
  int64_t magnitude = x >> 1;
  return x & 0x1 ? -magnitude : magnitude;
}

char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) {
  if (cstr == NULL)
    MaxLen = 0; // Zero this just in case someone does something funny.

  unsigned len = ReadInt();

  assert (MaxLen == 0 || (len + (isNullTerm ? 1 : 0)) <= MaxLen);

  if (!cstr)
    cstr = new char[len + (isNullTerm ? 1 : 0)];

  assert (cstr != NULL);

  for (unsigned i = 0; i < len; ++i)
    cstr[i] = (char) ReadInt();

  if (isNullTerm)
    cstr[len] = '\0';

  return cstr;
}

void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm,
                            unsigned Idx) {

  unsigned len = ReadInt();

  // If Idx is beyond the current before size, reduce Idx to refer to the
  // element after the last element.
  if (Idx > buff.size())
    Idx = buff.size();

  buff.reserve(len+Idx);
  buff.resize(Idx);

  for (unsigned i = 0; i < len; ++i)
    buff.push_back((char) ReadInt());

  if (isNullTerm)
    buff.push_back('\0');
}

void Deserializer::RegisterPtr(const SerializedPtrID& PtrId,
                               const void* Ptr) {

  MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));

  assert (!HasFinalPtr(E) && "Pointer already registered.");

#ifdef DEBUG_BACKPATCH
  llvm::cerr << "RegisterPtr: " << PtrId << " => " << Ptr << "\n";
#endif

  SetPtr(E,Ptr);
}

void Deserializer::ReadUIntPtr(uintptr_t& PtrRef,
                               const SerializedPtrID& PtrId,
                               bool AllowBackpatch) {
  if (PtrId == 0) {
    PtrRef = 0;
    return;
  }

  MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));

  if (HasFinalPtr(E)) {
    PtrRef = GetFinalPtr(E);

#ifdef DEBUG_BACKPATCH
    llvm::cerr << "ReadUintPtr: " << PtrId
               << " <-- " <<  (void*) GetFinalPtr(E) << '\n';
#endif
  }
  else {
    assert (AllowBackpatch &&
            "Client forbids backpatching for this pointer.");

#ifdef DEBUG_BACKPATCH
    llvm::cerr << "ReadUintPtr: " << PtrId << " (NO PTR YET)\n";
#endif

    // Register backpatch.  Check the freelist for a BPNode.
    BPNode* N;

    if (FreeList) {
      N = FreeList;
      FreeList = FreeList->Next;
    }
    else // No available BPNode.  Allocate one.
      N = (BPNode*) Allocator.Allocate<BPNode>();

    new (N) BPNode(GetBPNode(E),PtrRef);
    SetBPNode(E,N);
  }
}

uintptr_t Deserializer::ReadInternalRefPtr() {
  SerializedPtrID PtrId = ReadPtrID();

  assert (PtrId != 0 && "References cannot refer the NULL address.");

  MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));

  assert (HasFinalPtr(E) &&
          "Cannot backpatch references.  Object must be already deserialized.");

  return GetFinalPtr(E);
}

void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
  BPNode* Last = NULL;

  for (BPNode* N = Head; N != NULL; N=N->Next) {
    Last = N;
    N->PtrRef |= reinterpret_cast<uintptr_t>(P);
  }

  if (Last) {
    Last->Next = FreeList;
    FreeList = Head;
  }

  Ptr = const_cast<void*>(P);
}

#define INT_READ(TYPE)\
void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
  X = (TYPE) D.ReadInt(); }

INT_READ(bool)
INT_READ(unsigned char)
INT_READ(unsigned short)
INT_READ(unsigned int)
INT_READ(unsigned long)

#define SINT_READ(TYPE)\
void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
  X = (TYPE) D.ReadSInt(); }

INT_READ(signed char)
INT_READ(signed short)
INT_READ(signed int)
INT_READ(signed long)
<|endoftext|>


<commit_before>//===- Thumb1InstrInfo.cpp - Thumb-1 Instruction Information ----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the Thumb-1 implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//

#include "Thumb1InstrInfo.h"
#include "ARM.h"
#include "ARMGenInstrInfo.inc"
#include "ARMMachineFunctionInfo.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/ADT/SmallVector.h"
#include "Thumb1InstrInfo.h"

using namespace llvm;

Thumb1InstrInfo::Thumb1InstrInfo(const ARMSubtarget &STI)
  : ARMBaseInstrInfo(STI), RI(*this, STI) {
}

unsigned Thumb1InstrInfo::getUnindexedOpcode(unsigned Opc) const {
  return 0;
}

bool Thumb1InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
                                   MachineBasicBlock::iterator I,
                                   unsigned DestReg, unsigned SrcReg,
                                   const TargetRegisterClass *DestRC,
                                   const TargetRegisterClass *SrcRC) const {
  DebugLoc DL = DebugLoc::getUnknownLoc();
  if (I != MBB.end()) DL = I->getDebugLoc();

  if (DestRC == ARM::GPRRegisterClass) {
    if (SrcRC == ARM::GPRRegisterClass) {
      BuildMI(MBB, I, DL, get(ARM::tMOVgpr2gpr), DestReg).addReg(SrcReg);
      return true;
    } else if (SrcRC == ARM::tGPRRegisterClass) {
      BuildMI(MBB, I, DL, get(ARM::tMOVtgpr2gpr), DestReg).addReg(SrcReg);
      return true;
    }
  } else if (DestRC == ARM::tGPRRegisterClass) {
    if (SrcRC == ARM::GPRRegisterClass) {
      BuildMI(MBB, I, DL, get(ARM::tMOVgpr2tgpr), DestReg).addReg(SrcReg);
      return true;
    } else if (SrcRC == ARM::tGPRRegisterClass) {
      BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg).addReg(SrcReg);
      return true;
    }
  }

  return false;
}

bool Thumb1InstrInfo::
canFoldMemoryOperand(const MachineInstr *MI,
                     const SmallVectorImpl<unsigned> &Ops) const {
  if (Ops.size() != 1) return false;

  unsigned OpNum = Ops[0];
  unsigned Opc = MI->getOpcode();
  switch (Opc) {
  default: break;
  case ARM::tMOVr:
  case ARM::tMOVtgpr2gpr:
  case ARM::tMOVgpr2tgpr:
  case ARM::tMOVgpr2gpr: {
    if (OpNum == 0) { // move -> store
      unsigned SrcReg = MI->getOperand(1).getReg();
      if (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
          !isARMLowRegister(SrcReg))
        // tSpill cannot take a high register operand.
        return false;
    } else {          // move -> load
      unsigned DstReg = MI->getOperand(0).getReg();
      if (TargetRegisterInfo::isPhysicalRegister(DstReg) &&
          !isARMLowRegister(DstReg))
        // tRestore cannot target a high register operand.
        return false;
    }
    return true;
  }
  }

  return false;
}

void Thumb1InstrInfo::
storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
                    unsigned SrcReg, bool isKill, int FI,
                    const TargetRegisterClass *RC) const {
  DebugLoc DL = DebugLoc::getUnknownLoc();
  if (I != MBB.end()) DL = I->getDebugLoc();

  assert((RC == ARM::tGPRRegisterClass ||
          (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
           isARMLowRegister(SrcReg))) && "Unknown regclass!");

  if (RC == ARM::tGPRRegisterClass) {
    MachineFunction &MF = *MBB.getParent();
    MachineFrameInfo &MFI = *MF.getFrameInfo();
    MachineMemOperand *MMO =
      MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI),
                              MachineMemOperand::MOStore, 0,
                              MFI.getObjectSize(FI),
                              MFI.getObjectAlignment(FI));
    AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tSpill))
                   .addReg(SrcReg, getKillRegState(isKill))
                   .addFrameIndex(FI).addImm(0).addMemOperand(MMO));
  }
}

void Thumb1InstrInfo::
loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
                     unsigned DestReg, int FI,
                     const TargetRegisterClass *RC) const {
  DebugLoc DL = DebugLoc::getUnknownLoc();
  if (I != MBB.end()) DL = I->getDebugLoc();

  assert((RC == ARM::tGPRRegisterClass ||
          (TargetRegisterInfo::isPhysicalRegister(DestReg) &&
           isARMLowRegister(DestReg))) && "Unknown regclass!");

  if (RC == ARM::tGPRRegisterClass) {
    MachineFunction &MF = *MBB.getParent();
    MachineFrameInfo &MFI = *MF.getFrameInfo();
    MachineMemOperand *MMO =
      MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI),
                              MachineMemOperand::MOLoad, 0,
                              MFI.getObjectSize(FI),
                              MFI.getObjectAlignment(FI));
    AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tRestore), DestReg)
                   .addFrameIndex(FI).addImm(0).addMemOperand(MMO));
  }
}

bool Thumb1InstrInfo::
spillCalleeSavedRegisters(MachineBasicBlock &MBB,
                          MachineBasicBlock::iterator MI,
                          const std::vector<CalleeSavedInfo> &CSI) const {
  if (CSI.empty())
    return false;

  DebugLoc DL = DebugLoc::getUnknownLoc();
  if (MI != MBB.end()) DL = MI->getDebugLoc();

  MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get(ARM::tPUSH));
  AddDefaultPred(MIB);
  MIB.addReg(0); // No write back.
  for (unsigned i = CSI.size(); i != 0; --i) {
    unsigned Reg = CSI[i-1].getReg();
    // Add the callee-saved register as live-in. It's killed at the spill.
    MBB.addLiveIn(Reg);
    MIB.addReg(Reg, RegState::Kill);
  }
  return true;
}

bool Thumb1InstrInfo::
restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
                            MachineBasicBlock::iterator MI,
                            const std::vector<CalleeSavedInfo> &CSI) const {
  MachineFunction &MF = *MBB.getParent();
  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  if (CSI.empty())
    return false;

  bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
  DebugLoc DL = MI->getDebugLoc();
  MachineInstrBuilder MIB = BuildMI(MF, DL, get(ARM::tPOP));
  AddDefaultPred(MIB);
  MIB.addReg(0); // No write back.

  bool NumRegs = 0;
  for (unsigned i = CSI.size(); i != 0; --i) {
    unsigned Reg = CSI[i-1].getReg();
    if (Reg == ARM::LR) {
      // Special epilogue for vararg functions. See emitEpilogue
      if (isVarArg)
        continue;
      Reg = ARM::PC;
      (*MIB).setDesc(get(ARM::tPOP_RET));
      MI = MBB.erase(MI);
    }
    MIB.addReg(Reg, getDefRegState(true));
    ++NumRegs;
  }

  // It's illegal to emit pop instruction without operands.
  if (NumRegs)
    MBB.insert(MI, &*MIB);

  return true;
}

MachineInstr *Thumb1InstrInfo::
foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
                      const SmallVectorImpl<unsigned> &Ops, int FI) const {
  if (Ops.size() != 1) return NULL;

  unsigned OpNum = Ops[0];
  unsigned Opc = MI->getOpcode();
  MachineInstr *NewMI = NULL;
  switch (Opc) {
  default: break;
  case ARM::tMOVr:
  case ARM::tMOVtgpr2gpr:
  case ARM::tMOVgpr2tgpr:
  case ARM::tMOVgpr2gpr: {
    if (OpNum == 0) { // move -> store
      unsigned SrcReg = MI->getOperand(1).getReg();
      bool isKill = MI->getOperand(1).isKill();
      if (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
          !isARMLowRegister(SrcReg))
        // tSpill cannot take a high register operand.
        break;
      NewMI = AddDefaultPred(BuildMI(MF, MI->getDebugLoc(), get(ARM::tSpill))
                             .addReg(SrcReg, getKillRegState(isKill))
                             .addFrameIndex(FI).addImm(0));
    } else {          // move -> load
      unsigned DstReg = MI->getOperand(0).getReg();
      if (TargetRegisterInfo::isPhysicalRegister(DstReg) &&
          !isARMLowRegister(DstReg))
        // tRestore cannot target a high register operand.
        break;
      bool isDead = MI->getOperand(0).isDead();
      NewMI = AddDefaultPred(BuildMI(MF, MI->getDebugLoc(), get(ARM::tRestore))
                             .addReg(DstReg,
                                     RegState::Define | getDeadRegState(isDead))
                             .addFrameIndex(FI).addImm(0));
    }
    break;
  }
  }

  return NewMI;
}
<commit_msg>Silence a clang warning about the deprecated (but perfectly reasonable in context) increment-of-bool idiom.<commit_after>//===- Thumb1InstrInfo.cpp - Thumb-1 Instruction Information ----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the Thumb-1 implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//

#include "Thumb1InstrInfo.h"
#include "ARM.h"
#include "ARMGenInstrInfo.inc"
#include "ARMMachineFunctionInfo.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/ADT/SmallVector.h"
#include "Thumb1InstrInfo.h"

using namespace llvm;

Thumb1InstrInfo::Thumb1InstrInfo(const ARMSubtarget &STI)
  : ARMBaseInstrInfo(STI), RI(*this, STI) {
}

unsigned Thumb1InstrInfo::getUnindexedOpcode(unsigned Opc) const {
  return 0;
}

bool Thumb1InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
                                   MachineBasicBlock::iterator I,
                                   unsigned DestReg, unsigned SrcReg,
                                   const TargetRegisterClass *DestRC,
                                   const TargetRegisterClass *SrcRC) const {
  DebugLoc DL = DebugLoc::getUnknownLoc();
  if (I != MBB.end()) DL = I->getDebugLoc();

  if (DestRC == ARM::GPRRegisterClass) {
    if (SrcRC == ARM::GPRRegisterClass) {
      BuildMI(MBB, I, DL, get(ARM::tMOVgpr2gpr), DestReg).addReg(SrcReg);
      return true;
    } else if (SrcRC == ARM::tGPRRegisterClass) {
      BuildMI(MBB, I, DL, get(ARM::tMOVtgpr2gpr), DestReg).addReg(SrcReg);
      return true;
    }
  } else if (DestRC == ARM::tGPRRegisterClass) {
    if (SrcRC == ARM::GPRRegisterClass) {
      BuildMI(MBB, I, DL, get(ARM::tMOVgpr2tgpr), DestReg).addReg(SrcReg);
      return true;
    } else if (SrcRC == ARM::tGPRRegisterClass) {
      BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg).addReg(SrcReg);
      return true;
    }
  }

  return false;
}

bool Thumb1InstrInfo::
canFoldMemoryOperand(const MachineInstr *MI,
                     const SmallVectorImpl<unsigned> &Ops) const {
  if (Ops.size() != 1) return false;

  unsigned OpNum = Ops[0];
  unsigned Opc = MI->getOpcode();
  switch (Opc) {
  default: break;
  case ARM::tMOVr:
  case ARM::tMOVtgpr2gpr:
  case ARM::tMOVgpr2tgpr:
  case ARM::tMOVgpr2gpr: {
    if (OpNum == 0) { // move -> store
      unsigned SrcReg = MI->getOperand(1).getReg();
      if (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
          !isARMLowRegister(SrcReg))
        // tSpill cannot take a high register operand.
        return false;
    } else {          // move -> load
      unsigned DstReg = MI->getOperand(0).getReg();
      if (TargetRegisterInfo::isPhysicalRegister(DstReg) &&
          !isARMLowRegister(DstReg))
        // tRestore cannot target a high register operand.
        return false;
    }
    return true;
  }
  }

  return false;
}

void Thumb1InstrInfo::
storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
                    unsigned SrcReg, bool isKill, int FI,
                    const TargetRegisterClass *RC) const {
  DebugLoc DL = DebugLoc::getUnknownLoc();
  if (I != MBB.end()) DL = I->getDebugLoc();

  assert((RC == ARM::tGPRRegisterClass ||
          (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
           isARMLowRegister(SrcReg))) && "Unknown regclass!");

  if (RC == ARM::tGPRRegisterClass) {
    MachineFunction &MF = *MBB.getParent();
    MachineFrameInfo &MFI = *MF.getFrameInfo();
    MachineMemOperand *MMO =
      MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI),
                              MachineMemOperand::MOStore, 0,
                              MFI.getObjectSize(FI),
                              MFI.getObjectAlignment(FI));
    AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tSpill))
                   .addReg(SrcReg, getKillRegState(isKill))
                   .addFrameIndex(FI).addImm(0).addMemOperand(MMO));
  }
}

void Thumb1InstrInfo::
loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
                     unsigned DestReg, int FI,
                     const TargetRegisterClass *RC) const {
  DebugLoc DL = DebugLoc::getUnknownLoc();
  if (I != MBB.end()) DL = I->getDebugLoc();

  assert((RC == ARM::tGPRRegisterClass ||
          (TargetRegisterInfo::isPhysicalRegister(DestReg) &&
           isARMLowRegister(DestReg))) && "Unknown regclass!");

  if (RC == ARM::tGPRRegisterClass) {
    MachineFunction &MF = *MBB.getParent();
    MachineFrameInfo &MFI = *MF.getFrameInfo();
    MachineMemOperand *MMO =
      MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI),
                              MachineMemOperand::MOLoad, 0,
                              MFI.getObjectSize(FI),
                              MFI.getObjectAlignment(FI));
    AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tRestore), DestReg)
                   .addFrameIndex(FI).addImm(0).addMemOperand(MMO));
  }
}

bool Thumb1InstrInfo::
spillCalleeSavedRegisters(MachineBasicBlock &MBB,
                          MachineBasicBlock::iterator MI,
                          const std::vector<CalleeSavedInfo> &CSI) const {
  if (CSI.empty())
    return false;

  DebugLoc DL = DebugLoc::getUnknownLoc();
  if (MI != MBB.end()) DL = MI->getDebugLoc();

  MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get(ARM::tPUSH));
  AddDefaultPred(MIB);
  MIB.addReg(0); // No write back.
  for (unsigned i = CSI.size(); i != 0; --i) {
    unsigned Reg = CSI[i-1].getReg();
    // Add the callee-saved register as live-in. It's killed at the spill.
    MBB.addLiveIn(Reg);
    MIB.addReg(Reg, RegState::Kill);
  }
  return true;
}

bool Thumb1InstrInfo::
restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
                            MachineBasicBlock::iterator MI,
                            const std::vector<CalleeSavedInfo> &CSI) const {
  MachineFunction &MF = *MBB.getParent();
  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  if (CSI.empty())
    return false;

  bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
  DebugLoc DL = MI->getDebugLoc();
  MachineInstrBuilder MIB = BuildMI(MF, DL, get(ARM::tPOP));
  AddDefaultPred(MIB);
  MIB.addReg(0); // No write back.

  bool NumRegs = false;
  for (unsigned i = CSI.size(); i != 0; --i) {
    unsigned Reg = CSI[i-1].getReg();
    if (Reg == ARM::LR) {
      // Special epilogue for vararg functions. See emitEpilogue
      if (isVarArg)
        continue;
      Reg = ARM::PC;
      (*MIB).setDesc(get(ARM::tPOP_RET));
      MI = MBB.erase(MI);
    }
    MIB.addReg(Reg, getDefRegState(true));
    NumRegs = true;
  }

  // It's illegal to emit pop instruction without operands.
  if (NumRegs)
    MBB.insert(MI, &*MIB);

  return true;
}

MachineInstr *Thumb1InstrInfo::
foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
                      const SmallVectorImpl<unsigned> &Ops, int FI) const {
  if (Ops.size() != 1) return NULL;

  unsigned OpNum = Ops[0];
  unsigned Opc = MI->getOpcode();
  MachineInstr *NewMI = NULL;
  switch (Opc) {
  default: break;
  case ARM::tMOVr:
  case ARM::tMOVtgpr2gpr:
  case ARM::tMOVgpr2tgpr:
  case ARM::tMOVgpr2gpr: {
    if (OpNum == 0) { // move -> store
      unsigned SrcReg = MI->getOperand(1).getReg();
      bool isKill = MI->getOperand(1).isKill();
      if (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
          !isARMLowRegister(SrcReg))
        // tSpill cannot take a high register operand.
        break;
      NewMI = AddDefaultPred(BuildMI(MF, MI->getDebugLoc(), get(ARM::tSpill))
                             .addReg(SrcReg, getKillRegState(isKill))
                             .addFrameIndex(FI).addImm(0));
    } else {          // move -> load
      unsigned DstReg = MI->getOperand(0).getReg();
      if (TargetRegisterInfo::isPhysicalRegister(DstReg) &&
          !isARMLowRegister(DstReg))
        // tRestore cannot target a high register operand.
        break;
      bool isDead = MI->getOperand(0).isDead();
      NewMI = AddDefaultPred(BuildMI(MF, MI->getDebugLoc(), get(ARM::tRestore))
                             .addReg(DstReg,
                                     RegState::Define | getDeadRegState(isDead))
                             .addFrameIndex(FI).addImm(0));
    }
    break;
  }
  }

  return NewMI;
}
<|endoftext|>


<commit_before>#include "mbed.h"
#include "greentea-client/test_env.h"
#include "rtos.h"

#if defined(MBED_RTOS_SINGLE_THREAD)
  #error [NOT_SUPPORTED] test not supported
#endif

typedef struct {
    float    voltage;   /* AD result of measured voltage */
    float    current;   /* AD result of measured current */
    uint32_t counter;   /* A counter value               */
} message_t;

#define CREATE_VOLTAGE(COUNTER) (COUNTER * 0.1) * 33
#define CREATE_CURRENT(COUNTER) (COUNTER * 0.1) * 11
#define QUEUE_SIZE       16
#define QUEUE_PUT_DELAY  100

#define TEST_STACK_SIZE 512

MemoryPool<message_t, QUEUE_SIZE> mpool;
Queue<message_t, QUEUE_SIZE> queue;

/* Send Thread */
void send_thread () {
    static uint32_t i = 10;
    while (true) {
        i++; // Fake data update
        message_t *message = mpool.alloc();
        message->voltage = CREATE_VOLTAGE(i);
        message->current = CREATE_CURRENT(i);
        message->counter = i;
        queue.put(message);
        Thread::wait(QUEUE_PUT_DELAY);
    }
}

int main (void) {
    GREENTEA_SETUP(20, "default_auto");

    Thread thread(osPriorityNormal, TEST_STACK_SIZE);
    thread.start(send_thread);
    bool result = true;
    int result_counter = 0;

    while (true) {
        osEvent evt = queue.get();
        if (evt.status == osEventMessage) {
            message_t *message = (message_t*)evt.value.p;
            const float expected_voltage = CREATE_VOLTAGE(message->counter);
            const float expected_current = CREATE_CURRENT(message->counter);
            // Check using macros if received values correspond to values sent via queue
            bool expected_values = (expected_voltage == message->voltage) &&
                                   (expected_current == message->current);
            result = result && expected_values;
            const char *result_msg = expected_values ? "OK" : "FAIL";
            printf("%3d %.2fV %.2fA ... [%s]\r\n", message->counter,
                                                   message->voltage,
                                                   message->current,
                                                   result_msg);
            mpool.free(message);
            if (result == false || ++result_counter == QUEUE_SIZE) {
                break;
            }
        }
    }
    GREENTEA_TESTSUITE_RESULT(result);
    return 0;
}
<commit_msg>Tests: RTOS: Queue: Rework and extend tests<commit_after>#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "rtos.h"

#if defined(MBED_RTOS_SINGLE_THREAD)
  #error [NOT_SUPPORTED] test not supported
#endif

using namespace utest::v1;

#define THREAD_STACK_SIZE 512
#define TEST_UINT_MSG 0xDEADBEEF
#define TEST_UINT_MSG2 0xE1EE7
#define TEST_TIMEOUT 50

template <uint32_t ms>
void thread_put_uint_msg(Queue<uint32_t, 1> *q)
{
    Thread::wait(ms);
    osStatus stat = q->put((uint32_t*) TEST_UINT_MSG);
    TEST_ASSERT_EQUAL(osOK, stat);
}

template <uint32_t ms, uint32_t val>
void thread_get_uint_msg(Queue<uint32_t, 1> *q)
{
    Thread::wait(ms);
    osEvent evt = q->get();
    TEST_ASSERT_EQUAL(osEventMessage, evt.status);
    TEST_ASSERT_EQUAL(val, evt.value.v);
}

/** Test pass uint msg

    Given a queue for uint32_t messages with one slot
    When a uin32_t value is inserted into the queue
        and a message is extracted from the queue
    Then the extracted message is the same as previously inserted message
 */
void test_pass_uint()
{
    Queue<uint32_t, 1> q;
    osStatus stat = q.put((uint32_t*)TEST_UINT_MSG);
    TEST_ASSERT_EQUAL(osOK, stat);

    osEvent evt = q.get();
    TEST_ASSERT_EQUAL(osEventMessage, evt.status);
    TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v);
}

/** Test pass uint msg twice

    Given a queue for uint32_t messages with one slot
    When a uin32_t value is inserted into the queue
        and a message is extracted from the queue
        and the procedure is repeated with different message
    Then the extracted message is the same as previously inserted message for both iterations

 */
void test_pass_uint_twice()
{
    Queue<uint32_t, 1> q;
    osStatus stat = q.put((uint32_t*)TEST_UINT_MSG);
    TEST_ASSERT_EQUAL(osOK, stat);

    osEvent evt = q.get();
    TEST_ASSERT_EQUAL(osEventMessage, evt.status);
    TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v);

    stat = q.put((uint32_t*)TEST_UINT_MSG2);
    TEST_ASSERT_EQUAL(osOK, stat);

    evt = q.get();
    TEST_ASSERT_EQUAL(osEventMessage, evt.status);
    TEST_ASSERT_EQUAL(TEST_UINT_MSG2, evt.value.v);
}

/** Test pass ptr msg

    Given a queue for pointers to uint32_t messages with one slot
    When a pointer to an uint32_t is inserted into the queue
        and a message is extracted from the queue
    Then the extracted message is the same as previously inserted message
 */
void test_pass_ptr()
{
    Queue<uint32_t, 1> q;
    uint32_t msg = TEST_UINT_MSG;

    osStatus stat = q.put(&msg);
    TEST_ASSERT_EQUAL(osOK, stat);

    osEvent evt = q.get();
    TEST_ASSERT_EQUAL(osEventMessage, evt.status);
    TEST_ASSERT_EQUAL(&msg, evt.value.p);
}

/** Test get from empty queue

    Given an empty queue for uint32_t values
    When @a get is called on the queue with timeout of 0
    Then queue returns status of osOK, but no data
 */
void test_get_empty_no_timeout()
{
    Queue<uint32_t, 1> q;

    osEvent evt = q.get(0);
    TEST_ASSERT_EQUAL(osOK, evt.status);
}

/** Test get from empty queue with timeout

    Given an empty queue for uint32_t values
    When @a get is called on the queue with timeout of 50ms
    Then queue returns status of osEventTimeout after about 50ms wait
 */
void test_get_empty_timeout()
{
    Queue<uint32_t, 1> q;
    uint32_t start = us_ticker_read();

    osEvent evt = q.get(50);
    TEST_ASSERT_EQUAL(osEventTimeout, evt.status);
    TEST_ASSERT_UINT32_WITHIN(5000, 50000, us_ticker_read() - start);
}

/** Test get empty wait forever

    Given a two threads A & B and a queue for uint32_t values
    When thread A calls @a get on an empty queue with osWaitForever
    Then the thread A waits for a message to appear in the queue
    When thread B puts a message in the queue
    Then thread A wakes up and receives it
 */
void test_get_empty_wait_forever()
{
    Thread t(osPriorityNormal, THREAD_STACK_SIZE);
    Queue<uint32_t, 1> q;

    t.start(callback(thread_put_uint_msg<TEST_TIMEOUT>, &q));

    uint32_t start = us_ticker_read();

    osEvent evt = q.get();
    TEST_ASSERT_EQUAL(osEventMessage, evt.status);
    TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v);
    TEST_ASSERT_UINT32_WITHIN(TEST_TIMEOUT * 100, TEST_TIMEOUT * 1000, us_ticker_read() - start);
}

/** Test put full no timeout
 *
 * Given a queue with one slot for uint32_t data
 * When a thread tries to insert two messages
 * Then first operation succeeds and second fails with @a osErrorResource
 */
void test_put_full_no_timeout()
{
    Queue<uint32_t, 1> q;

    osStatus stat = q.put((uint32_t*) TEST_UINT_MSG);
    TEST_ASSERT_EQUAL(osOK, stat);

    stat = q.put((uint32_t*) TEST_UINT_MSG);
    TEST_ASSERT_EQUAL(osErrorResource, stat);
}

/** Test put full timeout
 *
 * Given a queue with one slot for uint32_t data
 * When a thread tries to insert two messages with @ TEST_TIMEOUT timeout
 * Then first operation succeeds and second fails with @a osErrorTimeout
 */
void test_put_full_timeout()
{
    Queue<uint32_t, 1> q;

    osStatus stat = q.put((uint32_t*) TEST_UINT_MSG, TEST_TIMEOUT);
    TEST_ASSERT_EQUAL(osOK, stat);

    uint32_t start = us_ticker_read();

    stat = q.put((uint32_t*) TEST_UINT_MSG, TEST_TIMEOUT);
    TEST_ASSERT_EQUAL(osErrorTimeout, stat);
    TEST_ASSERT_UINT32_WITHIN(TEST_TIMEOUT * 100, TEST_TIMEOUT * 1000, us_ticker_read() - start);
}

/** Test put full wait forever
 *
 * Given two threads A & B and a queue with one slot for uint32_t data
 * When thread A puts a message to the queue and tries to put second one with @a osWaitForever timeout
 * Then thread waits for a slot to become empty in the queue
 * When thread B takes one message out of the queue
 * Then thread A successfully inserts message into the queue
 */
void test_put_full_waitforever()
{
    Thread t(osPriorityNormal, THREAD_STACK_SIZE);
    Queue<uint32_t, 1> q;

    t.start(callback(thread_get_uint_msg<TEST_TIMEOUT, TEST_UINT_MSG>, &q));

    osStatus stat = q.put((uint32_t*) TEST_UINT_MSG);
    TEST_ASSERT_EQUAL(osOK, stat);

    uint32_t start = us_ticker_read();
    stat = q.put((uint32_t*) TEST_UINT_MSG, osWaitForever);
    TEST_ASSERT_EQUAL(osOK, stat);
    TEST_ASSERT_UINT32_WITHIN(TEST_TIMEOUT * 100, TEST_TIMEOUT * 1000, us_ticker_read() - start);

    t.join();
}

/** Test message ordering

    Given a queue of uint32_t data
    When two messages are inserted with equal priority
    Then messages should be returned in the exact order they were inserted
 */
void test_msg_order()
{
    Queue<uint32_t, 2> q;

    osStatus stat = q.put((uint32_t*) TEST_UINT_MSG, TEST_TIMEOUT);
    TEST_ASSERT_EQUAL(osOK, stat);

    stat = q.put((uint32_t*) TEST_UINT_MSG2, TEST_TIMEOUT);
    TEST_ASSERT_EQUAL(osOK, stat);

    osEvent evt = q.get();
    TEST_ASSERT_EQUAL(osEventMessage, evt.status);
    TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v);

    evt = q.get();
    TEST_ASSERT_EQUAL(osEventMessage, evt.status);
    TEST_ASSERT_EQUAL(TEST_UINT_MSG2, evt.value.v);
}

/** Test message priority

    Given a queue of uint32_t data
    When two messages are inserted with ascending priority
    Then messages should be returned in descending priority order
 */
void test_msg_prio()
{
    Queue<uint32_t, 2> q;

    osStatus stat = q.put((uint32_t*) TEST_UINT_MSG, TEST_TIMEOUT, 0);
    TEST_ASSERT_EQUAL(osOK, stat);

    stat = q.put((uint32_t*) TEST_UINT_MSG2, TEST_TIMEOUT, 1);
    TEST_ASSERT_EQUAL(osOK, stat);

    osEvent evt = q.get();
    TEST_ASSERT_EQUAL(osEventMessage, evt.status);
    TEST_ASSERT_EQUAL(TEST_UINT_MSG2, evt.value.v);

    evt = q.get();
    TEST_ASSERT_EQUAL(osEventMessage, evt.status);
    TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v);
}

utest::v1::status_t test_setup(const size_t number_of_cases)
{
    GREENTEA_SETUP(5, "default_auto");
    return verbose_test_setup_handler(number_of_cases);
}

Case cases[] = {
    Case("Test pass uint msg", test_pass_uint),
    Case("Test pass uint msg twice", test_pass_uint_twice),
    Case("Test pass ptr msg", test_pass_ptr),
    Case("Test get from empty queue no timeout", test_get_empty_no_timeout),
    Case("Test get from empty queue timeout", test_get_empty_timeout),
    Case("Test get empty wait forever", test_get_empty_wait_forever),
    Case("Test put full no timeout", test_put_full_no_timeout),
    Case("Test put full timeout", test_put_full_timeout),
    Case("Test put full wait forever", test_put_full_waitforever),
    Case("Test message ordering", test_msg_order),
    Case("Test message priority", test_msg_prio)
};

Specification specification(test_setup, cases);

int main()
{
    return !Harness::run(specification);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: tstring.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 01:04:40 $
 *
 *  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_tools.hxx"

#include <string.h>

#include "boost/static_assert.hpp"

#include "osl/diagnose.h"
#ifndef _OSL_INTERLCK_H
#include <osl/interlck.h>
#endif
#ifndef _RTL_ALLOC_H
#include <rtl/alloc.h>
#endif
#ifndef _RTL_MEMORY_H
#include <rtl/memory.h>
#endif
#ifndef _RTL_TENCINFO_H
#include <rtl/tencinfo.h>
#endif
#ifndef INCLUDED_RTL_INSTANCE_HXX
#include <rtl/instance.hxx>
#endif

#include <string.hxx>
#include <impstrg.hxx>

// For shared byte convert tables
#ifndef _TOOLS_TOOLSIN_HXX
#include <toolsin.hxx>
#endif

#include <debug.hxx>

// =======================================================================

DBG_NAME( ByteString )
DBG_NAMEEX( UniString )

// -----------------------------------------------------------------------

#define STRCODE         sal_Char
#define STRCODEU        unsigned char
#define STRING          ByteString
#define STRINGDATA      ByteStringData
#define DBGCHECKSTRING  DbgCheckByteString
#define STRING_TYPE     rtl_String
#define STRING_ACQUIRE  rtl_string_acquire
#define STRING_RELEASE  rtl_string_release
#define STRING_NEW      rtl_string_new

// -----------------------------------------------------------------------

xub_StrLen ImplStringLen( const sal_Char* pStr )
{
    const sal_Char* pTempStr = pStr;
    while( *pTempStr )
        ++pTempStr;
    return (xub_StrLen)(pTempStr-pStr);
}

// -----------------------------------------------------------------------

xub_StrLen ImplStringLen( const sal_Unicode* pStr )
{
    const sal_Unicode* pTempStr = pStr;
    while( *pTempStr )
        ++pTempStr;
    return (xub_StrLen)(pTempStr-pStr);
}

// -----------------------------------------------------------------------

#include <strimp.cxx>
#include <strcvt.cxx>

// -----------------------------------------------------------------------

ByteString ByteString::CreateFromInt32( sal_Int32 n, sal_Int16 nRadix )
{
    sal_Char aBuf[RTL_STR_MAX_VALUEOFINT32];
    BOOST_STATIC_ASSERT(RTL_STR_MAX_VALUEOFINT32 <= STRING_MAXLEN);
    return ByteString(
        aBuf,
        static_cast< xub_StrLen >(rtl_str_valueOfInt32( aBuf, n, nRadix )) );
}

// -----------------------------------------------------------------------

ByteString ByteString::CreateFromInt64( sal_Int64 n, sal_Int16 nRadix )
{
    sal_Char aBuf[RTL_STR_MAX_VALUEOFINT64];
    BOOST_STATIC_ASSERT(RTL_STR_MAX_VALUEOFINT64 <= STRING_MAXLEN);
    return ByteString(
        aBuf,
        static_cast< xub_StrLen >(rtl_str_valueOfInt64( aBuf, n, nRadix )) );
}

// -----------------------------------------------------------------------

ByteString ByteString::CreateFromFloat( float f )
{
    sal_Char aBuf[RTL_STR_MAX_VALUEOFFLOAT];
    BOOST_STATIC_ASSERT(RTL_STR_MAX_VALUEOFFLOAT <= STRING_MAXLEN);
    return ByteString(
        aBuf, static_cast< xub_StrLen >(rtl_str_valueOfFloat( aBuf, f )) );
}

// -----------------------------------------------------------------------

ByteString ByteString::CreateFromDouble( double d )
{
    sal_Char aBuf[RTL_STR_MAX_VALUEOFDOUBLE];
    BOOST_STATIC_ASSERT(RTL_STR_MAX_VALUEOFDOUBLE <= STRING_MAXLEN);
    return ByteString(
        aBuf, static_cast< xub_StrLen >(rtl_str_valueOfDouble( aBuf, d )) );
}

// -----------------------------------------------------------------------

namespace { struct Empty : public rtl::Static< const ByteString, Empty> {}; }
const ByteString& ByteString::EmptyString()
{
    return Empty::get();
}

// -----------------------------------------------------------------------

sal_Int32 ByteString::ToInt32() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    return atoi( mpData->maStr );
}

// -----------------------------------------------------------------------

sal_Int64 ByteString::ToInt64() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    return atoi( mpData->maStr );
}

// -----------------------------------------------------------------------

float ByteString::ToFloat() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    OSL_ENSURE(false, "ByteString::ToFloat unusable");
    return 0;
}

// -----------------------------------------------------------------------

double ByteString::ToDouble() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    OSL_ENSURE(false, "ByteString::ToDouble unusable");
    return 0;
}

// -----------------------------------------------------------------------

BOOL ByteString::IsLowerAscii() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    sal_Int32 nIndex = 0;
    sal_Int32 nLen = mpData->mnLen;
    const sal_Char* pStr = mpData->maStr;
    while ( nIndex < nLen )
    {
        if ( (*pStr >= 65) && (*pStr <= 90) )
            return FALSE;

        ++pStr,
        ++nIndex;
    }

    return TRUE;
}

// -----------------------------------------------------------------------

BOOL ByteString::IsUpperAscii() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    sal_Int32 nIndex = 0;
    sal_Int32 nLen = mpData->mnLen;
    const sal_Char* pStr = mpData->maStr;
    while ( nIndex < nLen )
    {
        if ( (*pStr >= 97) && (*pStr <= 122) )
            return FALSE;

        ++pStr,
        ++nIndex;
    }

    return TRUE;
}

// -----------------------------------------------------------------------

BOOL ByteString::IsAlphaAscii() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    sal_Int32 nIndex = 0;
    sal_Int32 nLen = mpData->mnLen;
    const sal_Char* pStr = mpData->maStr;
    while ( nIndex < nLen )
    {
        if ( !(((*pStr >= 97) && (*pStr <= 122)) ||
               ((*pStr >= 65) && (*pStr <=  90))) )
            return FALSE;

        ++pStr,
        ++nIndex;
    }

    return TRUE;
}

// -----------------------------------------------------------------------

BOOL ByteString::IsNumericAscii() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    sal_Int32 nIndex = 0;
    sal_Int32 nLen = mpData->mnLen;
    const sal_Char* pStr = mpData->maStr;
    while ( nIndex < nLen )
    {
        if ( !((*pStr >= 48) && (*pStr <= 57)) )
            return FALSE;

        ++pStr,
        ++nIndex;
    }

    return TRUE;
}

// -----------------------------------------------------------------------

BOOL ByteString::IsAlphaNumericAscii() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    sal_Int32 nIndex = 0;
    sal_Int32 nLen = mpData->mnLen;
    const sal_Char* pStr = mpData->maStr;
    while ( nIndex < nLen )
    {
        if ( !(((*pStr >= 97) && (*pStr <= 122)) ||
               ((*pStr >= 65) && (*pStr <=  90)) ||
               ((*pStr >= 48) && (*pStr <=  57))) )
            return FALSE;

        ++pStr,
        ++nIndex;
    }

    return TRUE;
}
<commit_msg>INTEGRATION: CWS vgbugs07 (1.9.90); FILE MERGED 2007/06/04 13:32:27 vg 1.9.90.1: #i76605# Remove -I .../inc/module hack introduced by hedaburemove01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: tstring.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 22:20:00 $
 *
 *  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_tools.hxx"

#include <string.h>

#include "boost/static_assert.hpp"

#include "osl/diagnose.h"
#ifndef _OSL_INTERLCK_H
#include <osl/interlck.h>
#endif
#ifndef _RTL_ALLOC_H
#include <rtl/alloc.h>
#endif
#ifndef _RTL_MEMORY_H
#include <rtl/memory.h>
#endif
#ifndef _RTL_TENCINFO_H
#include <rtl/tencinfo.h>
#endif
#ifndef INCLUDED_RTL_INSTANCE_HXX
#include <rtl/instance.hxx>
#endif

#include <tools/string.hxx>
#include <impstrg.hxx>

// For shared byte convert tables
#ifndef _TOOLS_TOOLSIN_HXX
#include <toolsin.hxx>
#endif

#include <tools/debug.hxx>

// =======================================================================

DBG_NAME( ByteString )
DBG_NAMEEX( UniString )

// -----------------------------------------------------------------------

#define STRCODE         sal_Char
#define STRCODEU        unsigned char
#define STRING          ByteString
#define STRINGDATA      ByteStringData
#define DBGCHECKSTRING  DbgCheckByteString
#define STRING_TYPE     rtl_String
#define STRING_ACQUIRE  rtl_string_acquire
#define STRING_RELEASE  rtl_string_release
#define STRING_NEW      rtl_string_new

// -----------------------------------------------------------------------

xub_StrLen ImplStringLen( const sal_Char* pStr )
{
    const sal_Char* pTempStr = pStr;
    while( *pTempStr )
        ++pTempStr;
    return (xub_StrLen)(pTempStr-pStr);
}

// -----------------------------------------------------------------------

xub_StrLen ImplStringLen( const sal_Unicode* pStr )
{
    const sal_Unicode* pTempStr = pStr;
    while( *pTempStr )
        ++pTempStr;
    return (xub_StrLen)(pTempStr-pStr);
}

// -----------------------------------------------------------------------

#include <strimp.cxx>
#include <strcvt.cxx>

// -----------------------------------------------------------------------

ByteString ByteString::CreateFromInt32( sal_Int32 n, sal_Int16 nRadix )
{
    sal_Char aBuf[RTL_STR_MAX_VALUEOFINT32];
    BOOST_STATIC_ASSERT(RTL_STR_MAX_VALUEOFINT32 <= STRING_MAXLEN);
    return ByteString(
        aBuf,
        static_cast< xub_StrLen >(rtl_str_valueOfInt32( aBuf, n, nRadix )) );
}

// -----------------------------------------------------------------------

ByteString ByteString::CreateFromInt64( sal_Int64 n, sal_Int16 nRadix )
{
    sal_Char aBuf[RTL_STR_MAX_VALUEOFINT64];
    BOOST_STATIC_ASSERT(RTL_STR_MAX_VALUEOFINT64 <= STRING_MAXLEN);
    return ByteString(
        aBuf,
        static_cast< xub_StrLen >(rtl_str_valueOfInt64( aBuf, n, nRadix )) );
}

// -----------------------------------------------------------------------

ByteString ByteString::CreateFromFloat( float f )
{
    sal_Char aBuf[RTL_STR_MAX_VALUEOFFLOAT];
    BOOST_STATIC_ASSERT(RTL_STR_MAX_VALUEOFFLOAT <= STRING_MAXLEN);
    return ByteString(
        aBuf, static_cast< xub_StrLen >(rtl_str_valueOfFloat( aBuf, f )) );
}

// -----------------------------------------------------------------------

ByteString ByteString::CreateFromDouble( double d )
{
    sal_Char aBuf[RTL_STR_MAX_VALUEOFDOUBLE];
    BOOST_STATIC_ASSERT(RTL_STR_MAX_VALUEOFDOUBLE <= STRING_MAXLEN);
    return ByteString(
        aBuf, static_cast< xub_StrLen >(rtl_str_valueOfDouble( aBuf, d )) );
}

// -----------------------------------------------------------------------

namespace { struct Empty : public rtl::Static< const ByteString, Empty> {}; }
const ByteString& ByteString::EmptyString()
{
    return Empty::get();
}

// -----------------------------------------------------------------------

sal_Int32 ByteString::ToInt32() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    return atoi( mpData->maStr );
}

// -----------------------------------------------------------------------

sal_Int64 ByteString::ToInt64() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    return atoi( mpData->maStr );
}

// -----------------------------------------------------------------------

float ByteString::ToFloat() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    OSL_ENSURE(false, "ByteString::ToFloat unusable");
    return 0;
}

// -----------------------------------------------------------------------

double ByteString::ToDouble() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    OSL_ENSURE(false, "ByteString::ToDouble unusable");
    return 0;
}

// -----------------------------------------------------------------------

BOOL ByteString::IsLowerAscii() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    sal_Int32 nIndex = 0;
    sal_Int32 nLen = mpData->mnLen;
    const sal_Char* pStr = mpData->maStr;
    while ( nIndex < nLen )
    {
        if ( (*pStr >= 65) && (*pStr <= 90) )
            return FALSE;

        ++pStr,
        ++nIndex;
    }

    return TRUE;
}

// -----------------------------------------------------------------------

BOOL ByteString::IsUpperAscii() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    sal_Int32 nIndex = 0;
    sal_Int32 nLen = mpData->mnLen;
    const sal_Char* pStr = mpData->maStr;
    while ( nIndex < nLen )
    {
        if ( (*pStr >= 97) && (*pStr <= 122) )
            return FALSE;

        ++pStr,
        ++nIndex;
    }

    return TRUE;
}

// -----------------------------------------------------------------------

BOOL ByteString::IsAlphaAscii() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    sal_Int32 nIndex = 0;
    sal_Int32 nLen = mpData->mnLen;
    const sal_Char* pStr = mpData->maStr;
    while ( nIndex < nLen )
    {
        if ( !(((*pStr >= 97) && (*pStr <= 122)) ||
               ((*pStr >= 65) && (*pStr <=  90))) )
            return FALSE;

        ++pStr,
        ++nIndex;
    }

    return TRUE;
}

// -----------------------------------------------------------------------

BOOL ByteString::IsNumericAscii() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    sal_Int32 nIndex = 0;
    sal_Int32 nLen = mpData->mnLen;
    const sal_Char* pStr = mpData->maStr;
    while ( nIndex < nLen )
    {
        if ( !((*pStr >= 48) && (*pStr <= 57)) )
            return FALSE;

        ++pStr,
        ++nIndex;
    }

    return TRUE;
}

// -----------------------------------------------------------------------

BOOL ByteString::IsAlphaNumericAscii() const
{
    DBG_CHKTHIS( ByteString, DbgCheckByteString );

    sal_Int32 nIndex = 0;
    sal_Int32 nLen = mpData->mnLen;
    const sal_Char* pStr = mpData->maStr;
    while ( nIndex < nLen )
    {
        if ( !(((*pStr >= 97) && (*pStr <= 122)) ||
               ((*pStr >= 65) && (*pStr <=  90)) ||
               ((*pStr >= 48) && (*pStr <=  57))) )
            return FALSE;

        ++pStr,
        ++nIndex;
    }

    return TRUE;
}
<|endoftext|>


<commit_before><commit_msg>fixed system time reading method.<commit_after><|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "benchmarker.h"
#include "commandlineparser.h"
#include "exception.h"

#include <QtCore/qcoreapplication.h>

#include <cstdlib>
#include <iostream>

using namespace qbsBenchmarker;

static bool hasRegression = false;

static int relativeChange(qint64 oldVal, qint64 newVal)
{
    return newVal == 0 ? 0 : newVal * 100 / oldVal - 100;
}

static QByteArray relativeChangeString(int change)
{
    QByteArray changeString = QByteArray::number(change);
    changeString += " %";
    if (change > 0)
        changeString.prepend('+');
    return changeString;
}

static void printResults(Activity activity, const BenchmarkResults &results,
                         int regressionThreshold)
{
    std::cout << "========== Performance data for ";
    switch (activity) {
    case ActivityResolving:
        std::cout << "Resolving";
        break;
    case ActivityRuleExecution:
        std::cout << "Rule Execution";
        break;
    case ActivityNullBuild:
        std::cout << "Null Build";
        break;
    }
    std::cout << " ==========" << std::endl;
    const BenchmarkResult result = results.value(activity);
    const char * const indent = "    ";
    std::cout << indent << "Old instruction count: " << result.oldInstructionCount << std::endl;
    std::cout << indent << "New instruction count: " << result.newInstructionCount << std::endl;
    int change = relativeChange(result.oldInstructionCount, result.newInstructionCount);
    if (change > regressionThreshold)
        hasRegression = true;
    std::cout << indent << "Relative change: "
              << relativeChangeString(change).constData()
              << std::endl;
    std::cout << indent << "Old peak memory usage: " << result.oldPeakMemoryUsage << " Bytes"
              << std::endl;
    std::cout << indent
              << "New peak memory usage: " << result.newPeakMemoryUsage << " Bytes" << std::endl;
    change = relativeChange(result.oldPeakMemoryUsage, result.newPeakMemoryUsage);
    if (change > regressionThreshold)
        hasRegression = true;
    std::cout << indent << "Relative change: "
              << relativeChangeString(change).constData()
              << std::endl;
}

static void printResults(Activities activities, const BenchmarkResults &results,
                         int regressionThreshold)
{
    if (activities & ActivityResolving)
        printResults(ActivityResolving, results, regressionThreshold);
    if (activities & ActivityRuleExecution)
        printResults(ActivityRuleExecution, results, regressionThreshold);
    if (activities & ActivityNullBuild)
        printResults(ActivityNullBuild, results, regressionThreshold);
}

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    CommandLineParser clParser;
    clParser.parse();
    Benchmarker benchmarker(clParser.activies(), clParser.oldCommit(), clParser.newCommit(),
                            clParser.testProjectFilePath(), clParser.qbsRepoDirPath());
    try {
        benchmarker.benchmark();
        printResults(clParser.activies(), benchmarker.results(), clParser.regressionThreshold());
        if (hasRegression) {
            benchmarker.keepRawData();
            std::cout << "Performance regression detected. Raw benchmarking data available "
                         "under " << qPrintable(benchmarker.rawDataBaseDir()) << '.' << std::endl;
        }
    } catch (const Exception &e) {
        benchmarker.keepRawData();
        std::cerr << qPrintable(e.description()) << std::endl;
        std::cerr << "Build data available under " << qPrintable(benchmarker.rawDataBaseDir())
                  << '.' << std::endl;
        return EXIT_FAILURE;
    }
}
<commit_msg>benchmarker: Fix crash when called with no parameters<commit_after>/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "benchmarker.h"
#include "commandlineparser.h"
#include "exception.h"

#include <QtCore/qcoreapplication.h>

#include <cstdlib>
#include <iostream>

using namespace qbsBenchmarker;

static bool hasRegression = false;

static int relativeChange(qint64 oldVal, qint64 newVal)
{
    return newVal == 0 ? 0 : newVal * 100 / oldVal - 100;
}

static QByteArray relativeChangeString(int change)
{
    QByteArray changeString = QByteArray::number(change);
    changeString += " %";
    if (change > 0)
        changeString.prepend('+');
    return changeString;
}

static void printResults(Activity activity, const BenchmarkResults &results,
                         int regressionThreshold)
{
    std::cout << "========== Performance data for ";
    switch (activity) {
    case ActivityResolving:
        std::cout << "Resolving";
        break;
    case ActivityRuleExecution:
        std::cout << "Rule Execution";
        break;
    case ActivityNullBuild:
        std::cout << "Null Build";
        break;
    }
    std::cout << " ==========" << std::endl;
    const BenchmarkResult result = results.value(activity);
    const char * const indent = "    ";
    std::cout << indent << "Old instruction count: " << result.oldInstructionCount << std::endl;
    std::cout << indent << "New instruction count: " << result.newInstructionCount << std::endl;
    int change = relativeChange(result.oldInstructionCount, result.newInstructionCount);
    if (change > regressionThreshold)
        hasRegression = true;
    std::cout << indent << "Relative change: "
              << relativeChangeString(change).constData()
              << std::endl;
    std::cout << indent << "Old peak memory usage: " << result.oldPeakMemoryUsage << " Bytes"
              << std::endl;
    std::cout << indent
              << "New peak memory usage: " << result.newPeakMemoryUsage << " Bytes" << std::endl;
    change = relativeChange(result.oldPeakMemoryUsage, result.newPeakMemoryUsage);
    if (change > regressionThreshold)
        hasRegression = true;
    std::cout << indent << "Relative change: "
              << relativeChangeString(change).constData()
              << std::endl;
}

static void printResults(Activities activities, const BenchmarkResults &results,
                         int regressionThreshold)
{
    if (activities & ActivityResolving)
        printResults(ActivityResolving, results, regressionThreshold);
    if (activities & ActivityRuleExecution)
        printResults(ActivityRuleExecution, results, regressionThreshold);
    if (activities & ActivityNullBuild)
        printResults(ActivityNullBuild, results, regressionThreshold);
}

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    CommandLineParser clParser;
    try {
        clParser.parse();
    } catch (const Exception &e) {
        std::cerr << qPrintable(e.description()) << std::endl;
        return EXIT_FAILURE;
    }

    Benchmarker benchmarker(clParser.activies(), clParser.oldCommit(), clParser.newCommit(),
                            clParser.testProjectFilePath(), clParser.qbsRepoDirPath());
    try {
        benchmarker.benchmark();
        printResults(clParser.activies(), benchmarker.results(), clParser.regressionThreshold());
        if (hasRegression) {
            benchmarker.keepRawData();
            std::cout << "Performance regression detected. Raw benchmarking data available "
                         "under " << qPrintable(benchmarker.rawDataBaseDir()) << '.' << std::endl;
        }
    } catch (const Exception &e) {
        benchmarker.keepRawData();
        std::cerr << qPrintable(e.description()) << std::endl;
        std::cerr << "Build data available under " << qPrintable(benchmarker.rawDataBaseDir())
                  << '.' << std::endl;
        return EXIT_FAILURE;
    }
}
<|endoftext|>


<commit_before>#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "SkXfermode.h"
#include "SkColorPriv.h"
#include "SkColorFilter.h"
#include "SkTime.h"
#include "SkTypeface.h"

#include "SkOSFile.h"
#include "SkStream.h"

#include "SkGpuDevice.h"

static SkDevice* make_bitmap(SkBitmap* bitmap, GrContext* ctx) {
    SkCanvas canvas;

    if (ctx) {
        SkDevice* dev = new SkGpuDevice(ctx, SkBitmap::kARGB_8888_Config, 64, 64);
        canvas.setDevice(dev)->unref();
        *bitmap = dev->accessBitmap(false);
    } else {
        bitmap->setConfig(SkBitmap::kARGB_8888_Config, 64, 64);
        bitmap->allocPixels();
        canvas.setBitmapDevice(*bitmap);
    }

    canvas.drawColor(SK_ColorRED);
    SkPaint paint;
    paint.setAntiAlias(true);
    const SkPoint pts[] = { { 0, 0 }, { 64, 64 } };
    const SkColor colors[] = { SK_ColorWHITE, SK_ColorBLUE };
    paint.setShader(SkGradientShader::CreateLinear(pts, colors, NULL, 2,
                                                   SkShader::kClamp_TileMode))->unref();
    canvas.drawCircle(32, 32, 32, paint);
}

class BitmapRectView : public SampleView {
public:
	BitmapRectView() {
        this->setBGColor(SK_ColorGRAY);
    }

protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "BitmapRect");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    virtual void onDrawContent(SkCanvas* canvas) {
        const SkIRect src[] = {
            { 0, 0, 32, 32 },
            { 0, 0, 80, 80 },
            { 32, 32, 96, 96 },
            { -32, -32, 32, 32, }
        };

        SkPaint paint;
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setColor(SK_ColorGREEN);

        SkBitmap bitmap;
        make_bitmap(&bitmap, NULL /*SampleCode::GetGr()*/);

        SkRect dstR = { 0, 200, 128, 380 };

        canvas->translate(16, 40);
        for (size_t i = 0; i < SK_ARRAY_COUNT(src); i++) {
            SkRect srcR;
            srcR.set(src[i]);

            canvas->drawBitmap(bitmap, 0, 0, &paint);
            canvas->drawBitmapRect(bitmap, &src[i], dstR, &paint);

            canvas->drawRect(dstR, paint);
            canvas->drawRect(srcR, paint);

            canvas->translate(160, 0);
        }
    }

private:
    typedef SkView INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory() { return new BitmapRectView; }
static SkViewRegister reg(MyFactory);

<commit_msg>fix return value for make_bitmap<commit_after>#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "SkXfermode.h"
#include "SkColorPriv.h"
#include "SkColorFilter.h"
#include "SkTime.h"
#include "SkTypeface.h"

#include "SkOSFile.h"
#include "SkStream.h"

#include "SkGpuDevice.h"

static void make_bitmap(SkBitmap* bitmap, GrContext* ctx) {
    SkCanvas canvas;

    if (ctx) {
        SkDevice* dev = new SkGpuDevice(ctx, SkBitmap::kARGB_8888_Config, 64, 64);
        canvas.setDevice(dev)->unref();
        *bitmap = dev->accessBitmap(false);
    } else {
        bitmap->setConfig(SkBitmap::kARGB_8888_Config, 64, 64);
        bitmap->allocPixels();
        canvas.setBitmapDevice(*bitmap);
    }

    canvas.drawColor(SK_ColorRED);
    SkPaint paint;
    paint.setAntiAlias(true);
    const SkPoint pts[] = { { 0, 0 }, { 64, 64 } };
    const SkColor colors[] = { SK_ColorWHITE, SK_ColorBLUE };
    paint.setShader(SkGradientShader::CreateLinear(pts, colors, NULL, 2,
                                                   SkShader::kClamp_TileMode))->unref();
    canvas.drawCircle(32, 32, 32, paint);
}

class BitmapRectView : public SampleView {
public:
	BitmapRectView() {
        this->setBGColor(SK_ColorGRAY);
    }

protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "BitmapRect");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    virtual void onDrawContent(SkCanvas* canvas) {
        GrContext* ctx = NULL;//SampleCode::GetGr();

        const SkIRect src[] = {
            { 0, 0, 32, 32 },
            { 0, 0, 80, 80 },
            { 32, 32, 96, 96 },
            { -32, -32, 32, 32, }
        };

        SkPaint paint;
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setColor(ctx ? SK_ColorGREEN : SK_ColorYELLOW);

        SkBitmap bitmap;
        make_bitmap(&bitmap, ctx);

        SkRect dstR = { 0, 200, 128, 380 };

        canvas->translate(16, 40);
        for (size_t i = 0; i < SK_ARRAY_COUNT(src); i++) {
            SkRect srcR;
            srcR.set(src[i]);

            canvas->drawBitmap(bitmap, 0, 0, &paint);
            canvas->drawBitmapRect(bitmap, &src[i], dstR, &paint);

            canvas->drawRect(dstR, paint);
            canvas->drawRect(srcR, paint);

            canvas->translate(160, 0);
        }
    }

private:
    typedef SkView INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory() { return new BitmapRectView; }
static SkViewRegister reg(MyFactory);

<|endoftext|>