<commit_before>//===- ScriptLexer.cpp ----------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a lexer for the linker script.
//
// The linker script's grammar is not complex but ambiguous due to the
// lack of the formal specification of the language. What we are trying to
// do in this and other files in LLD is to make a "reasonable" linker
// script processor.
//
// Among simplicity, compatibility and efficiency, we put the most
// emphasis on simplicity when we wrote this lexer. Compatibility with the
// GNU linkers is important, but we did not try to clone every tiny corner
// case of their lexers, as even ld.bfd and ld.gold are subtly different
// in various corner cases. We do not care much about efficiency because
// the time spent in parsing linker scripts is usually negligible.
//
// Our grammar of the linker script is LL(2), meaning that it needs at
// most two-token lookahead to parse. The only place we need two-token
// lookahead is labels in version scripts, where we need to parse "local :"
// as if "local:".
//
// Overall, this lexer works fine for most linker scripts. There might
// be room for improving compatibility, but that's probably not at the
// top of our todo list.
//
//===----------------------------------------------------------------------===//

#include "ScriptLexer.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/Twine.h"

using namespace llvm;
using namespace lld;
using namespace lld::elf;

// Returns a whole line containing the current token.
StringRef ScriptLexer::getLine() {
  StringRef S = getCurrentMB().getBuffer();
  StringRef Tok = Tokens[Pos - 1];

  size_t Pos = S.rfind('\n', Tok.data() - S.data());
  if (Pos != StringRef::npos)
    S = S.substr(Pos + 1);
  return S.substr(0, S.find_first_of("\r\n"));
}

// Returns 1-based line number of the current token.
size_t ScriptLexer::getLineNumber() {
  StringRef S = getCurrentMB().getBuffer();
  StringRef Tok = Tokens[Pos - 1];
  return S.substr(0, Tok.data() - S.data()).count('\n') + 1;
}

// Returns 0-based column number of the current token.
size_t ScriptLexer::getColumnNumber() {
  StringRef Tok = Tokens[Pos - 1];
  return Tok.data() - getLine().data();
}

std::string ScriptLexer::getCurrentLocation() {
  std::string Filename = getCurrentMB().getBufferIdentifier();
  return (Filename + ":" + Twine(getLineNumber())).str();
}

ScriptLexer::ScriptLexer(MemoryBufferRef MB) { tokenize(MB); }

// We don't want to record cascading errors. Keep only the first one.
void ScriptLexer::setError(const Twine &Msg) {
  if (errorCount())
    return;

  std::string S = (getCurrentLocation() + ": " + Msg).str();
  if (Pos)
    S += "\n>>> " + getLine().str() + "\n>>> " +
         std::string(getColumnNumber(), ' ') + "^";
  error(S);
}

// Split S into linker script tokens.
void ScriptLexer::tokenize(MemoryBufferRef MB) {
  std::vector<StringRef> Vec;
  MBs.push_back(MB);
  StringRef S = MB.getBuffer();
  StringRef Begin = S;

  for (;;) {
    S = skipSpace(S);
    if (S.empty())
      break;

    // Quoted token. Note that double-quote characters are parts of a token
    // because, in a glob match context, only unquoted tokens are interpreted
    // as glob patterns. Double-quoted tokens are literal patterns in that
    // context.
    if (S.startswith("\"")) {
      size_t E = S.find("\"", 1);
      if (E == StringRef::npos) {
        StringRef Filename = MB.getBufferIdentifier();
        size_t Lineno = Begin.substr(0, S.data() - Begin.data()).count('\n');
        error(Filename + ":" + Twine(Lineno + 1) + ": unclosed quote");
        return;
      }

      Vec.push_back(S.take_front(E + 1));
      S = S.substr(E + 1);
      continue;
    }

    // ">foo" is parsed to ">" and "foo", but ">>" is parsed to ">>".
    // "|", "||", "&" and "&&" are different operators.
    if (S.startswith("<<") || S.startswith("<=") || S.startswith(">>") ||
        S.startswith(">=") || S.startswith("||") || S.startswith("&&")) {
      Vec.push_back(S.substr(0, 2));
      S = S.substr(2);
      continue;
    }

    // Unquoted token. This is more relaxed than tokens in C-like language,
    // so that you can write "file-name.cpp" as one bare token, for example.
    size_t Pos = S.find_first_not_of(
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
        "0123456789_.$/\\~=+[]*?-!^:");

    // A character that cannot start a word (which is usually a
    // punctuation) forms a single character token.
    if (Pos == 0)
      Pos = 1;
    Vec.push_back(S.substr(0, Pos));
    S = S.substr(Pos);
  }

  Tokens.insert(Tokens.begin() + Pos, Vec.begin(), Vec.end());
}

// Skip leading whitespace characters or comments.
StringRef ScriptLexer::skipSpace(StringRef S) {
  for (;;) {
    if (S.startswith("/*")) {
      size_t E = S.find("*/", 2);
      if (E == StringRef::npos) {
        error("unclosed comment in a linker script");
        return "";
      }
      S = S.substr(E + 2);
      continue;
    }
    if (S.startswith("#")) {
      size_t E = S.find('\n', 1);
      if (E == StringRef::npos)
        E = S.size() - 1;
      S = S.substr(E + 1);
      continue;
    }
    size_t Size = S.size();
    S = S.ltrim();
    if (S.size() == Size)
      return S;
  }
}

// An erroneous token is handled as if it were the last token before EOF.
bool ScriptLexer::atEOF() { return errorCount() || Tokens.size() == Pos; }

// Split a given string as an expression.
// This function returns "3", "*" and "5" for "3*5" for example.
static std::vector<StringRef> tokenizeExpr(StringRef S) {
  StringRef Ops = "+-*/:!~"; // List of operators

  // Quoted strings are literal strings, so we don't want to split it.
  if (S.startswith("\""))
    return {S};

  // Split S with operators as separators.
  std::vector<StringRef> Ret;
  while (!S.empty()) {
    size_t E = S.find_first_of(Ops);

    // No need to split if there is no operator.
    if (E == StringRef::npos) {
      Ret.push_back(S);
      break;
    }

    // Get a token before the opreator.
    if (E != 0)
      Ret.push_back(S.substr(0, E));

    // Get the operator as a token. Keep != as one token.
    if (S.substr(E).startswith("!=")) {
      Ret.push_back(S.substr(E, 2));
      S = S.substr(E + 2);
    } else {
      Ret.push_back(S.substr(E, 1));
      S = S.substr(E + 1);
    }
  }
  return Ret;
}

// In contexts where expressions are expected, the lexer should apply
// different tokenization rules than the default one. By default,
// arithmetic operator characters are regular characters, but in the
// expression context, they should be independent tokens.
//
// For example, "foo*3" should be tokenized to "foo", "*" and "3" only
// in the expression context.
//
// This function may split the current token into multiple tokens.
void ScriptLexer::maybeSplitExpr() {
  if (!InExpr || errorCount() || atEOF())
    return;

  std::vector<StringRef> V = tokenizeExpr(Tokens[Pos]);
  if (V.size() == 1)
    return;
  Tokens.erase(Tokens.begin() + Pos);
  Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());
}

StringRef ScriptLexer::next() {
  maybeSplitExpr();

  if (errorCount())
    return "";
  if (atEOF()) {
    setError("unexpected EOF");
    return "";
  }
  return Tokens[Pos++];
}

StringRef ScriptLexer::peek() {
  StringRef Tok = next();
  if (errorCount())
    return "";
  Pos = Pos - 1;
  return Tok;
}

bool ScriptLexer::consume(StringRef Tok) {
  if (peek() == Tok) {
    skip();
    return true;
  }
  return false;
}

// Consumes Tok followed by ":". Space is allowed between Tok and ":".
bool ScriptLexer::consumeLabel(StringRef Tok) {
  if (consume((Tok + ":").str()))
    return true;
  if (Tokens.size() >= Pos + 2 && Tokens[Pos] == Tok &&
      Tokens[Pos + 1] == ":") {
    Pos += 2;
    return true;
  }
  return false;
}

void ScriptLexer::skip() { (void)next(); }

void ScriptLexer::expect(StringRef Expect) {
  if (errorCount())
    return;
  StringRef Tok = next();
  if (Tok != Expect)
    setError(Expect + " expected, but got " + Tok);
}

// Returns true if S encloses T.
static bool encloses(StringRef S, StringRef T) {
  return S.bytes_begin() <= T.bytes_begin() && T.bytes_end() <= S.bytes_end();
}

MemoryBufferRef ScriptLexer::getCurrentMB() {
  // Find input buffer containing the current token.
  assert(!MBs.empty());
  if (!Pos)
    return MBs[0];

  for (MemoryBufferRef MB : MBs)
    if (encloses(MB.getBuffer(), Tokens[Pos - 1]))
      return MB;
  llvm_unreachable("getCurrentMB: failed to find a token");
}
<commit_msg>[ELF] - Remove dead code #2.<commit_after>//===- ScriptLexer.cpp ----------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a lexer for the linker script.
//
// The linker script's grammar is not complex but ambiguous due to the
// lack of the formal specification of the language. What we are trying to
// do in this and other files in LLD is to make a "reasonable" linker
// script processor.
//
// Among simplicity, compatibility and efficiency, we put the most
// emphasis on simplicity when we wrote this lexer. Compatibility with the
// GNU linkers is important, but we did not try to clone every tiny corner
// case of their lexers, as even ld.bfd and ld.gold are subtly different
// in various corner cases. We do not care much about efficiency because
// the time spent in parsing linker scripts is usually negligible.
//
// Our grammar of the linker script is LL(2), meaning that it needs at
// most two-token lookahead to parse. The only place we need two-token
// lookahead is labels in version scripts, where we need to parse "local :"
// as if "local:".
//
// Overall, this lexer works fine for most linker scripts. There might
// be room for improving compatibility, but that's probably not at the
// top of our todo list.
//
//===----------------------------------------------------------------------===//

#include "ScriptLexer.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/Twine.h"

using namespace llvm;
using namespace lld;
using namespace lld::elf;

// Returns a whole line containing the current token.
StringRef ScriptLexer::getLine() {
  StringRef S = getCurrentMB().getBuffer();
  StringRef Tok = Tokens[Pos - 1];

  size_t Pos = S.rfind('\n', Tok.data() - S.data());
  if (Pos != StringRef::npos)
    S = S.substr(Pos + 1);
  return S.substr(0, S.find_first_of("\r\n"));
}

// Returns 1-based line number of the current token.
size_t ScriptLexer::getLineNumber() {
  StringRef S = getCurrentMB().getBuffer();
  StringRef Tok = Tokens[Pos - 1];
  return S.substr(0, Tok.data() - S.data()).count('\n') + 1;
}

// Returns 0-based column number of the current token.
size_t ScriptLexer::getColumnNumber() {
  StringRef Tok = Tokens[Pos - 1];
  return Tok.data() - getLine().data();
}

std::string ScriptLexer::getCurrentLocation() {
  std::string Filename = getCurrentMB().getBufferIdentifier();
  return (Filename + ":" + Twine(getLineNumber())).str();
}

ScriptLexer::ScriptLexer(MemoryBufferRef MB) { tokenize(MB); }

// We don't want to record cascading errors. Keep only the first one.
void ScriptLexer::setError(const Twine &Msg) {
  if (errorCount())
    return;

  std::string S = (getCurrentLocation() + ": " + Msg).str();
  if (Pos)
    S += "\n>>> " + getLine().str() + "\n>>> " +
         std::string(getColumnNumber(), ' ') + "^";
  error(S);
}

// Split S into linker script tokens.
void ScriptLexer::tokenize(MemoryBufferRef MB) {
  std::vector<StringRef> Vec;
  MBs.push_back(MB);
  StringRef S = MB.getBuffer();
  StringRef Begin = S;

  for (;;) {
    S = skipSpace(S);
    if (S.empty())
      break;

    // Quoted token. Note that double-quote characters are parts of a token
    // because, in a glob match context, only unquoted tokens are interpreted
    // as glob patterns. Double-quoted tokens are literal patterns in that
    // context.
    if (S.startswith("\"")) {
      size_t E = S.find("\"", 1);
      if (E == StringRef::npos) {
        StringRef Filename = MB.getBufferIdentifier();
        size_t Lineno = Begin.substr(0, S.data() - Begin.data()).count('\n');
        error(Filename + ":" + Twine(Lineno + 1) + ": unclosed quote");
        return;
      }

      Vec.push_back(S.take_front(E + 1));
      S = S.substr(E + 1);
      continue;
    }

    // ">foo" is parsed to ">" and "foo", but ">>" is parsed to ">>".
    // "|", "||", "&" and "&&" are different operators.
    if (S.startswith("<<") || S.startswith("<=") || S.startswith(">>") ||
        S.startswith(">=") || S.startswith("||") || S.startswith("&&")) {
      Vec.push_back(S.substr(0, 2));
      S = S.substr(2);
      continue;
    }

    // Unquoted token. This is more relaxed than tokens in C-like language,
    // so that you can write "file-name.cpp" as one bare token, for example.
    size_t Pos = S.find_first_not_of(
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
        "0123456789_.$/\\~=+[]*?-!^:");

    // A character that cannot start a word (which is usually a
    // punctuation) forms a single character token.
    if (Pos == 0)
      Pos = 1;
    Vec.push_back(S.substr(0, Pos));
    S = S.substr(Pos);
  }

  Tokens.insert(Tokens.begin() + Pos, Vec.begin(), Vec.end());
}

// Skip leading whitespace characters or comments.
StringRef ScriptLexer::skipSpace(StringRef S) {
  for (;;) {
    if (S.startswith("/*")) {
      size_t E = S.find("*/", 2);
      if (E == StringRef::npos) {
        error("unclosed comment in a linker script");
        return "";
      }
      S = S.substr(E + 2);
      continue;
    }
    if (S.startswith("#")) {
      size_t E = S.find('\n', 1);
      if (E == StringRef::npos)
        E = S.size() - 1;
      S = S.substr(E + 1);
      continue;
    }
    size_t Size = S.size();
    S = S.ltrim();
    if (S.size() == Size)
      return S;
  }
}

// An erroneous token is handled as if it were the last token before EOF.
bool ScriptLexer::atEOF() { return errorCount() || Tokens.size() == Pos; }

// Split a given string as an expression.
// This function returns "3", "*" and "5" for "3*5" for example.
static std::vector<StringRef> tokenizeExpr(StringRef S) {
  StringRef Ops = "+-*/:!~"; // List of operators

  // Quoted strings are literal strings, so we don't want to split it.
  if (S.startswith("\""))
    return {S};

  // Split S with operators as separators.
  std::vector<StringRef> Ret;
  while (!S.empty()) {
    size_t E = S.find_first_of(Ops);

    // No need to split if there is no operator.
    if (E == StringRef::npos) {
      Ret.push_back(S);
      break;
    }

    // Get a token before the opreator.
    if (E != 0)
      Ret.push_back(S.substr(0, E));

    // Get the operator as a token. Keep != as one token.
    if (S.substr(E).startswith("!=")) {
      Ret.push_back(S.substr(E, 2));
      S = S.substr(E + 2);
    } else {
      Ret.push_back(S.substr(E, 1));
      S = S.substr(E + 1);
    }
  }
  return Ret;
}

// In contexts where expressions are expected, the lexer should apply
// different tokenization rules than the default one. By default,
// arithmetic operator characters are regular characters, but in the
// expression context, they should be independent tokens.
//
// For example, "foo*3" should be tokenized to "foo", "*" and "3" only
// in the expression context.
//
// This function may split the current token into multiple tokens.
void ScriptLexer::maybeSplitExpr() {
  if (!InExpr || errorCount() || atEOF())
    return;

  std::vector<StringRef> V = tokenizeExpr(Tokens[Pos]);
  if (V.size() == 1)
    return;
  Tokens.erase(Tokens.begin() + Pos);
  Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());
}

StringRef ScriptLexer::next() {
  maybeSplitExpr();

  if (errorCount())
    return "";
  if (atEOF()) {
    setError("unexpected EOF");
    return "";
  }
  return Tokens[Pos++];
}

StringRef ScriptLexer::peek() {
  StringRef Tok = next();
  if (errorCount())
    return "";
  Pos = Pos - 1;
  return Tok;
}

bool ScriptLexer::consume(StringRef Tok) {
  if (peek() == Tok) {
    skip();
    return true;
  }
  return false;
}

// Consumes Tok followed by ":". Space is allowed between Tok and ":".
bool ScriptLexer::consumeLabel(StringRef Tok) {
  if (consume((Tok + ":").str()))
    return true;
  if (Tokens.size() >= Pos + 2 && Tokens[Pos] == Tok &&
      Tokens[Pos + 1] == ":") {
    Pos += 2;
    return true;
  }
  return false;
}

void ScriptLexer::skip() { (void)next(); }

void ScriptLexer::expect(StringRef Expect) {
  if (errorCount())
    return;
  StringRef Tok = next();
  if (Tok != Expect)
    setError(Expect + " expected, but got " + Tok);
}

// Returns true if S encloses T.
static bool encloses(StringRef S, StringRef T) {
  return S.bytes_begin() <= T.bytes_begin() && T.bytes_end() <= S.bytes_end();
}

MemoryBufferRef ScriptLexer::getCurrentMB() {
  // Find input buffer containing the current token.
  assert(!MBs.empty() && Pos > 0);
  for (MemoryBufferRef MB : MBs)
    if (encloses(MB.getBuffer(), Tokens[Pos - 1]))
      return MB;
  llvm_unreachable("getCurrentMB: failed to find a token");
}
<|endoftext|>


<commit_before>#include "EddystoneBeacon.h"

#define MAX_SERVICE_DATA_SIZE 20

#define FLAGS_UID 0x00
#define FLAGS_URL 0x10
#define FLAGS_TLM 0x20

static const char* EDDYSTONE_URL_BEACON_PREFIX_SUBSTITUTIONS[] = {
  "http://www.",
  "https://www.",
  "http://",
  "https://",
  "urn:uuid:"
};

static const char* EDDYSTONE_URL_BEACON_SUFFIX_SUBSTITUTIONS[] = {
  ".com/",
  ".org/",
  ".edu/",
  ".net/",
  ".info/",
  ".biz/",
  ".gov/",
  ".com",
  ".org",
  ".edu",
  ".net",
  ".info",
  ".biz",
  ".gov"
};

EddystoneBeacon::EddystoneBeacon(unsigned char req, unsigned char rdy, unsigned char rst) :
  BLEPeripheral(req, rdy, rst),
  _bleService("feaa"),
  _bleCharacteristic("feab", BLERead | BLEBroadcast, MAX_SERVICE_DATA_SIZE)
{
  this->setAdvertisedServiceUuid(this->_bleService.uuid());

  this->setConnectable(false);

  this->addAttribute(this->_bleService);
  this->addAttribute(this->_bleCharacteristic);
}

void EddystoneBeacon::begin(char power, const BLEUuid& uid) {
  unsigned char serviceData[MAX_SERVICE_DATA_SIZE];

  this->_power = power;

  memset(serviceData, 0x00, sizeof(serviceData));
  serviceData[0] = FLAGS_UID;
  serviceData[1] = this->_power;

  const unsigned char* uidData = uid.data();
  for (int i = 0; i < 16; i++) {
    serviceData[i + 2] = uidData[15 - i];
  }

  serviceData[18] = 0x00; // Reserved for future use, must be: 0x00
  serviceData[19] = 0x00; // Reserved for future use, must be: 0x00

  this->_bleCharacteristic.setValue(serviceData, sizeof(serviceData));

  BLEPeripheral::begin();

  this->_bleCharacteristic.broadcast();
}

void EddystoneBeacon::begin(char power, const char* uri) {
  this->_power = power;
  this->setURI(uri);

  BLEPeripheral::begin();

  this->_bleCharacteristic.broadcast();
}

void EddystoneBeacon::setURI(const char* uri) {
  unsigned char serviceData[MAX_SERVICE_DATA_SIZE];

  serviceData[0] = FLAGS_URL;
  serviceData[1] = this->_power;
  unsigned char compressedURIlength = this->compressURI(uri, (char *)&serviceData[2], sizeof(serviceData) - 2);

  this->_bleCharacteristic.setValue(serviceData, 2 + compressedURIlength);
}

unsigned char EddystoneBeacon::compressURI(const char* uri, char *compressedUri, unsigned char compressedUriSize) {
  String uriString = uri;

  // replace prefixes
  for (unsigned int i = 0; i < (sizeof(EDDYSTONE_URL_BEACON_PREFIX_SUBSTITUTIONS) / sizeof(char *)); i++) {
    String replacement = " ";
    replacement[0] = (char)(i | 0x80); // set high bit, String.replace does not like '\0' replacement

    uriString.replace(EDDYSTONE_URL_BEACON_PREFIX_SUBSTITUTIONS[i], replacement);
  }

  // replace suffixes
  for (unsigned int i = 0; i < (sizeof(EDDYSTONE_URL_BEACON_SUFFIX_SUBSTITUTIONS) / sizeof(char *)); i++) {
    String replacement = " ";
    replacement[0] = (char)(i | 0x80); // set high bit, String.replace does not like '\0' replacement

    uriString.replace(EDDYSTONE_URL_BEACON_SUFFIX_SUBSTITUTIONS[i], replacement);
  }

  unsigned char i = 0;
  for (i = 0; i < uriString.length() && i < compressedUriSize; i++) {
    compressedUri[i] = (uriString[i] & 0x7f); // assign byte after clearing hight bit
  }

  return i;
}

void EddystoneBeacon::loop() {
  this->poll();
}
<commit_msg>- move service UUID set from constructor to begin in EddystoneBeacon<commit_after>#include "EddystoneBeacon.h"

#define MAX_SERVICE_DATA_SIZE 20

#define FLAGS_UID 0x00
#define FLAGS_URL 0x10
#define FLAGS_TLM 0x20

static const char* EDDYSTONE_URL_BEACON_PREFIX_SUBSTITUTIONS[] = {
  "http://www.",
  "https://www.",
  "http://",
  "https://",
  "urn:uuid:"
};

static const char* EDDYSTONE_URL_BEACON_SUFFIX_SUBSTITUTIONS[] = {
  ".com/",
  ".org/",
  ".edu/",
  ".net/",
  ".info/",
  ".biz/",
  ".gov/",
  ".com",
  ".org",
  ".edu",
  ".net",
  ".info",
  ".biz",
  ".gov"
};

EddystoneBeacon::EddystoneBeacon(unsigned char req, unsigned char rdy, unsigned char rst) :
  BLEPeripheral(req, rdy, rst),
  _bleService("feaa"),
  _bleCharacteristic("feab", BLERead | BLEBroadcast, MAX_SERVICE_DATA_SIZE)
{
  this->setConnectable(false);

  this->addAttribute(this->_bleService);
  this->addAttribute(this->_bleCharacteristic);
}

void EddystoneBeacon::begin(char power, const BLEUuid& uid) {
  unsigned char serviceData[MAX_SERVICE_DATA_SIZE];

  this->_power = power;

  memset(serviceData, 0x00, sizeof(serviceData));
  serviceData[0] = FLAGS_UID;
  serviceData[1] = this->_power;

  const unsigned char* uidData = uid.data();
  for (int i = 0; i < 16; i++) {
    serviceData[i + 2] = uidData[15 - i];
  }

  serviceData[18] = 0x00; // Reserved for future use, must be: 0x00
  serviceData[19] = 0x00; // Reserved for future use, must be: 0x00

  this->_bleCharacteristic.setValue(serviceData, sizeof(serviceData));

  this->setAdvertisedServiceUuid(this->_bleService.uuid());

  BLEPeripheral::begin();

  this->_bleCharacteristic.broadcast();
}

void EddystoneBeacon::begin(char power, const char* uri) {
  this->_power = power;
  this->setURI(uri);

  BLEPeripheral::begin();

  this->_bleCharacteristic.broadcast();
}

void EddystoneBeacon::setURI(const char* uri) {
  unsigned char serviceData[MAX_SERVICE_DATA_SIZE];

  serviceData[0] = FLAGS_URL;
  serviceData[1] = this->_power;
  unsigned char compressedURIlength = this->compressURI(uri, (char *)&serviceData[2], sizeof(serviceData) - 2);

  this->_bleCharacteristic.setValue(serviceData, 2 + compressedURIlength);
}

unsigned char EddystoneBeacon::compressURI(const char* uri, char *compressedUri, unsigned char compressedUriSize) {
  String uriString = uri;

  // replace prefixes
  for (unsigned int i = 0; i < (sizeof(EDDYSTONE_URL_BEACON_PREFIX_SUBSTITUTIONS) / sizeof(char *)); i++) {
    String replacement = " ";
    replacement[0] = (char)(i | 0x80); // set high bit, String.replace does not like '\0' replacement

    uriString.replace(EDDYSTONE_URL_BEACON_PREFIX_SUBSTITUTIONS[i], replacement);
  }

  // replace suffixes
  for (unsigned int i = 0; i < (sizeof(EDDYSTONE_URL_BEACON_SUFFIX_SUBSTITUTIONS) / sizeof(char *)); i++) {
    String replacement = " ";
    replacement[0] = (char)(i | 0x80); // set high bit, String.replace does not like '\0' replacement

    uriString.replace(EDDYSTONE_URL_BEACON_SUFFIX_SUBSTITUTIONS[i], replacement);
  }

  unsigned char i = 0;
  for (i = 0; i < uriString.length() && i < compressedUriSize; i++) {
    compressedUri[i] = (uriString[i] & 0x7f); // assign byte after clearing hight bit
  }

  return i;
}

void EddystoneBeacon::loop() {
  this->poll();
}
<|endoftext|>


<commit_before>#include "database_connection.hpp"
#include "database_transaction.hpp"
#include "detail/sqlite_dbconn.hpp"
#include "sql_statement.hpp"
#include "sqloxx_exceptions.hpp"
#include "detail/sql_statement_impl.hpp"
#include <boost/filesystem/path.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp>
#include <iostream>
#include <climits>
#include <cstdio>
#include <limits>
#include <set>
#include <stdexcept>
#include <string>

#include <jewel/debug_log.hpp>

using boost::shared_ptr;
using boost::unordered_map;
using std::bad_alloc;
using std::cout;
using std::clog;
using std::endl;
using std::fprintf;
using std::numeric_limits;
using std::set;
using std::string;

namespace sqloxx
{

// Switch statement later relies on this being INT_MAX, and
// won't compile if it's changed to std::numeric_limits<int>::max().
int const
DatabaseConnection::s_max_nesting = INT_MAX;

DatabaseConnection::DatabaseConnection
(	StatementCache::size_type p_cache_capacity
):
	m_sqlite_dbconn(new detail::SQLiteDBConn),
	m_transaction_nesting_level(0),
	m_cache_capacity(p_cache_capacity)
{
}

DatabaseConnection::~DatabaseConnection()
{
	if (m_transaction_nesting_level > 0)
	{
		// We avoid streams here, because they might throw
		// (in theory, if exceptions have been enabled for the
		// stream).
		fprintf
		(	stderr,
			"Transaction(s) remained incomplete on closure of "
			"DatabaseConnection.\n"
		);
	}
#	ifdef DEBUG
		JEWEL_DEBUG_LOG << "\nThe following SQLStatements were cached during "
						<< "the life of the sqloxx::DatabaseConnection "
						<< "that is now being destructed:\n"
						<< endl;
		for
		(	StatementCache::const_iterator it = m_statement_cache.begin();
			it != m_statement_cache.end();
			++it
		)
		{
			JEWEL_DEBUG_LOG << "\"" << it->first << "\"" << endl;
		}
		JEWEL_DEBUG_LOG << "\nNumber of SQLStatements cached: "
		                << m_statement_cache.size()
						<< endl << endl;
#	endif
	m_statement_cache.clear();
}

bool
DatabaseConnection::is_valid() const
{
	return m_sqlite_dbconn->is_valid();
}

void
DatabaseConnection::open(boost::filesystem::path const& filepath)
{
	m_sqlite_dbconn->open(filepath);
	return;
}

void
DatabaseConnection::execute_sql(string const& str)
{
	m_sqlite_dbconn->execute_sql(str);
	return;
}

void
DatabaseConnection::setup_boolean_table()
{
	execute_sql("create table booleans(representation integer primary key)");
	execute_sql("insert into booleans(representation) values(0)");
	execute_sql("insert into booleans(representation) values(1)");
	return;
}

int
DatabaseConnection::max_nesting()
{
	return s_max_nesting;
}

void
DatabaseConnection::begin_transaction()
{
	switch (m_transaction_nesting_level)
	{
	case 0:
		unchecked_begin_transaction();
		break;
	case s_max_nesting:
		throw TransactionNestingException("Maximum nesting level reached.");
		assert (false);  // Execution never reaches here
	default:
		assert (m_transaction_nesting_level > 0);
		unchecked_set_savepoint();
		break;
	}
	++m_transaction_nesting_level;
	return;
}

void
DatabaseConnection::end_transaction()
{
	switch (m_transaction_nesting_level)
	{
	case 1:
		unchecked_end_transaction();
		break;
	case 0:
		throw TransactionNestingException
		(	"Cannot end SQL transaction when there in none open."
		);
		assert (false);  // Execution never reaches here
	default:
		assert (m_transaction_nesting_level > 1);
		unchecked_release_savepoint();
		break;
	}
	assert (m_transaction_nesting_level > 0);
	--m_transaction_nesting_level;
	return;
}

void
DatabaseConnection::cancel_transaction()
{
	switch (m_transaction_nesting_level)
	{
	case 1:
		unchecked_rollback_transaction();
		break;
	case 0:
		throw TransactionNestingException
		(	"Cannot cancel SQL transaction when there is none open."
		);
		assert (false);  // Execution never reaches here
	default:
		assert (m_transaction_nesting_level > 1);
		unchecked_rollback_to_savepoint();
		unchecked_release_savepoint();
		break;
	}
	--m_transaction_nesting_level;
	return;
}

shared_ptr<detail::SQLStatementImpl>
DatabaseConnection::provide_sql_statement(string const& statement_text)
{
	if (!is_valid())
	{
		throw InvalidConnection("Invalid database connection.");
	}
	StatementCache::const_iterator const it
	(	m_statement_cache.find(statement_text)
	);
	if (it != m_statement_cache.end())
	{
		shared_ptr<detail::SQLStatementImpl> existing_statement(it->second);
		if (!(existing_statement->is_locked()))
		{
			existing_statement->lock();
			return existing_statement;
		}
	}
	assert (it == m_statement_cache.end() || it->second->is_locked());
	shared_ptr<detail::SQLStatementImpl> new_statement
	(	new detail::SQLStatementImpl(*m_sqlite_dbconn, statement_text)
	);
	new_statement->lock();
	if (m_statement_cache.size() != m_cache_capacity)
	{
		assert (m_statement_cache.size() < m_cache_capacity);
		try
		{
			m_statement_cache[statement_text] = new_statement;
		}
		catch (bad_alloc&)
		{
			m_statement_cache.clear();
			assert (new_statement != 0);
		}
	}
	/*
	else
	{
		// Cache has reached capacity and caching has been
		// discontinued.
	}
	*/
	return new_statement;
}

void
DatabaseConnection::unchecked_begin_transaction()
{
	SQLStatement statement(*this, "begin");
	statement.step();
	return;
}

void
DatabaseConnection::unchecked_end_transaction()
{
	SQLStatement statement(*this, "end");
	statement.step();
	return;
}

void
DatabaseConnection::unchecked_set_savepoint()
{
	SQLStatement statement(*this, "savepoint sp");
	statement.step();
	return;
}

void
DatabaseConnection::unchecked_release_savepoint()
{
	SQLStatement statement(*this, "release sp");
	statement.step();
	return;
}

void
DatabaseConnection::unchecked_rollback_transaction()
{
	SQLStatement statement(*this, "rollback");
	statement.step();
	return;
}

void
DatabaseConnection::unchecked_rollback_to_savepoint()
{
	SQLStatement statement(*this, "rollback to savepoint sp");
	statement.step();
	return;
}

int
DatabaseConnection::self_test()
{
	int ret = 0;
	assert (m_transaction_nesting_level == 0);
	int const original_nesting = m_transaction_nesting_level;
	m_transaction_nesting_level = max_nesting() - 1;
	DatabaseTransaction transaction1(*this);  // Should be ok.
	++ret;
	try
	{
		DatabaseTransaction transaction2(*this);  // Should throw
	}
	catch (TransactionNestingException&)
	{
		--ret;
	}
	transaction1.cancel();
	m_transaction_nesting_level = original_nesting;
	return ret;

}

}  // namespace sqloxx
<commit_msg>Commented out logging code that outputs cached SQLStatements on destruction of DatabaseConnection.<commit_after>#include "database_connection.hpp"
#include "database_transaction.hpp"
#include "detail/sqlite_dbconn.hpp"
#include "sql_statement.hpp"
#include "sqloxx_exceptions.hpp"
#include "detail/sql_statement_impl.hpp"
#include <boost/filesystem/path.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp>
#include <iostream>
#include <climits>
#include <cstdio>
#include <limits>
#include <set>
#include <stdexcept>
#include <string>

#include <jewel/debug_log.hpp>

using boost::shared_ptr;
using boost::unordered_map;
using std::bad_alloc;
using std::cout;
using std::clog;
using std::endl;
using std::fprintf;
using std::numeric_limits;
using std::set;
using std::string;

namespace sqloxx
{

// Switch statement later relies on this being INT_MAX, and
// won't compile if it's changed to std::numeric_limits<int>::max().
int const
DatabaseConnection::s_max_nesting = INT_MAX;

DatabaseConnection::DatabaseConnection
(	StatementCache::size_type p_cache_capacity
):
	m_sqlite_dbconn(new detail::SQLiteDBConn),
	m_transaction_nesting_level(0),
	m_cache_capacity(p_cache_capacity)
{
}

DatabaseConnection::~DatabaseConnection()
{
	if (m_transaction_nesting_level > 0)
	{
		// We avoid streams here, because they might throw
		// (in theory, if exceptions have been enabled for the
		// stream).
		fprintf
		(	stderr,
			"Transaction(s) remained incomplete on closure of "
			"DatabaseConnection.\n"
		);
	}
/*
#	ifdef SQLOXX_PRINT_CACHED_STATEMENTS_ON_EXIT
		JEWEL_DEBUG_LOG << "\nThe following SQLStatements were cached during "
						<< "the life of the sqloxx::DatabaseConnection "
						<< "that is now being destructed:\n"
						<< endl;
		for
		(	StatementCache::const_iterator it = m_statement_cache.begin();
			it != m_statement_cache.end();
			++it
		)
		{
			JEWEL_DEBUG_LOG << "\"" << it->first << "\"" << endl;
		}
		JEWEL_DEBUG_LOG << "\nNumber of SQLStatements cached: "
		                << m_statement_cache.size()
						<< endl << endl;
#	endif
*/
	m_statement_cache.clear();
}

bool
DatabaseConnection::is_valid() const
{
	return m_sqlite_dbconn->is_valid();
}

void
DatabaseConnection::open(boost::filesystem::path const& filepath)
{
	m_sqlite_dbconn->open(filepath);
	return;
}

void
DatabaseConnection::execute_sql(string const& str)
{
	m_sqlite_dbconn->execute_sql(str);
	return;
}

void
DatabaseConnection::setup_boolean_table()
{
	execute_sql("create table booleans(representation integer primary key)");
	execute_sql("insert into booleans(representation) values(0)");
	execute_sql("insert into booleans(representation) values(1)");
	return;
}

int
DatabaseConnection::max_nesting()
{
	return s_max_nesting;
}

void
DatabaseConnection::begin_transaction()
{
	switch (m_transaction_nesting_level)
	{
	case 0:
		unchecked_begin_transaction();
		break;
	case s_max_nesting:
		throw TransactionNestingException("Maximum nesting level reached.");
		assert (false);  // Execution never reaches here
	default:
		assert (m_transaction_nesting_level > 0);
		unchecked_set_savepoint();
		break;
	}
	++m_transaction_nesting_level;
	return;
}

void
DatabaseConnection::end_transaction()
{
	switch (m_transaction_nesting_level)
	{
	case 1:
		unchecked_end_transaction();
		break;
	case 0:
		throw TransactionNestingException
		(	"Cannot end SQL transaction when there in none open."
		);
		assert (false);  // Execution never reaches here
	default:
		assert (m_transaction_nesting_level > 1);
		unchecked_release_savepoint();
		break;
	}
	assert (m_transaction_nesting_level > 0);
	--m_transaction_nesting_level;
	return;
}

void
DatabaseConnection::cancel_transaction()
{
	switch (m_transaction_nesting_level)
	{
	case 1:
		unchecked_rollback_transaction();
		break;
	case 0:
		throw TransactionNestingException
		(	"Cannot cancel SQL transaction when there is none open."
		);
		assert (false);  // Execution never reaches here
	default:
		assert (m_transaction_nesting_level > 1);
		unchecked_rollback_to_savepoint();
		unchecked_release_savepoint();
		break;
	}
	--m_transaction_nesting_level;
	return;
}

shared_ptr<detail::SQLStatementImpl>
DatabaseConnection::provide_sql_statement(string const& statement_text)
{
	if (!is_valid())
	{
		throw InvalidConnection("Invalid database connection.");
	}
	StatementCache::const_iterator const it
	(	m_statement_cache.find(statement_text)
	);
	if (it != m_statement_cache.end())
	{
		shared_ptr<detail::SQLStatementImpl> existing_statement(it->second);
		if (!(existing_statement->is_locked()))
		{
			existing_statement->lock();
			return existing_statement;
		}
	}
	assert (it == m_statement_cache.end() || it->second->is_locked());
	shared_ptr<detail::SQLStatementImpl> new_statement
	(	new detail::SQLStatementImpl(*m_sqlite_dbconn, statement_text)
	);
	new_statement->lock();
	if (m_statement_cache.size() != m_cache_capacity)
	{
		assert (m_statement_cache.size() < m_cache_capacity);
		try
		{
			m_statement_cache[statement_text] = new_statement;
		}
		catch (bad_alloc&)
		{
			m_statement_cache.clear();
			assert (new_statement != 0);
		}
	}
	/*
	else
	{
		// Cache has reached capacity and caching has been
		// discontinued.
	}
	*/
	return new_statement;
}

void
DatabaseConnection::unchecked_begin_transaction()
{
	SQLStatement statement(*this, "begin");
	statement.step();
	return;
}

void
DatabaseConnection::unchecked_end_transaction()
{
	SQLStatement statement(*this, "end");
	statement.step();
	return;
}

void
DatabaseConnection::unchecked_set_savepoint()
{
	SQLStatement statement(*this, "savepoint sp");
	statement.step();
	return;
}

void
DatabaseConnection::unchecked_release_savepoint()
{
	SQLStatement statement(*this, "release sp");
	statement.step();
	return;
}

void
DatabaseConnection::unchecked_rollback_transaction()
{
	SQLStatement statement(*this, "rollback");
	statement.step();
	return;
}

void
DatabaseConnection::unchecked_rollback_to_savepoint()
{
	SQLStatement statement(*this, "rollback to savepoint sp");
	statement.step();
	return;
}

int
DatabaseConnection::self_test()
{
	int ret = 0;
	assert (m_transaction_nesting_level == 0);
	int const original_nesting = m_transaction_nesting_level;
	m_transaction_nesting_level = max_nesting() - 1;
	DatabaseTransaction transaction1(*this);  // Should be ok.
	++ret;
	try
	{
		DatabaseTransaction transaction2(*this);  // Should throw
	}
	catch (TransactionNestingException&)
	{
		--ret;
	}
	transaction1.cancel();
	m_transaction_nesting_level = original_nesting;
	return ret;

}

}  // namespace sqloxx
<|endoftext|>


<commit_before>//
//  main.cpp
//  Euchre
//
//  Created by Dillon Hammond on 9/12/14.
//  Copyright (c) 2014 Learning. All rights reserved.
//

#define GLEW_STATIC
#include "GL/glew.h"
#include <SDL2/SDL.h>
#include "SOIL.h"
#define GLM_FORCE_RADIANS
#include "glm.hpp"
#include <iostream>
#include <fstream>

GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path) {

	// Create the shaders
	GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
	GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

	// Read the Vertex Shader code from the file
	std::string VertexShaderCode;
	std::ifstream VertexShaderStream;
	VertexShaderStream.open(vertex_file_path);
	if(VertexShaderStream.is_open())
	{
		std::string Line = "";
		while(getline(VertexShaderStream, Line))
			VertexShaderCode += "\n" + Line;
		VertexShaderStream.close();
	}

	// Read the Fragment Shader code from the file
	std::string FragmentShaderCode;
	std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
	if(FragmentShaderStream.is_open()){
		std::string Line = "";
		while(getline(FragmentShaderStream, Line))
			FragmentShaderCode += "\n" + Line;
		FragmentShaderStream.close();
	}
	GLint Result;
	// Compile Vertex Shader
	char const * VertexSourcePointer = VertexShaderCode.c_str();
	glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
	glCompileShader(VertexShaderID);
	glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
		if (Result == GL_FALSE) {
			std::cout << "NOOOV" << std::endl;
			std::cout << VertexSourcePointer << std::endl;
		}

	// Compile Fragment Shader
	char const * FragmentSourcePointer = FragmentShaderCode.c_str();
	glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
	glCompileShader(FragmentShaderID);
	glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
		if (Result == GL_FALSE) {
			std::cout << "NOOOF" << std::endl;
			std::cout << FragmentSourcePointer << std::endl;
		}

	// Link the program
	GLuint ProgramID = glCreateProgram();
	glAttachShader(ProgramID, VertexShaderID);
	glAttachShader(ProgramID, FragmentShaderID);
	glLinkProgram(ProgramID);

	glDeleteShader(VertexShaderID);
	glDeleteShader(FragmentShaderID);

	return ProgramID;
}

SDL_Window* createWindow(const char* title, int x, int y, int w, int h, Uint32 flags) {
	SDL_Init(SDL_INIT_VIDEO);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
	SDL_Window *window = SDL_CreateWindow(title, x, y, w, h, flags);
	return window;
}

void LoadTextures(GLuint textures[], const char* filename, const GLchar* texName, GLuint shaderProgram, int texNum) {
	int width, height;
	unsigned char* image;

	glActiveTexture(GL_TEXTURE0 + texNum);

	glBindTexture(GL_TEXTURE_2D, textures[texNum]);
	image = SOIL_load_image(filename, &width, &height, 0, SOIL_LOAD_RGB);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
	SOIL_free_image_data(image);
	glUniform1i(glGetUniformLocation(shaderProgram, "backGround"), texNum);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

int main() {
	SDL_Window* window = createWindow("Euchre", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL);
	SDL_GLContext context = SDL_GL_CreateContext(window);

	// Initialize GLEW
	glewExperimental = GL_TRUE;
	glewInit();

	// Initialize Depth Testing
	glEnable(GL_DEPTH_TEST);

	// Create Vertex Array Object
	GLuint vao;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	// Create a Vertex Buffer Object and copy the vertex data to it
	GLuint vbo;
	glGenBuffers(1, &vbo);

	GLfloat vertices[] = {
		-0.5f,  0.5f, 1.0f, 0.0f, 0.0f, // Top-left
		0.5f,  0.5f, 0.0f, 1.0f, 0.0f, // Top-right
		0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // Bottom-right
		-0.5f, -0.5f, 1.0f, 1.0f, 1.0f  // Bottom-left
	};

	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	// Create an element array
	GLuint ebo;
	glGenBuffers(1, &ebo);

	GLuint elements[] = { // Describes which set of points are drawn each time
		0, 1, 2,
		2, 3, 0
	};

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);

	GLuint shaderProgram = LoadShaders("./Resources/vertexShader.txt", "./Resources/fragmentShader.txt");
	glUseProgram(shaderProgram);

	// Specify the layout of the vertex data
	GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
	glEnableVertexAttribArray(posAttrib);
	glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);

	GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
	glEnableVertexAttribArray(colAttrib);
	glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
	SDL_Event windowEvent;
	while (true) {
		if (SDL_PollEvent(&windowEvent)) {
			if (windowEvent.type == SDL_QUIT) {
				break;
			}
		}

		// Clear the screen to black
		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

		// Draw a rectangle from the 2 triangles using 6 indices
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

		SDL_GL_SwapWindow(window);
	}
	glDeleteProgram(shaderProgram);

	glDeleteBuffers(1, &ebo);
	glDeleteBuffers(1, &vbo);

	glDeleteVertexArrays(1, &vao);

	SDL_GL_DeleteContext(context);
	return 0;
}<commit_msg>Added another comment<commit_after>//
//  main.cpp
//  Euchre
//
//  Created by Dillon Hammond on 9/12/14.
//  Copyright (c) 2014 Learning. All rights reserved.
//

#define GLEW_STATIC
#include "GL/glew.h"
#include <SDL2/SDL.h>
#include "SOIL.h"
#define GLM_FORCE_RADIANS
#include "glm.hpp"
#include <iostream>
#include <fstream>

GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path) {

	// Create the shaders
	GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
	GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

	// Read the Vertex Shader code from the file
	std::string VertexShaderCode;
	std::ifstream VertexShaderStream;
	VertexShaderStream.open(vertex_file_path);
	if(VertexShaderStream.is_open())
	{
		std::string Line = "";
		while(getline(VertexShaderStream, Line))
			VertexShaderCode += "\n" + Line;
		VertexShaderStream.close();
	}

	// Read the Fragment Shader code from the file
	std::string FragmentShaderCode;
	std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
	if(FragmentShaderStream.is_open()){
		std::string Line = "";
		while(getline(FragmentShaderStream, Line))
			FragmentShaderCode += "\n" + Line;
		FragmentShaderStream.close();
	}
	GLint Result;
	// Compile Vertex Shader
	char const * VertexSourcePointer = VertexShaderCode.c_str();
	glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
	glCompileShader(VertexShaderID);
	glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
		if (Result == GL_FALSE) {
			std::cout << "NOOOV" << std::endl;
			std::cout << VertexSourcePointer << std::endl;
		}

	// Compile Fragment Shader
	char const * FragmentSourcePointer = FragmentShaderCode.c_str();
	glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
	glCompileShader(FragmentShaderID);
	glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
		if (Result == GL_FALSE) {
			std::cout << "NOOOF" << std::endl;
			std::cout << FragmentSourcePointer << std::endl;
		}

	// Link the program
	GLuint ProgramID = glCreateProgram();
	glAttachShader(ProgramID, VertexShaderID);
	glAttachShader(ProgramID, FragmentShaderID);
	glLinkProgram(ProgramID);

	glDeleteShader(VertexShaderID);
	glDeleteShader(FragmentShaderID);

	return ProgramID;
}

SDL_Window* createWindow(const char* title, int x, int y, int w, int h, Uint32 flags) {
	SDL_Init(SDL_INIT_VIDEO);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
	SDL_Window *window = SDL_CreateWindow(title, x, y, w, h, flags);
	return window;
}

void LoadTextures(GLuint textures[], const char* filename, const GLchar* texName, GLuint shaderProgram, int texNum) {
	int width, height;
	unsigned char* image;

	glActiveTexture(GL_TEXTURE0 + texNum);

	glBindTexture(GL_TEXTURE_2D, textures[texNum]);
	image = SOIL_load_image(filename, &width, &height, 0, SOIL_LOAD_RGB);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
	SOIL_free_image_data(image);
	glUniform1i(glGetUniformLocation(shaderProgram, "backGround"), texNum);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

int main() {
	SDL_Window* window = createWindow("Euchre", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL);
	SDL_GLContext context = SDL_GL_CreateContext(window);

	// Initialize GLEW
	glewExperimental = GL_TRUE;
	glewInit();

	// Initialize Depth Testing
	glEnable(GL_DEPTH_TEST);

	// Create Vertex Array Object
	GLuint vao;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	// Create a Vertex Buffer Object and copy the vertex data to it
	GLuint vbo;
	glGenBuffers(1, &vbo);

	GLfloat vertices[] = {
		-0.5f,  0.5f, 1.0f, 0.0f, 0.0f, // Top-left (x,y,r,g,b)
		0.5f,  0.5f, 0.0f, 1.0f, 0.0f, // Top-right (x,y,r,g,b)
		0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // Bottom-right (x,y,r,g,b)
		-0.5f, -0.5f, 1.0f, 1.0f, 1.0f  // Bottom-left (x,y,r,g,b)
	};

	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	// Create an element array
	GLuint ebo;
	glGenBuffers(1, &ebo);

	GLuint elements[] = { // Describes which set of points are drawn each time
		0, 1, 2,
		2, 3, 0
	};

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);

	GLuint shaderProgram = LoadShaders("./Resources/vertexShader.txt", "./Resources/fragmentShader.txt");
	glUseProgram(shaderProgram);

	// Specify the layout of the vertex data
	GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
	glEnableVertexAttribArray(posAttrib);
	glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);

	GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
	glEnableVertexAttribArray(colAttrib);
	glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
	SDL_Event windowEvent;
	while (true) {
		if (SDL_PollEvent(&windowEvent)) {
			if (windowEvent.type == SDL_QUIT) {
				break;
			}
		}

		// Clear the screen to black
		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

		// Draw a rectangle from the 2 triangles using 6 indices
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

		SDL_GL_SwapWindow(window);
	}
	glDeleteProgram(shaderProgram);

	glDeleteBuffers(1, &ebo);
	glDeleteBuffers(1, &vbo);

	glDeleteVertexArrays(1, &vao);

	SDL_GL_DeleteContext(context);
	return 0;
}<|endoftext|>


<commit_before>// Copyright 2021 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

//===- SPIRVTile.cpp ------------------------------------------------------===//
//
// This pass tiles and Linalg ops with tensor semantics to invocations.
//
//===----------------------------------------------------------------------===//

#include "iree-dialects/Dialect/LinalgExt/IR/LinalgExtOps.h"
#include "iree/compiler/Codegen/Dialect/LoweringConfig.h"
#include "iree/compiler/Codegen/PassDetail.h"
#include "iree/compiler/Codegen/Passes.h"
#include "iree/compiler/Codegen/SPIRV/Utils.h"
#include "iree/compiler/Codegen/Utils/GPUUtils.h"
#include "iree/compiler/Codegen/Utils/MarkerUtils.h"
#include "iree/compiler/Dialect/Flow/IR/FlowOps.h"
#include "llvm/Support/Debug.h"
#include "mlir/Dialect/Affine/IR/AffineOps.h"
#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h"
#include "mlir/Dialect/Linalg/IR/Linalg.h"
#include "mlir/Dialect/Linalg/Transforms/Transforms.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
#include "mlir/Dialect/SCF/Transforms/Transforms.h"
#include "mlir/Dialect/Tensor/Transforms/Transforms.h"
#include "mlir/IR/Matchers.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"

#define DEBUG_TYPE "iree-spirv-tile"

namespace mlir {
namespace iree_compiler {

//===----------------------------------------------------------------------===//
// Tiling patterns
//===----------------------------------------------------------------------===//

/// Populates `patterns` with patterns that tiles convolution/matmul ops with
/// markers.
static void populateTilingReductionPatterns(RewritePatternSet &patterns) {
  MLIRContext *context = patterns.getContext();
  auto getTileSizeFn = [&](OpBuilder &builder, Operation *op) {
    return getTileSizes(builder, op, 2);
  };
  auto tilingOptions = linalg::LinalgTilingOptions()
                           .setLoopType(linalg::LinalgTilingLoopType::Loops)
                           .setTileSizeComputationFunction(getTileSizeFn);
  auto marker = StringAttr::get(context, getTileReductionMarker());
  auto filter = linalg::LinalgTransformationFilter({marker}, llvm::None);

  linalg::TilingPatterns<linalg::BatchMatmulOp, linalg::Conv2DNhwcHwcfOp,
                         linalg::DepthwiseConv2DNhwcHwcOp, linalg::GenericOp,
                         linalg::MatmulOp>::insert(patterns, tilingOptions,
                                                   filter);
}

/// Gets the given `attrOrValue` as an index value by creating constant ops
/// for attributes.
static Value getAsIndexValue(OpFoldResult attrOrValue, OpBuilder &builder,
                             Location loc) {
  IntegerAttr attr;
  if (Value val = attrOrValue.dyn_cast<Value>()) {
    if (val.getType().isIndex()) return val;
    matchPattern(val, m_Constant(&attr));
  } else {
    attr = attrOrValue.get<Attribute>().cast<IntegerAttr>();
  }
  return builder.createOrFold<arith::ConstantIndexOp>(
      loc, attr.getValue().getSExtValue());
}

namespace {

/// Concretizes tensor.pad op's result shape if its source op implements
/// OffsetSizeAndStrideOpInterface. For example, pad(extract_slice).
struct ConcretizePadResultShape final : public OpRewritePattern<tensor::PadOp> {
  using OpRewritePattern::OpRewritePattern;

  LogicalResult matchAndRewrite(tensor::PadOp padOp,
                                PatternRewriter &rewriter) const override {
    // If the result shape is already static, then nothing to do.
    if (padOp.getResultType().hasStaticShape()) return failure();

    int rank = padOp.getResultType().getRank();
    SmallVector<int64_t> staticShape;
    staticShape.reserve(rank);

    auto sourceIfxOp = dyn_cast_or_null<OffsetSizeAndStrideOpInterface>(
        padOp.getSource().getDefiningOp());
    if (!sourceIfxOp) return failure();

    SmallVector<OpFoldResult> lowPad = padOp.getMixedLowPad();
    SmallVector<OpFoldResult> source = sourceIfxOp.getMixedSizes();
    SmallVector<OpFoldResult> highPad = padOp.getMixedHighPad();

    MLIRContext *context = padOp.getContext();
    Location loc = padOp.getLoc();

    AffineExpr sym0, sym1, sym2;
    bindSymbols(context, sym0, sym1, sym2);
    auto addMap = AffineMap::get(0, 3, {sym0 + sym1 + sym2}, context);

    SmallVector<Value, 3> valueSizes;
    for (int dimIndex = 0; dimIndex < rank; ++dimIndex) {
      valueSizes.clear();
      valueSizes.push_back(getAsIndexValue(lowPad[dimIndex], rewriter, loc));
      valueSizes.push_back(getAsIndexValue(source[dimIndex], rewriter, loc));
      valueSizes.push_back(getAsIndexValue(highPad[dimIndex], rewriter, loc));

      // The pad op's result shape is low padding + source size + high padding.
      // Try to see if we can get a constant number by composing and
      // canonicalizing the result. We use affine mechanisms here because
      // generating arithmetic add ops over dim ops won't work, given they are
      // SSA values that would need invoking other patterns to simplify. We
      // cannot invoke patterns in patterns.
      AffineMap map = addMap;
      fullyComposeAffineMapAndOperands(&map, &valueSizes);
      canonicalizeMapAndOperands(&map, &valueSizes);

      auto cstExpr = map.getResult(0).dyn_cast<AffineConstantExpr>();
      // Specially handle the case where we have both dimensions and symbols and
      // they map to the same value, e.g.:
      //   affine_map<(d0, s0) -> (d0 - s0 + 4)>(%v, %v).
      // Due to the restrictions over dimensions and symbols, the above won't
      // simplify. Try to change dimensions for symbols for such cases.
      if (!cstExpr && llvm::is_splat(valueSizes)) {
        int numDims = map.getNumDims();
        int numSyms = map.getNumSymbols();
        DenseMap<AffineExpr, AffineExpr> dimToSymMap;
        for (int i = 0; i < numDims; ++i) {
          dimToSymMap[rewriter.getAffineDimExpr(i)] =
              rewriter.getAffineSymbolExpr(numSyms + i);
        }
        map = map.replace(dimToSymMap, /*numResultDims=*/0,
                          /*numResultSyms=*/numDims + numSyms);

        canonicalizeMapAndOperands(&map, &valueSizes);
        cstExpr = map.getResult(0).dyn_cast<AffineConstantExpr>();
      }
      if (!cstExpr) return failure();

      staticShape.push_back(cstExpr.getValue());
    }

    auto resultType = RankedTensorType::get(
        staticShape, padOp.getResultType().getElementType(),
        padOp.getResultType().getEncoding());

    rewriter.updateRootInPlace(
        padOp, [&]() { padOp.getResult().setType(resultType); });
    return success();
  }
};

}  // namespace

//===----------------------------------------------------------------------===//
// Main pass
//===----------------------------------------------------------------------===//

namespace {

class SPIRVTilePass final : public SPIRVTileBase<SPIRVTilePass> {
 public:
  SPIRVTilePass() = default;
  SPIRVTilePass(const SPIRVTilePass &pass) = default;

  void runOnOperation() override {
    MLIRContext *context = &getContext();
    func::FuncOp funcOp = getOperation();

    // Try to find computation ops which we will use as anchor to tile and fuse
    // again. If there are `scf.if` ops, we have both a fast and slow paths for
    // padding handling. Then we need to scan both regions to discover such
    // computation ops so that we can tile and fuse both regions.
    SmallVector<Operation *> computeOps;
    SmallVector<scf::IfOp, 1> ifOps;
    funcOp.walk([&ifOps](scf::IfOp ifOp) { ifOps.push_back(ifOp); });
    if (ifOps.empty()) {
      SmallVector<LoopTilingAndDistributionInfo> loopInfos;
      if (failed(getComputeOps(funcOp, computeOps, loopInfos))) {
        return signalPassFailure();
      }
      while (computeOps.size() > 1) computeOps.erase(computeOps.begin());
    } else {
      if (ifOps.size() > 1) {
        funcOp.emitError("expected to contain no more than one scf.if ops");
        return signalPassFailure();
      }

      for (Operation &op : llvm::reverse(*ifOps.front().thenBlock())) {
        if (isa<linalg::LinalgOp, IREE::LinalgExt::TiledOpInterface>(op)) {
          computeOps.push_back(&op);
          break;
        }
      }
      if (Block *elseBlock = ifOps.front().elseBlock()) {
        for (Operation &op : llvm::reverse(*elseBlock)) {
          if (isa<linalg::LinalgOp, IREE::LinalgExt::TiledOpInterface>(op)) {
            computeOps.push_back(&op);
            break;
          }
        }
      }
    }
    assert(computeOps.size() <= 2);

    // Now tile the last computation op to invocations and fuse all operand
    // computation ops into the materialized loop nest.
    for (Operation *computeOp : computeOps) {
      auto consumerOp = dyn_cast<linalg::LinalgOp>(computeOp);

      OpBuilder builder(context);
      SmallVector<int64_t> tileSizes = getTileSizes(consumerOp, 1);
      auto identityLoopOrder =
          llvm::to_vector<4>(llvm::seq<int64_t>(0, tileSizes.size()));

      FailureOr<linalg::TileLoopNest> loopNest =
          linalg::tileConsumerAndFuseProducers(builder, consumerOp, tileSizes,
                                               identityLoopOrder, llvm::None);
      if (failed(loopNest)) return signalPassFailure();

      consumerOp->replaceAllUsesWith(loopNest->getRootOpReplacementResults());

      // We don't distribute here; instead, it will be done in a later step
      // after bufferization. So add attributes to the tiled loop nest to
      // indicate that they should be distributed to invocations.
      ArrayRef<scf::ForOp> loops = loopNest->getLoopOps();
      assert(loops.size() <= kNumGPUDims);
      const char *attrName = getSPIRVDistributeAttrName();
      for (int i = loops.size() - 1, dim = 0; i >= 0; --i) {
        loops[i]->setAttr(attrName, builder.getIndexAttr(dim++));
      }
    }

    LLVM_DEBUG({
      llvm::dbgs() << "--- After tiling to invocations ---\n";
      funcOp.print(llvm::dbgs(), OpPrintingFlags().useLocalScope());
      llvm::dbgs() << "\n\n";
    });

    {  // Fuse `tensor.pad` op inside the materalized loop nest too.
      RewritePatternSet patterns(context);
      patterns.insert<linalg::ExtractSliceOfPadTensorSwapPattern>(
          context, [](tensor::ExtractSliceOp) { return false; });
      (void)applyPatternsAndFoldGreedily(funcOp, std::move(patterns));

      LLVM_DEBUG({
        llvm::dbgs() << "--- After fusing padding into consumers ---\n";
        funcOp.print(llvm::dbgs(), OpPrintingFlags().useLocalScope());
        llvm::dbgs() << "\n\n";
      });
    }

    {  // Canonicalize.
      RewritePatternSet patterns =
          linalg::getLinalgTilingCanonicalizationPatterns(context);
      // Pulling in upstream scf.for and affine.min canonicalization patterns.
      // They work on tiled (but not distributed) loops.
      scf::populateSCFForLoopCanonicalizationPatterns(patterns);
      // Pulling in IREE scf.for and affine.min canonicalization patterns.
      // They work on tiled and distributed loops.
      populateFoldAffineMinInDistributedLoopsPatterns(patterns);
      // Pulling in flow.dispatch.tensor.load op canonicalization patterns.
      // Tiling can generate dim ops taking them as operands.
      IREE::Flow::DispatchTensorLoadOp::getCanonicalizationPatterns(patterns,
                                                                    context);
      patterns.add<ConcretizePadResultShape>(context);
      (void)applyPatternsAndFoldGreedily(funcOp, std::move(patterns));

      LLVM_DEBUG({
        llvm::dbgs() << "--- After tiling canonicalization ---\n";
        funcOp.print(llvm::dbgs(), OpPrintingFlags().useLocalScope());
        llvm::dbgs() << "\n\n";
      });
    }

    {  // Set markers to drive tiling reduction dimensions.
      OpBuilder builder(context);
      auto marker = builder.getStringAttr(getTileReductionMarker());
      funcOp.walk([&](linalg::LinalgOp op) {
        if (isa<linalg::ContractionOpInterface>(*op) ||
            isa<linalg::ConvolutionOpInterface>(*op) ||
            isa<linalg::GenericOp>(*op)) {
          op->setAttr(linalg::LinalgTransforms::kLinalgTransformMarker, marker);
        }
      });
    }

    {  // Tile reduction dimensions.
      RewritePatternSet tilingPatterns(&getContext());
      populateTilingReductionPatterns(tilingPatterns);
      if (failed(applyPatternsAndFoldGreedily(funcOp,
                                              std::move(tilingPatterns)))) {
        return signalPassFailure();
      }

      LLVM_DEBUG({
        llvm::dbgs() << "--- After tiling reduction dimensions  ---\n";
        funcOp.print(llvm::dbgs(), OpPrintingFlags().useLocalScope());
        llvm::dbgs() << "\n\n";
      });
    }

    {  // Fuse `tensor.pad` op inside the materalized loop nest too.
      RewritePatternSet patterns(context);
      patterns.insert<linalg::ExtractSliceOfPadTensorSwapPattern>(
          context, [](tensor::ExtractSliceOp) { return false; });
      (void)applyPatternsAndFoldGreedily(funcOp, std::move(patterns));

      LLVM_DEBUG({
        llvm::dbgs() << "--- After fusing padding into consumers ---\n";
        funcOp.print(llvm::dbgs(), OpPrintingFlags().useLocalScope());
        llvm::dbgs() << "\n\n";
      });
    }

    {  // Canonicalize.
      RewritePatternSet patterns =
          linalg::getLinalgTilingCanonicalizationPatterns(context);
      // Pulling in upstream scf.for and affine.min canonicalization patterns.
      // They work on tiled (but not distributed) loops. We only tiled reduction
      // loops previously so this should be fine.
      scf::populateSCFForLoopCanonicalizationPatterns(patterns);
      // Pulling in flow.dispatch.tensor.load op canonicalization patterns.
      // Tiling can generate dim ops taking them as operands.
      IREE::Flow::DispatchTensorLoadOp::getCanonicalizationPatterns(patterns,
                                                                    context);
      patterns.add<ConcretizePadResultShape>(context);
      (void)applyPatternsAndFoldGreedily(funcOp, std::move(patterns));

      LLVM_DEBUG({
        llvm::dbgs() << "--- After tiling canonicalization  ---\n";
        funcOp.print(llvm::dbgs(), OpPrintingFlags().useLocalScope());
        llvm::dbgs() << "\n\n";
      });
    }
  }
};
}  // namespace

std::unique_ptr<OperationPass<func::FuncOp>> createSPIRVTilePass() {
  return std::make_unique<SPIRVTilePass>();
}

}  // namespace iree_compiler
}  // namespace mlir
<commit_msg>[spirv] NFC: print messages to make errors obvious (#9810)<commit_after>// Copyright 2021 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

//===- SPIRVTile.cpp ------------------------------------------------------===//
//
// This pass tiles and Linalg ops with tensor semantics to invocations.
//
//===----------------------------------------------------------------------===//

#include "iree-dialects/Dialect/LinalgExt/IR/LinalgExtOps.h"
#include "iree/compiler/Codegen/Dialect/LoweringConfig.h"
#include "iree/compiler/Codegen/PassDetail.h"
#include "iree/compiler/Codegen/Passes.h"
#include "iree/compiler/Codegen/SPIRV/Utils.h"
#include "iree/compiler/Codegen/Utils/GPUUtils.h"
#include "iree/compiler/Codegen/Utils/MarkerUtils.h"
#include "iree/compiler/Dialect/Flow/IR/FlowOps.h"
#include "llvm/Support/Debug.h"
#include "mlir/Dialect/Affine/IR/AffineOps.h"
#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h"
#include "mlir/Dialect/Linalg/IR/Linalg.h"
#include "mlir/Dialect/Linalg/Transforms/Transforms.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
#include "mlir/Dialect/SCF/Transforms/Transforms.h"
#include "mlir/Dialect/Tensor/Transforms/Transforms.h"
#include "mlir/IR/Matchers.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"

#define DEBUG_TYPE "iree-spirv-tile"

namespace mlir {
namespace iree_compiler {

//===----------------------------------------------------------------------===//
// Tiling patterns
//===----------------------------------------------------------------------===//

/// Populates `patterns` with patterns that tiles convolution/matmul ops with
/// markers.
static void populateTilingReductionPatterns(RewritePatternSet &patterns) {
  MLIRContext *context = patterns.getContext();
  auto getTileSizeFn = [&](OpBuilder &builder, Operation *op) {
    return getTileSizes(builder, op, 2);
  };
  auto tilingOptions = linalg::LinalgTilingOptions()
                           .setLoopType(linalg::LinalgTilingLoopType::Loops)
                           .setTileSizeComputationFunction(getTileSizeFn);
  auto marker = StringAttr::get(context, getTileReductionMarker());
  auto filter = linalg::LinalgTransformationFilter({marker}, llvm::None);

  linalg::TilingPatterns<linalg::BatchMatmulOp, linalg::Conv2DNhwcHwcfOp,
                         linalg::DepthwiseConv2DNhwcHwcOp, linalg::GenericOp,
                         linalg::MatmulOp>::insert(patterns, tilingOptions,
                                                   filter);
}

/// Gets the given `attrOrValue` as an index value by creating constant ops
/// for attributes.
static Value getAsIndexValue(OpFoldResult attrOrValue, OpBuilder &builder,
                             Location loc) {
  IntegerAttr attr;
  if (Value val = attrOrValue.dyn_cast<Value>()) {
    if (val.getType().isIndex()) return val;
    matchPattern(val, m_Constant(&attr));
  } else {
    attr = attrOrValue.get<Attribute>().cast<IntegerAttr>();
  }
  return builder.createOrFold<arith::ConstantIndexOp>(
      loc, attr.getValue().getSExtValue());
}

namespace {

/// Concretizes tensor.pad op's result shape if its source op implements
/// OffsetSizeAndStrideOpInterface. For example, pad(extract_slice).
struct ConcretizePadResultShape final : public OpRewritePattern<tensor::PadOp> {
  using OpRewritePattern::OpRewritePattern;

  LogicalResult matchAndRewrite(tensor::PadOp padOp,
                                PatternRewriter &rewriter) const override {
    // If the result shape is already static, then nothing to do.
    if (padOp.getResultType().hasStaticShape()) return failure();

    int rank = padOp.getResultType().getRank();
    SmallVector<int64_t> staticShape;
    staticShape.reserve(rank);

    auto sourceIfxOp = dyn_cast_or_null<OffsetSizeAndStrideOpInterface>(
        padOp.getSource().getDefiningOp());
    if (!sourceIfxOp) return failure();

    SmallVector<OpFoldResult> lowPad = padOp.getMixedLowPad();
    SmallVector<OpFoldResult> source = sourceIfxOp.getMixedSizes();
    SmallVector<OpFoldResult> highPad = padOp.getMixedHighPad();

    MLIRContext *context = padOp.getContext();
    Location loc = padOp.getLoc();

    AffineExpr sym0, sym1, sym2;
    bindSymbols(context, sym0, sym1, sym2);
    auto addMap = AffineMap::get(0, 3, {sym0 + sym1 + sym2}, context);

    SmallVector<Value, 3> valueSizes;
    for (int dimIndex = 0; dimIndex < rank; ++dimIndex) {
      valueSizes.clear();
      valueSizes.push_back(getAsIndexValue(lowPad[dimIndex], rewriter, loc));
      valueSizes.push_back(getAsIndexValue(source[dimIndex], rewriter, loc));
      valueSizes.push_back(getAsIndexValue(highPad[dimIndex], rewriter, loc));

      // The pad op's result shape is low padding + source size + high padding.
      // Try to see if we can get a constant number by composing and
      // canonicalizing the result. We use affine mechanisms here because
      // generating arithmetic add ops over dim ops won't work, given they are
      // SSA values that would need invoking other patterns to simplify. We
      // cannot invoke patterns in patterns.
      AffineMap map = addMap;
      fullyComposeAffineMapAndOperands(&map, &valueSizes);
      canonicalizeMapAndOperands(&map, &valueSizes);

      auto cstExpr = map.getResult(0).dyn_cast<AffineConstantExpr>();
      // Specially handle the case where we have both dimensions and symbols and
      // they map to the same value, e.g.:
      //   affine_map<(d0, s0) -> (d0 - s0 + 4)>(%v, %v).
      // Due to the restrictions over dimensions and symbols, the above won't
      // simplify. Try to change dimensions for symbols for such cases.
      if (!cstExpr && llvm::is_splat(valueSizes)) {
        int numDims = map.getNumDims();
        int numSyms = map.getNumSymbols();
        DenseMap<AffineExpr, AffineExpr> dimToSymMap;
        for (int i = 0; i < numDims; ++i) {
          dimToSymMap[rewriter.getAffineDimExpr(i)] =
              rewriter.getAffineSymbolExpr(numSyms + i);
        }
        map = map.replace(dimToSymMap, /*numResultDims=*/0,
                          /*numResultSyms=*/numDims + numSyms);

        canonicalizeMapAndOperands(&map, &valueSizes);
        cstExpr = map.getResult(0).dyn_cast<AffineConstantExpr>();
      }
      if (!cstExpr) return failure();

      staticShape.push_back(cstExpr.getValue());
    }

    auto resultType = RankedTensorType::get(
        staticShape, padOp.getResultType().getElementType(),
        padOp.getResultType().getEncoding());

    rewriter.updateRootInPlace(
        padOp, [&]() { padOp.getResult().setType(resultType); });
    return success();
  }
};

}  // namespace

//===----------------------------------------------------------------------===//
// Main pass
//===----------------------------------------------------------------------===//

namespace {

class SPIRVTilePass final : public SPIRVTileBase<SPIRVTilePass> {
 public:
  SPIRVTilePass() = default;
  SPIRVTilePass(const SPIRVTilePass &pass) = default;

  void runOnOperation() override {
    MLIRContext *context = &getContext();
    func::FuncOp funcOp = getOperation();

    // Try to find computation ops which we will use as anchor to tile and fuse
    // again. If there are `scf.if` ops, we have both a fast and slow paths for
    // padding handling. Then we need to scan both regions to discover such
    // computation ops so that we can tile and fuse both regions.
    SmallVector<Operation *> computeOps;
    SmallVector<scf::IfOp, 1> ifOps;
    funcOp.walk([&ifOps](scf::IfOp ifOp) { ifOps.push_back(ifOp); });
    if (ifOps.empty()) {
      SmallVector<LoopTilingAndDistributionInfo> loopInfos;
      if (failed(getComputeOps(funcOp, computeOps, loopInfos))) {
        funcOp.emitOpError("does not contain compute ops");
        return signalPassFailure();
      }
      while (computeOps.size() > 1) computeOps.erase(computeOps.begin());
    } else {
      if (ifOps.size() > 1) {
        funcOp.emitError("expected to contain no more than one scf.if ops");
        return signalPassFailure();
      }

      for (Operation &op : llvm::reverse(*ifOps.front().thenBlock())) {
        if (isa<linalg::LinalgOp, IREE::LinalgExt::TiledOpInterface>(op)) {
          computeOps.push_back(&op);
          break;
        }
      }
      if (Block *elseBlock = ifOps.front().elseBlock()) {
        for (Operation &op : llvm::reverse(*elseBlock)) {
          if (isa<linalg::LinalgOp, IREE::LinalgExt::TiledOpInterface>(op)) {
            computeOps.push_back(&op);
            break;
          }
        }
      }
    }
    assert(computeOps.size() <= 2);

    // Now tile the last computation op to invocations and fuse all operand
    // computation ops into the materialized loop nest.
    for (Operation *computeOp : computeOps) {
      auto consumerOp = dyn_cast<linalg::LinalgOp>(computeOp);

      OpBuilder builder(context);
      SmallVector<int64_t> tileSizes = getTileSizes(consumerOp, 1);
      auto identityLoopOrder =
          llvm::to_vector<4>(llvm::seq<int64_t>(0, tileSizes.size()));

      FailureOr<linalg::TileLoopNest> loopNest =
          linalg::tileConsumerAndFuseProducers(builder, consumerOp, tileSizes,
                                               identityLoopOrder, llvm::None);
      if (failed(loopNest)) {
        consumerOp.emitOpError("failed tiling and fusing producers");
        return signalPassFailure();
      }

      consumerOp->replaceAllUsesWith(loopNest->getRootOpReplacementResults());

      // We don't distribute here; instead, it will be done in a later step
      // after bufferization. So add attributes to the tiled loop nest to
      // indicate that they should be distributed to invocations.
      ArrayRef<scf::ForOp> loops = loopNest->getLoopOps();
      assert(loops.size() <= kNumGPUDims);
      const char *attrName = getSPIRVDistributeAttrName();
      for (int i = loops.size() - 1, dim = 0; i >= 0; --i) {
        loops[i]->setAttr(attrName, builder.getIndexAttr(dim++));
      }
    }

    LLVM_DEBUG({
      llvm::dbgs() << "--- After tiling to invocations ---\n";
      funcOp.print(llvm::dbgs(), OpPrintingFlags().useLocalScope());
      llvm::dbgs() << "\n\n";
    });

    {  // Fuse `tensor.pad` op inside the materalized loop nest too.
      RewritePatternSet patterns(context);
      patterns.insert<linalg::ExtractSliceOfPadTensorSwapPattern>(
          context, [](tensor::ExtractSliceOp) { return false; });
      (void)applyPatternsAndFoldGreedily(funcOp, std::move(patterns));

      LLVM_DEBUG({
        llvm::dbgs() << "--- After fusing padding into consumers ---\n";
        funcOp.print(llvm::dbgs(), OpPrintingFlags().useLocalScope());
        llvm::dbgs() << "\n\n";
      });
    }

    {  // Canonicalize.
      RewritePatternSet patterns =
          linalg::getLinalgTilingCanonicalizationPatterns(context);
      // Pulling in upstream scf.for and affine.min canonicalization patterns.
      // They work on tiled (but not distributed) loops.
      scf::populateSCFForLoopCanonicalizationPatterns(patterns);
      // Pulling in IREE scf.for and affine.min canonicalization patterns.
      // They work on tiled and distributed loops.
      populateFoldAffineMinInDistributedLoopsPatterns(patterns);
      // Pulling in flow.dispatch.tensor.load op canonicalization patterns.
      // Tiling can generate dim ops taking them as operands.
      IREE::Flow::DispatchTensorLoadOp::getCanonicalizationPatterns(patterns,
                                                                    context);
      patterns.add<ConcretizePadResultShape>(context);
      (void)applyPatternsAndFoldGreedily(funcOp, std::move(patterns));

      LLVM_DEBUG({
        llvm::dbgs() << "--- After tiling canonicalization ---\n";
        funcOp.print(llvm::dbgs(), OpPrintingFlags().useLocalScope());
        llvm::dbgs() << "\n\n";
      });
    }

    {  // Set markers to drive tiling reduction dimensions.
      OpBuilder builder(context);
      auto marker = builder.getStringAttr(getTileReductionMarker());
      funcOp.walk([&](linalg::LinalgOp op) {
        if (isa<linalg::ContractionOpInterface>(*op) ||
            isa<linalg::ConvolutionOpInterface>(*op) ||
            isa<linalg::GenericOp>(*op)) {
          op->setAttr(linalg::LinalgTransforms::kLinalgTransformMarker, marker);
        }
      });
    }

    {  // Tile reduction dimensions.
      RewritePatternSet tilingPatterns(&getContext());
      populateTilingReductionPatterns(tilingPatterns);
      if (failed(applyPatternsAndFoldGreedily(funcOp,
                                              std::move(tilingPatterns)))) {
        funcOp.emitError("failed tiling reduction dimensions");
        return signalPassFailure();
      }

      LLVM_DEBUG({
        llvm::dbgs() << "--- After tiling reduction dimensions  ---\n";
        funcOp.print(llvm::dbgs(), OpPrintingFlags().useLocalScope());
        llvm::dbgs() << "\n\n";
      });
    }

    {  // Fuse `tensor.pad` op inside the materalized loop nest too.
      RewritePatternSet patterns(context);
      patterns.insert<linalg::ExtractSliceOfPadTensorSwapPattern>(
          context, [](tensor::ExtractSliceOp) { return false; });
      (void)applyPatternsAndFoldGreedily(funcOp, std::move(patterns));

      LLVM_DEBUG({
        llvm::dbgs() << "--- After fusing padding into consumers ---\n";
        funcOp.print(llvm::dbgs(), OpPrintingFlags().useLocalScope());
        llvm::dbgs() << "\n\n";
      });
    }

    {  // Canonicalize.
      RewritePatternSet patterns =
          linalg::getLinalgTilingCanonicalizationPatterns(context);
      // Pulling in upstream scf.for and affine.min canonicalization patterns.
      // They work on tiled (but not distributed) loops. We only tiled reduction
      // loops previously so this should be fine.
      scf::populateSCFForLoopCanonicalizationPatterns(patterns);
      // Pulling in flow.dispatch.tensor.load op canonicalization patterns.
      // Tiling can generate dim ops taking them as operands.
      IREE::Flow::DispatchTensorLoadOp::getCanonicalizationPatterns(patterns,
                                                                    context);
      patterns.add<ConcretizePadResultShape>(context);
      (void)applyPatternsAndFoldGreedily(funcOp, std::move(patterns));

      LLVM_DEBUG({
        llvm::dbgs() << "--- After tiling canonicalization  ---\n";
        funcOp.print(llvm::dbgs(), OpPrintingFlags().useLocalScope());
        llvm::dbgs() << "\n\n";
      });
    }
  }
};
}  // namespace

std::unique_ptr<OperationPass<func::FuncOp>> createSPIRVTilePass() {
  return std::make_unique<SPIRVTilePass>();
}

}  // namespace iree_compiler
}  // namespace mlir
<|endoftext|>


<commit_before>#include "FASTAFormat.h"
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<string>

FASTAFormat::FASTAFormat(void)
{
	this->sequenceID = "";
	this->description = "";
	this->sequence = "";
}

FASTAFormat::~FASTAFormat(void)
{
	this->sequenceID.clear();
	this->description.clear();
	this->sequence.clear();
}

void FASTAFormat::addHeader(string header)
{
	string id = header.substr(0, header.find_first_of(' '));
	string desc = header.substr(header.find_first_of(' '), header.npos);
	this->sequenceID = id;
	this->description = desc;
}

string FASTAFormat::getSequenceID()
{
	return this->sequenceID;
}

void FASTAFormat::addSequence(string seq)
{
	this->sequence = seq;
}

string FASTAFormat::getSequence()
{
	return this->sequence;
}

const char* FASTAFormat::sequenceToCharArray()
{
	return this->sequence.c_str();
}

void FASTAFormat::readFASTAFile(string filePath)
{
	string path = "FASTA_example.txt";
	ifstream file(path);
    string str;
	if(file == NULL){
		cerr<<"Error during file opening!"<<endl;
		exit(-1);
	}
	while (getline(file, str))
    {
		char firstChar = str.at(0);
		if(firstChar == '>'){
			this->addHeader(str.substr(1,str.npos));
		}
		else{
			this->sequence.append(str);
		}
    }
	file.close();
}
<commit_msg>Ispravak metode za čitanje file-a!<commit_after>#include "FASTAFormat.h"
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<string>

FASTAFormat::FASTAFormat(void)
{
	this->sequenceID = "";
	this->description = "";
	this->sequence = "";
}

FASTAFormat::~FASTAFormat(void)
{
	this->sequenceID.clear();
	this->description.clear();
	this->sequence.clear();
}

void FASTAFormat::addHeader(string header)
{
	string id = header.substr(0, header.find_first_of(' '));
	string desc = header.substr(header.find_first_of(' '), header.npos);
	this->sequenceID = id;
	this->description = desc;
}

string FASTAFormat::getSequenceID()
{
	return this->sequenceID;
}

void FASTAFormat::addSequence(string seq)
{
	this->sequence = seq;
}

string FASTAFormat::getSequence()
{
	return this->sequence;
}

const char* FASTAFormat::sequenceToCharArray()
{
	return this->sequence.c_str();
}

void FASTAFormat::readFASTAFile(string filePath)
{
	ifstream file(filePath);
    string str;
	if(file == NULL){
		cerr<<"Error during file opening!"<<endl;
		exit(-1);
	}
	while (getline(file, str))
    {
		char firstChar = str.at(0);
		if(firstChar == '>'){
			this->addHeader(str.substr(1,str.npos));
		}
		else{
			this->sequence.append(str);
		}
    }
	file.close();
}
<|endoftext|>