<commit_before>//=-- InstrProf.cpp - Instrumented profiling format support -----------------=//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains support for clang's instrumentation based PGO and
// coverage.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"

using namespace llvm;

namespace {
class InstrProfErrorCategoryType : public std::error_category {
  const char *name() const LLVM_NOEXCEPT override { return "llvm.instrprof"; }
  std::string message(int IE) const override {
    instrprof_error E = static_cast<instrprof_error>(IE);
    switch (E) {
    case instrprof_error::success:
      return "Success";
    case instrprof_error::eof:
      return "End of File";
    case instrprof_error::unrecognized_format:
      return "Unrecognized instrumentation profile encoding format";
    case instrprof_error::bad_magic:
      return "Invalid instrumentation profile data (bad magic)";
    case instrprof_error::bad_header:
      return "Invalid instrumentation profile data (file header is corrupt)";
    case instrprof_error::unsupported_version:
      return "Unsupported instrumentation profile format version";
    case instrprof_error::unsupported_hash_type:
      return "Unsupported instrumentation profile hash type";
    case instrprof_error::too_large:
      return "Too much profile data";
    case instrprof_error::truncated:
      return "Truncated profile data";
    case instrprof_error::malformed:
      return "Malformed instrumentation profile data";
    case instrprof_error::unknown_function:
      return "No profile data available for function";
    case instrprof_error::hash_mismatch:
      return "Function control flow change detected (hash mismatch)";
    case instrprof_error::count_mismatch:
      return "Function basic block count change detected (counter mismatch)";
    case instrprof_error::counter_overflow:
      return "Counter overflow";
    case instrprof_error::value_site_count_mismatch:
      return "Function value site count change detected (counter mismatch)";
    }
    llvm_unreachable("A value of instrprof_error has no message.");
  }
};
}

static ManagedStatic<InstrProfErrorCategoryType> ErrorCategory;

const std::error_category &llvm::instrprof_category() {
  return *ErrorCategory;
}

namespace llvm {

std::string getPGOFuncName(StringRef RawFuncName,
                           GlobalValue::LinkageTypes Linkage,
                           StringRef FileName) {

  // Function names may be prefixed with a binary '1' to indicate
  // that the backend should not modify the symbols due to any platform
  // naming convention. Do not include that '1' in the PGO profile name.
  if (RawFuncName[0] == '\1')
    RawFuncName = RawFuncName.substr(1);

  std::string FuncName = RawFuncName;
  if (llvm::GlobalValue::isLocalLinkage(Linkage)) {
    // For local symbols, prepend the main file name to distinguish them.
    // Do not include the full path in the file name since there's no guarantee
    // that it will stay the same, e.g., if the files are checked out from
    // version control in different locations.
    if (FileName.empty())
      FuncName = FuncName.insert(0, "<unknown>:");
    else
      FuncName = FuncName.insert(0, FileName.str() + ":");
  }
  return FuncName;
}

std::string getPGOFuncName(const Function &F) {
  return getPGOFuncName(F.getName(), F.getLinkage(), F.getParent()->getName());
}

GlobalVariable *createPGOFuncNameVar(Module &M,
                                     GlobalValue::LinkageTypes Linkage,
                                     StringRef FuncName) {

  // We generally want to match the function's linkage, but available_externally
  // and extern_weak both have the wrong semantics, and anything that doesn't
  // need to link across compilation units doesn't need to be visible at all.
  if (Linkage == GlobalValue::ExternalWeakLinkage)
    Linkage = GlobalValue::LinkOnceAnyLinkage;
  else if (Linkage == GlobalValue::AvailableExternallyLinkage)
    Linkage = GlobalValue::LinkOnceODRLinkage;
  else if (Linkage == GlobalValue::InternalLinkage ||
           Linkage == GlobalValue::ExternalLinkage)
    Linkage = GlobalValue::PrivateLinkage;

  auto *Value = ConstantDataArray::getString(M.getContext(), FuncName, false);
  auto FuncNameVar =
      new GlobalVariable(M, Value->getType(), true, Linkage, Value,
                         Twine(getInstrProfNameVarPrefix()) + FuncName);

  // Hide the symbol so that we correctly get a copy for each executable.
  if (!GlobalValue::isLocalLinkage(FuncNameVar->getLinkage()))
    FuncNameVar->setVisibility(GlobalValue::HiddenVisibility);

  return FuncNameVar;
}

GlobalVariable *createPGOFuncNameVar(Function &F, StringRef FuncName) {
  return createPGOFuncNameVar(*F.getParent(), F.getLinkage(), FuncName);
}

uint64_t stringToHash(uint32_t ValueKind, uint64_t Value) {
  switch (ValueKind) {
  case IPVK_IndirectCallTarget:
    return IndexedInstrProf::ComputeHash(IndexedInstrProf::HashType,
                                         (const char *)Value);
    break;
  default:
    llvm_unreachable("value kind not handled !");
  }
  return Value;
}

void ValueProfRecord::deserializeTo(InstrProfRecord &Record,
                                    InstrProfRecord::ValueMapType *VMap) {
  Record.reserveSites(Kind, NumValueSites);

  InstrProfValueData *ValueData = this->getValueData();
  for (uint64_t VSite = 0; VSite < NumValueSites; ++VSite) {
    uint8_t ValueDataCount = this->SiteCountArray[VSite];
    Record.addValueData(Kind, VSite, ValueData, ValueDataCount, VMap);
    ValueData += ValueDataCount;
  }
}

void ValueProfRecord::serializeFrom(const InstrProfRecord &Record,
                                    uint32_t ValueKind,
                                    uint32_t NumValueSites) {
  Kind = ValueKind;
  this->NumValueSites = NumValueSites;
  InstrProfValueData *DstVD = getValueData();
  for (uint32_t S = 0; S < NumValueSites; S++) {
    uint32_t ND = Record.getNumValueDataForSite(ValueKind, S);
    SiteCountArray[S] = ND;
    Record.getValueForSite(DstVD, ValueKind, S, stringToHash);
    DstVD += ND;
  }
}

template <class T>
static T swapToHostOrder(const unsigned char *&D, support::endianness Orig) {
  using namespace support;
  if (Orig == little)
    return endian::readNext<T, little, unaligned>(D);
  else
    return endian::readNext<T, big, unaligned>(D);
}

// For writing/serializing,  Old is the host endianness, and  New is
// byte order intended on disk. For Reading/deserialization, Old
// is the on-disk source endianness, and New is the host endianness.
void ValueProfRecord::swapBytes(support::endianness Old,
                                support::endianness New) {
  using namespace support;
  if (Old == New)
    return;

  if (getHostEndianness() != Old) {
    sys::swapByteOrder<uint32_t>(NumValueSites);
    sys::swapByteOrder<uint32_t>(Kind);
  }
  uint32_t ND = getNumValueData();
  InstrProfValueData *VD = getValueData();

  // No need to swap byte array: SiteCountArrray.
  for (uint32_t I = 0; I < ND; I++) {
    sys::swapByteOrder<uint64_t>(VD[I].Value);
    sys::swapByteOrder<uint64_t>(VD[I].Count);
  }
  if (getHostEndianness() == Old) {
    sys::swapByteOrder<uint32_t>(NumValueSites);
    sys::swapByteOrder<uint32_t>(Kind);
  }
}

uint32_t ValueProfData::getSize(const InstrProfRecord &Record) {
  uint32_t TotalSize = sizeof(ValueProfData);
  uint32_t NumValueKinds = Record.getNumValueKinds();
  if (NumValueKinds == 0)
    return TotalSize;

  for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
    uint32_t NumValueSites = Record.getNumValueSites(Kind);
    if (!NumValueSites)
      continue;
    TotalSize +=
        getValueProfRecordSize(NumValueSites, Record.getNumValueData(Kind));
  }
  return TotalSize;
}

void ValueProfData::deserializeTo(InstrProfRecord &Record,
                                  InstrProfRecord::ValueMapType *VMap) {
  if (NumValueKinds == 0)
    return;

  ValueProfRecord *VR = getFirstValueProfRecord();
  for (uint32_t K = 0; K < NumValueKinds; K++) {
    VR->deserializeTo(Record, VMap);
    VR = VR->getNext();
  }
}

static std::unique_ptr<ValueProfData> AllocValueProfData(uint32_t TotalSize) {
  return std::unique_ptr<ValueProfData>(new (::operator new(TotalSize))
                                            ValueProfData());
}

std::unique_ptr<ValueProfData>
ValueProfData::serializeFrom(const InstrProfRecord &Record) {
  uint32_t TotalSize = getSize(Record);

  std::unique_ptr<ValueProfData> VPD = AllocValueProfData(TotalSize);

  VPD->TotalSize = TotalSize;
  VPD->NumValueKinds = Record.getNumValueKinds();
  ValueProfRecord *VR = VPD->getFirstValueProfRecord();
  for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
    uint32_t NumValueSites = Record.getNumValueSites(Kind);
    if (!NumValueSites)
      continue;
    VR->serializeFrom(Record, Kind, NumValueSites);
    VR = VR->getNext();
  }
  return VPD;
}

ErrorOr<std::unique_ptr<ValueProfData>>
ValueProfData::getValueProfData(const unsigned char *D,
                                const unsigned char *const BufferEnd,
                                support::endianness Endianness) {
  using namespace support;
  if (D + sizeof(ValueProfData) > BufferEnd)
    return instrprof_error::truncated;

  const unsigned char *Header = D;
  uint32_t TotalSize = swapToHostOrder<uint32_t>(Header, Endianness);
  uint32_t NumValueKinds = swapToHostOrder<uint32_t>(Header, Endianness);

  if (D + TotalSize > BufferEnd)
    return instrprof_error::too_large;
  if (NumValueKinds > IPVK_Last + 1)
    return instrprof_error::malformed;
  // Total size needs to be mulltiple of quadword size.
  if (TotalSize % sizeof(uint64_t))
    return instrprof_error::malformed;

  std::unique_ptr<ValueProfData> VPD = AllocValueProfData(TotalSize);

  memcpy(VPD.get(), D, TotalSize);
  // Byte swap.
  VPD->swapBytesToHost(Endianness);

  // Data integrety check:
  ValueProfRecord *VR = VPD->getFirstValueProfRecord();
  for (uint32_t K = 0; K < VPD->NumValueKinds; K++) {
    if (VR->Kind > IPVK_Last)
      return instrprof_error::malformed;
    VR = VR->getNext();
    if ((char *)VR - (char *)VPD.get() > (ptrdiff_t)TotalSize)
      return instrprof_error::malformed;
  }

  return std::move(VPD);
}

void ValueProfData::swapBytesToHost(support::endianness Endianness) {
  using namespace support;
  if (Endianness == getHostEndianness())
    return;

  sys::swapByteOrder<uint32_t>(TotalSize);
  sys::swapByteOrder<uint32_t>(NumValueKinds);

  ValueProfRecord *VR = getFirstValueProfRecord();
  for (uint32_t K = 0; K < NumValueKinds; K++) {
    VR->swapBytes(Endianness, getHostEndianness());
    VR = VR->getNext();
  }
}

void ValueProfData::swapBytesFromHost(support::endianness Endianness) {
  using namespace support;
  if (Endianness == getHostEndianness())
    return;

  ValueProfRecord *VR = getFirstValueProfRecord();
  for (uint32_t K = 0; K < NumValueKinds; K++) {
    ValueProfRecord *NVR = VR->getNext();
    VR->swapBytes(getHostEndianness(), Endianness);
    VR = NVR;
  }
  sys::swapByteOrder<uint32_t>(TotalSize);
  sys::swapByteOrder<uint32_t>(NumValueKinds);
}

ValueProfRecord *ValueProfData::getFirstValueProfRecord() {
  return reinterpret_cast<ValueProfRecord *>((char *)this +
                                             sizeof(ValueProfData));
}

uint32_t ValueProfRecord::getNumValueData() const {
  uint32_t NumValueData = 0;
  for (uint32_t I = 0; I < NumValueSites; I++)
    NumValueData += SiteCountArray[I];
  return NumValueData;
}

ValueProfRecord *ValueProfRecord::getNext() {
  return reinterpret_cast<ValueProfRecord *>((char *)this + getSize());
}

InstrProfValueData *ValueProfRecord::getValueData() {
  return reinterpret_cast<InstrProfValueData *>(
      (char *)this + getValueProfRecordHeaderSize(NumValueSites));
}
}
<commit_msg>Move member functions closer to others of the same class (NFC)<commit_after>//=-- InstrProf.cpp - Instrumented profiling format support -----------------=//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains support for clang's instrumentation based PGO and
// coverage.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"

using namespace llvm;

namespace {
class InstrProfErrorCategoryType : public std::error_category {
  const char *name() const LLVM_NOEXCEPT override { return "llvm.instrprof"; }
  std::string message(int IE) const override {
    instrprof_error E = static_cast<instrprof_error>(IE);
    switch (E) {
    case instrprof_error::success:
      return "Success";
    case instrprof_error::eof:
      return "End of File";
    case instrprof_error::unrecognized_format:
      return "Unrecognized instrumentation profile encoding format";
    case instrprof_error::bad_magic:
      return "Invalid instrumentation profile data (bad magic)";
    case instrprof_error::bad_header:
      return "Invalid instrumentation profile data (file header is corrupt)";
    case instrprof_error::unsupported_version:
      return "Unsupported instrumentation profile format version";
    case instrprof_error::unsupported_hash_type:
      return "Unsupported instrumentation profile hash type";
    case instrprof_error::too_large:
      return "Too much profile data";
    case instrprof_error::truncated:
      return "Truncated profile data";
    case instrprof_error::malformed:
      return "Malformed instrumentation profile data";
    case instrprof_error::unknown_function:
      return "No profile data available for function";
    case instrprof_error::hash_mismatch:
      return "Function control flow change detected (hash mismatch)";
    case instrprof_error::count_mismatch:
      return "Function basic block count change detected (counter mismatch)";
    case instrprof_error::counter_overflow:
      return "Counter overflow";
    case instrprof_error::value_site_count_mismatch:
      return "Function value site count change detected (counter mismatch)";
    }
    llvm_unreachable("A value of instrprof_error has no message.");
  }
};
}

static ManagedStatic<InstrProfErrorCategoryType> ErrorCategory;

const std::error_category &llvm::instrprof_category() {
  return *ErrorCategory;
}

namespace llvm {

std::string getPGOFuncName(StringRef RawFuncName,
                           GlobalValue::LinkageTypes Linkage,
                           StringRef FileName) {

  // Function names may be prefixed with a binary '1' to indicate
  // that the backend should not modify the symbols due to any platform
  // naming convention. Do not include that '1' in the PGO profile name.
  if (RawFuncName[0] == '\1')
    RawFuncName = RawFuncName.substr(1);

  std::string FuncName = RawFuncName;
  if (llvm::GlobalValue::isLocalLinkage(Linkage)) {
    // For local symbols, prepend the main file name to distinguish them.
    // Do not include the full path in the file name since there's no guarantee
    // that it will stay the same, e.g., if the files are checked out from
    // version control in different locations.
    if (FileName.empty())
      FuncName = FuncName.insert(0, "<unknown>:");
    else
      FuncName = FuncName.insert(0, FileName.str() + ":");
  }
  return FuncName;
}

std::string getPGOFuncName(const Function &F) {
  return getPGOFuncName(F.getName(), F.getLinkage(), F.getParent()->getName());
}

GlobalVariable *createPGOFuncNameVar(Module &M,
                                     GlobalValue::LinkageTypes Linkage,
                                     StringRef FuncName) {

  // We generally want to match the function's linkage, but available_externally
  // and extern_weak both have the wrong semantics, and anything that doesn't
  // need to link across compilation units doesn't need to be visible at all.
  if (Linkage == GlobalValue::ExternalWeakLinkage)
    Linkage = GlobalValue::LinkOnceAnyLinkage;
  else if (Linkage == GlobalValue::AvailableExternallyLinkage)
    Linkage = GlobalValue::LinkOnceODRLinkage;
  else if (Linkage == GlobalValue::InternalLinkage ||
           Linkage == GlobalValue::ExternalLinkage)
    Linkage = GlobalValue::PrivateLinkage;

  auto *Value = ConstantDataArray::getString(M.getContext(), FuncName, false);
  auto FuncNameVar =
      new GlobalVariable(M, Value->getType(), true, Linkage, Value,
                         Twine(getInstrProfNameVarPrefix()) + FuncName);

  // Hide the symbol so that we correctly get a copy for each executable.
  if (!GlobalValue::isLocalLinkage(FuncNameVar->getLinkage()))
    FuncNameVar->setVisibility(GlobalValue::HiddenVisibility);

  return FuncNameVar;
}

GlobalVariable *createPGOFuncNameVar(Function &F, StringRef FuncName) {
  return createPGOFuncNameVar(*F.getParent(), F.getLinkage(), FuncName);
}

uint64_t stringToHash(uint32_t ValueKind, uint64_t Value) {
  switch (ValueKind) {
  case IPVK_IndirectCallTarget:
    return IndexedInstrProf::ComputeHash(IndexedInstrProf::HashType,
                                         (const char *)Value);
    break;
  default:
    llvm_unreachable("value kind not handled !");
  }
  return Value;
}

uint32_t ValueProfRecord::getNumValueData() const {
  uint32_t NumValueData = 0;
  for (uint32_t I = 0; I < NumValueSites; I++)
    NumValueData += SiteCountArray[I];
  return NumValueData;
}

ValueProfRecord *ValueProfRecord::getNext() {
  return reinterpret_cast<ValueProfRecord *>((char *)this + getSize());
}

InstrProfValueData *ValueProfRecord::getValueData() {
  return reinterpret_cast<InstrProfValueData *>(
      (char *)this + getValueProfRecordHeaderSize(NumValueSites));
}

void ValueProfRecord::deserializeTo(InstrProfRecord &Record,
                                    InstrProfRecord::ValueMapType *VMap) {
  Record.reserveSites(Kind, NumValueSites);

  InstrProfValueData *ValueData = this->getValueData();
  for (uint64_t VSite = 0; VSite < NumValueSites; ++VSite) {
    uint8_t ValueDataCount = this->SiteCountArray[VSite];
    Record.addValueData(Kind, VSite, ValueData, ValueDataCount, VMap);
    ValueData += ValueDataCount;
  }
}

void ValueProfRecord::serializeFrom(const InstrProfRecord &Record,
                                    uint32_t ValueKind,
                                    uint32_t NumValueSites) {
  Kind = ValueKind;
  this->NumValueSites = NumValueSites;
  InstrProfValueData *DstVD = getValueData();
  for (uint32_t S = 0; S < NumValueSites; S++) {
    uint32_t ND = Record.getNumValueDataForSite(ValueKind, S);
    SiteCountArray[S] = ND;
    Record.getValueForSite(DstVD, ValueKind, S, stringToHash);
    DstVD += ND;
  }
}

template <class T>
static T swapToHostOrder(const unsigned char *&D, support::endianness Orig) {
  using namespace support;
  if (Orig == little)
    return endian::readNext<T, little, unaligned>(D);
  else
    return endian::readNext<T, big, unaligned>(D);
}

// For writing/serializing,  Old is the host endianness, and  New is
// byte order intended on disk. For Reading/deserialization, Old
// is the on-disk source endianness, and New is the host endianness.
void ValueProfRecord::swapBytes(support::endianness Old,
                                support::endianness New) {
  using namespace support;
  if (Old == New)
    return;

  if (getHostEndianness() != Old) {
    sys::swapByteOrder<uint32_t>(NumValueSites);
    sys::swapByteOrder<uint32_t>(Kind);
  }
  uint32_t ND = getNumValueData();
  InstrProfValueData *VD = getValueData();

  // No need to swap byte array: SiteCountArrray.
  for (uint32_t I = 0; I < ND; I++) {
    sys::swapByteOrder<uint64_t>(VD[I].Value);
    sys::swapByteOrder<uint64_t>(VD[I].Count);
  }
  if (getHostEndianness() == Old) {
    sys::swapByteOrder<uint32_t>(NumValueSites);
    sys::swapByteOrder<uint32_t>(Kind);
  }
}

uint32_t ValueProfData::getSize(const InstrProfRecord &Record) {
  uint32_t TotalSize = sizeof(ValueProfData);
  uint32_t NumValueKinds = Record.getNumValueKinds();
  if (NumValueKinds == 0)
    return TotalSize;

  for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
    uint32_t NumValueSites = Record.getNumValueSites(Kind);
    if (!NumValueSites)
      continue;
    TotalSize +=
        getValueProfRecordSize(NumValueSites, Record.getNumValueData(Kind));
  }
  return TotalSize;
}

void ValueProfData::deserializeTo(InstrProfRecord &Record,
                                  InstrProfRecord::ValueMapType *VMap) {
  if (NumValueKinds == 0)
    return;

  ValueProfRecord *VR = getFirstValueProfRecord();
  for (uint32_t K = 0; K < NumValueKinds; K++) {
    VR->deserializeTo(Record, VMap);
    VR = VR->getNext();
  }
}

static std::unique_ptr<ValueProfData> AllocValueProfData(uint32_t TotalSize) {
  return std::unique_ptr<ValueProfData>(new (::operator new(TotalSize))
                                            ValueProfData());
}

std::unique_ptr<ValueProfData>
ValueProfData::serializeFrom(const InstrProfRecord &Record) {
  uint32_t TotalSize = getSize(Record);

  std::unique_ptr<ValueProfData> VPD = AllocValueProfData(TotalSize);

  VPD->TotalSize = TotalSize;
  VPD->NumValueKinds = Record.getNumValueKinds();
  ValueProfRecord *VR = VPD->getFirstValueProfRecord();
  for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
    uint32_t NumValueSites = Record.getNumValueSites(Kind);
    if (!NumValueSites)
      continue;
    VR->serializeFrom(Record, Kind, NumValueSites);
    VR = VR->getNext();
  }
  return VPD;
}

ErrorOr<std::unique_ptr<ValueProfData>>
ValueProfData::getValueProfData(const unsigned char *D,
                                const unsigned char *const BufferEnd,
                                support::endianness Endianness) {
  using namespace support;
  if (D + sizeof(ValueProfData) > BufferEnd)
    return instrprof_error::truncated;

  const unsigned char *Header = D;
  uint32_t TotalSize = swapToHostOrder<uint32_t>(Header, Endianness);
  uint32_t NumValueKinds = swapToHostOrder<uint32_t>(Header, Endianness);

  if (D + TotalSize > BufferEnd)
    return instrprof_error::too_large;
  if (NumValueKinds > IPVK_Last + 1)
    return instrprof_error::malformed;
  // Total size needs to be mulltiple of quadword size.
  if (TotalSize % sizeof(uint64_t))
    return instrprof_error::malformed;

  std::unique_ptr<ValueProfData> VPD = AllocValueProfData(TotalSize);

  memcpy(VPD.get(), D, TotalSize);
  // Byte swap.
  VPD->swapBytesToHost(Endianness);

  // Data integrety check:
  ValueProfRecord *VR = VPD->getFirstValueProfRecord();
  for (uint32_t K = 0; K < VPD->NumValueKinds; K++) {
    if (VR->Kind > IPVK_Last)
      return instrprof_error::malformed;
    VR = VR->getNext();
    if ((char *)VR - (char *)VPD.get() > (ptrdiff_t)TotalSize)
      return instrprof_error::malformed;
  }

  return std::move(VPD);
}

void ValueProfData::swapBytesToHost(support::endianness Endianness) {
  using namespace support;
  if (Endianness == getHostEndianness())
    return;

  sys::swapByteOrder<uint32_t>(TotalSize);
  sys::swapByteOrder<uint32_t>(NumValueKinds);

  ValueProfRecord *VR = getFirstValueProfRecord();
  for (uint32_t K = 0; K < NumValueKinds; K++) {
    VR->swapBytes(Endianness, getHostEndianness());
    VR = VR->getNext();
  }
}

void ValueProfData::swapBytesFromHost(support::endianness Endianness) {
  using namespace support;
  if (Endianness == getHostEndianness())
    return;

  ValueProfRecord *VR = getFirstValueProfRecord();
  for (uint32_t K = 0; K < NumValueKinds; K++) {
    ValueProfRecord *NVR = VR->getNext();
    VR->swapBytes(getHostEndianness(), Endianness);
    VR = NVR;
  }
  sys::swapByteOrder<uint32_t>(TotalSize);
  sys::swapByteOrder<uint32_t>(NumValueKinds);
}

ValueProfRecord *ValueProfData::getFirstValueProfRecord() {
  return reinterpret_cast<ValueProfRecord *>((char *)this +
                                             sizeof(ValueProfData));
}

}

<|endoftext|>


<commit_before>#include <cmath>
#include <iostream>
#include <string>
#include <vector>

#define MAX_M 4096
#define MAX_m 12

using namespace std;

int main(int argc, char const *argv[]) {
    int t; // test cases
    int M, e, max_query_allowed; // a test case
    int the_real_M; // trick if M isn't power of 2

    string code[MAX_m][MAX_M]; // all the codewords
    bool is_code[MAX_m]; // has the codeword been made?
    int code_distance[MAX_m][MAX_M]; // only distance from 0 to 1..M
    int code_min[MAX_m]; // min distance
    int code_order[MAX_m][MAX_M]; // the best efficient order of code
    int code_order_pointer[MAX_m]; // how many codeword is sorted?
    bool code_order_check[MAX_m][MAX_M]; // is the codeword sorted?
    int code_minimal[MAX_m][MAX_M/2+2]; // param: d needed; return: query

    cin >> t;
    while (t--) {
        cin >> M >> e >> max_query_allowed;

        the_real_M = M;
        M = pow(2, ceil(log2(M))); // M is the closest power(2)

        int m = log2(M); // log2(M)
        int d = (2*e + 1); // minimal distance

        /* initial coding, if hasnt made yet */
        if (!is_code[m]) {
            is_code[m] = 1;
            /* Make a perfect (M-1,M,M/2) binary code */
            for (int i = 1; i < M; ++i) {
                string ans = "";
                /* binary start from 0 to M */
                for (int j = 0; j < M; ++j) {
                    int bitstring = i & j;
                    short binary = 0;
                    /* counting bit set */
                    for (binary = 0; bitstring; bitstring >>= 1) {
                        binary ^= bitstring & 1;
                    }
                    ans += '0' + binary;
                }
                code[m][i] = ans;
            }

            /* generate initial code order (m,M,1) */
            int two = 1; // power of two
            for (int i = 0; i < m; ++i, two <<= 1) {
                code_order[m][code_order_pointer[m]++] = two;
                code_order_check[m][two] = 1;
                for (int j = 1; j < M; ++j) { // update the distances
                    code_distance[m][j] += (code[m][two][0] != code[m][two][j]);
                }
            }
            code_min[m] = 1;
            code_minimal[m][1] = code_order_pointer[m];
        }

        /* find the best order */
        while (code_min[m] < d && code_min[m] < M/2) {
            int best = 0;
            int delta = MAX_M;
            /* each loop find the one best code order candidate */
            for (int i = 1; i < M; ++i) {
                int min = MAX_M;
                int max = 0;
                if (code_order_check[m][i]) continue;
                for (int j = 1; j < M; ++j) { // test the distance
                    int local = code_distance[m][j] + (code[m][i][0] != code[m][i][j]);
                    if (local > max) max = local;
                    if (local < min) min = local;
                }
                if (max - min < delta) { // save the best
                    best = i;
                    delta = max - min;
                }
            }

            /* update the distance */
            code_min[m] = MAX_M;
            for (int j = 1; j < M; ++j) {
                code_distance[m][j] += (code[m][best][0] != code[m][best][j]);
                if (code_distance[m][j] < code_min[m]) {
                    code_min[m] = code_distance[m][j];
                }
            }

            /* update the code order */
            code_order[m][code_order_pointer[m]++] = best;
            code_order_check[m][best] = 1;
            if (code_minimal[m][code_min[m]] == 0) {
                code_minimal[m][code_min[m]] = code_order_pointer[m];
            }
        }

        /* Debug code_minimal *
        for (int i = 1; i < M/2 + 1; ++i) {
            cout << code_minimal[m][i] << "|";
        }
        cout << endl;
        //*/

        /* total query needed */
        int rounds = d / (M / 2);
        int mod = d % (M / 2);
        bool new_algo = code_minimal[m][mod] < mod * m;
        int total = rounds * (M - 1) + (new_algo ? code_minimal[m][mod] : mod * m);

        // cout << (new_algo? "true " : "false ");
        cout << total << endl;

        for (int i = 0; i < rounds; ++i) { // round query
            for (int j = 1; j < M; ++j) {
                cout << code[m][j].substr(0, the_real_M) << endl;
            }
        }
        if (new_algo) {
            for (int i = 0; i < code_minimal[m][mod]; ++i) { // mod query
                cout << code[m][code_order[m][i]].substr(0, the_real_M) << endl;
            }
        } else {
            for (int i = 0; i < mod; ++i) { // old query
                for (int j = 0; j < m; ++j) {
                    cout << code[m][code_order[m][j]].substr(0, the_real_M) << endl;
                }
            }
        }
    }
    return 0;
}<commit_msg>bruteforce ordering: min then min_count<commit_after>#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
using namespace std;

#define MAX_M 4096
#define MAX_m 12

/**
 * Print first n bit of a code
 */
void print_codeword(char *code, int n) {
    for (int i = 0; i < n; ++i) {
        putchar(code[i]);
    }
    putchar('\n');
}

int main(int argc, char const *argv[]) {
    int t; // test cases
    int M, e, max_query_allowed; // a test case
    int the_real_M; // trick if M isn't power of 2

    // string code[MAX_m][MAX_M]; // all the codewords
    char **code[MAX_m]; // all the codewords
    bool is_code[MAX_m]; // has the codeword been made?
    int code_distance[MAX_m][MAX_M]; // only distance from 0 to 1..M
    int code_min[MAX_m]; // min distance
    int code_order[MAX_m][MAX_M]; // the best efficient order of code
    int code_order_pointer[MAX_m]; // how many codeword is sorted?
    bool code_order_check[MAX_m][MAX_M]; // is the codeword sorted?
    int code_minimal[MAX_m][MAX_M/2+2]; // param: d needed; return: query

    scanf("%d", &t);
    while (t--) {
        scanf("%d%d%d", &M, &e, &max_query_allowed);
        int d = (2*e + 1); // minimal distance
        the_real_M = M; // save the real M for printing the query

        /* M must be power of two */
        int m = ceil(log2(M)); // log2(M)
        M = pow(2, m); // M is the closest power(2)

        /* initial coding, if hasnt made yet */
        if (!is_code[m]) {
            is_code[m] = 1;
            /* Make a perfect (M-1,M,M/2) binary code */
            code[m] = (char**) malloc(sizeof(char*) * M);
            char ans[M+1];
            for (int i = 1; i < M; ++i) {
                /* binary start from 0 to M */
                for (int j = 0; j < M; ++j) {
                    int bitstring = i & j;
                    short binary = 0;
                    /* counting bit set */
                    for (binary = 0; bitstring; bitstring >>= 1) {
                        binary ^= bitstring & 1;
                    }
                    ans[j] = '0' + binary;
                }
                ans[M] = 0; // close the string
                code[m][i] = strdup(ans);
            }
        }

        /* find the best order */
        while (code_min[m] < d && code_min[m] < M/2) {
            int best = 0; // best candidate
            int best_min = 0; // most
            int best_max = MAX_M; // least
            int best_min_count = MAX_M; // least
            int best_max_count = MAX_M; // least
            /* each loop find the one best code order candidate */
            for (int i = 1; i < M; ++i) {
                int min = MAX_M;
                int max = 0;
                int min_count, max_count;
                if (code_order_check[m][i]) continue; // skip used code
                for (int j = 1; j < M; ++j) { // test the distance
                    int local = code_distance[m][j] + (code[m][i][0] != code[m][i][j]);
                    if (local >= max) {
                        if (local == max) {
                            max_count++;
                        } else {
                            max = local;
                            max_count = 1;
                        }
                    }
                    if (local <= min) {
                        if (local == min) {
                            min_count++;
                        } else {
                            min = local;
                            min_count = 1;
                        }
                    }
                }
                /* save the best */
                if (min > best_min || (min == best_min && min_count < best_min_count)) {
                    best = i;
                    best_min = min;
                    best_max = max;
                    best_min_count = min_count;
                }
            }

            /* update the distance */
            code_min[m] = MAX_M;
            for (int j = 1; j < M; ++j) {
                code_distance[m][j] += (code[m][best][0] != code[m][best][j]);
                if (code_distance[m][j] < code_min[m]) {
                    code_min[m] = code_distance[m][j];
                }
            }

            /* update the code order */
            code_order[m][code_order_pointer[m]++] = best;
            code_order_check[m][best] = 1;
            if (code_minimal[m][code_min[m]] == 0) {
                code_minimal[m][code_min[m]] = code_order_pointer[m];
            }
        }

        /* Debug: show code_minimal *
        for (int i = 1; i < M/2 + 1; ++i) {
            cout << code_minimal[m][i] << "|";
        }
        cout << endl;
        //*/

        /* total query needed */
        int rounds = d / (M / 2);
        int mod = d % (M / 2);
        bool new_algo = code_minimal[m][mod] <= mod * m;
        int total = rounds * (M - 1) + (new_algo ? code_minimal[m][mod] : mod * m);

        printf("%d\t%d\t%s\t", M, e, new_algo? "1" : "0");
        printf("%d\n", total);

        continue; // Debug: skip print the codes
        for (int i = 0; i < rounds; ++i) { // round query
            for (int j = 1; j < M; ++j) {
                print_codeword(code[m][j], the_real_M);
            }
        }
        if (new_algo) {
            for (int i = 0; i < code_minimal[m][mod]; ++i) { // mod query
                print_codeword(code[m][code_order[m][i]], the_real_M);
            }
        } else {
            for (int i = 0; i < mod; ++i) { // old query
                for (int j = 0; j < m; ++j) {
                    print_codeword(code[m][code_order[m][j]], the_real_M);
                }
            }
        }
    }
    int two = 1;
    for (int i = 0; i < MAX_m; ++i, two <<= 1) {
        free(code[i]);
        /* Debug: show the generated code order */
        if (is_code[i]) {
            printf("%d:", two);
            for (int j = 0; j < code_order_pointer[i]; ++j) {
                printf(" %d", code_order[i][j]);
            }
            printf("\n");
        }
    }
    return 0;
}<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU General Public License as published by the Free  *
* Software Foundation; either version 2 of the License, or (at your option)   *
* any later version.                                                          *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
* more details.                                                               *
*                                                                             *
* You should have received a copy of the GNU General Public License along     *
* with this program; if not, write to the Free Software Foundation, Inc., 51  *
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
*******************************************************************************
*                            SOFA :: Applications                             *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include "PieWidget.h"
#include <iostream>

#include <QGridLayout>
#include <QStringList>
#include <QHeaderView>
#include <QSplitter>

namespace sofa
{

namespace gui
{

namespace qt
{

std::vector< defaulttype::Vec<3,int> > PieWidget::colorArray;

defaulttype::Vec<3,int> PieWidget::getColor(int i)
{
    defaulttype::Vec<3,int> res=PieWidget::colorArray[i%PieWidget::colorArray.size()];
    float factor=1.0/(1.0+(0.3*(i/PieWidget::colorArray.size())));
    res[0] = (int)(res[0]*factor);
    res[1] = (int)(res[1]*factor);
    res[2] = (int)(res[2]*factor);
    return res;
}

PieWidget::PieWidget(QWidget *parent): QWidget(parent)
{
    if (PieWidget::colorArray.empty())
    {
        colorArray.push_back(  defaulttype::Vec<3,int>(250,125,70) );
        colorArray.push_back(  defaulttype::Vec<3,int>(120,220,110) );
        colorArray.push_back(  defaulttype::Vec<3,int>(215,90,215) );
        colorArray.push_back(  defaulttype::Vec<3,int>(255,210,40) );
        colorArray.push_back(  defaulttype::Vec<3,int>(75,210,210) );
    }
}
void PieWidget::paintEvent( QPaintEvent* )
{
    sizePie = (int)(std::min(this->width(),this->height())*0.95);
    if (data.empty()) return;

    QPainter p( this );

    int initDraw=0;
    int startAngle=0;

    p.setBrush(Qt::SolidPattern);

    for (unsigned int i=0; i<data.size() && i<selection; ++i)
    {
        defaulttype::Vec<3,int> c=PieWidget::getColor(i);
        QColor color(c[0],c[1],c[2]);
        p.setBrush(color);
        int spanAngle=(int)(16*360*data[i].time/totalTime);
        p.drawPie(initDraw,initDraw,sizePie,sizePie,startAngle,spanAngle);
        startAngle+= spanAngle;
    }
}

void PieWidget::setChart( std::vector< dataTime >& value, unsigned int s)
{
    data=value;
    selection=s;
    totalTime=0;
    for (unsigned int i=0; i<value.size() && i<selection; ++i)
    {
        totalTime +=data[i].time;
    }
}

void PieWidget::clear()
{
    data.clear();
    repaint();
}

ChartsWidget::ChartsWidget(const std::string &name, QWidget *parent): QWidget(parent)
{
    QSplitter *splitter=new QSplitter(this);
    splitter->setOrientation(Qt::Horizontal);
    QGridLayout *grid = new QGridLayout(this);
    pie = new PieWidget(splitter);

    table = new QTableWidget(0,3,splitter);
    table->horizontalHeader()->setSectionResizeMode(0,QHeaderView::Fixed);
    table->horizontalHeader()->resizeSection(0,30);
    table->horizontalHeader()->setSectionResizeMode(1,QHeaderView::ResizeToContents);
    table->horizontalHeader()->setSectionResizeMode(2,QHeaderView::ResizeToContents);
    QStringList list; list<<"Id" << name.c_str() << "Time";
    table->setHorizontalHeaderLabels(list);

    grid->addWidget(splitter,0,0);

}

void ChartsWidget::clear()
{
    int rows=table->rowCount();

    for (int i=0; i<rows; ++i) table->removeRow(0);
    pie->clear();
}

void ChartsWidget::setChart( std::vector< dataTime >& value, unsigned int s)
{
    clear();
    pie->setChart(value,s);
    selection=s;
    for (unsigned int i=0; i<value.size() && i<selection; ++i)
    {
        table->insertRow(i);

        defaulttype::Vec<3,int> c=PieWidget::getColor(i);
        QColor color(c[0],c[1],c[2]);

        QString text(value[i].name.c_str());
        QString time= QString::number(value[i].time);
        time += QString(" ms");
        if (!value[i].type.empty())
        {
            text+="(";
            text+= QString(value[i].type.c_str());
            text+=")";
        }

        QTableWidgetItem *itemColor = new QTableWidgetItem();
        itemColor->setBackgroundColor(color);
        QTableWidgetItem *item = new QTableWidgetItem();
        QTableWidgetItem *itemTime = new QTableWidgetItem();
        table->setItem(i,0, itemColor);
        item->setText(text);
        table->setItem(i,1, item);
        itemTime->setText(time);
        table->setItem(i,2, itemTime);
        table->resizeColumnToContents(1);
        itemColor->setFlags(0);
        item->setFlags(0);
        itemTime->setFlags(0);

    }
    pie->repaint();

}

}
}
}
<commit_msg>Fix compilation while using Qt4 and activating the macro SOFA_DUMP_VISITOR to get graphical profiling<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU General Public License as published by the Free  *
* Software Foundation; either version 2 of the License, or (at your option)   *
* any later version.                                                          *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
* more details.                                                               *
*                                                                             *
* You should have received a copy of the GNU General Public License along     *
* with this program; if not, write to the Free Software Foundation, Inc., 51  *
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
*******************************************************************************
*                            SOFA :: Applications                             *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include "PieWidget.h"
#include <iostream>

#include <QGridLayout>
#include <QStringList>
#include <QHeaderView>
#include <QSplitter>

namespace sofa
{

namespace gui
{

namespace qt
{

std::vector< defaulttype::Vec<3,int> > PieWidget::colorArray;

defaulttype::Vec<3,int> PieWidget::getColor(int i)
{
    defaulttype::Vec<3,int> res=PieWidget::colorArray[i%PieWidget::colorArray.size()];
    float factor=1.0/(1.0+(0.3*(i/PieWidget::colorArray.size())));
    res[0] = (int)(res[0]*factor);
    res[1] = (int)(res[1]*factor);
    res[2] = (int)(res[2]*factor);
    return res;
}

PieWidget::PieWidget(QWidget *parent): QWidget(parent)
{
    if (PieWidget::colorArray.empty())
    {
        colorArray.push_back(  defaulttype::Vec<3,int>(250,125,70) );
        colorArray.push_back(  defaulttype::Vec<3,int>(120,220,110) );
        colorArray.push_back(  defaulttype::Vec<3,int>(215,90,215) );
        colorArray.push_back(  defaulttype::Vec<3,int>(255,210,40) );
        colorArray.push_back(  defaulttype::Vec<3,int>(75,210,210) );
    }
}
void PieWidget::paintEvent( QPaintEvent* )
{
    sizePie = (int)(std::min(this->width(),this->height())*0.95);
    if (data.empty()) return;

    QPainter p( this );

    int initDraw=0;
    int startAngle=0;

    p.setBrush(Qt::SolidPattern);

    for (unsigned int i=0; i<data.size() && i<selection; ++i)
    {
        defaulttype::Vec<3,int> c=PieWidget::getColor(i);
        QColor color(c[0],c[1],c[2]);
        p.setBrush(color);
        int spanAngle=(int)(16*360*data[i].time/totalTime);
        p.drawPie(initDraw,initDraw,sizePie,sizePie,startAngle,spanAngle);
        startAngle+= spanAngle;
    }
}

void PieWidget::setChart( std::vector< dataTime >& value, unsigned int s)
{
    data=value;
    selection=s;
    totalTime=0;
    for (unsigned int i=0; i<value.size() && i<selection; ++i)
    {
        totalTime +=data[i].time;
    }
}

void PieWidget::clear()
{
    data.clear();
    repaint();
}

ChartsWidget::ChartsWidget(const std::string &name, QWidget *parent): QWidget(parent)
{
    QSplitter *splitter=new QSplitter(this);
    splitter->setOrientation(Qt::Horizontal);
    QGridLayout *grid = new QGridLayout(this);
    pie = new PieWidget(splitter);

    table = new QTableWidget(0,3,splitter);

#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
    table->horizontalHeader()->setResizeMode(0,QHeaderView::Fixed);
    table->horizontalHeader()->setResizeMode(1,QHeaderView::ResizeToContents);
    table->horizontalHeader()->setResizeMode(2,QHeaderView::ResizeToContents);
#else
    table->horizontalHeader()->setSectionResizeMode(0,QHeaderView::Fixed);
    table->horizontalHeader()->setSectionResizeMode(1,QHeaderView::ResizeToContents);
    table->horizontalHeader()->setSectionResizeMode(2,QHeaderView::ResizeToContents);
#endif // QT_VERSION < QT_VERSION_CHECK(5, 0, 0)

    table->horizontalHeader()->resizeSection(0,30);

    QStringList list; list<<"Id" << name.c_str() << "Time";
    table->setHorizontalHeaderLabels(list);

    grid->addWidget(splitter,0,0);

}

void ChartsWidget::clear()
{
    int rows=table->rowCount();

    for (int i=0; i<rows; ++i) table->removeRow(0);
    pie->clear();
}

void ChartsWidget::setChart( std::vector< dataTime >& value, unsigned int s)
{
    clear();
    pie->setChart(value,s);
    selection=s;
    for (unsigned int i=0; i<value.size() && i<selection; ++i)
    {
        table->insertRow(i);

        defaulttype::Vec<3,int> c=PieWidget::getColor(i);
        QColor color(c[0],c[1],c[2]);

        QString text(value[i].name.c_str());
        QString time= QString::number(value[i].time);
        time += QString(" ms");
        if (!value[i].type.empty())
        {
            text+="(";
            text+= QString(value[i].type.c_str());
            text+=")";
        }

        QTableWidgetItem *itemColor = new QTableWidgetItem();
        itemColor->setBackgroundColor(color);
        QTableWidgetItem *item = new QTableWidgetItem();
        QTableWidgetItem *itemTime = new QTableWidgetItem();
        table->setItem(i,0, itemColor);
        item->setText(text);
        table->setItem(i,1, item);
        itemTime->setText(time);
        table->setItem(i,2, itemTime);
        table->resizeColumnToContents(1);
        itemColor->setFlags(0);
        item->setFlags(0);
        itemTime->setFlags(0);

    }
    pie->repaint();

}

}
}
}
<|endoftext|>


<commit_before>/*************************************************************************
 * Copyright (c) 2014 eProsima. All rights reserved.
 *
 * This copy of eProsima RTPS is licensed to you under the terms described in the
 * EPROSIMARTPS_LIBRARY_LICENSE file included in this distribution.
 *
 *************************************************************************/

/**
 * @file WriterQos.cpp
 *
 */

#include "eprosimartps/qos/WriterQos.h"
#include "eprosimartps/utils/RTPSLog.h"

namespace eprosima {
namespace dds {

WriterQos::WriterQos()
{
	this->m_reliability.kind = RELIABLE_RELIABILITY_QOS;
}

WriterQos::~WriterQos()
{

}

void WriterQos::setQos( WriterQos& qos, bool first_time)
{
	if(first_time)
	{
		m_durability = qos.m_durability;
		m_durability.hasChanged = true;
	}
	if(m_deadline.period != qos.m_deadline.period)
	{
		m_deadline = qos.m_deadline;
		m_deadline.hasChanged = true;
	}
	if(m_latencyBudget.duration != qos.m_latencyBudget.duration)
	{
		m_latencyBudget = qos.m_latencyBudget;
		m_latencyBudget.hasChanged = true;
	}
	if(m_liveliness.lease_duration != qos.m_liveliness.lease_duration)
	{
		m_liveliness.lease_duration = qos.m_liveliness.lease_duration;
		m_liveliness.hasChanged = true;
	}
	if(first_time)
	{
		m_liveliness = qos.m_liveliness;
		m_liveliness.hasChanged = true;
	}
	if(first_time)
	{
		m_reliability = qos.m_reliability;
		m_reliability.hasChanged = true;
	}
	if(first_time)
	{
		m_ownership = qos.m_ownership;
		m_ownership.hasChanged = true;
	}
	if(m_destinationOrder.kind != qos.m_destinationOrder.kind )
	{
		m_destinationOrder = qos.m_destinationOrder;
		m_destinationOrder.hasChanged = true;
	}
	if(m_userData.data != qos.m_userData.data )
	{
		m_userData = qos.m_userData;
		m_userData.hasChanged = true;
	}
	if(m_timeBasedFilter.minimum_separation != qos.m_timeBasedFilter.minimum_separation )
	{
		m_timeBasedFilter = qos.m_timeBasedFilter;
		m_timeBasedFilter.hasChanged = true;
	}
	if(m_presentation.access_scope != qos.m_presentation.access_scope ||
			m_presentation.coherent_access != qos.m_presentation.coherent_access ||
			m_presentation.ordered_access != qos.m_presentation.ordered_access)
	{
		m_presentation = qos.m_presentation;
		m_presentation.hasChanged = true;
	}
	if(first_time)
	{
		m_partition = qos.m_partition;
		m_partition.hasChanged = true;
	}
	if(m_topicData.value != qos.m_topicData.value )
	{
		m_topicData = qos.m_topicData;
		m_topicData.hasChanged = true;
	}
	if(m_groupData.value != qos.m_groupData.value )
	{
		m_groupData = qos.m_groupData;
		m_groupData.hasChanged = true;
	}
	if(m_durabilityService.history_kind != qos.m_durabilityService.history_kind ||
			m_durabilityService.history_depth != qos.m_durabilityService.history_depth ||
			m_durabilityService.max_instances != qos.m_durabilityService.max_instances ||
			m_durabilityService.max_samples != qos.m_durabilityService.max_samples||
			m_durabilityService.max_samples_per_instance != qos.m_durabilityService.max_samples_per_instance ||
			m_durabilityService.service_cleanup_delay != qos.m_durabilityService.service_cleanup_delay
	)
	{
		m_durabilityService = qos.m_durabilityService;
		m_durabilityService.hasChanged = true;
	}
	if(m_lifespan.duration != qos.m_lifespan.duration )
	{
		m_lifespan = qos.m_lifespan;
		m_lifespan.hasChanged = true;
	}
	if(first_time)
	{
		m_ownershipStrength = qos.m_ownershipStrength;
		m_ownershipStrength.hasChanged = true;
	}
}

bool WriterQos::checkQos()
{
	if(m_durability.kind == TRANSIENT_DURABILITY_QOS)
	{
		pError("TRANSIENT Durability not supported"<<endl);
		return false;
	}
	if(m_durability.kind == PERSISTENT_DURABILITY_QOS)
	{
		pError("PERSISTENT Durability not supported"<<endl);
		return false;
	}
	if(m_destinationOrder.kind == BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS)
	{
		pError("BY SOURCE TIMESTAMP DestinationOrder not supported"<<endl);
		return false;
	}
	if(m_reliability.kind == BEST_EFFORT_RELIABILITY_QOS && m_ownership.kind == EXCLUSIVE_OWNERSHIP_QOS)
	{
		pError("BEST_EFFORT incompatible with EXCLUSIVE ownership"<<endl);
		return false;
	}
	return true;
}

} /* namespace dds */
} /* namespace eprosima */
<commit_msg>Check that leaseDuration is > announcementPeriod<commit_after>/*************************************************************************
 * Copyright (c) 2014 eProsima. All rights reserved.
 *
 * This copy of eProsima RTPS is licensed to you under the terms described in the
 * EPROSIMARTPS_LIBRARY_LICENSE file included in this distribution.
 *
 *************************************************************************/

/**
 * @file WriterQos.cpp
 *
 */

#include "eprosimartps/qos/WriterQos.h"
#include "eprosimartps/utils/RTPSLog.h"

namespace eprosima {
namespace dds {

WriterQos::WriterQos()
{
	this->m_reliability.kind = RELIABLE_RELIABILITY_QOS;
}

WriterQos::~WriterQos()
{

}

void WriterQos::setQos( WriterQos& qos, bool first_time)
{
	if(first_time)
	{
		m_durability = qos.m_durability;
		m_durability.hasChanged = true;
	}
	if(m_deadline.period != qos.m_deadline.period)
	{
		m_deadline = qos.m_deadline;
		m_deadline.hasChanged = true;
	}
	if(m_latencyBudget.duration != qos.m_latencyBudget.duration)
	{
		m_latencyBudget = qos.m_latencyBudget;
		m_latencyBudget.hasChanged = true;
	}
	if(m_liveliness.lease_duration != qos.m_liveliness.lease_duration)
	{
		m_liveliness.lease_duration = qos.m_liveliness.lease_duration;
		m_liveliness.hasChanged = true;
	}
	if(first_time)
	{
		m_liveliness = qos.m_liveliness;
		m_liveliness.hasChanged = true;
	}
	if(first_time)
	{
		m_reliability = qos.m_reliability;
		m_reliability.hasChanged = true;
	}
	if(first_time)
	{
		m_ownership = qos.m_ownership;
		m_ownership.hasChanged = true;
	}
	if(m_destinationOrder.kind != qos.m_destinationOrder.kind )
	{
		m_destinationOrder = qos.m_destinationOrder;
		m_destinationOrder.hasChanged = true;
	}
	if(m_userData.data != qos.m_userData.data )
	{
		m_userData = qos.m_userData;
		m_userData.hasChanged = true;
	}
	if(m_timeBasedFilter.minimum_separation != qos.m_timeBasedFilter.minimum_separation )
	{
		m_timeBasedFilter = qos.m_timeBasedFilter;
		m_timeBasedFilter.hasChanged = true;
	}
	if(m_presentation.access_scope != qos.m_presentation.access_scope ||
			m_presentation.coherent_access != qos.m_presentation.coherent_access ||
			m_presentation.ordered_access != qos.m_presentation.ordered_access)
	{
		m_presentation = qos.m_presentation;
		m_presentation.hasChanged = true;
	}
	if(first_time)
	{
		m_partition = qos.m_partition;
		m_partition.hasChanged = true;
	}
	if(m_topicData.value != qos.m_topicData.value )
	{
		m_topicData = qos.m_topicData;
		m_topicData.hasChanged = true;
	}
	if(m_groupData.value != qos.m_groupData.value )
	{
		m_groupData = qos.m_groupData;
		m_groupData.hasChanged = true;
	}
	if(m_durabilityService.history_kind != qos.m_durabilityService.history_kind ||
			m_durabilityService.history_depth != qos.m_durabilityService.history_depth ||
			m_durabilityService.max_instances != qos.m_durabilityService.max_instances ||
			m_durabilityService.max_samples != qos.m_durabilityService.max_samples||
			m_durabilityService.max_samples_per_instance != qos.m_durabilityService.max_samples_per_instance ||
			m_durabilityService.service_cleanup_delay != qos.m_durabilityService.service_cleanup_delay
	)
	{
		m_durabilityService = qos.m_durabilityService;
		m_durabilityService.hasChanged = true;
	}
	if(m_lifespan.duration != qos.m_lifespan.duration )
	{
		m_lifespan = qos.m_lifespan;
		m_lifespan.hasChanged = true;
	}
	if(first_time)
	{
		m_ownershipStrength = qos.m_ownershipStrength;
		m_ownershipStrength.hasChanged = true;
	}
}

bool WriterQos::checkQos()
{
	if(m_durability.kind == TRANSIENT_DURABILITY_QOS)
	{
		pError("TRANSIENT Durability not supported"<<endl);
		return false;
	}
	if(m_durability.kind == PERSISTENT_DURABILITY_QOS)
	{
		pError("PERSISTENT Durability not supported"<<endl);
		return false;
	}
	if(m_destinationOrder.kind == BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS)
	{
		pError("BY SOURCE TIMESTAMP DestinationOrder not supported"<<endl);
		return false;
	}
	if(m_reliability.kind == BEST_EFFORT_RELIABILITY_QOS && m_ownership.kind == EXCLUSIVE_OWNERSHIP_QOS)
	{
		pError("BEST_EFFORT incompatible with EXCLUSIVE ownership"<<endl);
		return false;
	}
	if(m_liveliness.kind == AUTOMATIC_LIVELINESS_QOS || m_liveliness.kind == MANUAL_BY_PARTICIPANT_LIVELINESS_QOS)
	{
		if(m_liveliness.lease_duration <= m_liveliness.announcement_period)
		{
			pError("WRITERQOS: LeaseDuration <= announcement period " << endl;);
			return false;
		}
	}
	return true;
}

} /* namespace dds */
} /* namespace eprosima */
<|endoftext|>


<commit_before>/*
  Copyright (c) 2012 Matthew Stump

  This file is part of libcql.

  libcql is free software; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by
  the Free Software Foundation; either version 3 of the License, or
  (at your option) any later version.

  libcql 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 program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iomanip>
#include <sstream>

#include "serialization.hpp"
#include "util.hpp"
#include "cql_message_query.hpp"

cql::cql_message_query_t::cql_message_query_t() :
    _consistency(0),
    _query()
{}

cql::cql_message_query_t::cql_message_query_t(const std::string& query,
                                              cql_short_t consistency) :
    _consistency(consistency),
    _query(query)
{}

const std::string&
cql::cql_message_query_t::query() const
{
    return _query;
}

cql_short_t
cql::cql_message_query_t::consistency() const
{
    return _consistency;
}

void
cql::cql_message_query_t::query(const std::string& q)
{
    _query = q;
}

void
cql::cql_message_query_t::consistency(cql_short_t consistency)
{
    _consistency = consistency;
}

cql_byte_t
cql::cql_message_query_t::opcode() const
{
    return CQL_OPCODE_QUERY;
}

cql_int_t
cql::cql_message_query_t::size() const
{
    std::stringstream ss(std::stringstream::out);
    write(ss);
    return ss.str().size();
}

std::string
cql::cql_message_query_t::str() const
{
    std::stringstream output;
    output << _query;
    output << " " << std::setfill('0') << std::string("0x") << std::setw(2);
    output << cql::internal::hex(_consistency);
    return output.str();
}

std::istream&
cql::cql_message_query_t::read(std::istream& input)
{
    cql::internal::decode_long_string(input, _query);
    input.read(reinterpret_cast<char*>(&_consistency), sizeof(_consistency));
    _consistency = ntohs(_consistency);
    return input;
}

std::ostream&
cql::cql_message_query_t::write(std::ostream& output) const
{
    cql::internal::encode_long_string(output, _query);
    cql_short_t consistency = htons(_consistency);
    output.write(reinterpret_cast<char*>(&consistency), sizeof(consistency));
    return output;
}
<commit_msg>use the central serialization methods for encoding the consistency of a query message<commit_after>/*
  Copyright (c) 2012 Matthew Stump

  This file is part of libcql.

  libcql is free software; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by
  the Free Software Foundation; either version 3 of the License, or
  (at your option) any later version.

  libcql 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 program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iomanip>
#include <sstream>

#include "serialization.hpp"
#include "util.hpp"
#include "cql_message_query.hpp"

cql::cql_message_query_t::cql_message_query_t() :
    _consistency(0),
    _query()
{}

cql::cql_message_query_t::cql_message_query_t(const std::string& query,
                                              cql_short_t consistency) :
    _consistency(consistency),
    _query(query)
{}

const std::string&
cql::cql_message_query_t::query() const
{
    return _query;
}

cql_short_t
cql::cql_message_query_t::consistency() const
{
    return _consistency;
}

void
cql::cql_message_query_t::query(const std::string& q)
{
    _query = q;
}

void
cql::cql_message_query_t::consistency(cql_short_t consistency)
{
    _consistency = consistency;
}

cql_byte_t
cql::cql_message_query_t::opcode() const
{
    return CQL_OPCODE_QUERY;
}

cql_int_t
cql::cql_message_query_t::size() const
{
    std::stringstream ss(std::stringstream::out);
    write(ss);
    return ss.str().size();
}

std::string
cql::cql_message_query_t::str() const
{
    std::stringstream output;
    output << _query;
    output << " " << std::setfill('0') << std::string("0x") << std::setw(2);
    output << cql::internal::hex(_consistency);
    return output.str();
}

std::istream&
cql::cql_message_query_t::read(std::istream& input)
{
    cql::internal::decode_long_string(input, _query);
    input.read(reinterpret_cast<char*>(&_consistency), sizeof(_consistency));
    _consistency = ntohs(_consistency);
    return input;
}

std::ostream&
cql::cql_message_query_t::write(std::ostream& output) const
{
    cql::internal::encode_long_string(output, _query);
    cql::internal::encode_short(output, _consistency);
    return output;
}
<|endoftext|>


<commit_before>#pragma ident "$Id:$"
/**
*  ConstellationList - Produce comma separated list of PRN ID values for
*  the SVs that are in the constellation.  In order to do this, the program
*  needs:
*    (1.)  An input file that defines the GPS constellation at a given date
*          (or dates)
*    (2.)  The year of interest (2-digit or 4-digit will do)
*    (3.)  The day of year of interest (Julian day, 0-365/366)
*  The user may also specify if they want the list in the "baseline 24", the
*  "excess" above the baseline, or both.
*
*  USAGE:
*  >ConstellationList -i<definitionFile> -y<year> -j<DOY> [-b] [-x] [-n] [-O]
*  -i : Constellation defintion file
*  -y : year (2-digit or 4-digit)
*  -j : day of year (0-365|366)
*  -b : List "baseline 24" PRN IDs
*  -x : List PRN IDs "in excess of" the baseline 24, but in-use on orbit
*  -n : List PRN IDs that are current not in baseline 24, either on-orbit
*       "excess" or simply not in use at this time.
*  -O : Assume input file is in form of USCG Ops Advisory.  By default a
*       comma separated value file is assumed.
*
*/
//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk 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 GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2009, The University of Texas at Austin
//
//============================================================================

//============================================================================
//
//This software developed by Applied Research Laboratories at the University of
//Texas at Austin, under contract to an agency or agencies within the U.S.
//Department of Defense. The U.S. Government retains all rights to use,
//duplicate, distribute, disclose, or release this software.
//
//Pursuant to DoD Directive 523024
//
// DISTRIBUTION STATEMENT A: This software has been approved for public
//                           release, distribution is unlimited.
//
//=============================================================================
// System
#include <stdio.h>

// Library
#include "BasicFramework.hpp"
#include "DayTime.hpp"
#include "icd_200_constants.hpp"

// Project
#include "ConstellationSet.hpp"

using namespace std;
using namespace gpstk;

class ConstellationList : public gpstk::BasicFramework
{
public:
   ConstellationList(const std::string& applName,
              const std::string& applDesc) throw();
   ~ConstellationList() {}
   virtual bool initialize(int argc, char *argv[]) throw();

protected:
   virtual void process();
   gpstk::CommandOptionWithAnyArg inputOption;
   gpstk::CommandOptionNoArg typeOption;
   gpstk::CommandOptionWithAnyArg yearOption;
   gpstk::CommandOptionWithAnyArg DOYOption;
   gpstk::CommandOptionNoArg base24Option;
   gpstk::CommandOptionNoArg excessOption;
   gpstk::CommandOptionNoArg notBase24Option;
   gpstk::CommandOptionNoArg SVNOption;

   FILE *logfp;
   ConstellationSet cs;

   bool outputPRN;
};

int main( int argc, char*argv[] )
{
   try
   {
      ConstellationList fc("ConstellationList", "List the satellites in or out of the Base 24.");
      if (!fc.initialize(argc, argv)) return(false);
      fc.run();
   }
   catch(gpstk::Exception& exc)
   {
      cout << exc << endl;
      return 1;
   }
   catch(...)
   {
      cout << "Caught an unnamed exception. Exiting." << endl;
      return 1;
   }
   return 0;
}

ConstellationList::ConstellationList(const std::string& applName,
                       const std::string& applDesc) throw()
          :BasicFramework(applName, applDesc),
           inputOption('i', "input-file", "The name of the ConstallationDefinition file(s) to read.", true),
           typeOption('O', "OpsAd","Assume input file is Op Advisory format (CSV is default)",false),
           yearOption('y', "year", "Year of interest.", true),
           DOYOption('j',"day-of-year","Day of year.", true),
           SVNOption('s',"SVN Output","Output SVN in place of PRN (only valid fo -O)",false),
           base24Option('b',"Base24", "List PRNs in Base 24 constellation", false),
           notBase24Option('n',"notBase24","List PRNs NOT used in Base 24 constellation",false),
           excessOption('x',"excessSVs","List PRNs in use, but in excess of the Base 24 constellation",false)
{
   inputOption.setMaxCount(10);
   yearOption.setMaxCount(1);
   DOYOption.setMaxCount(1);
}

bool ConstellationList::initialize(int argc, char *argv[])
   throw()
{
   if (!BasicFramework::initialize(argc, argv)) return false;

      // Load constellation defintions.
   int totalCount = 0;

   vector<string> values;

   ConstellationSet::FileType ft = ConstellationSet::CSV;
   if (typeOption.getCount()>0)
   {
      ft = ConstellationSet::OpAdvisory;
   }

   values = inputOption.getValue();
   vector<string>::const_iterator vi;
   for (vi=values.begin();vi!=values.end();++vi)
   {
      string filename = *vi;
      int count = cs.loadFile( filename, ft );
      totalCount += count;
   }
   if (totalCount<1)
   {
      cout << "Failure reading input file." << endl;
      return false;
   }

   outputPRN = true;
   if (ft==ConstellationSet::CSV && SVNOption.getCount()>0) outputPRN = false;
   return true;
}

void ConstellationList::process()
{
      // Get day of interest from command line arguments
      // Arrange so this'll work with either 2-digit or 4-digit year numbers
   int year = StringUtils::asInt( yearOption.getValue().front() );
   if (year>=0 && year<=70) year += 2000;
   if (year<100) year += 1900;

   int DOY = StringUtils::asInt( DOYOption.getValue().front() );

   DayTime dt = DayTime( (short) year, (short) DOY, (DayTime::SEC_DAY / 2));

      // Try some samples
   ConstellationDefinition cd = cs.findCD( dt );

      // Test each PRN ID in order and
      // output a comma separated list of those match the selected criteriaz
   bool first = true;
   for (int PRNID=1; PRNID<=gpstk::MAX_PRN; ++PRNID)
   {
      SatID SV = SatID( PRNID, SatID::systemGPS );
      try
      {
         bool inBase24 = cd.inBase24(SV);
         if (notBase24Option.getCount()!=0)
         {
            if (!inBase24)
            {
               if (!first) cout << ", ";
               //cout << PRNID;
               if (outputPRN) cout << PRNID;
                else cout << cd.getSVN(SV);
               first = false;
            }
         }
         else
         {
            if ( ( inBase24 && base24Option.getCount()!=0) ||
                 (!inBase24 && excessOption.getCount()!=0) )
            {
               if (!first) cout << ", ";
               //cout << PRNID;
               if (outputPRN) cout << PRNID;
                else cout << cd.getSVN(SV);
               first = false;
            }
         }
      }
      catch(ConstellationDefinition::NoSlotFoundForSV e)
      { //Do nothing but continue
        //Except in case -n, in which we want to add this PRN ID to the list
         if (notBase24Option.getCount()!=0)
         {
            if (!first) cout << ", ";
            //cout << PRNID;
            if (outputPRN) cout << PRNID;
             else cout << cd.getSVN(SV);
            first = false;
         }
      }
   }
   cout << endl;
}
<commit_msg>Minor argument updates to ConstellationList<commit_after>#pragma ident "$Id:$"
/**
*  ConstellationList - Produce comma separated list of PRN ID values for
*  the SVs that are in the constellation.  In order to do this, the program
*  needs:
*    (1.)  An input file that defines the GPS constellation at a given date
*          (or dates)
*    (2.)  The year of interest (2-digit or 4-digit will do)
*    (3.)  The day of year of interest (Julian day, 0-365/366)
*  The user may also specify if they want the list in the "baseline 24", the
*  "excess" above the baseline, or both.
*
*  USAGE:
*  >ConstellationList -i<definitionFile> -y<year> -j<DOY> [-b] [-x] [-n] [-O]
*  -i : Constellation defintion file
*  -y : year (2-digit or 4-digit)
*  -j : day of year (0-365|366)
*  -b : List "baseline 24" PRN IDs
*  -x : List PRN IDs "in excess of" the baseline 24, but in-use on orbit
*  -n : List PRN IDs that are current not in baseline 24, either on-orbit
*       "excess" or simply not in use at this time.
*  -O : Assume input file is in form of USCG Ops Advisory.  By default a
*       comma separated value file is assumed.
*
*/
//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk 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 GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2009, The University of Texas at Austin
//
//============================================================================

//============================================================================
//
//This software developed by Applied Research Laboratories at the University of
//Texas at Austin, under contract to an agency or agencies within the U.S.
//Department of Defense. The U.S. Government retains all rights to use,
//duplicate, distribute, disclose, or release this software.
//
//Pursuant to DoD Directive 523024
//
// DISTRIBUTION STATEMENT A: This software has been approved for public
//                           release, distribution is unlimited.
//
//=============================================================================
// System
#include <stdio.h>

// Library
#include "BasicFramework.hpp"
#include "DayTime.hpp"
#include "icd_200_constants.hpp"

// Project
#include "ConstellationSet.hpp"

using namespace std;
using namespace gpstk;

class ConstellationList : public gpstk::BasicFramework
{
public:
   ConstellationList(const std::string& applName,
              const std::string& applDesc) throw();
   ~ConstellationList() {}
   virtual bool initialize(int argc, char *argv[]) throw();

protected:
   virtual void process();
   gpstk::CommandOptionWithAnyArg inputOption;
   gpstk::CommandOptionNoArg typeOption;
   gpstk::CommandOptionWithAnyArg yearOption;
   gpstk::CommandOptionWithAnyArg DOYOption;
   gpstk::CommandOptionNoArg base24Option;
   gpstk::CommandOptionNoArg excessOption;
   gpstk::CommandOptionNoArg notBase24Option;
   gpstk::CommandOptionNoArg SVNOption;

   FILE *logfp;
   ConstellationSet cs;

   bool outputPRN;
};

int main( int argc, char*argv[] )
{
   try
   {
      ConstellationList fc("ConstellationList", "List the satellites in or out of the Base 24.");
      if (!fc.initialize(argc, argv)) return(false);
      fc.run();
   }
   catch(gpstk::Exception& exc)
   {
      cout << exc << endl;
      return 1;
   }
   catch(...)
   {
      cout << "Caught an unnamed exception. Exiting." << endl;
      return 1;
   }
   return 0;
}

ConstellationList::ConstellationList(const std::string& applName,
                       const std::string& applDesc) throw()
          :BasicFramework(applName, applDesc),
           inputOption('i', "input-file", "The name of the ConstallationDefinition file(s) to read.", true),
           typeOption('O', "OpsAd","Assume input file is Op Advisory format (CSV is default)",false),
           yearOption('y', "year", "Year of interest.", true),
           DOYOption('j',"day-of-year","Day of year.", true),
           SVNOption('s',"SVN Output","Output SVN in place of PRN (not valid for -O)",false),
           base24Option('b',"Base24", "List PRNs in Base 24 constellation", false),
           notBase24Option('n',"notBase24","List PRNs NOT used in Base 24 constellation",false),
           excessOption('x',"excessSVs","List PRNs in use, but in excess of the Base 24 constellation",false)
{
   inputOption.setMaxCount(10);
   yearOption.setMaxCount(1);
   DOYOption.setMaxCount(1);
}

bool ConstellationList::initialize(int argc, char *argv[])
   throw()
{
   if (!BasicFramework::initialize(argc, argv)) return false;

      // Load constellation defintions.
   int totalCount = 0;

   vector<string> values;

   ConstellationSet::FileType ft = ConstellationSet::CSV;
   if (typeOption.getCount()>0)
   {
      ft = ConstellationSet::OpAdvisory;
   }

   values = inputOption.getValue();
   vector<string>::const_iterator vi;
   for (vi=values.begin();vi!=values.end();++vi)
   {
      string filename = *vi;
      int count = cs.loadFile( filename, ft );
      totalCount += count;
   }
   if (totalCount<1)
   {
      cout << "Failure reading input file." << endl;
      return false;
   }

   outputPRN = true;
   if (ft==ConstellationSet::CSV && SVNOption.getCount()>0) outputPRN = false;
   return true;
}

void ConstellationList::process()
{
      // Get day of interest from command line arguments
      // Arrange so this'll work with either 2-digit or 4-digit year numbers
   int year = StringUtils::asInt( yearOption.getValue().front() );
   if (year>=0 && year<=70) year += 2000;
   if (year<100) year += 1900;

   int DOY = StringUtils::asInt( DOYOption.getValue().front() );

   DayTime dt = DayTime( (short) year, (short) DOY, (DayTime::SEC_DAY / 2));

      // Try some samples
   ConstellationDefinition cd = cs.findCD( dt );

      // Test each PRN ID in order and
      // output a comma separated list of those match the selected criteriaz
   bool first = true;
   for (int PRNID=1; PRNID<=gpstk::MAX_PRN; ++PRNID)
   {
      SatID SV = SatID( PRNID, SatID::systemGPS );
      try
      {
         bool inBase24 = cd.inBase24(SV);
         if (notBase24Option.getCount()!=0)
         {
            if (!inBase24)
            {
               if (!first) cout << ", ";
               //cout << PRNID;
               if (outputPRN) cout << PRNID;
                else cout << cd.getSVN(SV);
               first = false;
            }
         }
         else
         {
            if ( ( inBase24 && base24Option.getCount()!=0) ||
                 (!inBase24 && excessOption.getCount()!=0) )
            {
               if (!first) cout << ", ";
               //cout << PRNID;
               if (outputPRN) cout << PRNID;
                else cout << cd.getSVN(SV);
               first = false;
            }
         }
      }
      catch(ConstellationDefinition::NoSlotFoundForSV e)
      { //Do nothing but continue
        //Except in case -n, in which we want to add this PRN ID to the list
         if (notBase24Option.getCount()!=0)
         {
            if (!first) cout << ", ";
            //cout << PRNID;
            if (outputPRN) cout << PRNID;
             else cout << cd.getSVN(SV);
            first = false;
         }
      }
   }
   cout << endl;
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2003 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */
// todo make this turn off for .net
#if defined(_WIN32)
	#pragma warning(disable: 4786)
#endif

#include <string.h>
#include <math.h>
#include <ctype.h>
#include <fstream>
#include "common.h"
#include "global.h"
#include "Ping.h"
#include "Protocol.h"
#include "TimeKeeper.h"
#include "bzfio.h"

// incessint rebuilding for current versioning
#include "version.h"

//
// PingPacket
//

const int		PingPacket::PacketSize = ServerIdPLen + 52;

PingPacket::PingPacket() : gameStyle(PlainGameStyle),
				maxShots(1),
				shakeWins(0),
				shakeTimeout(0),
				maxPlayerScore(0),
				maxTeamScore(0),
				maxTime(0),
				maxPlayers(1),
				rogueCount(0),
				rogueMax(1),
				redCount(0),
				redMax(1),
				greenCount(0),
				greenMax(1),
				blueCount(0),
				blueMax(1),
				purpleCount(0),
				purpleMax(1),
				observerCount(0),
				observerMax(1)
{
  // do nothing
}

PingPacket::~PingPacket()
{
  // do nothing
}

bool			PingPacket::read(int fd, struct sockaddr_in* addr)
{
  char buffer[PacketSize], serverVersion[9];
  uint16_t len, code;

  // get packet
  int n = recvMulticast(fd, buffer, sizeof(buffer), addr);
  if (n < 4)
    return false;

  // decode header
  void* buf = buffer;
  buf = nboUnpackUShort(buf, len);
  buf = nboUnpackUShort(buf, code);

  // make sure we got the rest of the message
  if (len != n - 4)
    return false;

  // check that it's a reply
  if (code != MsgPingCodeReply)
    return false;

  // unpack body of reply
  buf = unpack(buf, serverVersion);

  // compare version against my version.  ignore last character of
  // version number.  that's only used to indicate compatible
  // client-side changes.
  return (strncmp(serverVersion, getServerVersion(), 7) == 0);
}

bool			PingPacket::waitForReply(int fd,
				const Address& from,
				int millisecondsToBlock)
{
  // block waiting on input.  if the incoming message is not from the
  // indicated source then ignore it and go back to waiting.  if the
  // incoming message is not a ping then ignore it and go back to waiting.
  float blockTime = 0.0001f * (float)millisecondsToBlock;
  TimeKeeper startTime = TimeKeeper::getCurrent();
  TimeKeeper currentTime = startTime;
  do {
    // prepare timeout
    const float timeLeft = blockTime - (currentTime - startTime);
    struct timeval timeout;
    timeout.tv_sec = long(floorf(timeLeft));
    timeout.tv_usec = long(1.0e+6f * (timeLeft - floorf(timeLeft)));

    // wait for input
    fd_set read_set;
    FD_ZERO(&read_set);
// turn off == signed/unsigned mismatch on win32
#if defined(_WIN32)
#pragma warning(disable: 4018)
#endif
    FD_SET(fd, &read_set);
#if defined(_WIN32)
#pragma warning(default: 4018)
#endif
    int nfound = select(fd+1, (fd_set*)&read_set, NULL, NULL, &timeout);

    // if got a message read it.  if a ping packet and from right
    // sender then return success.
    if (nfound < 0)
      return false;
    if (nfound > 0 && read(fd, NULL))
      if (sourceAddr == from)
	return true;

    currentTime = TimeKeeper::getCurrent();
  } while (currentTime - startTime < blockTime);
  return false;
}

bool			PingPacket::write(int fd,
					const struct sockaddr_in* addr) const
{
  char buffer[PacketSize];
  void* buf = buffer;
  buf = nboPackUShort(buf, PacketSize - 4);
  buf = nboPackUShort(buf, MsgPingCodeReply);
  buf = pack(buf, getServerVersion());
  return sendMulticast(fd, buffer, sizeof(buffer), addr) == sizeof(buffer);
}

bool			PingPacket::isRequest(int fd,
				struct sockaddr_in* addr)
{
  if (fd < 0) return false;
  char buffer[6];
  void *msg = buffer;
  uint16_t len, code;
  int size = recvMulticast(fd, buffer, sizeof(buffer), addr);
  if (size < 2) return false;
  msg = nboUnpackUShort(msg, len);
  msg = nboUnpackUShort(msg, code);
  return code == MsgPingCodeRequest;
}

bool			PingPacket::sendRequest(int fd,
					const struct sockaddr_in* addr)
{
  if (fd < 0 || !addr) return false;
  char buffer[6];
  void *msg = buffer;
  msg = nboPackUShort(msg, 2);
  msg = nboPackUShort(msg, MsgPingCodeRequest);
  msg = nboPackUShort(msg, (uint16_t) 0);
  return sendMulticast(fd, buffer, sizeof(buffer), addr) == sizeof(buffer);
}

void*			PingPacket::unpack(void* buf, char* version)
{
  buf = nboUnpackString(buf, version, 8);
  buf = serverId.unpack(buf);
  buf = sourceAddr.unpack(buf);
  buf = nboUnpackUShort(buf, gameStyle);
  buf = nboUnpackUShort(buf, maxShots);
  buf = nboUnpackUShort(buf, shakeWins);
  buf = nboUnpackUShort(buf, shakeTimeout);
  buf = nboUnpackUShort(buf, maxPlayerScore);
  buf = nboUnpackUShort(buf, maxTeamScore);
  buf = nboUnpackUShort(buf, maxTime);
  buf = nboUnpackUByte(buf, maxPlayers);
  buf = nboUnpackUByte(buf, rogueCount);
  buf = nboUnpackUByte(buf, rogueMax);
  buf = nboUnpackUByte(buf, redCount);
  buf = nboUnpackUByte(buf, redMax);
  buf = nboUnpackUByte(buf, greenCount);
  buf = nboUnpackUByte(buf, greenMax);
  buf = nboUnpackUByte(buf, blueCount);
  buf = nboUnpackUByte(buf, blueMax);
  buf = nboUnpackUByte(buf, purpleCount);
  buf = nboUnpackUByte(buf, purpleMax);
  buf = nboUnpackUByte(buf, observerCount);
  buf = nboUnpackUByte(buf, observerMax);
  return buf;
}

void*			PingPacket::pack(void* buf, const char* version) const
{
  buf = nboPackString(buf, version, 8);
  buf = serverId.pack(buf);
  buf = sourceAddr.pack(buf);
  buf = nboPackUShort(buf, gameStyle);
  buf = nboPackUShort(buf, maxShots);
  buf = nboPackUShort(buf, shakeWins);
  buf = nboPackUShort(buf, shakeTimeout);	// 1/10ths of second
  buf = nboPackUShort(buf, maxPlayerScore);
  buf = nboPackUShort(buf, maxTeamScore);
  buf = nboPackUShort(buf, maxTime);
  buf = nboPackUByte(buf, maxPlayers);
  buf = nboPackUByte(buf, rogueCount);
  buf = nboPackUByte(buf, rogueMax);
  buf = nboPackUByte(buf, redCount);
  buf = nboPackUByte(buf, redMax);
  buf = nboPackUByte(buf, greenCount);
  buf = nboPackUByte(buf, greenMax);
  buf = nboPackUByte(buf, blueCount);
  buf = nboPackUByte(buf, blueMax);
  buf = nboPackUByte(buf, purpleCount);
  buf = nboPackUByte(buf, purpleMax);
  buf = nboPackUByte(buf, observerCount);
  buf = nboPackUByte(buf, observerMax);
  return buf;
}

void			PingPacket::packHex(char* buf) const
{
  buf = packHex16(buf, gameStyle);
  buf = packHex16(buf, maxShots);
  buf = packHex16(buf, shakeWins);
  buf = packHex16(buf, shakeTimeout);
  buf = packHex16(buf, maxPlayerScore);
  buf = packHex16(buf, maxTeamScore);
  buf = packHex16(buf, maxTime);
  buf = packHex8(buf, maxPlayers);
  buf = packHex8(buf, rogueCount);
  buf = packHex8(buf, rogueMax);
  buf = packHex8(buf, redCount);
  buf = packHex8(buf, redMax);
  buf = packHex8(buf, greenCount);
  buf = packHex8(buf, greenMax);
  buf = packHex8(buf, blueCount);
  buf = packHex8(buf, blueMax);
  buf = packHex8(buf, purpleCount);
  buf = packHex8(buf, purpleMax);
  buf = packHex8(buf, observerCount);
  buf = packHex8(buf, observerMax);
  *buf = 0;
}

void			PingPacket::unpackHex(char* buf)
{
  buf = unpackHex16(buf, gameStyle);
  buf = unpackHex16(buf, maxShots);
  buf = unpackHex16(buf, shakeWins);
  buf = unpackHex16(buf, shakeTimeout);
  buf = unpackHex16(buf, maxPlayerScore);
  buf = unpackHex16(buf, maxTeamScore);
  buf = unpackHex16(buf, maxTime);
  buf = unpackHex8(buf, maxPlayers);
  buf = unpackHex8(buf, rogueCount);
  buf = unpackHex8(buf, rogueMax);
  buf = unpackHex8(buf, redCount);
  buf = unpackHex8(buf, redMax);
  buf = unpackHex8(buf, greenCount);
  buf = unpackHex8(buf, greenMax);
  buf = unpackHex8(buf, blueCount);
  buf = unpackHex8(buf, blueMax);
  buf = unpackHex8(buf, purpleCount);
  buf = unpackHex8(buf, purpleMax);
  buf = unpackHex8(buf, observerCount);
  buf = unpackHex8(buf, observerMax);
}

int			PingPacket::hex2bin(char d)
{
  switch (d) {
    case '0': return 0;
    case '1': return 1;
    case '2': return 2;
    case '3': return 3;
    case '4': return 4;
    case '5': return 5;
    case '6': return 6;
    case '7': return 7;
    case '8': return 8;
    case '9': return 9;
    case 'A':
    case 'a': return 10;
    case 'B':
    case 'b': return 11;
    case 'C':
    case 'c': return 12;
    case 'D':
    case 'd': return 13;
    case 'E':
    case 'e': return 14;
    case 'F':
    case 'f': return 15;
  }
  return 0;
}

char			PingPacket::bin2hex(int d)
{
  static const char* digit = "0123456789abcdef";
  return digit[d];
}

char*			PingPacket::packHex16(char* buf, uint16_t v)
{
  *buf++ = bin2hex((v >> 12) & 0xf);
  *buf++ = bin2hex((v >>  8) & 0xf);
  *buf++ = bin2hex((v >>  4) & 0xf);
  *buf++ = bin2hex( v        & 0xf);
  return buf;
}

char*			PingPacket::unpackHex16(char* buf, uint16_t& v)
{
  uint16_t d = 0;
  d = (d << 4) | hex2bin(*buf++);
  d = (d << 4) | hex2bin(*buf++);
  d = (d << 4) | hex2bin(*buf++);
  d = (d << 4) | hex2bin(*buf++);
  v = d;
  return buf;
}

char*			PingPacket::packHex8(char* buf, uint8_t v)
{
  *buf++ = bin2hex((v >>  4) & 0xf);
  *buf++ = bin2hex( v        & 0xf);
  return buf;
}

char*			PingPacket::unpackHex8(char* buf, uint8_t& v)
{
  uint16_t d = 0;
  d = (d << 4) | hex2bin(*buf++);
  d = (d << 4) | hex2bin(*buf++);
  v = d;
  return buf;
}

void			 PingPacket::zeroPlayerCounts()
{
  rogueCount = 0;
  redCount = 0;
  greenCount = 0;
  blueCount = 0;
  purpleCount = 0;
  observerCount = 0;
}

// serialize packet to file -- note lack of error checking
// must write to a binary file if we use plain "pack"
void			 PingPacket::writeToFile (std::ostream& out) const
{
  if (!out) return;

  char buffer[PingPacket::PacketSize];
  void* buf = buffer;
  buf = nboPackUShort(buf, PingPacket::PacketSize - 4);
  buf = nboPackUShort(buf, MsgPingCodeReply);
  buf = pack(buf, getServerVersion());
  out.write(buffer,sizeof(buffer));
}

// de serialize packet from file
// must read from a binary file if we use plain "unpack"
bool			 PingPacket::readFromFile(std::istream& in)
{
  if (!in) return false;

  char buffer[PingPacket::PacketSize], serverVersion[9];
  uint16_t len, code;

  // get packet
  in.read(buffer, sizeof(buffer));
  if ((size_t)in.gcount() < sizeof(buffer)){
    return false;
  }

  // decode header
  void* buf = buffer;
  buf = nboUnpackUShort(buf, len);
  buf = nboUnpackUShort(buf, code);

  // make sure we got the rest of the message
  if (len != in.gcount() - 4){
    return false;
  }

  // unpack body of reply
  buf = unpack(buf, serverVersion);

  // compare version against my version.  ignore last character of
  // version number.  that's only used to indicate compatible
  // client-side changes.
  return (strncmp(serverVersion, getServerVersion(), 7) == 0);
}

// Local variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<commit_msg>typecast 2byte value to 1 byte value<commit_after>/* bzflag
 * Copyright (c) 1993 - 2003 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */
// todo make this turn off for .net
#if defined(_WIN32)
	#pragma warning(disable: 4786)
#endif

#include <string.h>
#include <math.h>
#include <ctype.h>
#include <fstream>
#include "common.h"
#include "global.h"
#include "Ping.h"
#include "Protocol.h"
#include "TimeKeeper.h"
#include "bzfio.h"

// incessint rebuilding for current versioning
#include "version.h"

//
// PingPacket
//

const int		PingPacket::PacketSize = ServerIdPLen + 52;

PingPacket::PingPacket() : gameStyle(PlainGameStyle),
				maxShots(1),
				shakeWins(0),
				shakeTimeout(0),
				maxPlayerScore(0),
				maxTeamScore(0),
				maxTime(0),
				maxPlayers(1),
				rogueCount(0),
				rogueMax(1),
				redCount(0),
				redMax(1),
				greenCount(0),
				greenMax(1),
				blueCount(0),
				blueMax(1),
				purpleCount(0),
				purpleMax(1),
				observerCount(0),
				observerMax(1)
{
  // do nothing
}

PingPacket::~PingPacket()
{
  // do nothing
}

bool			PingPacket::read(int fd, struct sockaddr_in* addr)
{
  char buffer[PacketSize], serverVersion[9];
  uint16_t len, code;

  // get packet
  int n = recvMulticast(fd, buffer, sizeof(buffer), addr);
  if (n < 4)
    return false;

  // decode header
  void* buf = buffer;
  buf = nboUnpackUShort(buf, len);
  buf = nboUnpackUShort(buf, code);

  // make sure we got the rest of the message
  if (len != n - 4)
    return false;

  // check that it's a reply
  if (code != MsgPingCodeReply)
    return false;

  // unpack body of reply
  buf = unpack(buf, serverVersion);

  // compare version against my version.  ignore last character of
  // version number.  that's only used to indicate compatible
  // client-side changes.
  return (strncmp(serverVersion, getServerVersion(), 7) == 0);
}

bool			PingPacket::waitForReply(int fd,
				const Address& from,
				int millisecondsToBlock)
{
  // block waiting on input.  if the incoming message is not from the
  // indicated source then ignore it and go back to waiting.  if the
  // incoming message is not a ping then ignore it and go back to waiting.
  float blockTime = 0.0001f * (float)millisecondsToBlock;
  TimeKeeper startTime = TimeKeeper::getCurrent();
  TimeKeeper currentTime = startTime;
  do {
    // prepare timeout
    const float timeLeft = blockTime - (currentTime - startTime);
    struct timeval timeout;
    timeout.tv_sec = long(floorf(timeLeft));
    timeout.tv_usec = long(1.0e+6f * (timeLeft - floorf(timeLeft)));

    // wait for input
    fd_set read_set;
    FD_ZERO(&read_set);
// turn off == signed/unsigned mismatch on win32
#if defined(_WIN32)
#pragma warning(disable: 4018)
#endif
    FD_SET(fd, &read_set);
#if defined(_WIN32)
#pragma warning(default: 4018)
#endif
    int nfound = select(fd+1, (fd_set*)&read_set, NULL, NULL, &timeout);

    // if got a message read it.  if a ping packet and from right
    // sender then return success.
    if (nfound < 0)
      return false;
    if (nfound > 0 && read(fd, NULL))
      if (sourceAddr == from)
	return true;

    currentTime = TimeKeeper::getCurrent();
  } while (currentTime - startTime < blockTime);
  return false;
}

bool			PingPacket::write(int fd,
					const struct sockaddr_in* addr) const
{
  char buffer[PacketSize];
  void* buf = buffer;
  buf = nboPackUShort(buf, PacketSize - 4);
  buf = nboPackUShort(buf, MsgPingCodeReply);
  buf = pack(buf, getServerVersion());
  return sendMulticast(fd, buffer, sizeof(buffer), addr) == sizeof(buffer);
}

bool			PingPacket::isRequest(int fd,
				struct sockaddr_in* addr)
{
  if (fd < 0) return false;
  char buffer[6];
  void *msg = buffer;
  uint16_t len, code;
  int size = recvMulticast(fd, buffer, sizeof(buffer), addr);
  if (size < 2) return false;
  msg = nboUnpackUShort(msg, len);
  msg = nboUnpackUShort(msg, code);
  return code == MsgPingCodeRequest;
}

bool			PingPacket::sendRequest(int fd,
					const struct sockaddr_in* addr)
{
  if (fd < 0 || !addr) return false;
  char buffer[6];
  void *msg = buffer;
  msg = nboPackUShort(msg, 2);
  msg = nboPackUShort(msg, MsgPingCodeRequest);
  msg = nboPackUShort(msg, (uint16_t) 0);
  return sendMulticast(fd, buffer, sizeof(buffer), addr) == sizeof(buffer);
}

void*			PingPacket::unpack(void* buf, char* version)
{
  buf = nboUnpackString(buf, version, 8);
  buf = serverId.unpack(buf);
  buf = sourceAddr.unpack(buf);
  buf = nboUnpackUShort(buf, gameStyle);
  buf = nboUnpackUShort(buf, maxShots);
  buf = nboUnpackUShort(buf, shakeWins);
  buf = nboUnpackUShort(buf, shakeTimeout);
  buf = nboUnpackUShort(buf, maxPlayerScore);
  buf = nboUnpackUShort(buf, maxTeamScore);
  buf = nboUnpackUShort(buf, maxTime);
  buf = nboUnpackUByte(buf, maxPlayers);
  buf = nboUnpackUByte(buf, rogueCount);
  buf = nboUnpackUByte(buf, rogueMax);
  buf = nboUnpackUByte(buf, redCount);
  buf = nboUnpackUByte(buf, redMax);
  buf = nboUnpackUByte(buf, greenCount);
  buf = nboUnpackUByte(buf, greenMax);
  buf = nboUnpackUByte(buf, blueCount);
  buf = nboUnpackUByte(buf, blueMax);
  buf = nboUnpackUByte(buf, purpleCount);
  buf = nboUnpackUByte(buf, purpleMax);
  buf = nboUnpackUByte(buf, observerCount);
  buf = nboUnpackUByte(buf, observerMax);
  return buf;
}

void*			PingPacket::pack(void* buf, const char* version) const
{
  buf = nboPackString(buf, version, 8);
  buf = serverId.pack(buf);
  buf = sourceAddr.pack(buf);
  buf = nboPackUShort(buf, gameStyle);
  buf = nboPackUShort(buf, maxShots);
  buf = nboPackUShort(buf, shakeWins);
  buf = nboPackUShort(buf, shakeTimeout);	// 1/10ths of second
  buf = nboPackUShort(buf, maxPlayerScore);
  buf = nboPackUShort(buf, maxTeamScore);
  buf = nboPackUShort(buf, maxTime);
  buf = nboPackUByte(buf, maxPlayers);
  buf = nboPackUByte(buf, rogueCount);
  buf = nboPackUByte(buf, rogueMax);
  buf = nboPackUByte(buf, redCount);
  buf = nboPackUByte(buf, redMax);
  buf = nboPackUByte(buf, greenCount);
  buf = nboPackUByte(buf, greenMax);
  buf = nboPackUByte(buf, blueCount);
  buf = nboPackUByte(buf, blueMax);
  buf = nboPackUByte(buf, purpleCount);
  buf = nboPackUByte(buf, purpleMax);
  buf = nboPackUByte(buf, observerCount);
  buf = nboPackUByte(buf, observerMax);
  return buf;
}

void			PingPacket::packHex(char* buf) const
{
  buf = packHex16(buf, gameStyle);
  buf = packHex16(buf, maxShots);
  buf = packHex16(buf, shakeWins);
  buf = packHex16(buf, shakeTimeout);
  buf = packHex16(buf, maxPlayerScore);
  buf = packHex16(buf, maxTeamScore);
  buf = packHex16(buf, maxTime);
  buf = packHex8(buf, maxPlayers);
  buf = packHex8(buf, rogueCount);
  buf = packHex8(buf, rogueMax);
  buf = packHex8(buf, redCount);
  buf = packHex8(buf, redMax);
  buf = packHex8(buf, greenCount);
  buf = packHex8(buf, greenMax);
  buf = packHex8(buf, blueCount);
  buf = packHex8(buf, blueMax);
  buf = packHex8(buf, purpleCount);
  buf = packHex8(buf, purpleMax);
  buf = packHex8(buf, observerCount);
  buf = packHex8(buf, observerMax);
  *buf = 0;
}

void			PingPacket::unpackHex(char* buf)
{
  buf = unpackHex16(buf, gameStyle);
  buf = unpackHex16(buf, maxShots);
  buf = unpackHex16(buf, shakeWins);
  buf = unpackHex16(buf, shakeTimeout);
  buf = unpackHex16(buf, maxPlayerScore);
  buf = unpackHex16(buf, maxTeamScore);
  buf = unpackHex16(buf, maxTime);
  buf = unpackHex8(buf, maxPlayers);
  buf = unpackHex8(buf, rogueCount);
  buf = unpackHex8(buf, rogueMax);
  buf = unpackHex8(buf, redCount);
  buf = unpackHex8(buf, redMax);
  buf = unpackHex8(buf, greenCount);
  buf = unpackHex8(buf, greenMax);
  buf = unpackHex8(buf, blueCount);
  buf = unpackHex8(buf, blueMax);
  buf = unpackHex8(buf, purpleCount);
  buf = unpackHex8(buf, purpleMax);
  buf = unpackHex8(buf, observerCount);
  buf = unpackHex8(buf, observerMax);
}

int			PingPacket::hex2bin(char d)
{
  switch (d) {
    case '0': return 0;
    case '1': return 1;
    case '2': return 2;
    case '3': return 3;
    case '4': return 4;
    case '5': return 5;
    case '6': return 6;
    case '7': return 7;
    case '8': return 8;
    case '9': return 9;
    case 'A':
    case 'a': return 10;
    case 'B':
    case 'b': return 11;
    case 'C':
    case 'c': return 12;
    case 'D':
    case 'd': return 13;
    case 'E':
    case 'e': return 14;
    case 'F':
    case 'f': return 15;
  }
  return 0;
}

char			PingPacket::bin2hex(int d)
{
  static const char* digit = "0123456789abcdef";
  return digit[d];
}

char*			PingPacket::packHex16(char* buf, uint16_t v)
{
  *buf++ = bin2hex((v >> 12) & 0xf);
  *buf++ = bin2hex((v >>  8) & 0xf);
  *buf++ = bin2hex((v >>  4) & 0xf);
  *buf++ = bin2hex( v        & 0xf);
  return buf;
}

char*			PingPacket::unpackHex16(char* buf, uint16_t& v)
{
  uint16_t d = 0;
  d = (d << 4) | hex2bin(*buf++);
  d = (d << 4) | hex2bin(*buf++);
  d = (d << 4) | hex2bin(*buf++);
  d = (d << 4) | hex2bin(*buf++);
  v = d;
  return buf;
}

char*			PingPacket::packHex8(char* buf, uint8_t v)
{
  *buf++ = bin2hex((v >>  4) & 0xf);
  *buf++ = bin2hex( v        & 0xf);
  return buf;
}

char*			PingPacket::unpackHex8(char* buf, uint8_t& v)
{
  uint16_t d = 0;
  d = (d << 4) | hex2bin(*buf++);
  d = (d << 4) | hex2bin(*buf++);
  v = (uint8_t)d;
  return buf;
}

void			 PingPacket::zeroPlayerCounts()
{
  rogueCount = 0;
  redCount = 0;
  greenCount = 0;
  blueCount = 0;
  purpleCount = 0;
  observerCount = 0;
}

// serialize packet to file -- note lack of error checking
// must write to a binary file if we use plain "pack"
void			 PingPacket::writeToFile (std::ostream& out) const
{
  if (!out) return;

  char buffer[PingPacket::PacketSize];
  void* buf = buffer;
  buf = nboPackUShort(buf, PingPacket::PacketSize - 4);
  buf = nboPackUShort(buf, MsgPingCodeReply);
  buf = pack(buf, getServerVersion());
  out.write(buffer,sizeof(buffer));
}

// de serialize packet from file
// must read from a binary file if we use plain "unpack"
bool			 PingPacket::readFromFile(std::istream& in)
{
  if (!in) return false;

  char buffer[PingPacket::PacketSize], serverVersion[9];
  uint16_t len, code;

  // get packet
  in.read(buffer, sizeof(buffer));
  if ((size_t)in.gcount() < sizeof(buffer)){
    return false;
  }

  // decode header
  void* buf = buffer;
  buf = nboUnpackUShort(buf, len);
  buf = nboUnpackUShort(buf, code);

  // make sure we got the rest of the message
  if (len != in.gcount() - 4){
    return false;
  }

  // unpack body of reply
  buf = unpack(buf, serverVersion);

  // compare version against my version.  ignore last character of
  // version number.  that's only used to indicate compatible
  // client-side changes.
  return (strncmp(serverVersion, getServerVersion(), 7) == 0);
}

// Local variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<|endoftext|>