<commit_before>//===--- CacheTokens.cpp - Caching of lexer tokens for PCH support --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This provides a possible implementation of PCH support for Clang that is
// based on caching lexed tokens and identifiers.
//
//===----------------------------------------------------------------------===//

#include "clang.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"

using namespace clang;

typedef uint32_t Offset;

typedef llvm::DenseMap<const FileEntry*,std::pair<Offset,Offset> > PCHMap;
typedef llvm::DenseMap<const IdentifierInfo*,uint32_t> IDMap;

static void Emit8(llvm::raw_ostream& Out, uint32_t V) {
  Out << (unsigned char)(V);
}

static void Emit32(llvm::raw_ostream& Out, uint32_t V) {
  Out << (unsigned char)(V);
  Out << (unsigned char)(V >>  8);
  Out << (unsigned char)(V >> 16);
  Out << (unsigned char)(V >> 24);
}

static void Emit16(llvm::raw_ostream& Out, uint32_t V) {
  Out << (unsigned char)(V);
  Out << (unsigned char)(V >>  8);
  assert((V >> 16) == 0);
}

static void Emit24(llvm::raw_ostream& Out, uint32_t V) {
  Out << (unsigned char)(V);
  Out << (unsigned char)(V >>  8);
  Out << (unsigned char)(V >> 16);
  assert((V >> 24) == 0);
}

static void EmitBuf(llvm::raw_ostream& Out, const char* I, const char* E) {
  for ( ; I != E ; ++I) Out << *I;
}

static uint32_t ResolveID(IDMap& IM, uint32_t& idx, const IdentifierInfo* II) {

  // Null IdentifierInfo's map to the persistent ID 0.
  if (!II)
    return 0;

  IDMap::iterator I = IM.find(II);

  if (I == IM.end()) {
    IM[II] = ++idx; // Pre-increment since '0' is reserved for NULL.
    return idx;
  }

  return I->second; // We've already added 1.
}

static void EmitToken(llvm::raw_ostream& Out, const Token& T,
                      const SourceManager& SMgr,
                      uint32_t& idcount, IDMap& IM) {

  Emit8(Out, T.getKind());
  Emit8(Out, T.getFlags());
  Emit24(Out, ResolveID(IM, idcount, T.getIdentifierInfo()));
  Emit32(Out, SMgr.getFullFilePos(T.getLocation()));
  Emit16(Out, T.getLength());
}

struct IDData {
  const IdentifierInfo* II;
  uint32_t FileOffset;
  const IdentifierTable::const_iterator::value_type* Str;
};

static std::pair<Offset,Offset>
EmitIdentifierTable(llvm::raw_fd_ostream& Out, uint32_t max,
                    const IdentifierTable& T, const IDMap& IM) {

  // Build an inverse map from persistent IDs -> IdentifierInfo*.
  typedef std::vector<IDData> InverseIDMap;
  InverseIDMap IIDMap;
  IIDMap.resize(max);

  // Generate mapping from persistent IDs -> IdentifierInfo*.
  for (IDMap::const_iterator I=IM.begin(), E=IM.end(); I!=E; ++I) {
    // Decrement by 1 because we are using a vector for the lookup and
    // 0 is reserved for NULL.
    assert(I->second > 0);
    assert(I->second-1 < IIDMap.size());
    IIDMap[I->second-1].II = I->first;
  }

  // Get the string data associated with the IdentifierInfo.
  for (IdentifierTable::const_iterator I=T.begin(), E=T.end(); I!=E; ++I) {
    IDMap::const_iterator IDI = IM.find(&(I->getValue()));
    if (IDI == IM.end()) continue;
    IIDMap[IDI->second-1].Str = &(*I);
  }

  Offset DataOff = Out.tell();

  for (InverseIDMap::iterator I=IIDMap.begin(), E=IIDMap.end(); I!=E; ++I) {
    // Record the location for this data.
    I->FileOffset = Out.tell();
    // Write out the keyword.
    unsigned len = I->Str->getKeyLength();
    Emit32(Out, len);
    const char* buf = I->Str->getKeyData();
    EmitBuf(Out, buf, buf+len);
  }

  // Now emit the table mapping from persistent IDs to PTH file offsets.
  Offset IDOff = Out.tell();

  // Emit the number of identifiers.
  Emit32(Out, max);

  for (InverseIDMap::iterator I=IIDMap.begin(), E=IIDMap.end(); I!=E; ++I)
    Emit32(Out, I->FileOffset);

  return std::make_pair(DataOff, IDOff);
}

Offset EmitFileTable(llvm::raw_fd_ostream& Out, SourceManager& SM, PCHMap& PM) {

  Offset off = (Offset) Out.tell();

  // Output the size of the table.
  Emit32(Out, PM.size());

  for (PCHMap::iterator I=PM.begin(), E=PM.end(); I!=E; ++I) {
    const FileEntry* FE = I->first;
    const char* Name = FE->getName();
    unsigned size = strlen(Name);
    Emit32(Out, size);
    EmitBuf(Out, Name, Name+size);
    Emit32(Out, I->second.first);
    Emit32(Out, I->second.second);
  }

  return off;
}

static std::pair<Offset,Offset>
LexTokens(llvm::raw_fd_ostream& Out, Lexer& L, Preprocessor& PP,
          uint32_t& idcount, IDMap& IM) {

  // Record the location within the token file.
  Offset off = (Offset) Out.tell();
  SourceManager& SMgr = PP.getSourceManager();

  // Keep track of matching '#if' ... '#endif'.
  typedef std::vector<std::pair<Offset, unsigned> > PPCondTable;
  PPCondTable PPCond;
  std::vector<unsigned> PPStartCond;
  bool ParsingPreprocessorDirective = false;

  Token Tok;

  do {
    L.LexFromRawLexer(Tok);

    if ((Tok.isAtStartOfLine() || Tok.is(tok::eof)) &&
        ParsingPreprocessorDirective) {
      // Insert an eom token into the token cache.  It has the same
      // position as the next token that is not on the same line as the
      // preprocessor directive.  Observe that we continue processing
      // 'Tok' when we exit this branch.
      Token Tmp = Tok;
      Tmp.setKind(tok::eom);
      Tmp.clearFlag(Token::StartOfLine);
      Tmp.setIdentifierInfo(0);
      EmitToken(Out, Tmp, SMgr, idcount, IM);
      ParsingPreprocessorDirective = false;
    }

    if (Tok.is(tok::identifier)) {
      Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
      continue;
    }

    if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
      // Special processing for #include.  Store the '#' token and lex
      // the next token.
      assert(!ParsingPreprocessorDirective);
      Offset HashOff = (Offset) Out.tell();
      EmitToken(Out, Tok, SMgr, idcount, IM);

      // Get the next token.
      L.LexFromRawLexer(Tok);

      assert(!Tok.isAtStartOfLine());

      // Did we see 'include'/'import'/'include_next'?
      if (!Tok.is(tok::identifier))
        continue;

      IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok);
      Tok.setIdentifierInfo(II);
      tok::PPKeywordKind K = II->getPPKeywordID();

      assert(K != tok::pp_not_keyword);
      ParsingPreprocessorDirective = true;

      switch (K) {
      default:
        break;
      case tok::pp_include:
      case tok::pp_import:
      case tok::pp_include_next: {
        // Save the 'include' token.
        EmitToken(Out, Tok, SMgr, idcount, IM);
        // Lex the next token as an include string.
        L.setParsingPreprocessorDirective(true);
        L.LexIncludeFilename(Tok);
        L.setParsingPreprocessorDirective(false);
        assert(!Tok.isAtStartOfLine());
        if (Tok.is(tok::identifier))
          Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));

        break;
      }
      case tok::pp_if:
      case tok::pp_ifdef:
      case tok::pp_ifndef: {
        // Ad an entry for '#if' and friends.  We initially set the target index
        // to 0.  This will get backpatched when we hit #endif.
        PPStartCond.push_back(PPCond.size());
        PPCond.push_back(std::make_pair(HashOff, 0U));
        break;
      }
      case tok::pp_endif: {
        // Add an entry for '#endif'.  We set the target table index to itself.
        // This will later be set to zero when emitting to the PTH file.  We
        // use 0 for uninitialized indices because that is easier to debug.
        unsigned index = PPCond.size();
        // Backpatch the opening '#if' entry.
        assert(!PPStartCond.empty());
        assert(PPCond.size() > PPStartCond.back());
        assert(PPCond[PPStartCond.back()].second == 0);
        PPCond[PPStartCond.back()].second = index;
        PPStartCond.pop_back();
        // Add the new entry to PPCond.
        PPCond.push_back(std::make_pair(HashOff, index));
        break;
      }
      case tok::pp_elif:
      case tok::pp_else: {
        // Add an entry for #elif or #else.
        // This serves as both a closing and opening of a conditional block.
        // This means that its entry will get backpatched later.
        unsigned index = PPCond.size();
        // Backpatch the previous '#if' entry.
        assert(!PPStartCond.empty());
        assert(PPCond.size() > PPStartCond.back());
        assert(PPCond[PPStartCond.back()].second == 0);
        PPCond[PPStartCond.back()].second = index;
        PPStartCond.pop_back();
        // Now add '#elif' as a new block opening.
        PPCond.push_back(std::make_pair(HashOff, 0U));
        PPStartCond.push_back(index);
        break;
      }
      }
    }
  }
  while (EmitToken(Out, Tok, SMgr, idcount, IM), Tok.isNot(tok::eof));

  assert(PPStartCond.empty() && "Error: imblanced preprocessor conditionals.");

  // Next write out PPCond.
  Offset PPCondOff = (Offset) Out.tell();

  // Write out the size of PPCond so that clients can identifer empty tables.
  Emit32(Out, PPCond.size());

  for (unsigned i = 0, e = PPCond.size(); i!=e; ++i) {
    Emit32(Out, PPCond[i].first - off);
    uint32_t x = PPCond[i].second;
    assert(x != 0 && "PPCond entry not backpatched.");
    // Emit zero for #endifs.  This allows us to do checking when
    // we read the PTH file back in.
    Emit32(Out, x == i ? 0 : x);
  }

  return std::make_pair(off,PPCondOff);
}

void clang::CacheTokens(Preprocessor& PP, const std::string& OutFile) {
  // Lex through the entire file.  This will populate SourceManager with
  // all of the header information.
  Token Tok;
  PP.EnterMainSourceFile();
  do { PP.Lex(Tok); } while (Tok.isNot(tok::eof));

  // Iterate over all the files in SourceManager.  Create a lexer
  // for each file and cache the tokens.
  SourceManager& SM = PP.getSourceManager();
  const LangOptions& LOpts = PP.getLangOptions();
  llvm::raw_ostream& os = llvm::errs();

  PCHMap PM;
  IDMap  IM;
  uint32_t idcount = 0;

  std::string ErrMsg;
  llvm::raw_fd_ostream Out(OutFile.c_str(), true, ErrMsg);

  if (!ErrMsg.empty()) {
    os << "PTH error: " << ErrMsg << "\n";
    return;
  }

  for (SourceManager::fileid_iterator I=SM.fileid_begin(), E=SM.fileid_end();
       I!=E; ++I) {

    const SrcMgr::ContentCache* C = I.getFileIDInfo().getContentCache();
    if (!C) continue;

    const FileEntry* FE = C->Entry;    // Does this entry correspond to a file?
    if (!FE) continue;

    // FIXME: Handle files with non-absolute paths.
    llvm::sys::Path P(FE->getName());
    if (!P.isAbsolute())
      continue;

    PCHMap::iterator PI = PM.find(FE); // Have we already processed this file?
    if (PI != PM.end()) continue;

    const llvm::MemoryBuffer* B = C->Buffer;
    if (!B) continue;

    Lexer L(SourceLocation::getFileLoc(I.getFileID(), 0), LOpts,
            B->getBufferStart(), B->getBufferEnd(), B);

    PM[FE] = LexTokens(Out, L, PP, idcount, IM);
  }

  // Write out the identifier table.
  std::pair<Offset,Offset> IdTableOff =
    EmitIdentifierTable(Out, idcount, PP.getIdentifierTable(), IM);

  // Write out the file table.
  Offset FileTableOff = EmitFileTable(Out, SM, PM);

  // Finally, write out the offset table at the end.
  Emit32(Out, IdTableOff.first);
  Emit32(Out, IdTableOff.second);
  Emit32(Out, FileTableOff);
}
<commit_msg>use getBuffer() to fix compile error.  Ted, please review.<commit_after>//===--- CacheTokens.cpp - Caching of lexer tokens for PCH support --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This provides a possible implementation of PCH support for Clang that is
// based on caching lexed tokens and identifiers.
//
//===----------------------------------------------------------------------===//

#include "clang.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"

using namespace clang;

typedef uint32_t Offset;

typedef llvm::DenseMap<const FileEntry*,std::pair<Offset,Offset> > PCHMap;
typedef llvm::DenseMap<const IdentifierInfo*,uint32_t> IDMap;

static void Emit8(llvm::raw_ostream& Out, uint32_t V) {
  Out << (unsigned char)(V);
}

static void Emit32(llvm::raw_ostream& Out, uint32_t V) {
  Out << (unsigned char)(V);
  Out << (unsigned char)(V >>  8);
  Out << (unsigned char)(V >> 16);
  Out << (unsigned char)(V >> 24);
}

static void Emit16(llvm::raw_ostream& Out, uint32_t V) {
  Out << (unsigned char)(V);
  Out << (unsigned char)(V >>  8);
  assert((V >> 16) == 0);
}

static void Emit24(llvm::raw_ostream& Out, uint32_t V) {
  Out << (unsigned char)(V);
  Out << (unsigned char)(V >>  8);
  Out << (unsigned char)(V >> 16);
  assert((V >> 24) == 0);
}

static void EmitBuf(llvm::raw_ostream& Out, const char* I, const char* E) {
  for ( ; I != E ; ++I) Out << *I;
}

static uint32_t ResolveID(IDMap& IM, uint32_t& idx, const IdentifierInfo* II) {

  // Null IdentifierInfo's map to the persistent ID 0.
  if (!II)
    return 0;

  IDMap::iterator I = IM.find(II);

  if (I == IM.end()) {
    IM[II] = ++idx; // Pre-increment since '0' is reserved for NULL.
    return idx;
  }

  return I->second; // We've already added 1.
}

static void EmitToken(llvm::raw_ostream& Out, const Token& T,
                      const SourceManager& SMgr,
                      uint32_t& idcount, IDMap& IM) {

  Emit8(Out, T.getKind());
  Emit8(Out, T.getFlags());
  Emit24(Out, ResolveID(IM, idcount, T.getIdentifierInfo()));
  Emit32(Out, SMgr.getFullFilePos(T.getLocation()));
  Emit16(Out, T.getLength());
}

struct IDData {
  const IdentifierInfo* II;
  uint32_t FileOffset;
  const IdentifierTable::const_iterator::value_type* Str;
};

static std::pair<Offset,Offset>
EmitIdentifierTable(llvm::raw_fd_ostream& Out, uint32_t max,
                    const IdentifierTable& T, const IDMap& IM) {

  // Build an inverse map from persistent IDs -> IdentifierInfo*.
  typedef std::vector<IDData> InverseIDMap;
  InverseIDMap IIDMap;
  IIDMap.resize(max);

  // Generate mapping from persistent IDs -> IdentifierInfo*.
  for (IDMap::const_iterator I=IM.begin(), E=IM.end(); I!=E; ++I) {
    // Decrement by 1 because we are using a vector for the lookup and
    // 0 is reserved for NULL.
    assert(I->second > 0);
    assert(I->second-1 < IIDMap.size());
    IIDMap[I->second-1].II = I->first;
  }

  // Get the string data associated with the IdentifierInfo.
  for (IdentifierTable::const_iterator I=T.begin(), E=T.end(); I!=E; ++I) {
    IDMap::const_iterator IDI = IM.find(&(I->getValue()));
    if (IDI == IM.end()) continue;
    IIDMap[IDI->second-1].Str = &(*I);
  }

  Offset DataOff = Out.tell();

  for (InverseIDMap::iterator I=IIDMap.begin(), E=IIDMap.end(); I!=E; ++I) {
    // Record the location for this data.
    I->FileOffset = Out.tell();
    // Write out the keyword.
    unsigned len = I->Str->getKeyLength();
    Emit32(Out, len);
    const char* buf = I->Str->getKeyData();
    EmitBuf(Out, buf, buf+len);
  }

  // Now emit the table mapping from persistent IDs to PTH file offsets.
  Offset IDOff = Out.tell();

  // Emit the number of identifiers.
  Emit32(Out, max);

  for (InverseIDMap::iterator I=IIDMap.begin(), E=IIDMap.end(); I!=E; ++I)
    Emit32(Out, I->FileOffset);

  return std::make_pair(DataOff, IDOff);
}

Offset EmitFileTable(llvm::raw_fd_ostream& Out, SourceManager& SM, PCHMap& PM) {

  Offset off = (Offset) Out.tell();

  // Output the size of the table.
  Emit32(Out, PM.size());

  for (PCHMap::iterator I=PM.begin(), E=PM.end(); I!=E; ++I) {
    const FileEntry* FE = I->first;
    const char* Name = FE->getName();
    unsigned size = strlen(Name);
    Emit32(Out, size);
    EmitBuf(Out, Name, Name+size);
    Emit32(Out, I->second.first);
    Emit32(Out, I->second.second);
  }

  return off;
}

static std::pair<Offset,Offset>
LexTokens(llvm::raw_fd_ostream& Out, Lexer& L, Preprocessor& PP,
          uint32_t& idcount, IDMap& IM) {

  // Record the location within the token file.
  Offset off = (Offset) Out.tell();
  SourceManager& SMgr = PP.getSourceManager();

  // Keep track of matching '#if' ... '#endif'.
  typedef std::vector<std::pair<Offset, unsigned> > PPCondTable;
  PPCondTable PPCond;
  std::vector<unsigned> PPStartCond;
  bool ParsingPreprocessorDirective = false;

  Token Tok;

  do {
    L.LexFromRawLexer(Tok);

    if ((Tok.isAtStartOfLine() || Tok.is(tok::eof)) &&
        ParsingPreprocessorDirective) {
      // Insert an eom token into the token cache.  It has the same
      // position as the next token that is not on the same line as the
      // preprocessor directive.  Observe that we continue processing
      // 'Tok' when we exit this branch.
      Token Tmp = Tok;
      Tmp.setKind(tok::eom);
      Tmp.clearFlag(Token::StartOfLine);
      Tmp.setIdentifierInfo(0);
      EmitToken(Out, Tmp, SMgr, idcount, IM);
      ParsingPreprocessorDirective = false;
    }

    if (Tok.is(tok::identifier)) {
      Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
      continue;
    }

    if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
      // Special processing for #include.  Store the '#' token and lex
      // the next token.
      assert(!ParsingPreprocessorDirective);
      Offset HashOff = (Offset) Out.tell();
      EmitToken(Out, Tok, SMgr, idcount, IM);

      // Get the next token.
      L.LexFromRawLexer(Tok);

      assert(!Tok.isAtStartOfLine());

      // Did we see 'include'/'import'/'include_next'?
      if (!Tok.is(tok::identifier))
        continue;

      IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok);
      Tok.setIdentifierInfo(II);
      tok::PPKeywordKind K = II->getPPKeywordID();

      assert(K != tok::pp_not_keyword);
      ParsingPreprocessorDirective = true;

      switch (K) {
      default:
        break;
      case tok::pp_include:
      case tok::pp_import:
      case tok::pp_include_next: {
        // Save the 'include' token.
        EmitToken(Out, Tok, SMgr, idcount, IM);
        // Lex the next token as an include string.
        L.setParsingPreprocessorDirective(true);
        L.LexIncludeFilename(Tok);
        L.setParsingPreprocessorDirective(false);
        assert(!Tok.isAtStartOfLine());
        if (Tok.is(tok::identifier))
          Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));

        break;
      }
      case tok::pp_if:
      case tok::pp_ifdef:
      case tok::pp_ifndef: {
        // Ad an entry for '#if' and friends.  We initially set the target index
        // to 0.  This will get backpatched when we hit #endif.
        PPStartCond.push_back(PPCond.size());
        PPCond.push_back(std::make_pair(HashOff, 0U));
        break;
      }
      case tok::pp_endif: {
        // Add an entry for '#endif'.  We set the target table index to itself.
        // This will later be set to zero when emitting to the PTH file.  We
        // use 0 for uninitialized indices because that is easier to debug.
        unsigned index = PPCond.size();
        // Backpatch the opening '#if' entry.
        assert(!PPStartCond.empty());
        assert(PPCond.size() > PPStartCond.back());
        assert(PPCond[PPStartCond.back()].second == 0);
        PPCond[PPStartCond.back()].second = index;
        PPStartCond.pop_back();
        // Add the new entry to PPCond.
        PPCond.push_back(std::make_pair(HashOff, index));
        break;
      }
      case tok::pp_elif:
      case tok::pp_else: {
        // Add an entry for #elif or #else.
        // This serves as both a closing and opening of a conditional block.
        // This means that its entry will get backpatched later.
        unsigned index = PPCond.size();
        // Backpatch the previous '#if' entry.
        assert(!PPStartCond.empty());
        assert(PPCond.size() > PPStartCond.back());
        assert(PPCond[PPStartCond.back()].second == 0);
        PPCond[PPStartCond.back()].second = index;
        PPStartCond.pop_back();
        // Now add '#elif' as a new block opening.
        PPCond.push_back(std::make_pair(HashOff, 0U));
        PPStartCond.push_back(index);
        break;
      }
      }
    }
  }
  while (EmitToken(Out, Tok, SMgr, idcount, IM), Tok.isNot(tok::eof));

  assert(PPStartCond.empty() && "Error: imblanced preprocessor conditionals.");

  // Next write out PPCond.
  Offset PPCondOff = (Offset) Out.tell();

  // Write out the size of PPCond so that clients can identifer empty tables.
  Emit32(Out, PPCond.size());

  for (unsigned i = 0, e = PPCond.size(); i!=e; ++i) {
    Emit32(Out, PPCond[i].first - off);
    uint32_t x = PPCond[i].second;
    assert(x != 0 && "PPCond entry not backpatched.");
    // Emit zero for #endifs.  This allows us to do checking when
    // we read the PTH file back in.
    Emit32(Out, x == i ? 0 : x);
  }

  return std::make_pair(off,PPCondOff);
}

void clang::CacheTokens(Preprocessor& PP, const std::string& OutFile) {
  // Lex through the entire file.  This will populate SourceManager with
  // all of the header information.
  Token Tok;
  PP.EnterMainSourceFile();
  do { PP.Lex(Tok); } while (Tok.isNot(tok::eof));

  // Iterate over all the files in SourceManager.  Create a lexer
  // for each file and cache the tokens.
  SourceManager& SM = PP.getSourceManager();
  const LangOptions& LOpts = PP.getLangOptions();
  llvm::raw_ostream& os = llvm::errs();

  PCHMap PM;
  IDMap  IM;
  uint32_t idcount = 0;

  std::string ErrMsg;
  llvm::raw_fd_ostream Out(OutFile.c_str(), true, ErrMsg);

  if (!ErrMsg.empty()) {
    os << "PTH error: " << ErrMsg << "\n";
    return;
  }

  for (SourceManager::fileid_iterator I=SM.fileid_begin(), E=SM.fileid_end();
       I!=E; ++I) {

    const SrcMgr::ContentCache* C = I.getFileIDInfo().getContentCache();
    if (!C) continue;

    const FileEntry* FE = C->Entry;    // Does this entry correspond to a file?
    if (!FE) continue;

    // FIXME: Handle files with non-absolute paths.
    llvm::sys::Path P(FE->getName());
    if (!P.isAbsolute())
      continue;

    PCHMap::iterator PI = PM.find(FE); // Have we already processed this file?
    if (PI != PM.end()) continue;

    const llvm::MemoryBuffer* B = C->getBuffer();
    if (!B) continue;

    Lexer L(SourceLocation::getFileLoc(I.getFileID(), 0), LOpts,
            B->getBufferStart(), B->getBufferEnd(), B);

    PM[FE] = LexTokens(Out, L, PP, idcount, IM);
  }

  // Write out the identifier table.
  std::pair<Offset,Offset> IdTableOff =
    EmitIdentifierTable(Out, idcount, PP.getIdentifierTable(), IM);

  // Write out the file table.
  Offset FileTableOff = EmitFileTable(Out, SM, PM);

  // Finally, write out the offset table at the end.
  Emit32(Out, IdTableOff.first);
  Emit32(Out, IdTableOff.second);
  Emit32(Out, FileTableOff);
}
<|endoftext|>


<commit_before>/*************** <auto-copyright.pl BEGIN do not edit this line> **************
 *
 * VR Juggler is (C) Copyright 1998-2005 by Iowa State University
 *
 * Original Authors:
 *   Allen Bierbaum, Christopher Just,
 *   Patrick Hartling, Kevin Meinert,
 *   Carolina Cruz-Neira, Albert Baker
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * -----------------------------------------------------------------
 * File:          $RCSfile$
 * Date modified: $Date$
 * Version:       $Revision$
 * -----------------------------------------------------------------
 *
 *************** <auto-copyright.pl END do not edit this line> ***************/

#include <gadget/Devices/DriverConfig.h>

#include <vector>

#include <vpr/vpr.h>
#include <vpr/System.h>

#include <jccl/Config/ConfigElement.h>
#include <gadget/gadgetParam.h>
#include <gadget/InputManager.h>
#include <gadget/Type/DeviceConstructor.h>

#include "buttondevice.h"

/** Entry point function for the device driver plug-in. */
extern "C" GADGET_DRIVER_EXPORT(vpr::Uint32) getGadgeteerVersion()
{
   return __GADGET_version;
}

/** Entry point function for the device driver plug-in. */
extern "C" GADGET_DRIVER_EXPORT(void) initDevice(InputManager* inputMgr)
{
   new DeviceConstructor<ButtonDevice>(inputMgr);
}

// Returns a string that matches this device's configuration element type.
std::string ButtonDevice::getElementType()
{
   return std::string("button_device");
}

// When the system detects a configuration change for your driver, it will
// pass the jccl::ConfigElementPtr into this function.  See the documentation
// on config elements, for information on how to access them.
bool ButtonDevice::config(jccl::ConfigElementPtr e)
{
  // Configure all our base classes first.  If any of those fail, we cannot
  // finish configuring ourself.
  if ( ! Input::config(e) && ! Digital::config(e) )
  {
     return false;
  }

  mPort = e->getProperty<std::string>("port");
  mBaud = e->getProperty<int>("baud");

  return true;
}

// Spanws the sample thread, which calls ButtonDevice::sample() repeatedly.
bool ButtonDevice::startSampling()
{
   mRunning = true;
   mSampleThread = new vpr::Thread(threadedSampleFunction, (void*) this);

   if ( ! mSampleThread->valid() )
   {
      mRunning = false;
      return false; // thread creation failed
   }
   else
   {
      return true; // thread creation success
   }
}

// Records (or samples) the current data.  This is called repeatedly by the
// sample thread created by startSampling().
bool ButtonDevice::sample()
{
   bool status(false);

   if ( mRunning )
   {
      // Here you would add your code to sample the hardware for a button
      // press:
      std::vector<DigitalData> samples(1);
      samples[0] = 1;
      addDigitalSample(samples);

      // Successful sample.
      status = true;
   }

   return status;
}

// Kills the sample thread.
bool ButtonDevice::stopSampling()
{
   mRunning = false;

   if (mSampleThread != NULL)
   {
      mSampleThread->kill(); // Not guaranteed to work on all platforms
      mSampleThread->join();
      delete mSampleThread;
      mSampleThread = NULL;
   }
   return true;
}

void ButtonDevice::updateData()
{
   if ( mRunning )
   {
      swapDigitalBuffers();
   }
}

// Our sampling function that is executed by the spawned sample thread.
// This function is declared as a static member of ButtonDevice.  It simply
// calls ButtonDevice::sample() over and over.
void ButtonDevice::threadedSampleFunction(void* classPointer)
{
   ButtonDevice* this_ptr = static_cast<ButtonDevice*>( classPointer );

   // spin until someone kills "mSampleThread"
   while ( this_ptr->mRunning )
   {
     this_ptr->sample();
     vpr::System::sleep(1); //specify some time here, so you don't waste CPU cycles
   }
}

<commit_msg>Fixed incorrect indentation.  Whitespace only.<commit_after>/*************** <auto-copyright.pl BEGIN do not edit this line> **************
 *
 * VR Juggler is (C) Copyright 1998-2005 by Iowa State University
 *
 * Original Authors:
 *   Allen Bierbaum, Christopher Just,
 *   Patrick Hartling, Kevin Meinert,
 *   Carolina Cruz-Neira, Albert Baker
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * -----------------------------------------------------------------
 * File:          $RCSfile$
 * Date modified: $Date$
 * Version:       $Revision$
 * -----------------------------------------------------------------
 *
 *************** <auto-copyright.pl END do not edit this line> ***************/

#include <gadget/Devices/DriverConfig.h>

#include <vector>

#include <vpr/vpr.h>
#include <vpr/System.h>

#include <jccl/Config/ConfigElement.h>
#include <gadget/gadgetParam.h>
#include <gadget/InputManager.h>
#include <gadget/Type/DeviceConstructor.h>

#include "buttondevice.h"

/** Entry point function for the device driver plug-in. */
extern "C" GADGET_DRIVER_EXPORT(vpr::Uint32) getGadgeteerVersion()
{
   return __GADGET_version;
}

/** Entry point function for the device driver plug-in. */
extern "C" GADGET_DRIVER_EXPORT(void) initDevice(InputManager* inputMgr)
{
   new DeviceConstructor<ButtonDevice>(inputMgr);
}

// Returns a string that matches this device's configuration element type.
std::string ButtonDevice::getElementType()
{
   return std::string("button_device");
}

// When the system detects a configuration change for your driver, it will
// pass the jccl::ConfigElementPtr into this function.  See the documentation
// on config elements, for information on how to access them.
bool ButtonDevice::config(jccl::ConfigElementPtr e)
{
   // Configure all our base classes first.  If any of those fail, we cannot
   // finish configuring ourself.
   if ( ! Input::config(e) && ! Digital::config(e) )
   {
      return false;
   }

   mPort = e->getProperty<std::string>("port");
   mBaud = e->getProperty<int>("baud");

   return true;
}

// Spanws the sample thread, which calls ButtonDevice::sample() repeatedly.
bool ButtonDevice::startSampling()
{
   mRunning = true;
   mSampleThread = new vpr::Thread(threadedSampleFunction, (void*) this);

   if ( ! mSampleThread->valid() )
   {
      mRunning = false;
      return false; // thread creation failed
   }
   else
   {
      return true; // thread creation success
   }
}

// Records (or samples) the current data.  This is called repeatedly by the
// sample thread created by startSampling().
bool ButtonDevice::sample()
{
   bool status(false);

   if ( mRunning )
   {
      // Here you would add your code to sample the hardware for a button
      // press:
      std::vector<DigitalData> samples(1);
      samples[0] = 1;
      addDigitalSample(samples);

      // Successful sample.
      status = true;
   }

   return status;
}

// Kills the sample thread.
bool ButtonDevice::stopSampling()
{
   mRunning = false;

   if (mSampleThread != NULL)
   {
      mSampleThread->kill(); // Not guaranteed to work on all platforms
      mSampleThread->join();
      delete mSampleThread;
      mSampleThread = NULL;
   }
   return true;
}

void ButtonDevice::updateData()
{
   if ( mRunning )
   {
      swapDigitalBuffers();
   }
}

// Our sampling function that is executed by the spawned sample thread.
// This function is declared as a static member of ButtonDevice.  It simply
// calls ButtonDevice::sample() over and over.
void ButtonDevice::threadedSampleFunction(void* classPointer)
{
   ButtonDevice* this_ptr = static_cast<ButtonDevice*>( classPointer );

   // spin until someone kills "mSampleThread"
   while ( this_ptr->mRunning )
   {
     this_ptr->sample();
     vpr::System::sleep(1); //specify some time here, so you don't waste CPU cycles
   }
}

<|endoftext|>


<commit_before><commit_msg>Fix warnings<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (c) 2021 Morwenn
 * SPDX-License-Identifier: MIT
 */
#include <array>
#include <iterator>
#include <numeric>
#include <vector>
#include <catch2/catch.hpp>
#include <cpp-sort/fixed/sorting_network_sorter.h>
#include <cpp-sort/utility/sorting_networks.h>
#include <testing-tools/distributions.h>

TEST_CASE( "sorting with index pairs", "[utility][sorting_networks]" )
{
    // Index pairs for a "brick" sorting network to sort 8 inputs
    constexpr std::array<cppsort::utility::index_pair<int>, 28> pairs = {{
        {0, 1}, {2, 3}, {4, 5}, {6, 7},
        {1, 2}, {3, 4}, {5, 6},
        {0, 1}, {2, 3}, {4, 5}, {6, 7},
        {1, 2}, {3, 4}, {5, 6},
        {0, 1}, {2, 3}, {4, 5}, {6, 7},
        {1, 2}, {3, 4}, {5, 6},
        {0, 1}, {2, 3}, {4, 5}, {6, 7},
        {1, 2}, {3, 4}, {5, 6},
    }};

    std::vector<int> vec;
    auto distribution = dist::shuffled{};
    distribution(std::back_inserter(vec), 8);

    SECTION( "swap_index_pairs" )
    {
        swap_index_pairs(vec.begin(), pairs);
        CHECK( std::is_sorted(vec.begin(), vec.end()) );
    }

    SECTION( "swap_index_pairs_force_unroll" )
    {
        swap_index_pairs_force_unroll(vec.begin(), pairs);
        CHECK( std::is_sorted(vec.begin(), vec.end()) );
    }
}

TEST_CASE( "sorting with index pairs from sorting_network_sorter",
           "[utility][sorting_networks]" )
{
    constexpr auto pairs = cppsort::sorting_network_sorter<8>::index_pairs<int>();

    std::vector<int> vec;
    auto distribution = dist::shuffled{};
    distribution(std::back_inserter(vec), 8);

    SECTION( "swap_index_pairs" )
    {
        swap_index_pairs(vec.begin(), pairs);
        CHECK( std::is_sorted(vec.begin(), vec.end()) );
    }

    SECTION( "swap_index_pairs_force_unroll" )
    {
        swap_index_pairs_force_unroll(vec.begin(), pairs);
        CHECK( std::is_sorted(vec.begin(), vec.end()) );
    }
}
<commit_msg>Fully qualify some functions in tests<commit_after>/*
 * Copyright (c) 2021 Morwenn
 * SPDX-License-Identifier: MIT
 */
#include <array>
#include <iterator>
#include <numeric>
#include <vector>
#include <catch2/catch.hpp>
#include <cpp-sort/fixed/sorting_network_sorter.h>
#include <cpp-sort/utility/sorting_networks.h>
#include <testing-tools/distributions.h>

TEST_CASE( "sorting with index pairs", "[utility][sorting_networks]" )
{
    // Index pairs for a "brick" sorting network to sort 8 inputs
    constexpr std::array<cppsort::utility::index_pair<int>, 28> pairs = {{
        {0, 1}, {2, 3}, {4, 5}, {6, 7},
        {1, 2}, {3, 4}, {5, 6},
        {0, 1}, {2, 3}, {4, 5}, {6, 7},
        {1, 2}, {3, 4}, {5, 6},
        {0, 1}, {2, 3}, {4, 5}, {6, 7},
        {1, 2}, {3, 4}, {5, 6},
        {0, 1}, {2, 3}, {4, 5}, {6, 7},
        {1, 2}, {3, 4}, {5, 6},
    }};

    std::vector<int> vec;
    auto distribution = dist::shuffled{};
    distribution(std::back_inserter(vec), 8);

    SECTION( "swap_index_pairs" )
    {
        cppsort::utility::swap_index_pairs(vec.begin(), pairs);
        CHECK( std::is_sorted(vec.begin(), vec.end()) );
    }

    SECTION( "swap_index_pairs_force_unroll" )
    {
        cppsort::utility::swap_index_pairs_force_unroll(vec.begin(), pairs);
        CHECK( std::is_sorted(vec.begin(), vec.end()) );
    }
}

TEST_CASE( "sorting with index pairs from sorting_network_sorter",
           "[utility][sorting_networks]" )
{
    constexpr auto pairs = cppsort::sorting_network_sorter<8>::index_pairs<int>();

    std::vector<int> vec;
    auto distribution = dist::shuffled{};
    distribution(std::back_inserter(vec), 8);

    SECTION( "swap_index_pairs" )
    {
        cppsort::utility::swap_index_pairs(vec.begin(), pairs);
        CHECK( std::is_sorted(vec.begin(), vec.end()) );
    }

    SECTION( "swap_index_pairs_force_unroll" )
    {
        cppsort::utility::swap_index_pairs_force_unroll(vec.begin(), pairs);
        CHECK( std::is_sorted(vec.begin(), vec.end()) );
    }
}
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2013, 2014 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file ets_airspeed.cpp
 * @author Simon Wilks
 *
 * Driver for the Eagle Tree Airspeed V3 connected via I2C.
 */

#include <nuttx/config.h>

#include <drivers/device/i2c.h>

#include <sys/types.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <semaphore.h>
#include <string.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
#include <stdio.h>
#include <math.h>
#include <unistd.h>

#include <nuttx/arch.h>
#include <nuttx/wqueue.h>
#include <nuttx/clock.h>

#include <arch/board/board.h>

#include <systemlib/airspeed.h>
#include <systemlib/err.h>
#include <systemlib/param/param.h>
#include <systemlib/perf_counter.h>

#include <drivers/drv_airspeed.h>
#include <drivers/drv_hrt.h>
#include <drivers/device/ringbuffer.h>

#include <uORB/uORB.h>
#include <uORB/topics/differential_pressure.h>
#include <uORB/topics/subsystem_info.h>

#include <drivers/airspeed/airspeed.h>

Airspeed::Airspeed(int bus, int address, unsigned conversion_interval, const char* path) :
	I2C("Airspeed", path, bus, address, 100000),
	_reports(nullptr),
	_buffer_overflows(perf_alloc(PC_COUNT, "airspeed_buffer_overflows")),
	_max_differential_pressure_pa(0),
	_sensor_ok(false),
	_last_published_sensor_ok(true), /* initialize differently to force publication */
	_measure_ticks(0),
	_collect_phase(false),
	_diff_pres_offset(0.0f),
	_airspeed_pub(-1),
	_subsys_pub(-1),
	_class_instance(-1),
	_conversion_interval(conversion_interval),
	_sample_perf(perf_alloc(PC_ELAPSED, "airspeed_read")),
	_comms_errors(perf_alloc(PC_COUNT, "airspeed_comms_errors"))
{
	// enable debug() calls
	_debug_enabled = false;

	// work_cancel in the dtor will explode if we don't do this...
	memset(&_work, 0, sizeof(_work));
}

Airspeed::~Airspeed()
{
	/* make sure we are truly inactive */
	stop();

	if (_class_instance != -1)
		unregister_class_devname(AIRSPEED_DEVICE_PATH, _class_instance);

	/* free any existing reports */
	if (_reports != nullptr)
		delete _reports;

	// free perf counters
	perf_free(_sample_perf);
	perf_free(_comms_errors);
	perf_free(_buffer_overflows);
}

int
Airspeed::init()
{
	int ret = ERROR;

	/* do I2C init (and probe) first */
	if (I2C::init() != OK)
		goto out;

	/* allocate basic report buffers */
	_reports = new RingBuffer(2, sizeof(differential_pressure_s));
	if (_reports == nullptr)
		goto out;

	/* register alternate interfaces if we have to */
	_class_instance = register_class_devname(AIRSPEED_DEVICE_PATH);

	/* publication init */
	if (_class_instance == CLASS_DEVICE_PRIMARY) {

		/* advertise sensor topic, measure manually to initialize valid report */
		struct differential_pressure_s arp;
		measure();
		_reports->get(&arp);

		/* measurement will have generated a report, publish */
		_airspeed_pub = orb_advertise(ORB_ID(differential_pressure), &arp);

		if (_airspeed_pub < 0)
			warnx("uORB started?");
	}

	ret = OK;

out:
	return ret;
}

int
Airspeed::probe()
{
	/* on initial power up the device needs more than one retry
	   for detection. Once it is running then retries aren't
	   needed
	*/
	_retries = 4;
	int ret = measure();
	_retries = 0;
	return ret;
}

int
Airspeed::ioctl(struct file *filp, int cmd, unsigned long arg)
{
	switch (cmd) {

	case SENSORIOCSPOLLRATE: {
			switch (arg) {

				/* switching to manual polling */
			case SENSOR_POLLRATE_MANUAL:
				stop();
				_measure_ticks = 0;
				return OK;

				/* external signalling (DRDY) not supported */
			case SENSOR_POLLRATE_EXTERNAL:

				/* zero would be bad */
			case 0:
				return -EINVAL;

				/* set default/max polling rate */
			case SENSOR_POLLRATE_MAX:
			case SENSOR_POLLRATE_DEFAULT: {
					/* do we need to start internal polling? */
					bool want_start = (_measure_ticks == 0);

					/* set interval for next measurement to minimum legal value */
					_measure_ticks = USEC2TICK(_conversion_interval);

					/* if we need to start the poll state machine, do it */
					if (want_start)
						start();

					return OK;
				}

				/* adjust to a legal polling interval in Hz */
			default: {
					/* do we need to start internal polling? */
					bool want_start = (_measure_ticks == 0);

					/* convert hz to tick interval via microseconds */
					unsigned ticks = USEC2TICK(1000000 / arg);

					/* check against maximum rate */
					if (ticks < USEC2TICK(_conversion_interval))
						return -EINVAL;

					/* update interval for next measurement */
					_measure_ticks = ticks;

					/* if we need to start the poll state machine, do it */
					if (want_start)
						start();

					return OK;
				}
			}
		}

	case SENSORIOCGPOLLRATE:
		if (_measure_ticks == 0)
			return SENSOR_POLLRATE_MANUAL;

		return (1000 / _measure_ticks);

	case SENSORIOCSQUEUEDEPTH: {
			/* lower bound is mandatory, upper bound is a sanity check */
			if ((arg < 1) || (arg > 100))
				return -EINVAL;

			irqstate_t flags = irqsave();
			if (!_reports->resize(arg)) {
				irqrestore(flags);
				return -ENOMEM;
			}
			irqrestore(flags);

			return OK;
		}

	case SENSORIOCGQUEUEDEPTH:
		return _reports->size();

	case SENSORIOCRESET:
		/* XXX implement this */
		return -EINVAL;

	case AIRSPEEDIOCSSCALE: {
		struct airspeed_scale *s = (struct airspeed_scale*)arg;
		_diff_pres_offset = s->offset_pa;
		return OK;
		}

	case AIRSPEEDIOCGSCALE: {
		struct airspeed_scale *s = (struct airspeed_scale*)arg;
		s->offset_pa = _diff_pres_offset;
		s->scale = 1.0f;
		return OK;
		}

	default:
		/* give it to the superclass */
		return I2C::ioctl(filp, cmd, arg);
	}
}

ssize_t
Airspeed::read(struct file *filp, char *buffer, size_t buflen)
{
	unsigned count = buflen / sizeof(differential_pressure_s);
	differential_pressure_s *abuf = reinterpret_cast<differential_pressure_s *>(buffer);
	int ret = 0;

	/* buffer must be large enough */
	if (count < 1)
		return -ENOSPC;

	/* if automatic measurement is enabled */
	if (_measure_ticks > 0) {

		/*
		 * While there is space in the caller's buffer, and reports, copy them.
		 * Note that we may be pre-empted by the workq thread while we are doing this;
		 * we are careful to avoid racing with them.
		 */
		while (count--) {
			if (_reports->get(abuf)) {
				ret += sizeof(*abuf);
				abuf++;
			}
		}

		/* if there was no data, warn the caller */
		return ret ? ret : -EAGAIN;
	}

	/* manual measurement - run one conversion */
	do {
		_reports->flush();

		/* trigger a measurement */
		if (OK != measure()) {
			ret = -EIO;
			break;
		}

		/* wait for it to complete */
		usleep(_conversion_interval);

		/* run the collection phase */
		if (OK != collect()) {
			ret = -EIO;
			break;
		}

		/* state machine will have generated a report, copy it out */
		if (_reports->get(abuf)) {
			ret = sizeof(*abuf);
		}

	} while (0);

	return ret;
}

void
Airspeed::start()
{
	/* reset the report ring and state machine */
	_collect_phase = false;
	_reports->flush();

	/* schedule a cycle to start things */
	work_queue(HPWORK, &_work, (worker_t)&Airspeed::cycle_trampoline, this, 1);
}

void
Airspeed::stop()
{
	work_cancel(HPWORK, &_work);
}

void
Airspeed::update_status()
{
	if (_sensor_ok != _last_published_sensor_ok) {
		/* notify about state change */
		struct subsystem_info_s info = {
			true,
			true,
			_sensor_ok,
			SUBSYSTEM_TYPE_DIFFPRESSURE
		};

		if (_subsys_pub > 0) {
			orb_publish(ORB_ID(subsystem_info), _subsys_pub, &info);
		} else {
			_subsys_pub = orb_advertise(ORB_ID(subsystem_info), &info);
		}

		_last_published_sensor_ok = _sensor_ok;
	}
}

void
Airspeed::cycle_trampoline(void *arg)
{
	Airspeed *dev = (Airspeed *)arg;

	dev->cycle();
	// XXX we do not know if this is
	// really helping - do not update the
	// subsys state right now
	//dev->update_status();
}

void
Airspeed::print_info()
{
	perf_print_counter(_sample_perf);
	perf_print_counter(_comms_errors);
	perf_print_counter(_buffer_overflows);
	warnx("poll interval:  %u ticks", _measure_ticks);
	_reports->print_info("report queue");
}

void
Airspeed::new_report(const differential_pressure_s &report)
{
	if (!_reports->force(&report))
		perf_count(_buffer_overflows);
}
<commit_msg>airspeed: use _retries=2 for I2C retries once initialised<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2013, 2014 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file ets_airspeed.cpp
 * @author Simon Wilks
 *
 * Driver for the Eagle Tree Airspeed V3 connected via I2C.
 */

#include <nuttx/config.h>

#include <drivers/device/i2c.h>

#include <sys/types.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <semaphore.h>
#include <string.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
#include <stdio.h>
#include <math.h>
#include <unistd.h>

#include <nuttx/arch.h>
#include <nuttx/wqueue.h>
#include <nuttx/clock.h>

#include <arch/board/board.h>

#include <systemlib/airspeed.h>
#include <systemlib/err.h>
#include <systemlib/param/param.h>
#include <systemlib/perf_counter.h>

#include <drivers/drv_airspeed.h>
#include <drivers/drv_hrt.h>
#include <drivers/device/ringbuffer.h>

#include <uORB/uORB.h>
#include <uORB/topics/differential_pressure.h>
#include <uORB/topics/subsystem_info.h>

#include <drivers/airspeed/airspeed.h>

Airspeed::Airspeed(int bus, int address, unsigned conversion_interval, const char* path) :
	I2C("Airspeed", path, bus, address, 100000),
	_reports(nullptr),
	_buffer_overflows(perf_alloc(PC_COUNT, "airspeed_buffer_overflows")),
	_max_differential_pressure_pa(0),
	_sensor_ok(false),
	_last_published_sensor_ok(true), /* initialize differently to force publication */
	_measure_ticks(0),
	_collect_phase(false),
	_diff_pres_offset(0.0f),
	_airspeed_pub(-1),
	_subsys_pub(-1),
	_class_instance(-1),
	_conversion_interval(conversion_interval),
	_sample_perf(perf_alloc(PC_ELAPSED, "airspeed_read")),
	_comms_errors(perf_alloc(PC_COUNT, "airspeed_comms_errors"))
{
	// enable debug() calls
	_debug_enabled = false;

	// work_cancel in the dtor will explode if we don't do this...
	memset(&_work, 0, sizeof(_work));
}

Airspeed::~Airspeed()
{
	/* make sure we are truly inactive */
	stop();

	if (_class_instance != -1)
		unregister_class_devname(AIRSPEED_DEVICE_PATH, _class_instance);

	/* free any existing reports */
	if (_reports != nullptr)
		delete _reports;

	// free perf counters
	perf_free(_sample_perf);
	perf_free(_comms_errors);
	perf_free(_buffer_overflows);
}

int
Airspeed::init()
{
	int ret = ERROR;

	/* do I2C init (and probe) first */
	if (I2C::init() != OK)
		goto out;

	/* allocate basic report buffers */
	_reports = new RingBuffer(2, sizeof(differential_pressure_s));
	if (_reports == nullptr)
		goto out;

	/* register alternate interfaces if we have to */
	_class_instance = register_class_devname(AIRSPEED_DEVICE_PATH);

	/* publication init */
	if (_class_instance == CLASS_DEVICE_PRIMARY) {

		/* advertise sensor topic, measure manually to initialize valid report */
		struct differential_pressure_s arp;
		measure();
		_reports->get(&arp);

		/* measurement will have generated a report, publish */
		_airspeed_pub = orb_advertise(ORB_ID(differential_pressure), &arp);

		if (_airspeed_pub < 0)
			warnx("uORB started?");
	}

	ret = OK;

out:
	return ret;
}

int
Airspeed::probe()
{
	/* on initial power up the device may need more than one retry
	   for detection. Once it is running the number of retries can
	   be reduced
	*/
	_retries = 4;
	int ret = measure();

        // drop back to 2 retries once initialised
	_retries = 2;
	return ret;
}

int
Airspeed::ioctl(struct file *filp, int cmd, unsigned long arg)
{
	switch (cmd) {

	case SENSORIOCSPOLLRATE: {
			switch (arg) {

				/* switching to manual polling */
			case SENSOR_POLLRATE_MANUAL:
				stop();
				_measure_ticks = 0;
				return OK;

				/* external signalling (DRDY) not supported */
			case SENSOR_POLLRATE_EXTERNAL:

				/* zero would be bad */
			case 0:
				return -EINVAL;

				/* set default/max polling rate */
			case SENSOR_POLLRATE_MAX:
			case SENSOR_POLLRATE_DEFAULT: {
					/* do we need to start internal polling? */
					bool want_start = (_measure_ticks == 0);

					/* set interval for next measurement to minimum legal value */
					_measure_ticks = USEC2TICK(_conversion_interval);

					/* if we need to start the poll state machine, do it */
					if (want_start)
						start();

					return OK;
				}

				/* adjust to a legal polling interval in Hz */
			default: {
					/* do we need to start internal polling? */
					bool want_start = (_measure_ticks == 0);

					/* convert hz to tick interval via microseconds */
					unsigned ticks = USEC2TICK(1000000 / arg);

					/* check against maximum rate */
					if (ticks < USEC2TICK(_conversion_interval))
						return -EINVAL;

					/* update interval for next measurement */
					_measure_ticks = ticks;

					/* if we need to start the poll state machine, do it */
					if (want_start)
						start();

					return OK;
				}
			}
		}

	case SENSORIOCGPOLLRATE:
		if (_measure_ticks == 0)
			return SENSOR_POLLRATE_MANUAL;

		return (1000 / _measure_ticks);

	case SENSORIOCSQUEUEDEPTH: {
			/* lower bound is mandatory, upper bound is a sanity check */
			if ((arg < 1) || (arg > 100))
				return -EINVAL;

			irqstate_t flags = irqsave();
			if (!_reports->resize(arg)) {
				irqrestore(flags);
				return -ENOMEM;
			}
			irqrestore(flags);

			return OK;
		}

	case SENSORIOCGQUEUEDEPTH:
		return _reports->size();

	case SENSORIOCRESET:
		/* XXX implement this */
		return -EINVAL;

	case AIRSPEEDIOCSSCALE: {
		struct airspeed_scale *s = (struct airspeed_scale*)arg;
		_diff_pres_offset = s->offset_pa;
		return OK;
		}

	case AIRSPEEDIOCGSCALE: {
		struct airspeed_scale *s = (struct airspeed_scale*)arg;
		s->offset_pa = _diff_pres_offset;
		s->scale = 1.0f;
		return OK;
		}

	default:
		/* give it to the superclass */
		return I2C::ioctl(filp, cmd, arg);
	}
}

ssize_t
Airspeed::read(struct file *filp, char *buffer, size_t buflen)
{
	unsigned count = buflen / sizeof(differential_pressure_s);
	differential_pressure_s *abuf = reinterpret_cast<differential_pressure_s *>(buffer);
	int ret = 0;

	/* buffer must be large enough */
	if (count < 1)
		return -ENOSPC;

	/* if automatic measurement is enabled */
	if (_measure_ticks > 0) {

		/*
		 * While there is space in the caller's buffer, and reports, copy them.
		 * Note that we may be pre-empted by the workq thread while we are doing this;
		 * we are careful to avoid racing with them.
		 */
		while (count--) {
			if (_reports->get(abuf)) {
				ret += sizeof(*abuf);
				abuf++;
			}
		}

		/* if there was no data, warn the caller */
		return ret ? ret : -EAGAIN;
	}

	/* manual measurement - run one conversion */
	do {
		_reports->flush();

		/* trigger a measurement */
		if (OK != measure()) {
			ret = -EIO;
			break;
		}

		/* wait for it to complete */
		usleep(_conversion_interval);

		/* run the collection phase */
		if (OK != collect()) {
			ret = -EIO;
			break;
		}

		/* state machine will have generated a report, copy it out */
		if (_reports->get(abuf)) {
			ret = sizeof(*abuf);
		}

	} while (0);

	return ret;
}

void
Airspeed::start()
{
	/* reset the report ring and state machine */
	_collect_phase = false;
	_reports->flush();

	/* schedule a cycle to start things */
	work_queue(HPWORK, &_work, (worker_t)&Airspeed::cycle_trampoline, this, 1);
}

void
Airspeed::stop()
{
	work_cancel(HPWORK, &_work);
}

void
Airspeed::update_status()
{
	if (_sensor_ok != _last_published_sensor_ok) {
		/* notify about state change */
		struct subsystem_info_s info = {
			true,
			true,
			_sensor_ok,
			SUBSYSTEM_TYPE_DIFFPRESSURE
		};

		if (_subsys_pub > 0) {
			orb_publish(ORB_ID(subsystem_info), _subsys_pub, &info);
		} else {
			_subsys_pub = orb_advertise(ORB_ID(subsystem_info), &info);
		}

		_last_published_sensor_ok = _sensor_ok;
	}
}

void
Airspeed::cycle_trampoline(void *arg)
{
	Airspeed *dev = (Airspeed *)arg;

	dev->cycle();
	// XXX we do not know if this is
	// really helping - do not update the
	// subsys state right now
	//dev->update_status();
}

void
Airspeed::print_info()
{
	perf_print_counter(_sample_perf);
	perf_print_counter(_comms_errors);
	perf_print_counter(_buffer_overflows);
	warnx("poll interval:  %u ticks", _measure_ticks);
	_reports->print_info("report queue");
}

void
Airspeed::new_report(const differential_pressure_s &report)
{
	if (!_reports->force(&report))
		perf_count(_buffer_overflows);
}
<|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "avl.h"

using namespace NP_AVL;

TEST_CASE("Testing inserting and balances", "[avl]") {
	auto item = avl<int>();

	SECTION("adding one item") {
		item.insert(1);
		REQUIRE(item.getHeight() == 1);
	}

	cin.get(); // keep window open
}<commit_msg>generate basic tests for insertion<commit_after>#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "avl.h"

using namespace NP_AVL;

TEST_CASE("Testing inserting and balances") {
	avl<int> test = avl<int>();

	SECTION("empty tree sanity test") {
		REQUIRE(test.getHeight() == 0);
		REQUIRE(test.getNumberOfNodes() == 0);
	}

	SECTION("adding one item") {
		test.insert(50);
		REQUIRE(test.getNumberOfNodes() == 1);
		REQUIRE(test.getHeight() == 1);
	}

	SECTION("adding more items and check height/node count without balancing") {
		test.insert(50);
		test.insert(75);
		REQUIRE(test.getNumberOfNodes() == 2);
		REQUIRE(test.getHeight() == 2);

		test.insert(25);
		REQUIRE(test.getNumberOfNodes() == 3);
		REQUIRE(test.getHeight() == 2);

		test.insert(15);
		REQUIRE(test.getNumberOfNodes() == 4);
		REQUIRE(test.getHeight() == 3);

		test.insert(60);
		REQUIRE(test.getNumberOfNodes() == 5);
		REQUIRE(test.getHeight() == 3);

		test.insert(35);
		REQUIRE(test.getNumberOfNodes() == 6);
		REQUIRE(test.getHeight() == 3);

		test.insert(100);
		REQUIRE(test.getNumberOfNodes() == 7);
		REQUIRE(test.getHeight() == 3);

		test.insert(10);
		REQUIRE(test.getNumberOfNodes() == 8);
		REQUIRE(test.getHeight() == 4);

		test.insert(30);
		REQUIRE(test.getNumberOfNodes() == 9);
		REQUIRE(test.getHeight() == 4);

		test.insert(55);
		REQUIRE(test.getNumberOfNodes() == 10);
		REQUIRE(test.getHeight() == 4);

		test.insert(80);
		REQUIRE(test.getNumberOfNodes() == 11);
		REQUIRE(test.getHeight() == 4);

		test.insert(17);
		REQUIRE(test.getNumberOfNodes() == 12);
		REQUIRE(test.getHeight() == 4);

		test.insert(45);
		REQUIRE(test.getNumberOfNodes() == 13);
		REQUIRE(test.getHeight() == 4);

		test.insert(70);
		REQUIRE(test.getNumberOfNodes() == 14);
		REQUIRE(test.getHeight() == 4);

		test.insert(150);
		REQUIRE(test.getNumberOfNodes() == 15);
		REQUIRE(test.getHeight() == 4);
	}

	SECTION("test insert and right balancing") {
		test.insert(50);
		test.insert(75);
		test.insert(150);
		REQUIRE(test.getNumberOfNodes() == 3);
		REQUIRE(test.getHeight() == 2);
		REQUIRE(*(test.getroot()) == 75);
		REQUIRE(*(test.getroot()->left) == 50);
		REQUIRE(*(test.getroot()->right) == 150);
	}

	SECTION("test insert and left balancing") {
		test.insert(150);
		test.insert(75);
		test.insert(50);
		REQUIRE(test.getNumberOfNodes() == 3);
		REQUIRE(test.getHeight() == 2);
		REQUIRE(*(test.getroot()) == 75);
		REQUIRE(*(test.getroot()->left) == 50);
		REQUIRE(*(test.getroot()->right) == 150);
	}

	SECTION("test insert and secondary right tree formation") {
		/*
			Given the input 50, 75, 150, 200, 250
			This AVL takes it a step further, resulting in the following
			tree:
					75
				50		200
					  150  250
		*/
		test.insert(50);
		test.insert(75);
		test.insert(150);

		test.insert(200);
		REQUIRE(test.getNumberOfNodes() == 4);
		REQUIRE(test.getHeight() == 3);
		REQUIRE(*(test.getroot()) == 75);
		REQUIRE(*(test.getroot()->left) == 50);
		REQUIRE(*(test.getroot()->right) == 150);
		REQUIRE(*(test.getroot()->right->right) == 200);

		test.insert(250);
		REQUIRE(test.getNumberOfNodes() == 5);
		REQUIRE(test.getHeight() == 3);
		REQUIRE(*(test.getroot()) == 75);
		REQUIRE(*(test.getroot()->left) == 50);
		REQUIRE(*(test.getroot()->right) == 200);
		REQUIRE(*(test.getroot()->right->right) == 250);
		REQUIRE(*(test.getroot()->right->left) == 150);
	}

	SECTION("test insert and secondary left tree formation") {
		/*
		Given the input 250, 200, 150, 75, 50

		This AVL takes it a step further, resulting in the following
		tree:
				200
			75		250
		  50  150
		*/
		test.insert(250);
		test.insert(200);
		test.insert(150);

		test.insert(75);
		REQUIRE(test.getNumberOfNodes() == 4);
		REQUIRE(test.getHeight() == 3);
		REQUIRE(*(test.getroot()) == 200);
		REQUIRE(*(test.getroot()->left) == 150);
		REQUIRE(*(test.getroot()->right) == 250);
		REQUIRE(*(test.getroot()->left->left) == 75);

		test.insert(50);
		REQUIRE(test.getNumberOfNodes() == 5);
		REQUIRE(test.getHeight() == 3);
		REQUIRE(*(test.getroot()) == 200);
		REQUIRE(*(test.getroot()->left) == 75);
		REQUIRE(*(test.getroot()->right) == 250);
		REQUIRE(*(test.getroot()->left->left) == 50);
		REQUIRE(*(test.getroot()->left->right) == 150);
	}

	SECTION("test insert zig-zag on right side") {
		/*
			Given the input 50, 75, 60
			The AVL tree should output
					60
				50		75

		*/
		test.insert(50);
		test.insert(75);
		test.insert(60);

		REQUIRE(test.getHeight() == 2);
		REQUIRE(test.getNumberOfNodes() == 3);

		REQUIRE(*(test.getroot()) == 60);
		REQUIRE(*(test.getroot()->left) == 50);
		REQUIRE(*(test.getroot()->right) == 75);
	}

	SECTION("test insert heavy zig-zag on right side") {
		/*
		Given the input 50, 75, 60, 70
		The AVL tree should output
			60
		50		75
		       70

		*/
		test.insert(50);
		test.insert(75);
		test.insert(60);
		test.insert(70);

		REQUIRE(test.getHeight() == 3);
		REQUIRE(test.getNumberOfNodes() == 4);

		REQUIRE(*(test.getroot()) == 60);
		REQUIRE(*(test.getroot()->left) == 50);
		REQUIRE(*(test.getroot()->right) == 75);
		REQUIRE(*(test.getroot()->right->left) == 70);

		test.insert(65);

		REQUIRE(test.getHeight() == 3);
		REQUIRE(test.getNumberOfNodes() == 5);

		REQUIRE(*(test.getroot()) == 60);
		REQUIRE(*(test.getroot()->left) == 50);
		REQUIRE(*(test.getroot()->right) == 70);
		REQUIRE(*(test.getroot()->right->left) == 65);
		REQUIRE(*(test.getroot()->right->right) == 75);
	}

}

<|endoftext|>


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

Daemon GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.

This file is part of the Daemon GPL Source Code (Daemon Source Code).

Daemon Source Code 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 3 of the License, or
(at your option) any later version.

Daemon Source Code 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 Daemon Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Daemon Source Code is also subject to certain additional terms.
You should have received a copy of these additional terms immediately following the
terms and conditions of the GNU General Public License which accompanied the Daemon
Source Code.  If not, please request a copy in writing from id Software at the address
below.

If you have questions concerning this license or the applicable additional terms, you
may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville,
Maryland 20850 USA.

===========================================================================
*/

#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
#include "../renderer/tr_public.h"

void RE_Shutdown( qboolean destroyWindow ) { }
qhandle_t RE_RegisterModel( const char *name )
{
	return 1;
}
qhandle_t RE_RegisterSkin( const char *name )
{
	return 1;
}
qhandle_t RE_RegisterShader( const char *name, RegisterShaderFlags_t flags )
{
	return 1;
}
qhandle_t RE_RegisterShaderNoMip( const char *name )
{
	return 1;
}
void RE_RegisterFont( const char *fontName, const char *fallbackName, int pointSize, fontInfo_t *font ) { }
void RE_Glyph( fontInfo_t *font, const char *str, glyphInfo_t *glyphh ) { }
void RE_GlyphChar( fontInfo_t *font, int ch, glyphInfo_t *glyph ) { }
void RE_UnregisterFont( fontInfo_t *font ) { }
void RE_RegisterFontVM( const char *fontName, const char *fallbackName, int pointSize, fontMetrics_t *font ) { }
void RE_GlyphVM( fontHandle_t font, const char *ch, glyphInfo_t *glyph ) { }
void RE_GlyphCharVM( fontHandle_t font, int ch, glyphInfo_t *glyph ) { }
void RE_UnregisterFontVM( fontHandle_t font ) { }
void RE_LoadWorldMap( const char *name ) { }
qboolean RE_GetSkinModel( qhandle_t skinid, const char *type, char *name )
{
	return qtrue;
}
qhandle_t RE_GetShaderFromModel( qhandle_t modelid, int surfnum, int withlightmap )
{
	return qtrue;
}
void RE_SetWorldVisData( const byte *vis ) { }
void RE_EndRegistration( void ) { }
void RE_ClearScene( void ) { }
void RE_AddRefEntityToScene( const refEntity_t *ref ) { }
int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir )
{
	return 0;
}
void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts ) { }
void RE_AddPolysToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ) { }
void RE_AddLightToScene( const vec3_t org, float radius, float intensity, float r, float g, float b, qhandle_t hShader, int flags ) { }
void RE_AddLightToSceneQ3A( const vec3_t org, float intensity, float r, float g, float b ) { }
void RE_AddCoronaToScene( const vec3_t org, float r, float g, float b, float scale, int id, qboolean visible ) { }
void R_SetFog( int fogvar, int var1, int var2, float r, float g, float b, float density ) { }
void RE_RenderScene( const refdef_t *fd ) { }
void RE_SaveViewParms( void ) { }
void RE_RestoreViewParms( void ) { }
void RE_SetColor( const float *rgba ) { }
void RE_SetClipRegion( const float *region ) { }
void RE_StretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t hShader ) { }
void RE_RotatedPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t hShader, float angle ) { }
void RE_StretchPicGradient( float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t hShader, const float *gradientColor, int gradientType ) { }
void RE_2DPolyies( polyVert_t *polys, int numverts, qhandle_t hShader ) { }
void RE_StretchRaw( int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty ) { }
void RE_UploadCinematic( int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty ) { }
void RE_BeginFrame( stereoFrame_t stereoFrame ) { }
void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) { }
int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection, int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer )
{
	return 0;
}
void RE_ProjectDecal( qhandle_t hShader, int numPoints, vec3_t *points, vec4_t projection, vec4_t color, int lifeTime, int fadeTime ) { }
void RE_ClearDecals( void ) { }
int R_LerpTag( orientation_t *tag, const refEntity_t *refent, const char *tagName, int startIndex )
{
	return 0;
}
void R_ModelBounds( qhandle_t model, vec3_t mins, vec3_t maxs ) { }
void R_RemapShader( const char *oldShader, const char *newShader, const char *offsetTime ) { }
void R_DebugPolygon( int color, int numpoints, float *points ) { }
void R_DebugText( const vec3_t org, float r, float g, float b, const char *text, qboolean neverOcclude ) { }
qboolean R_GetEntityToken( char *buffer, int size )
{
	return qtrue;
}
void RE_AddPolyBufferToScene( polyBuffer_t *pPolyBuffer ) { }
void RE_SetGlobalFog( qboolean restore, int duration, float r, float g, float b, float depthForOpaque ) { }
qboolean R_inPVS( const vec3_t p1, const vec3_t p2 )
{
	return qfalse;
}
qboolean R_inPVVS( const vec3_t p1, const vec3_t p2 )
{
	return qfalse;
}
void R_PurgeCache( void ) { }
qboolean RE_LoadDynamicShader( const char *shadername, const char *shadertext )
{
	return qtrue;
}
void RE_RenderToTexture( int textureid, int x, int y, int w, int h ) { }
int R_GetTextureId( const char *imagename )
{
	return 0;
}
void RE_Finish( void ) { }
void RE_TakeVideoFrame( int h, int w, byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg ) { }
void RE_AddRefLightToScene( const refLight_t *light ) { }
int RE_RegisterAnimation( const char *name )
{
	return 1;
}
int RE_CheckSkeleton( refSkeleton_t *skel, qhandle_t model, qhandle_t anim )
{
	return 1;
}
int RE_BuildSkeleton( refSkeleton_t *skel, qhandle_t anim, int startFrame, int endFrame, float frac, qboolean clearOrigin )
{
	return 0;
}
int RE_BlendSkeleton( refSkeleton_t *skel, const refSkeleton_t *blend, float frac )
{
	return 0;
}
int RE_BoneIndex( qhandle_t hModel, const char *boneName )
{
	return 0;
}
int RE_AnimNumFrames( qhandle_t hAnim )
{
	return 1;
}
int RE_AnimFrameRate( qhandle_t hAnim )
{
	return 1;
}
qhandle_t RE_RegisterVisTest( void )
{
	return 1;
}
void RE_AddVisTestToScene( qhandle_t hTest, vec3_t pos, float depthAdjust, float area ) { }
float RE_CheckVisibility( qhandle_t hTest )
{
	return 0.0f;
}
void RE_UnregisterVisTest( qhandle_t hTest ) { }
void     RE_SetColorGrading( int slot, qhandle_t hShader ) { }
void                                RE_ScissorEnable( qboolean enable ) { }
void                                RE_ScissorSet( int x, int y, int w, int h ) { }
void     R_SetAltShaderTokens( const char *name ) { }

qboolean RE_BeginRegistration( glconfig_t *config, glconfig2_t *glconfig2 )
{
	Com_Memset( config, 0, sizeof( glconfig_t ) );
	Com_Memset( glconfig2, 0, sizeof( glconfig2_t ) );

	return qtrue;
}

refexport_t    *GetRefAPI( int apiVersion, refimport_t *rimp )
{
    static refexport_t re;

    memset( &re, 0, sizeof( re ) );

    re.Shutdown = RE_Shutdown;

    re.BeginRegistration = RE_BeginRegistration;
    re.RegisterModel = RE_RegisterModel;
    re.RegisterSkin = RE_RegisterSkin;
    re.RegisterShader = RE_RegisterShader;
    re.RegisterShader = RE_RegisterShader;
    re.RegisterFont = RE_RegisterFont;
    re.Glyph = RE_Glyph;
    re.GlyphChar = RE_GlyphChar;
    re.UnregisterFont = RE_UnregisterFont;
    re.RegisterFontVM = RE_RegisterFontVM;
    re.GlyphVM = RE_GlyphVM;
    re.GlyphCharVM = RE_GlyphCharVM;
    re.UnregisterFontVM = RE_UnregisterFontVM;
    re.LoadWorld = RE_LoadWorldMap;
    //----(SA) added
    re.GetSkinModel = RE_GetSkinModel;
    re.GetShaderFromModel = RE_GetShaderFromModel;
    //----(SA) end
    re.SetWorldVisData = RE_SetWorldVisData;
    re.EndRegistration = RE_EndRegistration;

    re.ClearScene = RE_ClearScene;
    re.AddRefEntityToScene = RE_AddRefEntityToScene;
    re.LightForPoint = R_LightForPoint;

    re.AddPolyToScene = RE_AddPolyToScene;
    // Ridah
    re.AddPolysToScene = RE_AddPolysToScene;
    // done.
    re.AddLightToScene = RE_AddLightToScene;
    re.AddAdditiveLightToScene = RE_AddLightToSceneQ3A;
    //----(SA)
    re.AddCoronaToScene = RE_AddCoronaToScene;
    re.SetFog = R_SetFog;
    //----(SA)

    re.RenderScene = RE_RenderScene;
    re.SaveViewParms = RE_SaveViewParms;
    re.RestoreViewParms = RE_RestoreViewParms;

    re.SetColor = RE_SetColor;
    re.SetClipRegion = RE_SetClipRegion;
    re.DrawStretchPic = RE_StretchPic;
    re.DrawRotatedPic = RE_RotatedPic; // NERVE - SMF
    re.DrawStretchPicGradient = RE_StretchPicGradient;
    re.Add2dPolys = RE_2DPolyies;
    re.DrawStretchRaw = RE_StretchRaw;
    re.UploadCinematic = RE_UploadCinematic;
    re.BeginFrame = RE_BeginFrame;
    re.EndFrame = RE_EndFrame;

    re.MarkFragments = R_MarkFragments;
    re.ProjectDecal = RE_ProjectDecal;
    re.ClearDecals = RE_ClearDecals;

    re.LerpTag = R_LerpTag;
    re.ModelBounds = R_ModelBounds;

    re.RemapShader = R_RemapShader;
    re.DrawDebugPolygon = R_DebugPolygon;
    re.DrawDebugText = R_DebugText;
    re.GetEntityToken = R_GetEntityToken;

    re.AddPolyBufferToScene = RE_AddPolyBufferToScene;

    re.SetGlobalFog = RE_SetGlobalFog;

    re.inPVS = R_inPVS;
    re.inPVVS = R_inPVVS;

    re.purgeCache = R_PurgeCache;

    //bani
    re.LoadDynamicShader = RE_LoadDynamicShader;
    // fretn
    re.RenderToTexture = RE_RenderToTexture;
    re.GetTextureId = R_GetTextureId;
    //bani
    re.Finish = RE_Finish;

    re.TakeVideoFrame = RE_TakeVideoFrame;
    re.AddRefLightToScene = RE_AddRefLightToScene;

    // RB: alternative skeletal animation system
    re.RegisterAnimation = RE_RegisterAnimation;
    re.CheckSkeleton = RE_CheckSkeleton;
    re.BuildSkeleton = RE_BuildSkeleton;
    re.BlendSkeleton = RE_BlendSkeleton;
    re.BoneIndex = RE_BoneIndex;
    re.AnimNumFrames = RE_AnimNumFrames;
    re.AnimFrameRate = RE_AnimFrameRate;

    re.RegisterVisTest = RE_RegisterVisTest;
    re.AddVisTestToScene = RE_AddVisTestToScene;
    re.CheckVisibility = RE_CheckVisibility;
    re.UnregisterVisTest = RE_UnregisterVisTest;

    re.SetColorGrading = RE_SetColorGrading;
    re.SetAltShaderTokens = R_SetAltShaderTokens;

    re.ScissorEnable = RE_ScissorEnable;
    re.ScissorSet = RE_ScissorSet;

    return &re;
}

<commit_msg>Some fixes for the tty client<commit_after>/*
===========================================================================

Daemon GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.

This file is part of the Daemon GPL Source Code (Daemon Source Code).

Daemon Source Code 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 3 of the License, or
(at your option) any later version.

Daemon Source Code 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 Daemon Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Daemon Source Code is also subject to certain additional terms.
You should have received a copy of these additional terms immediately following the
terms and conditions of the GNU General Public License which accompanied the Daemon
Source Code.  If not, please request a copy in writing from id Software at the address
below.

If you have questions concerning this license or the applicable additional terms, you
may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville,
Maryland 20850 USA.

===========================================================================
*/

#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
#include "../renderer/tr_public.h"

void RE_Shutdown( qboolean destroyWindow ) { }
qhandle_t RE_RegisterModel( const char *name )
{
	return FS_FOpenFileRead( name, NULL, qfalse );
}
qhandle_t RE_RegisterSkin( const char *name )
{
	return FS_FOpenFileRead( name, NULL, qfalse );
}
qhandle_t RE_RegisterShader( const char *name, RegisterShaderFlags_t flags )
{
	return 1;
}
qhandle_t RE_RegisterShaderNoMip( const char *name )
{
	return 1;
}
void RE_RegisterFont( const char *fontName, const char *fallbackName, int pointSize, fontInfo_t *font )
{
	font->pointSize = pointSize;
	font->height = 1;
	font->glyphScale = 1.0f;
	font->name[0] = '\0';
}
void RE_Glyph( fontInfo_t *font, const char *str, glyphInfo_t *glyph )
{
	glyph->height = 1;
	glyph->top = 1;
	glyph->bottom = 0;
	glyph->pitch = 1;
	glyph->xSkip = 1;
	glyph->imageWidth = 1;
	glyph->imageHeight = 1;
	glyph->s = 0.0f;
	glyph->t = 0.0f;
	glyph->s2 = 1.0f;
	glyph->t2 = 1.0f;
	glyph->glyph = 1;
	glyph->shaderName[0] = '\0';
}
void RE_GlyphChar( fontInfo_t *font, int ch, glyphInfo_t *glyph )
{
	RE_Glyph( font, NULL, glyph );
}
void RE_UnregisterFont( fontInfo_t *font ) { }
void RE_RegisterFontVM( const char *fontName, const char *fallbackName, int pointSize, fontMetrics_t *font )
{
	font->handle = 1;
	font->isBitmap = qtrue;
	font->pointSize = pointSize;
	font->height = 1;
	font->glyphScale = 1.0f;
}
void RE_GlyphVM( fontHandle_t font, const char *ch, glyphInfo_t *glyph ) { }
void RE_GlyphCharVM( fontHandle_t font, int ch, glyphInfo_t *glyph ) { }
void RE_UnregisterFontVM( fontHandle_t font ) { }
void RE_LoadWorldMap( const char *name ) { }
qboolean RE_GetSkinModel( qhandle_t skinid, const char *type, char *name )
{
	return qtrue;
}
qhandle_t RE_GetShaderFromModel( qhandle_t modelid, int surfnum, int withlightmap )
{
	return qtrue;
}
void RE_SetWorldVisData( const byte *vis ) { }
void RE_EndRegistration( void ) { }
void RE_ClearScene( void ) { }
void RE_AddRefEntityToScene( const refEntity_t *ref ) { }
int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir )
{
	return 0;
}
void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts ) { }
void RE_AddPolysToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ) { }
void RE_AddLightToScene( const vec3_t org, float radius, float intensity, float r, float g, float b, qhandle_t hShader, int flags ) { }
void RE_AddLightToSceneQ3A( const vec3_t org, float intensity, float r, float g, float b ) { }
void RE_AddCoronaToScene( const vec3_t org, float r, float g, float b, float scale, int id, qboolean visible ) { }
void R_SetFog( int fogvar, int var1, int var2, float r, float g, float b, float density ) { }
void RE_RenderScene( const refdef_t *fd ) { }
void RE_SaveViewParms( void ) { }
void RE_RestoreViewParms( void ) { }
void RE_SetColor( const float *rgba ) { }
void RE_SetClipRegion( const float *region ) { }
void RE_StretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t hShader ) { }
void RE_RotatedPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t hShader, float angle ) { }
void RE_StretchPicGradient( float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t hShader, const float *gradientColor, int gradientType ) { }
void RE_2DPolyies( polyVert_t *polys, int numverts, qhandle_t hShader ) { }
void RE_StretchRaw( int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty ) { }
void RE_UploadCinematic( int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty ) { }
void RE_BeginFrame( stereoFrame_t stereoFrame ) { }
void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) { }
int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection, int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer )
{
	return 0;
}
void RE_ProjectDecal( qhandle_t hShader, int numPoints, vec3_t *points, vec4_t projection, vec4_t color, int lifeTime, int fadeTime ) { }
void RE_ClearDecals( void ) { }
int R_LerpTag( orientation_t *tag, const refEntity_t *refent, const char *tagName, int startIndex )
{
	return 0;
}
void R_ModelBounds( qhandle_t model, vec3_t mins, vec3_t maxs ) { }
void R_RemapShader( const char *oldShader, const char *newShader, const char *offsetTime ) { }
void R_DebugPolygon( int color, int numpoints, float *points ) { }
void R_DebugText( const vec3_t org, float r, float g, float b, const char *text, qboolean neverOcclude ) { }
qboolean R_GetEntityToken( char *buffer, int size )
{
	return qtrue;
}
void RE_AddPolyBufferToScene( polyBuffer_t *pPolyBuffer ) { }
void RE_SetGlobalFog( qboolean restore, int duration, float r, float g, float b, float depthForOpaque ) { }
qboolean R_inPVS( const vec3_t p1, const vec3_t p2 )
{
	return qfalse;
}
qboolean R_inPVVS( const vec3_t p1, const vec3_t p2 )
{
	return qfalse;
}
void R_PurgeCache( void ) { }
qboolean RE_LoadDynamicShader( const char *shadername, const char *shadertext )
{
	return qtrue;
}
void RE_RenderToTexture( int textureid, int x, int y, int w, int h ) { }
int R_GetTextureId( const char *imagename )
{
	return 0;
}
void RE_Finish( void ) { }
void RE_TakeVideoFrame( int h, int w, byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg ) { }
void RE_AddRefLightToScene( const refLight_t *light ) { }
int RE_RegisterAnimation( const char *name )
{
	return 1;
}
int RE_CheckSkeleton( refSkeleton_t *skel, qhandle_t model, qhandle_t anim )
{
	return 1;
}
int RE_BuildSkeleton( refSkeleton_t *skel, qhandle_t anim, int startFrame, int endFrame, float frac, qboolean clearOrigin )
{
	return 1;
}
int RE_BlendSkeleton( refSkeleton_t *skel, const refSkeleton_t *blend, float frac )
{
	return 1;
}
int RE_BoneIndex( qhandle_t hModel, const char *boneName )
{
	return 0;
}
int RE_AnimNumFrames( qhandle_t hAnim )
{
	return 1;
}
int RE_AnimFrameRate( qhandle_t hAnim )
{
	return 1;
}
qhandle_t RE_RegisterVisTest( void )
{
	return 1;
}
void RE_AddVisTestToScene( qhandle_t hTest, vec3_t pos, float depthAdjust, float area ) { }
float RE_CheckVisibility( qhandle_t hTest )
{
	return 0.0f;
}
void RE_UnregisterVisTest( qhandle_t hTest ) { }
void     RE_SetColorGrading( int slot, qhandle_t hShader ) { }
void                                RE_ScissorEnable( qboolean enable ) { }
void                                RE_ScissorSet( int x, int y, int w, int h ) { }
void     R_SetAltShaderTokens( const char *name ) { }

qboolean RE_BeginRegistration( glconfig_t *config, glconfig2_t *glconfig2 )
{
	Com_Memset( config, 0, sizeof( glconfig_t ) );
	config->vidWidth = 640;
	config->vidHeight = 480;
	config->windowAspect = 1.0f;
	Com_Memset( glconfig2, 0, sizeof( glconfig2_t ) );

	return qtrue;
}

refexport_t    *GetRefAPI( int apiVersion, refimport_t *rimp )
{
    static refexport_t re;

    memset( &re, 0, sizeof( re ) );

    re.Shutdown = RE_Shutdown;

    re.BeginRegistration = RE_BeginRegistration;
    re.RegisterModel = RE_RegisterModel;
    re.RegisterSkin = RE_RegisterSkin;
    re.RegisterShader = RE_RegisterShader;
    re.RegisterShader = RE_RegisterShader;
    re.RegisterFont = RE_RegisterFont;
    re.Glyph = RE_Glyph;
    re.GlyphChar = RE_GlyphChar;
    re.UnregisterFont = RE_UnregisterFont;
    re.RegisterFontVM = RE_RegisterFontVM;
    re.GlyphVM = RE_GlyphVM;
    re.GlyphCharVM = RE_GlyphCharVM;
    re.UnregisterFontVM = RE_UnregisterFontVM;
    re.LoadWorld = RE_LoadWorldMap;
    //----(SA) added
    re.GetSkinModel = RE_GetSkinModel;
    re.GetShaderFromModel = RE_GetShaderFromModel;
    //----(SA) end
    re.SetWorldVisData = RE_SetWorldVisData;
    re.EndRegistration = RE_EndRegistration;

    re.ClearScene = RE_ClearScene;
    re.AddRefEntityToScene = RE_AddRefEntityToScene;
    re.LightForPoint = R_LightForPoint;

    re.AddPolyToScene = RE_AddPolyToScene;
    // Ridah
    re.AddPolysToScene = RE_AddPolysToScene;
    // done.
    re.AddLightToScene = RE_AddLightToScene;
    re.AddAdditiveLightToScene = RE_AddLightToSceneQ3A;
    //----(SA)
    re.AddCoronaToScene = RE_AddCoronaToScene;
    re.SetFog = R_SetFog;
    //----(SA)

    re.RenderScene = RE_RenderScene;
    re.SaveViewParms = RE_SaveViewParms;
    re.RestoreViewParms = RE_RestoreViewParms;

    re.SetColor = RE_SetColor;
    re.SetClipRegion = RE_SetClipRegion;
    re.DrawStretchPic = RE_StretchPic;
    re.DrawRotatedPic = RE_RotatedPic; // NERVE - SMF
    re.DrawStretchPicGradient = RE_StretchPicGradient;
    re.Add2dPolys = RE_2DPolyies;
    re.DrawStretchRaw = RE_StretchRaw;
    re.UploadCinematic = RE_UploadCinematic;
    re.BeginFrame = RE_BeginFrame;
    re.EndFrame = RE_EndFrame;

    re.MarkFragments = R_MarkFragments;
    re.ProjectDecal = RE_ProjectDecal;
    re.ClearDecals = RE_ClearDecals;

    re.LerpTag = R_LerpTag;
    re.ModelBounds = R_ModelBounds;

    re.RemapShader = R_RemapShader;
    re.DrawDebugPolygon = R_DebugPolygon;
    re.DrawDebugText = R_DebugText;
    re.GetEntityToken = R_GetEntityToken;

    re.AddPolyBufferToScene = RE_AddPolyBufferToScene;

    re.SetGlobalFog = RE_SetGlobalFog;

    re.inPVS = R_inPVS;
    re.inPVVS = R_inPVVS;

    re.purgeCache = R_PurgeCache;

    //bani
    re.LoadDynamicShader = RE_LoadDynamicShader;
    // fretn
    re.RenderToTexture = RE_RenderToTexture;
    re.GetTextureId = R_GetTextureId;
    //bani
    re.Finish = RE_Finish;

    re.TakeVideoFrame = RE_TakeVideoFrame;
    re.AddRefLightToScene = RE_AddRefLightToScene;

    // RB: alternative skeletal animation system
    re.RegisterAnimation = RE_RegisterAnimation;
    re.CheckSkeleton = RE_CheckSkeleton;
    re.BuildSkeleton = RE_BuildSkeleton;
    re.BlendSkeleton = RE_BlendSkeleton;
    re.BoneIndex = RE_BoneIndex;
    re.AnimNumFrames = RE_AnimNumFrames;
    re.AnimFrameRate = RE_AnimFrameRate;

    re.RegisterVisTest = RE_RegisterVisTest;
    re.AddVisTestToScene = RE_AddVisTestToScene;
    re.CheckVisibility = RE_CheckVisibility;
    re.UnregisterVisTest = RE_UnregisterVisTest;

    re.SetColorGrading = RE_SetColorGrading;
    re.SetAltShaderTokens = R_SetAltShaderTokens;

    re.ScissorEnable = RE_ScissorEnable;
    re.ScissorSet = RE_ScissorSet;

    return &re;
}

<|endoftext|>


<commit_before>/*
	Copyright (c) 2014, Madd Games.
	All rights reserved.

	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are met:

	* Redistributions of source code must retain the above copyright notice, this
	  list of conditions and the following disclaimer.

	* Redistributions in binary form must reproduce the above copyright notice,
	  this list of conditions and the following disclaimer in the documentation
	  and/or other materials provided with the distribution.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
	DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
	FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
	DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
	SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
	CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
	OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <Apoc/Math/Matrix.h>

Matrix::Matrix()
{
};

Matrix::Matrix(const Matrix &mat)
{
	int i;
	for (i=0; i<4; i++)
	{
		columns[i] = mat.columns[i];
	};
};

Matrix& Matrix::operator=(Matrix mat)
{
	int i;
	for (i=0; i<4; i++)
	{
		columns[i] = mat[i];
	};

	return *this;
};

Vector& Matrix::operator[](int i)
{
	return columns[i];
};

Matrix Matrix::transpose()
{
	Matrix out;
	int i, j;
	for (i=0; i<4; i++)
	{
		for (j=0; j<4; j++)
		{
			out[i][j] = columns[j][i];
		};
	};
};

Matrix Matrix::operator*(Matrix b)
{
	Matrix a = transpose();
	Matrix out;

	int i, j;
	for (i=0; i<4; i++)
	{
		for (j=0; j<4; j++)
		{
			out[i][j] = a[j].dot(b[i]);
		};
	};

	return out;
};
<commit_msg>Update Matrix.cpp<commit_after>/*
	Copyright (c) 2014, Madd Games.
	All rights reserved.

	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are met:

	* Redistributions of source code must retain the above copyright notice, this
	  list of conditions and the following disclaimer.

	* Redistributions in binary form must reproduce the above copyright notice,
	  this list of conditions and the following disclaimer in the documentation
	  and/or other materials provided with the distribution.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
	DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
	FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
	DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
	SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
	CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
	OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <Apoc/Math/Matrix.h>

Matrix::Matrix()
{
};

Matrix::Matrix(const Matrix &mat)
{
	int i;
	for (i=0; i<4; i++)
	{
		columns[i] = mat.columns[i];
	};
};

Matrix& Matrix::operator=(Matrix mat)
{
	int i;
	for (i=0; i<4; i++)
	{
		columns[i] = mat[i];
	};

	return *this;
};

Vector& Matrix::operator[](int i)
{
	return columns[i];
};

Matrix Matrix::transpose()
{
	Matrix out;
	int i, j;
	for (i=0; i<4; i++)
	{
		for (j=0; j<4; j++)
		{
			out[i][j] = columns[j][i];
		};
	};
};

Matrix Matrix::operator*(Matrix b)
{
	Matrix a = transpose();
	Matrix out;

	int i, j;
	for (i=0; i<4; i++)
	{
		for (j=0; j<4; j++)
		{
			out[i][j] = a[j].dot(b[i]);
		};
	};

	return out;
};

Vector Matrix::operator*(Vector vec)
{
	Vector out;
	int i;
	for (i=0; i<4; i++)
	{
		out[i] = columns[i].dot(vec);
	};
	return out;
};
<|endoftext|>