<commit_before>//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Fri Jan 29 18:58:32 PST 2021
// Last Modified: Sun Jan 31 01:22:56 PST 2021
// Filename:      humxml.cpp
// URL:           https://github.com/craigsapp/humlib/blob/master/cli/humxml.cpp
// Syntax:        C++11
// vim:           ts=3 noexpandtab nowrap
//
// Description:   Reveal data structure of Humdrum file and internal parameters.
//                Optionally run various alysises of the data to calculate
//                content-based parameters.
//

#include "humlib.h"

using namespace std;
using namespace hum;

int main(int argc, char **argv) {
	Options options;
	options.define("A|all=b",              "do all analyses");
	options.define("a|accidentals=b",      "analyze visual accidental states");
	options.define("p|phrases=b",          "analyze phrases");
	options.define("r|rest-positions=b",   "analyze rest positions");
	options.define("s|slurs=b",            "analyze slurs");
	options.define("t|ties=b",             "analyze ties");
	options.define("x|text-repetitions=b", "analyze text repetitions");

	// Processing not run automatically with -A option:

	options.process(argc, argv);

	bool allQ = options.getBoolean("all");

	HumdrumFile infile;
	if (options.getArgCount() == 0) {
		infile.read(cin);
	} else {
		infile.read(options.getArg(1));
	}

	// Do content analysis of the data (mostly **kern data):
	if (allQ || options.getBoolean("accidentals")) {
		// This analysis calculates the visible state of
		// accidentals for **kern data notes for conversion
		// to graphical CMN music notation. **kern data
		// encodes the sounding accidentals.  These may
		// be shown in notation or hidden due to the
		// key signature or previous notes in the measure,
		// or modified by !LO:N:acc parameters. An "X" after
		// an accidental will force it to be displayed, and
		// a "y" after an accidental will force it to
		// be hidden.
		infile.analyzeKernAccidentals();
	}
	if (allQ || options.getBoolean("phrases")) {
		// Link phrase endings to each other.  Phrase start
		// is "{" and phrase end is "}".  Phrase markings
		// are typically for analytic purposes, with slurs
		// usually used for phasing slurs.  Phrases that cross
		// other phrases are prefixed with one or more "&".
		infile.analyzeSlurs();
	}
	if (allQ || options.getBoolean("rest-positions")) {
		// Specify the vertical position of rests on the staff.
		infile.analyzeRestPositions();
	}
	if (allQ || options.getBoolean("slurs")) {
		// Link slur endings to each other.  Slur start is
		// "(" and slur end is ")".  Slurs that cross other
		// active slurs are prefixed with one or more "&".
		infile.analyzeSlurs();
	}
	if (allQ || options.getBoolean("ties")) {
		// Link tie endings to each other.  Tie starts
		// are "[", tie continuations (a end and a start on the
		// same note are "_", and tie ends are "]".  When the
		// tie character is doubled, then that is a discontinuous
		// tie, where the two tied notes are not melocially adjacent
		// (this can happen in music to simplify the notatation
		// of written out arpeggiations).
		// This analysis seems to not generate HumHash data, but
		// proably adjusted fixed variables for HumdrumTokens.
		infile.analyzeKernTies();
	}
	if (allQ || options.getBoolean("text-repetitions")) {
		// Something to do with **text text-repeat markers.
		infile.analyzeTextRepetition();
	}

	infile.printXml();
}

<commit_msg>Update humxml.cpp<commit_after>//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Fri Jan 29 18:58:32 PST 2021
// Last Modified: Sun Jan 31 01:22:56 PST 2021
// Filename:      humxml.cpp
// URL:           https://github.com/craigsapp/humlib/blob/master/cli/humxml.cpp
// Syntax:        C++11
// vim:           ts=3 noexpandtab nowrap
//
// Description:   Reveal data structure of Humdrum file and internal parameters.
//                Optionally run various analyses of the data to calculate
//                content-based parameters.
//

#include "humlib.h"

using namespace std;
using namespace hum;

int main(int argc, char **argv) {
	Options options;
	options.define("A|all=b",              "do all analyses");
	options.define("a|accidentals=b",      "analyze visual accidental states");
	options.define("p|phrases=b",          "analyze phrases");
	options.define("r|rest-positions=b",   "analyze rest positions");
	options.define("s|slurs=b",            "analyze slurs");
	options.define("t|ties=b",             "analyze ties");
	options.define("x|text-repetitions=b", "analyze text repetitions");

	// Processing not run automatically with -A option:

	options.process(argc, argv);

	bool allQ = options.getBoolean("all");

	HumdrumFile infile;
	if (options.getArgCount() == 0) {
		infile.read(cin);
	} else {
		infile.read(options.getArg(1));
	}

	// Do content analysis of the data (mostly **kern data):
	if (allQ || options.getBoolean("accidentals")) {
		// This analysis calculates the visible state of
		// accidentals for **kern data notes for conversion
		// to graphical CMN music notation. **kern data
		// encodes the sounding accidentals.  These may
		// be shown in notation or hidden due to the
		// key signature or previous notes in the measure,
		// or modified by !LO:N:acc parameters. An "X" after
		// an accidental will force it to be displayed, and
		// a "y" after an accidental will force it to
		// be hidden.
		infile.analyzeKernAccidentals();
	}
	if (allQ || options.getBoolean("phrases")) {
		// Link phrase endings to each other.  Phrase start
		// is "{" and phrase end is "}".  Phrase markings
		// are typically for analytic purposes, with slurs
		// usually used for phasing slurs.  Phrases that cross
		// other phrases are prefixed with one or more "&".
		infile.analyzeSlurs();
	}
	if (allQ || options.getBoolean("rest-positions")) {
		// Specify the vertical position of rests on the staff.
		infile.analyzeRestPositions();
	}
	if (allQ || options.getBoolean("slurs")) {
		// Link slur endings to each other.  Slur start is
		// "(" and slur end is ")".  Slurs that cross other
		// active slurs are prefixed with one or more "&".
		infile.analyzeSlurs();
	}
	if (allQ || options.getBoolean("ties")) {
		// Link tie endings to each other.  Tie starts
		// are "[", tie continuations (a end and a start on the
		// same note are "_", and tie ends are "]".  When the
		// tie character is doubled, then that is a discontinuous
		// tie, where the two tied notes are not melocially adjacent
		// (this can happen in music to simplify the notatation
		// of written out arpeggiations).
		// This analysis seems to not generate HumHash data, but
		// proably adjusted fixed variables for HumdrumTokens.
		infile.analyzeKernTies();
	}
	if (allQ || options.getBoolean("text-repetitions")) {
		// Something to do with **text text-repeat markers.
		infile.analyzeTextRepetition();
	}

	infile.printXml();
}

<|endoftext|>


<commit_before>// Copyright (c) 2021 Roberto Raggi <roberto.raggi@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <cxx/lexer.h>
#include <fmt/format.h>
#include <utf8.h>

#include <cassert>
#include <cctype>
#include <unordered_map>

#include "keywords-priv.h"

namespace cxx {

inline namespace {

enum struct EncodingPrefix { kNone, kWide, kUtf8, kUtf16, kUtf32 };

const std::unordered_map<std::string_view, std::tuple<EncodingPrefix, bool>>
    kStringLiteralPrefixes{
        {"R", {EncodingPrefix::kNone, true}},
        {"L", {EncodingPrefix::kWide, false}},
        {"u8", {EncodingPrefix::kUtf8, false}},
        {"u", {EncodingPrefix::kUtf16, false}},
        {"U", {EncodingPrefix::kUtf32, false}},
        {"LR", {EncodingPrefix::kWide, true}},
        {"u8R", {EncodingPrefix::kUtf8, true}},
        {"uR", {EncodingPrefix::kUtf16, true}},
        {"UR", {EncodingPrefix::kUtf32, true}},
    };

const std::unordered_map<std::string_view, EncodingPrefix>
    kCharacterLiteralPrefixes{
        {"L", EncodingPrefix::kWide},
        {"u8", EncodingPrefix::kUtf8},
        {"u", EncodingPrefix::kUtf16},
        {"U", EncodingPrefix::kUtf32},
    };

inline bool is_idcont(int ch) {
  return ch == '_' || std::isalnum((unsigned char)ch);
}

template <typename It>
inline uint32_t peekNext(It it, It end) {
  while (it + 1 < end && *it == '\\' && it[1] == '\n') it += 2;
  return it < end ? utf8::peek_next(it, end) : 0;
}

template <typename It>
inline void readNext(It& it, It end) {
  while (it + 1 < end && *it == '\\' && it[1] == '\n') it += 2;
  if (it < end) utf8::next(it, end);
}

template <typename It>
inline void advance(It& it, int n, It end) {
  if (n > 0) {
    while (it < end && n--) readNext(it, end);
  } else {
    throw std::runtime_error("offset not valid");
  }
}

}  // namespace

Lexer::Lexer(const std::string_view& source)
    : source_(source), pos_(cbegin(source_)), end_(cend(source_)) {
  currentChar_ = pos_ < end_ ? peekNext(pos_, end_) : 0;
}

void Lexer::consume() {
  readNext(pos_, end_);
  currentChar_ = pos_ < end_ ? peekNext(pos_, end_) : 0;
}

void Lexer::consume(int n) {
  advance(pos_, n, end_);
  currentChar_ = pos_ < end_ ? peekNext(pos_, end_) : 0;
}

uint32_t Lexer::LA(int n) const {
  auto it = pos_;
  advance(it, n, end_);
  return it < end_ ? peekNext(it, end_) : 0;
}

TokenKind Lexer::readToken() {
  const auto hasMoreChars = skipSpaces();

  tokenIsClean_ = true;
  tokenPos_ = pos_ - cbegin(source_);
  text_.clear();

  if (!hasMoreChars) return TokenKind::T_EOF_SYMBOL;

  const auto ch = LA();

  if (std::isdigit(ch)) {
    bool integer_literal = true;
    while (pos_ != end_) {
      const auto ch = LA();
      if (pos_ + 1 < end_ &&
          (ch == 'e' || ch == 'E' || ch == 'p' || ch == 'P') &&
          (LA(1) == '+' || LA(1) == '-')) {
        consume(2);
        integer_literal = false;
      } else if (pos_ + 1 < end_ && ch == '\'' && is_idcont(LA(1))) {
        consume();
      } else if (is_idcont(ch)) {
        consume();
      } else if (ch == '.') {
        consume();
        integer_literal = false;
      } else {
        break;
      }
    }
    return integer_literal ? TokenKind::T_INTEGER_LITERAL
                           : TokenKind::T_FLOATING_POINT_LITERAL;
  }

  EncodingPrefix encodingPrefix = EncodingPrefix::kNone;

  bool isRawStringLiteral = false;

  if (std::isalpha(ch) || ch == '_') {
    do {
      text_ += (char)LA();
      consume();
    } while (pos_ != end_ && is_idcont(LA()));

    bool isStringOrCharacterLiteral = false;

    if (pos_ != end_ && LA() == '"') {
      auto it = kStringLiteralPrefixes.find(text_);
      if (it != kStringLiteralPrefixes.end()) {
        auto [enc, raw] = it->second;
        encodingPrefix = enc;
        isRawStringLiteral = raw;
        isStringOrCharacterLiteral = true;
      }
    } else if (pos_ != end_ && LA() == '\'') {
      auto it = kCharacterLiteralPrefixes.find(text_);
      if (it != kCharacterLiteralPrefixes.end()) {
        encodingPrefix = it->second;
        isStringOrCharacterLiteral = true;
      }
    }

    if (!isStringOrCharacterLiteral) {
      tokenIsClean_ = text_.length() == tokenLength();

      return !preprocessing_ ? classify(text_.c_str(), int(text_.length()))
                             : TokenKind::T_IDENTIFIER;
    }
  }

  if (LA() == '"') {
    consume();

    std::string_view delimiter;
    const auto startDelimiter = pos_;
    auto endDelimiter = pos_;

    if (isRawStringLiteral) {
      for (; pos_ != end_; consume()) {
        const auto ch = LA();
        if (ch == '(' || ch == '"' || ch == '\\' || ch == '\n') break;
      }
      endDelimiter = pos_;
      delimiter = source_.substr(startDelimiter - cbegin(source_),
                                 endDelimiter - startDelimiter);
    }

    while (pos_ != end_) {
      if (LA() == '"') {
        consume();

        if (!isRawStringLiteral) break;

        const auto S = startDelimiter - pos_;
        const auto N = endDelimiter - startDelimiter;

        if (LA(N - 2) == ')') {
          bool didMatch = true;
          for (int i = 0; i < N; ++i) {
            if (LA(S + i) != LA(N - i - 1)) {
              didMatch = false;
              break;
            }
          }
          if (didMatch) break;
        }
      } else if (pos_ + 1 < end_ && LA() == '\\') {
        consume(2);
      } else {
        consume();
      }
    }
    bool ud = false;
    if (std::isalpha(LA()) || LA() == '_') {
      ud = true;
      do {
        consume();
      } while (pos_ != end_ && is_idcont(LA()));
    }
    return !ud ? TokenKind::T_STRING_LITERAL
               : TokenKind::T_USER_DEFINED_STRING_LITERAL;
  }

  if (LA() == '\'') {
    consume();
    while (pos_ != end_ && LA() != '\'') {
      if (pos_ + 1 < end_ && LA() == '\\') {
        consume(2);
      } else {
        consume();
      }
    }
    if (LA() == '\'') {
      consume();
    }

    return TokenKind::T_CHARACTER_LITERAL;
  }

  if (pos_ + 1 < end_ && LA() == '.' && std::isdigit(LA(1))) {
    consume();
    while (pos_ != end_) {
      const auto ch = LA();
      if (pos_ + 1 < end_ &&
          (ch == 'e' || ch == 'E' || ch == 'p' || ch == 'P') &&
          (LA(1) == '+' || LA(1) == '-')) {
        consume(2);
      } else if (pos_ + 1 < end_ && ch == '\'' && is_idcont(LA(1))) {
        consume();
      } else if (is_idcont(ch)) {
        consume();
      } else {
        break;
      }
    }
    return TokenKind::T_FLOATING_POINT_LITERAL;
  }

  consume();

  switch (ch) {
    case '#':
      if (pos_ != end_ && LA() == '#') {
        consume();
        return TokenKind::T_HASH_HASH;
      }
      return TokenKind::T_HASH;

    case '=':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_EQUAL_EQUAL;
      }
      return TokenKind::T_EQUAL;

    case ',':
      return TokenKind::T_COMMA;

    case '~':
      return TokenKind::T_TILDE;

    case '{':
      return TokenKind::T_LBRACE;

    case '}':
      return TokenKind::T_RBRACE;

    case '[':
      return TokenKind::T_LBRACKET;

    case ']':
      return TokenKind::T_RBRACKET;

    case '(':
      return TokenKind::T_LPAREN;

    case ')':
      return TokenKind::T_RPAREN;

    case ';':
      return TokenKind::T_SEMICOLON;

    case ':':
      if (pos_ != end_ && LA() == ':') {
        consume();
        return TokenKind::T_COLON_COLON;
      }
      return TokenKind::T_COLON;

    case '.':
      if (pos_ + 1 < end_ && LA() == '.' && LA(1) == '.') {
        consume(2);
        return TokenKind::T_DOT_DOT_DOT;
      } else if (pos_ != end_ && LA() == '*') {
        consume();
        return TokenKind::T_DOT_STAR;
      }
      return TokenKind::T_DOT;

    case '?':
      return TokenKind::T_QUESTION;

    case '*':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_STAR_EQUAL;
      }
      return TokenKind::T_STAR;

    case '%':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_PERCENT_EQUAL;
      }
      return TokenKind::T_PERCENT;

    case '^':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_CARET_EQUAL;
      }
      return TokenKind::T_CARET;

    case '&':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_AMP_EQUAL;
      } else if (pos_ != end_ && LA() == '&') {
        consume();
        return TokenKind::T_AMP_AMP;
      }
      return TokenKind::T_AMP;

    case '|':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_BAR_EQUAL;
      } else if (pos_ != end_ && LA() == '|') {
        consume();
        return TokenKind::T_BAR_BAR;
      }
      return TokenKind::T_BAR;

    case '!':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_EXCLAIM_EQUAL;
      }
      return TokenKind::T_EXCLAIM;

    case '+':
      if (pos_ != end_ && LA() == '+') {
        consume();
        return TokenKind::T_PLUS_PLUS;
      } else if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_PLUS_EQUAL;
      }
      return TokenKind::T_PLUS;

    case '-':
      if (pos_ != end_ && LA() == '-') {
        consume();
        return TokenKind::T_MINUS_MINUS;
      } else if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_MINUS_EQUAL;
      } else if (pos_ != end_ && LA() == '>') {
        consume();
        if (pos_ != end_ && LA() == '*') {
          consume();
          return TokenKind::T_MINUS_GREATER_STAR;
        } else {
          return TokenKind::T_MINUS_GREATER;
        }
      }
      return TokenKind::T_MINUS;

    case '<':
      if (pos_ != end_ && LA() == '=') {
        consume();
        if (pos_ != end_ && LA() == '>') {
          consume();
          return TokenKind::T_LESS_EQUAL_GREATER;
        }
        return TokenKind::T_LESS_EQUAL;
      } else if (pos_ != end_ && LA() == '<') {
        consume();
        if (pos_ != end_ && LA() == '=') {
          consume();
          return TokenKind::T_LESS_LESS_EQUAL;
        }
        return TokenKind::T_LESS_LESS;
      }
      return TokenKind::T_LESS;

    case '>':
      if (preprocessing_) {
        if (pos_ != end_ && LA() == '=') {
          consume();
          return TokenKind::T_GREATER_EQUAL;
        } else if (pos_ != end_ && LA() == '>') {
          consume();
          if (pos_ != end_ && LA() == '=') {
            consume();
            return TokenKind::T_GREATER_GREATER_EQUAL;
          }
          return TokenKind::T_GREATER_GREATER;
        }
      } else if (LA() == '>') {
        TokenKind k = TokenKind::T_GREATER_GREATER;

        if (LA(1) == '=') k = TokenKind::T_GREATER_GREATER_EQUAL;

        tokenValue_.tokenKindValue = k;
      } else if (LA() == '=') {
        tokenValue_.tokenKindValue = TokenKind::T_GREATER_EQUAL;
      }

      return TokenKind::T_GREATER;

    case '/':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_SLASH_EQUAL;
      }
      return TokenKind::T_SLASH;
  }

  return TokenKind::T_ERROR;
}  // namespace cxx

bool Lexer::skipSpaces() {
  tokenLeadingSpace_ = leadingSpace_;
  tokenStartOfLine_ = startOfLine_;

  while (pos_ != end_) {
    const auto ch = LA();

    if (std::isspace(ch)) {
      if (ch == '\n') {
        tokenStartOfLine_ = true;
        tokenLeadingSpace_ = false;
      } else {
        tokenLeadingSpace_ = true;
      }
      consume();
    } else if (pos_ + 1 < end_ && ch == '/' && LA(1) == '/') {
      consume(2);
      for (; pos_ != end_; consume()) {
        if (pos_ != end_ && LA() == '\n') {
          break;
        }
      }
    } else if (pos_ + 1 < end_ && ch == '/' && LA(1) == '*') {
      while (pos_ != end_) {
        if (pos_ + 1 < end_ && LA() == '*' && LA(1) == '/') {
          consume(2);
          break;
        } else {
          consume();
        }
      }
      // unexpected eof
    } else {
      break;
    }
  }

  leadingSpace_ = false;
  startOfLine_ = false;

  return pos_ != end_;
}

TokenKind Lexer::classifyKeyword(const std::string_view& text) {
  return classify(text.data(), int(text.size()));
}

}  // namespace cxx
<commit_msg>Handle CRLF eols following merge-line tokens<commit_after>// Copyright (c) 2021 Roberto Raggi <roberto.raggi@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <cxx/lexer.h>
#include <fmt/format.h>
#include <utf8.h>

#include <cassert>
#include <cctype>
#include <unordered_map>

#include "keywords-priv.h"

namespace cxx {

inline namespace {

enum struct EncodingPrefix { kNone, kWide, kUtf8, kUtf16, kUtf32 };

const std::unordered_map<std::string_view, std::tuple<EncodingPrefix, bool>>
    kStringLiteralPrefixes{
        {"R", {EncodingPrefix::kNone, true}},
        {"L", {EncodingPrefix::kWide, false}},
        {"u8", {EncodingPrefix::kUtf8, false}},
        {"u", {EncodingPrefix::kUtf16, false}},
        {"U", {EncodingPrefix::kUtf32, false}},
        {"LR", {EncodingPrefix::kWide, true}},
        {"u8R", {EncodingPrefix::kUtf8, true}},
        {"uR", {EncodingPrefix::kUtf16, true}},
        {"UR", {EncodingPrefix::kUtf32, true}},
    };

const std::unordered_map<std::string_view, EncodingPrefix>
    kCharacterLiteralPrefixes{
        {"L", EncodingPrefix::kWide},
        {"u8", EncodingPrefix::kUtf8},
        {"u", EncodingPrefix::kUtf16},
        {"U", EncodingPrefix::kUtf32},
    };

inline bool is_idcont(int ch) {
  return ch == '_' || std::isalnum((unsigned char)ch);
}

template <typename It>
inline It skipSlash(It it, It end) {
  while (it < end && *it == '\\') {
    if (it + 1 < end && it[1] == '\n')
      it += 2;
    else if (it + 2 < end && it[1] == '\r' && it[2] == '\n')
      it += 3;
    else
      break;
  }
  return it;
}

template <typename It>
inline uint32_t peekNext(It it, It end) {
  it = skipSlash(it, end);
  return it < end ? utf8::peek_next(it, end) : 0;
}

template <typename It>
inline void readNext(It& it, It end) {
  it = skipSlash(it, end);
  if (it < end) utf8::next(it, end);
}

template <typename It>
inline void advance(It& it, int n, It end) {
  if (n > 0) {
    while (it < end && n--) readNext(it, end);
  } else {
    throw std::runtime_error("offset not valid");
  }
}

}  // namespace

Lexer::Lexer(const std::string_view& source)
    : source_(source), pos_(cbegin(source_)), end_(cend(source_)) {
  currentChar_ = pos_ < end_ ? peekNext(pos_, end_) : 0;
}

void Lexer::consume() {
  readNext(pos_, end_);
  currentChar_ = pos_ < end_ ? peekNext(pos_, end_) : 0;
}

void Lexer::consume(int n) {
  advance(pos_, n, end_);
  currentChar_ = pos_ < end_ ? peekNext(pos_, end_) : 0;
}

uint32_t Lexer::LA(int n) const {
  auto it = pos_;
  advance(it, n, end_);
  return it < end_ ? peekNext(it, end_) : 0;
}

TokenKind Lexer::readToken() {
  const auto hasMoreChars = skipSpaces();

  tokenIsClean_ = true;
  tokenPos_ = pos_ - cbegin(source_);
  text_.clear();

  if (!hasMoreChars) return TokenKind::T_EOF_SYMBOL;

  const auto ch = LA();

  if (std::isdigit(ch)) {
    bool integer_literal = true;
    while (pos_ != end_) {
      const auto ch = LA();
      if (pos_ + 1 < end_ &&
          (ch == 'e' || ch == 'E' || ch == 'p' || ch == 'P') &&
          (LA(1) == '+' || LA(1) == '-')) {
        consume(2);
        integer_literal = false;
      } else if (pos_ + 1 < end_ && ch == '\'' && is_idcont(LA(1))) {
        consume();
      } else if (is_idcont(ch)) {
        consume();
      } else if (ch == '.') {
        consume();
        integer_literal = false;
      } else {
        break;
      }
    }
    return integer_literal ? TokenKind::T_INTEGER_LITERAL
                           : TokenKind::T_FLOATING_POINT_LITERAL;
  }

  EncodingPrefix encodingPrefix = EncodingPrefix::kNone;

  bool isRawStringLiteral = false;

  if (std::isalpha(ch) || ch == '_') {
    do {
      text_ += (char)LA();
      consume();
    } while (pos_ != end_ && is_idcont(LA()));

    bool isStringOrCharacterLiteral = false;

    if (pos_ != end_ && LA() == '"') {
      auto it = kStringLiteralPrefixes.find(text_);
      if (it != kStringLiteralPrefixes.end()) {
        auto [enc, raw] = it->second;
        encodingPrefix = enc;
        isRawStringLiteral = raw;
        isStringOrCharacterLiteral = true;
      }
    } else if (pos_ != end_ && LA() == '\'') {
      auto it = kCharacterLiteralPrefixes.find(text_);
      if (it != kCharacterLiteralPrefixes.end()) {
        encodingPrefix = it->second;
        isStringOrCharacterLiteral = true;
      }
    }

    if (!isStringOrCharacterLiteral) {
      tokenIsClean_ = text_.length() == tokenLength();

      return !preprocessing_ ? classify(text_.c_str(), int(text_.length()))
                             : TokenKind::T_IDENTIFIER;
    }
  }

  if (LA() == '"') {
    consume();

    std::string_view delimiter;
    const auto startDelimiter = pos_;
    auto endDelimiter = pos_;

    if (isRawStringLiteral) {
      for (; pos_ != end_; consume()) {
        const auto ch = LA();
        if (ch == '(' || ch == '"' || ch == '\\' || ch == '\n') break;
      }
      endDelimiter = pos_;
      delimiter = source_.substr(startDelimiter - cbegin(source_),
                                 endDelimiter - startDelimiter);
    }

    while (pos_ != end_) {
      if (LA() == '"') {
        consume();

        if (!isRawStringLiteral) break;

        const auto S = startDelimiter - pos_;
        const auto N = endDelimiter - startDelimiter;

        if (LA(N - 2) == ')') {
          bool didMatch = true;
          for (int i = 0; i < N; ++i) {
            if (LA(S + i) != LA(N - i - 1)) {
              didMatch = false;
              break;
            }
          }
          if (didMatch) break;
        }
      } else if (pos_ + 1 < end_ && LA() == '\\') {
        consume(2);
      } else {
        consume();
      }
    }
    bool ud = false;
    if (std::isalpha(LA()) || LA() == '_') {
      ud = true;
      do {
        consume();
      } while (pos_ != end_ && is_idcont(LA()));
    }
    return !ud ? TokenKind::T_STRING_LITERAL
               : TokenKind::T_USER_DEFINED_STRING_LITERAL;
  }

  if (LA() == '\'') {
    consume();
    while (pos_ != end_ && LA() != '\'') {
      if (pos_ + 1 < end_ && LA() == '\\') {
        consume(2);
      } else {
        consume();
      }
    }
    if (LA() == '\'') {
      consume();
    }

    return TokenKind::T_CHARACTER_LITERAL;
  }

  if (pos_ + 1 < end_ && LA() == '.' && std::isdigit(LA(1))) {
    consume();
    while (pos_ != end_) {
      const auto ch = LA();
      if (pos_ + 1 < end_ &&
          (ch == 'e' || ch == 'E' || ch == 'p' || ch == 'P') &&
          (LA(1) == '+' || LA(1) == '-')) {
        consume(2);
      } else if (pos_ + 1 < end_ && ch == '\'' && is_idcont(LA(1))) {
        consume();
      } else if (is_idcont(ch)) {
        consume();
      } else {
        break;
      }
    }
    return TokenKind::T_FLOATING_POINT_LITERAL;
  }

  consume();

  switch (ch) {
    case '#':
      if (pos_ != end_ && LA() == '#') {
        consume();
        return TokenKind::T_HASH_HASH;
      }
      return TokenKind::T_HASH;

    case '=':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_EQUAL_EQUAL;
      }
      return TokenKind::T_EQUAL;

    case ',':
      return TokenKind::T_COMMA;

    case '~':
      return TokenKind::T_TILDE;

    case '{':
      return TokenKind::T_LBRACE;

    case '}':
      return TokenKind::T_RBRACE;

    case '[':
      return TokenKind::T_LBRACKET;

    case ']':
      return TokenKind::T_RBRACKET;

    case '(':
      return TokenKind::T_LPAREN;

    case ')':
      return TokenKind::T_RPAREN;

    case ';':
      return TokenKind::T_SEMICOLON;

    case ':':
      if (pos_ != end_ && LA() == ':') {
        consume();
        return TokenKind::T_COLON_COLON;
      }
      return TokenKind::T_COLON;

    case '.':
      if (pos_ + 1 < end_ && LA() == '.' && LA(1) == '.') {
        consume(2);
        return TokenKind::T_DOT_DOT_DOT;
      } else if (pos_ != end_ && LA() == '*') {
        consume();
        return TokenKind::T_DOT_STAR;
      }
      return TokenKind::T_DOT;

    case '?':
      return TokenKind::T_QUESTION;

    case '*':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_STAR_EQUAL;
      }
      return TokenKind::T_STAR;

    case '%':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_PERCENT_EQUAL;
      }
      return TokenKind::T_PERCENT;

    case '^':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_CARET_EQUAL;
      }
      return TokenKind::T_CARET;

    case '&':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_AMP_EQUAL;
      } else if (pos_ != end_ && LA() == '&') {
        consume();
        return TokenKind::T_AMP_AMP;
      }
      return TokenKind::T_AMP;

    case '|':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_BAR_EQUAL;
      } else if (pos_ != end_ && LA() == '|') {
        consume();
        return TokenKind::T_BAR_BAR;
      }
      return TokenKind::T_BAR;

    case '!':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_EXCLAIM_EQUAL;
      }
      return TokenKind::T_EXCLAIM;

    case '+':
      if (pos_ != end_ && LA() == '+') {
        consume();
        return TokenKind::T_PLUS_PLUS;
      } else if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_PLUS_EQUAL;
      }
      return TokenKind::T_PLUS;

    case '-':
      if (pos_ != end_ && LA() == '-') {
        consume();
        return TokenKind::T_MINUS_MINUS;
      } else if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_MINUS_EQUAL;
      } else if (pos_ != end_ && LA() == '>') {
        consume();
        if (pos_ != end_ && LA() == '*') {
          consume();
          return TokenKind::T_MINUS_GREATER_STAR;
        } else {
          return TokenKind::T_MINUS_GREATER;
        }
      }
      return TokenKind::T_MINUS;

    case '<':
      if (pos_ != end_ && LA() == '=') {
        consume();
        if (pos_ != end_ && LA() == '>') {
          consume();
          return TokenKind::T_LESS_EQUAL_GREATER;
        }
        return TokenKind::T_LESS_EQUAL;
      } else if (pos_ != end_ && LA() == '<') {
        consume();
        if (pos_ != end_ && LA() == '=') {
          consume();
          return TokenKind::T_LESS_LESS_EQUAL;
        }
        return TokenKind::T_LESS_LESS;
      }
      return TokenKind::T_LESS;

    case '>':
      if (preprocessing_) {
        if (pos_ != end_ && LA() == '=') {
          consume();
          return TokenKind::T_GREATER_EQUAL;
        } else if (pos_ != end_ && LA() == '>') {
          consume();
          if (pos_ != end_ && LA() == '=') {
            consume();
            return TokenKind::T_GREATER_GREATER_EQUAL;
          }
          return TokenKind::T_GREATER_GREATER;
        }
      } else if (LA() == '>') {
        TokenKind k = TokenKind::T_GREATER_GREATER;

        if (LA(1) == '=') k = TokenKind::T_GREATER_GREATER_EQUAL;

        tokenValue_.tokenKindValue = k;
      } else if (LA() == '=') {
        tokenValue_.tokenKindValue = TokenKind::T_GREATER_EQUAL;
      }

      return TokenKind::T_GREATER;

    case '/':
      if (pos_ != end_ && LA() == '=') {
        consume();
        return TokenKind::T_SLASH_EQUAL;
      }
      return TokenKind::T_SLASH;
  }

  return TokenKind::T_ERROR;
}  // namespace cxx

bool Lexer::skipSpaces() {
  tokenLeadingSpace_ = leadingSpace_;
  tokenStartOfLine_ = startOfLine_;

  while (pos_ != end_) {
    const auto ch = LA();

    if (std::isspace(ch)) {
      if (ch == '\n') {
        tokenStartOfLine_ = true;
        tokenLeadingSpace_ = false;
      } else {
        tokenLeadingSpace_ = true;
      }
      consume();
    } else if (pos_ + 1 < end_ && ch == '/' && LA(1) == '/') {
      consume(2);
      for (; pos_ != end_; consume()) {
        if (pos_ != end_ && LA() == '\n') {
          break;
        }
      }
    } else if (pos_ + 1 < end_ && ch == '/' && LA(1) == '*') {
      while (pos_ != end_) {
        if (pos_ + 1 < end_ && LA() == '*' && LA(1) == '/') {
          consume(2);
          break;
        } else {
          consume();
        }
      }
      // unexpected eof
    } else {
      break;
    }
  }

  leadingSpace_ = false;
  startOfLine_ = false;

  return pos_ != end_;
}

TokenKind Lexer::classifyKeyword(const std::string_view& text) {
  return classify(text.data(), int(text.size()));
}

}  // namespace cxx
<|endoftext|>


<commit_before>/**
 * @file		icomponent.hpp
 * @brief		Component(Shared Library) interface
 * @author		Byunghun Hwang<bhhwang@nsynapse.com>
 * @date 		2015. 6. 21
 * @details		Component interface class
 */

#ifndef _COSSB_ICOMPONENT_HPP_
#define _COSSB_ICOMPONENT_HPP_

#include <string>
#include "iprofile.hpp"
#include "imessage.hpp"

using namespace std;

namespace cossb {

namespace component {
	enum class status : unsigned int { IDLE=0, RUNNING, STOPPED };
}

namespace interface {

/**
* @brief		component interface class
* @details		base component interface, lifecycle is (setup-run-stop)
* @author		Byunghun Hwang<bhhwang@nsynapse.com>
* @date		2015. 6. 22
*/
class icomponent {

public:
	/**
	 * @brief
	 */
	virtual ~icomponent() {
		if(_profile)
			delete _profile;
	}

	/**
	 * @brief		initialization
	 * @details		this function will be called at first
	 * @return		true if it is success
	 */
	virtual bool setup() = 0;

	/**
	 * @brief		process logic in here
	 * @details		if request message comes in, this function will be called
	 */
	virtual bool run() = 0;

	/**
	 * @brief	stop interface
	 */
	virtual bool stop() = 0;

	/**
	 * @brief	message request
	 */
	virtual void request(imessage* msg) = 0;

	/**
	 * @brief
	 */
	const char* get_name() const {
		return _name.c_str();
	}

	/**
	 * @brief
	 */
	iprofile* get_profile() const {
		return _profile;
	}

	/**
	 * @brief	getting status
	 */
	component::status get_status() { return _status; }

	/**
	 * @brief	set component profile
	 */
	bool set_profile(iprofile* profile, const char* path)
	{
		_profile = profile;
		return _profile->load(path);
	}

protected:
	explicit icomponent(const char* name)
	:_name(name), _profile(nullptr), _status(component::status::IDLE) {

	}

private:
	string _name;
	iprofile* _profile = nullptr;

protected:
	component::status _status;

};

} /* namespace interface */

typedef interface::icomponent*(*create_component)(void);
typedef void(*destroy_component)(void);

} /* namespace cossb */

#endif /* _COSSB_ICOMPONENT_HPP_ */
<commit_msg>add comment<commit_after>/**
 * @file		icomponent.hpp
 * @brief		Component(Shared Library) interface
 * @author		Byunghun Hwang<bhhwang@nsynapse.com>
 * @date 		2015. 6. 21
 * @details		Component interface class
 */

#ifndef _COSSB_ICOMPONENT_HPP_
#define _COSSB_ICOMPONENT_HPP_

#include <string>
#include "iprofile.hpp"
#include "imessage.hpp"

using namespace std;

namespace cossb {

namespace component {
	enum class status : unsigned int { IDLE=0, RUNNING, STOPPED };
}

namespace interface {

/**
* @brief		component interface class
* @details		base component interface, lifecycle is (setup-run-stop)
* @author		Byunghun Hwang<bhhwang@nsynapse.com>
* @date		2015. 6. 22
*/
class icomponent {

public:
	/**
	 * @brief
	 */
	virtual ~icomponent() {
		if(_profile)
			delete _profile;
	}

	/**
	 * @brief		initialization
	 * @details	this function will be called once when load component
	 * @return		true if it is success
	 */
	virtual bool setup() = 0;

	/**
	 * @brief		start signal comes in, this function will be called
	 * @details
	 */
	virtual bool run() = 0;

	/**
	 * @brief	stop interface
	 * @brief	stop signal comes in, this function will be called
	 */
	virtual bool stop() = 0;

	/**
	 * @brief	message request
	 * @details	if request message comes in, this function will be called
	 */
	virtual void request(imessage* msg) = 0;

	/**
	 * @brief
	 */
	const char* get_name() const {
		return _name.c_str();
	}

	/**
	 * @brief
	 */
	iprofile* get_profile() const {
		return _profile;
	}

	/**
	 * @brief	getting status
	 */
	component::status get_status() { return _status; }

	/**
	 * @brief	set component profile
	 */
	bool set_profile(iprofile* profile, const char* path)
	{
		_profile = profile;
		return _profile->load(path);
	}

protected:
	explicit icomponent(const char* name)
	:_name(name), _profile(nullptr), _status(component::status::IDLE) {

	}

private:
	string _name;
	iprofile* _profile = nullptr;

protected:
	component::status _status;

};

} /* namespace interface */

typedef interface::icomponent*(*create_component)(void);
typedef void(*destroy_component)(void);

} /* namespace cossb */

#endif /* _COSSB_ICOMPONENT_HPP_ */
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
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.
    * Neither the name of the author 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.

*/

#ifndef TORRENT_PEER_INFO_HPP_INCLUDED
#define TORRENT_PEER_INFO_HPP_INCLUDED

#include <vector>
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"

namespace libtorrent
{
	struct peer_info
	{
		enum
		{
			interesting = 0x1,
			choked = 0x2,
			remote_interested = 0x4,
			remote_choked = 0x8,
			supports_extensions = 0x10,
			local_connection = 0x20
		};
		unsigned int flags;
		address ip;
		float up_speed;
		float down_speed;
		unsigned int total_download;
		unsigned int total_upload;
		peer_id id;
		std::vector<bool> pieces;
		int upload_limit;
		int upload_ceiling;

		int load_balancing;

		// this is the number of requests
		// we have sent to this peer
		// that we haven't got a response
		// for yet
		int download_queue_length;

		// the currently downloading piece
		// if piece index is -1 all associated
		// members are just set to 0
		int downloading_piece_index;
		int downloading_block_index;
		int downloading_progress;
		int downloading_total;
	};

}

#endif // TORRENT_PEER_INFO_HPP_INCLUDED
<commit_msg>*** empty log message ***<commit_after>/*

Copyright (c) 2003, Arvid Norberg
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.
    * Neither the name of the author 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.

*/

#ifndef TORRENT_PEER_INFO_HPP_INCLUDED
#define TORRENT_PEER_INFO_HPP_INCLUDED

#include <vector>
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"

namespace libtorrent
{
	struct peer_info
	{
		enum
		{
			interesting = 0x1,
			choked = 0x2,
			remote_interested = 0x4,
			remote_choked = 0x8,
			supports_extensions = 0x10,
			local_connection = 0x20
		};
		unsigned int flags;
		address ip;
		float up_speed;
		float down_speed;
		unsigned int total_download;
		unsigned int total_upload;
		peer_id id;
		std::vector<bool> pieces;
		int upload_limit; // from peer_connection
		int upload_ceiling; // from the global upload limiter

		int load_balancing;

		// this is the number of requests
		// we have sent to this peer
		// that we haven't got a response
		// for yet
		int download_queue_length;

		// the currently downloading piece
		// if piece index is -1 all associated
		// members are just set to 0
		int downloading_piece_index;
		int downloading_block_index;
		int downloading_progress;
		int downloading_total;
	};

}

#endif // TORRENT_PEER_INFO_HPP_INCLUDED
<|endoftext|>


<commit_before>/*
 * Copyright 2008, 2009 Google Inc.
 * Copyright 2007 Nintendo Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <sys/stat.h>
#include <sys/types.h>
#include <set>
#include "java.h"

namespace
{

FILE* createFile(const std::string package, const Node* node)
{
    std::string filename = package;

    size_t pos = 0;
    for (;;)
    {
        pos = filename.find('.', pos);
        if (pos == std::string::npos)
        {
            break;
        }
        filename[pos] = '/';
    }

    filename += "/" + node->getName() + ".java";

    std::string dir;
    std::string path(filename);
    for (;;)
    {
        size_t slash = path.find("/");
        if (slash == std::string::npos)
        {
            break;
        }
        dir += path.substr(0, slash);
        path.erase(0, slash + 1);
        mkdir(dir.c_str(), 0777);
        dir += '/';
    }

    printf("# %s in %s\n", node->getName().c_str(), filename.c_str());
    return fopen(filename.c_str(), "w");
}

}  // namespace

class JavaInterface : public Java
{
    // TODO: Move to Java
    void visitInterfaceElement(const Interface* interface, Node* element)
    {
        if (dynamic_cast<Interface*>(element))
        {
            // Do not process Constructor.
            return;
        }

        optionalStage = 0;
        do
        {
            optionalCount = 0;
            element->accept(this);
            ++optionalStage;
        } while (optionalStage <= optionalCount);
    }

public:
    JavaInterface(const char* source, FILE* file, const char* indent = "es") :
        Java(source, file, indent)
    {
    }

    virtual void at(const ExceptDcl* node)
    {
        writetab();
        if (node->getJavadoc().size())
        {
            write("%s\n", node->getJavadoc().c_str());
            writetab();
        }
        write("public class %s extends RuntimeException {\n", node->getName().c_str());
            // TODO(Shiki): Need a constructor.
            printChildren(node);
        writeln("}");
    }

    virtual void at(const Interface* node)
    {
        assert(!(node->getAttr() & Interface::Supplemental) && !node->isLeaf());
        writetab();
        if (node->getJavadoc().size())
        {
            write("%s\n", node->getJavadoc().c_str());
            writetab();
        }

        std::string name = node->getQualifiedName();
        name = getInterfaceName(name);
        write("public interface %s", name.substr(name.rfind(':') + 1).c_str());
        if (node->getExtends())
        {
            const char* separator = " extends ";
            for (NodeList::iterator i = node->getExtends()->begin();
                 i != node->getExtends()->end();
                 ++i)
            {
                if ((*i)->getName() == Node::getBaseObjectName())
                {
                    // Do not extend from 'Object'.
                    continue;
                }
                write(separator);
                separator = ", ";
                (*i)->accept(this);
            }
        }
        write(" {\n");

        for (NodeList::iterator i = node->begin(); i != node->end(); ++i)
        {
            visitInterfaceElement(node, *i);
        }

        // Expand mixins
        std::list<const Interface*> interfaceList;
        node->collectMixins(&interfaceList, node);
        for (std::list<const Interface*>::const_iterator i = interfaceList.begin();
                i != interfaceList.end();
                ++i)
        {
            if (*i == node)
            {
                continue;
            }
            writeln("// %s", (*i)->getName().c_str());
            for (NodeList::iterator j = (*i)->begin(); j != (*i)->end(); ++j)
            {
                visitInterfaceElement(*i, *j);
            }
        }

        writeln("}");
    }

    virtual void at(const BinaryExpr* node)
    {
        node->getLeft()->accept(this);
        write(" %s ", node->getName().c_str());
        node->getRight()->accept(this);
    }

    virtual void at(const UnaryExpr* node)
    {
        write("%s", node->getName().c_str());
        NodeList::iterator elem = node->begin();
        (*elem)->accept(this);
    }

    virtual void at(const GroupingExpression* node)
    {
        write("(");
        NodeList::iterator elem = node->begin();
        (*elem)->accept(this);
        write(")");
    }

    virtual void at(const Literal* node)
    {
        write("%s", node->getName().c_str());
    }

    virtual void at(const Member* node)
    {
        if (node->isTypedef(node->getParent()))
        {
            return;
        }

        writetab();
        write("public ");
        node->getSpec()->accept(this);
        write(" %s;\n", node->getName().c_str());
    }

    virtual void at(const ArrayDcl* node)
    {
        assert(!node->isLeaf());
        if (node->isTypedef(node->getParent()))
        {
            return;
        }

        writetab();
        node->getSpec()->accept(this);
        write(" %s", node->getName().c_str());
        for (NodeList::iterator i = node->begin(); i != node->end(); ++i)
        {
            write("[");
            (*i)->accept(this);
            write("]");
        }
        if (node->isTypedef(node->getParent()))
        {
            write(";\n");
        }
    }

    virtual void at(const ConstDcl* node)
    {
        writetab();
        if (node->getJavadoc().size())
        {
            write("%s\n", node->getJavadoc().c_str());
            writetab();
        }
        write("public static final ");
        node->getSpec()->accept(this);
        write(" %s = ", node->getName().c_str());
        node->getExp()->accept(this);
        write(";\n");
    }

    virtual void at(const Attribute* node)
    {
        writetab();
        if (node->getJavadoc().size())
        {
            write("%s\n", node->getJavadoc().c_str());
            writetab();
        }

        // getter
        Java::getter(node);
        write(";\n");

        if (!node->isReadonly() || node->isPutForwards() || node->isReplaceable())
        {
            // setter
            writetab();
            Java::setter(node);
            write(";\n");
        }
    }

    virtual void at(const OpDcl* node)
    {
        writetab();
        if (node->getJavadoc().size())
        {
            write("%s\n", node->getJavadoc().c_str());
            writetab();
        }
        Java::at(node);
        write(";\n");
    }
};

class JavaImport : public Visitor, public Formatter
{
    std::string package;
    const Interface* current;
    bool printed;
    std::string prefixedName;
    std::set<std::string> importSet;

public:
    JavaImport(std::string package, FILE* file, const char* indent) :
        Formatter(file, indent),
        package(package),
        current(0)
    {
    }

    virtual void at(const Node* node)
    {
        visitChildren(node);
    }

    virtual void at(const ScopedName* node)
    {
        assert(current);

        if (node->isBaseObject())
        {
            return;
        }
        std::string name = node->getName();
        Node* resolved = resolve(current, name);
        if (resolved)
        {
            if (Module* module = dynamic_cast<Module*>(resolved->getParent()))
            {
                if (prefixedName != module->getPrefixedName())
                {
                    importSet.insert(Java::getPackageName(module->getPrefixedName()) + "." + node->getIdentifier());
                }
            }
        }
    }

    virtual void at(const Interface* node)
    {
        if (current)
        {
            return;
        }
        current = node;
        if (Module* module = dynamic_cast<Module*>(node->getParent()))
        {
            prefixedName = module->getPrefixedName();
        }
        visitChildren(node->getExtends());
        visitChildren(node);
        // Expand mixins
        std::list<const Interface*> interfaceList;
        node->collectMixins(&interfaceList, node);
        for (std::list<const Interface*>::const_iterator i = interfaceList.begin();
             i != interfaceList.end();
             ++i)
        {
            if (*i == node)
            {
                continue;
            }
            visitChildren(*i);
        }
    }

    virtual void at(const Attribute* node)
    {
        node->getSpec()->accept(this);
        visitChildren(node->getGetRaises());
        if (!node->isReadonly() || node->isPutForwards() || node->isReplaceable())
        {
            visitChildren(node->getSetRaises());
        }
    }

    virtual void at(const OpDcl* node)
    {
        node->getSpec()->accept(this);
        visitChildren(node);
        visitChildren(node->getRaises());
    }

    virtual void at(const ParamDcl* node)
    {
        node->getSpec()->accept(this);
    }

    void print()
    {
        if (importSet.empty())
        {
            return;
        }
        for (std::set<std::string>::iterator i = importSet.begin();
             i != importSet.end();
             ++i)
        {
            write("import %s;\n", (*i).c_str());
        }
        write("\n");
    }
};

class JavaVisitor : public Visitor
{
    const char* source;
    const char* indent;

    std::string prefixedName;

public:
    JavaVisitor(const char* source, const char* indent = "es") :
        source(source),
        indent(indent)
    {
    }

    virtual void at(const Node* node)
    {
        if (1 < node->getRank())
        {
            return;
        }
        visitChildren(node);
    }

    virtual void at(const Module* node)
    {
        std::string enclosed = prefixedName;
        prefixedName = node->getPrefixedName();
        at(static_cast<const Node*>(node));
        prefixedName = enclosed;
    }

    virtual void at(const ExceptDcl* node)
    {
        if (1 < node->getRank() || node->isLeaf() || !node->isDefinedIn(source))
        {
            return;
        }

        FILE* file = createFile(Java::getPackageName(prefixedName), node);
        if (!file)
        {
            return;
        }

        fprintf(file, "// Generated by esidl %s.\n\n", VERSION);
        fprintf(file, "package %s;\n\n", Java::getPackageName(prefixedName).c_str());

        JavaInterface javaInterface(source, file, indent);
        javaInterface.at(node);

        fclose(file);
    }

    virtual void at(const Interface* node)
    {
        if (1 < node->getRank() || node->isLeaf() || !node->isDefinedIn(source) ||
            (node->getAttr() & Interface::Supplemental))
        {
            return;
        }

        FILE* file = createFile(Java::getPackageName(prefixedName), node);
        if (!file)
        {
            return;
        }

        fprintf(file, "// Generated by esidl %s.\n\n", VERSION);
        fprintf(file, "package %s;\n\n", Java::getPackageName(prefixedName).c_str());

        JavaImport import(Java::getPackageName(prefixedName), file, indent);
        import.at(node);
        import.print();

        JavaInterface javaInterface(source, file, indent);
        javaInterface.at(node);

        fclose(file);
    }
};

void printJava(const char* source, const char* indent)
{
    JavaVisitor visitor(source, indent);
    getSpecification()->accept(&visitor);
}
<commit_msg>(at(const ScopedName* node)) : Fix to follow typedef name.<commit_after>/*
 * Copyright 2008, 2009 Google Inc.
 * Copyright 2007 Nintendo Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <sys/stat.h>
#include <sys/types.h>
#include <set>
#include "java.h"

namespace
{

FILE* createFile(const std::string package, const Node* node)
{
    std::string filename = package;

    size_t pos = 0;
    for (;;)
    {
        pos = filename.find('.', pos);
        if (pos == std::string::npos)
        {
            break;
        }
        filename[pos] = '/';
    }

    filename += "/" + node->getName() + ".java";

    std::string dir;
    std::string path(filename);
    for (;;)
    {
        size_t slash = path.find("/");
        if (slash == std::string::npos)
        {
            break;
        }
        dir += path.substr(0, slash);
        path.erase(0, slash + 1);
        mkdir(dir.c_str(), 0777);
        dir += '/';
    }

    printf("# %s in %s\n", node->getName().c_str(), filename.c_str());
    return fopen(filename.c_str(), "w");
}

}  // namespace

class JavaInterface : public Java
{
    // TODO: Move to Java
    void visitInterfaceElement(const Interface* interface, Node* element)
    {
        if (dynamic_cast<Interface*>(element))
        {
            // Do not process Constructor.
            return;
        }

        optionalStage = 0;
        do
        {
            optionalCount = 0;
            element->accept(this);
            ++optionalStage;
        } while (optionalStage <= optionalCount);
    }

public:
    JavaInterface(const char* source, FILE* file, const char* indent = "es") :
        Java(source, file, indent)
    {
    }

    virtual void at(const ExceptDcl* node)
    {
        writetab();
        if (node->getJavadoc().size())
        {
            write("%s\n", node->getJavadoc().c_str());
            writetab();
        }
        write("public class %s extends RuntimeException {\n", node->getName().c_str());
            // TODO(Shiki): Need a constructor.
            printChildren(node);
        writeln("}");
    }

    virtual void at(const Interface* node)
    {
        assert(!(node->getAttr() & Interface::Supplemental) && !node->isLeaf());
        writetab();
        if (node->getJavadoc().size())
        {
            write("%s\n", node->getJavadoc().c_str());
            writetab();
        }

        std::string name = node->getQualifiedName();
        name = getInterfaceName(name);
        write("public interface %s", name.substr(name.rfind(':') + 1).c_str());
        if (node->getExtends())
        {
            const char* separator = " extends ";
            for (NodeList::iterator i = node->getExtends()->begin();
                 i != node->getExtends()->end();
                 ++i)
            {
                if ((*i)->getName() == Node::getBaseObjectName())
                {
                    // Do not extend from 'Object'.
                    continue;
                }
                write(separator);
                separator = ", ";
                (*i)->accept(this);
            }
        }
        write(" {\n");

        for (NodeList::iterator i = node->begin(); i != node->end(); ++i)
        {
            visitInterfaceElement(node, *i);
        }

        // Expand mixins
        std::list<const Interface*> interfaceList;
        node->collectMixins(&interfaceList, node);
        for (std::list<const Interface*>::const_iterator i = interfaceList.begin();
                i != interfaceList.end();
                ++i)
        {
            if (*i == node)
            {
                continue;
            }
            writeln("// %s", (*i)->getName().c_str());
            for (NodeList::iterator j = (*i)->begin(); j != (*i)->end(); ++j)
            {
                visitInterfaceElement(*i, *j);
            }
        }

        writeln("}");
    }

    virtual void at(const BinaryExpr* node)
    {
        node->getLeft()->accept(this);
        write(" %s ", node->getName().c_str());
        node->getRight()->accept(this);
    }

    virtual void at(const UnaryExpr* node)
    {
        write("%s", node->getName().c_str());
        NodeList::iterator elem = node->begin();
        (*elem)->accept(this);
    }

    virtual void at(const GroupingExpression* node)
    {
        write("(");
        NodeList::iterator elem = node->begin();
        (*elem)->accept(this);
        write(")");
    }

    virtual void at(const Literal* node)
    {
        write("%s", node->getName().c_str());
    }

    virtual void at(const Member* node)
    {
        if (node->isTypedef(node->getParent()))
        {
            return;
        }

        writetab();
        write("public ");
        node->getSpec()->accept(this);
        write(" %s;\n", node->getName().c_str());
    }

    virtual void at(const ArrayDcl* node)
    {
        assert(!node->isLeaf());
        if (node->isTypedef(node->getParent()))
        {
            return;
        }

        writetab();
        node->getSpec()->accept(this);
        write(" %s", node->getName().c_str());
        for (NodeList::iterator i = node->begin(); i != node->end(); ++i)
        {
            write("[");
            (*i)->accept(this);
            write("]");
        }
        if (node->isTypedef(node->getParent()))
        {
            write(";\n");
        }
    }

    virtual void at(const ConstDcl* node)
    {
        writetab();
        if (node->getJavadoc().size())
        {
            write("%s\n", node->getJavadoc().c_str());
            writetab();
        }
        write("public static final ");
        node->getSpec()->accept(this);
        write(" %s = ", node->getName().c_str());
        node->getExp()->accept(this);
        write(";\n");
    }

    virtual void at(const Attribute* node)
    {
        writetab();
        if (node->getJavadoc().size())
        {
            write("%s\n", node->getJavadoc().c_str());
            writetab();
        }

        // getter
        Java::getter(node);
        write(";\n");

        if (!node->isReadonly() || node->isPutForwards() || node->isReplaceable())
        {
            // setter
            writetab();
            Java::setter(node);
            write(";\n");
        }
    }

    virtual void at(const OpDcl* node)
    {
        writetab();
        if (node->getJavadoc().size())
        {
            write("%s\n", node->getJavadoc().c_str());
            writetab();
        }
        Java::at(node);
        write(";\n");
    }
};

class JavaImport : public Visitor, public Formatter
{
    std::string package;
    const Interface* current;
    bool printed;
    std::string prefixedName;
    std::set<std::string> importSet;

public:
    JavaImport(std::string package, FILE* file, const char* indent) :
        Formatter(file, indent),
        package(package),
        current(0)
    {
    }

    virtual void at(const Node* node)
    {
        visitChildren(node);
    }

    virtual void at(const ScopedName* node)
    {
        assert(current);

        if (node->isBaseObject())
        {
            return;
        }
        std::string name = node->getName();
        Node* resolved = node->search(current);
        if (resolved)
        {
            if (Module* module = dynamic_cast<Module*>(resolved->getParent()))
            {
                if (prefixedName != module->getPrefixedName())
                {
                    importSet.insert(Java::getPackageName(module->getPrefixedName()) + "." + node->getIdentifier());
                }
            }
        }
    }

    virtual void at(const Interface* node)
    {
        if (current)
        {
            return;
        }
        current = node;
        if (Module* module = dynamic_cast<Module*>(node->getParent()))
        {
            prefixedName = module->getPrefixedName();
        }
        visitChildren(node->getExtends());
        visitChildren(node);
        // Expand mixins
        std::list<const Interface*> interfaceList;
        node->collectMixins(&interfaceList, node);
        for (std::list<const Interface*>::const_iterator i = interfaceList.begin();
             i != interfaceList.end();
             ++i)
        {
            if (*i == node)
            {
                continue;
            }
            visitChildren(*i);
        }
    }

    virtual void at(const Attribute* node)
    {
        node->getSpec()->accept(this);
        visitChildren(node->getGetRaises());
        if (!node->isReadonly() || node->isPutForwards() || node->isReplaceable())
        {
            visitChildren(node->getSetRaises());
        }
    }

    virtual void at(const OpDcl* node)
    {
        node->getSpec()->accept(this);
        visitChildren(node);
        visitChildren(node->getRaises());
    }

    virtual void at(const ParamDcl* node)
    {
        node->getSpec()->accept(this);
    }

    void print()
    {
        if (importSet.empty())
        {
            return;
        }
        for (std::set<std::string>::iterator i = importSet.begin();
             i != importSet.end();
             ++i)
        {
            write("import %s;\n", (*i).c_str());
        }
        write("\n");
    }
};

class JavaVisitor : public Visitor
{
    const char* source;
    const char* indent;

    std::string prefixedName;

public:
    JavaVisitor(const char* source, const char* indent = "es") :
        source(source),
        indent(indent)
    {
    }

    virtual void at(const Node* node)
    {
        if (1 < node->getRank())
        {
            return;
        }
        visitChildren(node);
    }

    virtual void at(const Module* node)
    {
        std::string enclosed = prefixedName;
        prefixedName = node->getPrefixedName();
        at(static_cast<const Node*>(node));
        prefixedName = enclosed;
    }

    virtual void at(const ExceptDcl* node)
    {
        if (1 < node->getRank() || node->isLeaf() || !node->isDefinedIn(source))
        {
            return;
        }

        FILE* file = createFile(Java::getPackageName(prefixedName), node);
        if (!file)
        {
            return;
        }

        fprintf(file, "// Generated by esidl %s.\n\n", VERSION);
        fprintf(file, "package %s;\n\n", Java::getPackageName(prefixedName).c_str());

        JavaInterface javaInterface(source, file, indent);
        javaInterface.at(node);

        fclose(file);
    }

    virtual void at(const Interface* node)
    {
        if (1 < node->getRank() || node->isLeaf() || !node->isDefinedIn(source) ||
            (node->getAttr() & Interface::Supplemental))
        {
            return;
        }

        FILE* file = createFile(Java::getPackageName(prefixedName), node);
        if (!file)
        {
            return;
        }

        fprintf(file, "// Generated by esidl %s.\n\n", VERSION);
        fprintf(file, "package %s;\n\n", Java::getPackageName(prefixedName).c_str());

        JavaImport import(Java::getPackageName(prefixedName), file, indent);
        import.at(node);
        import.print();

        JavaInterface javaInterface(source, file, indent);
        javaInterface.at(node);

        fclose(file);
    }
};

void printJava(const char* source, const char* indent)
{
    JavaVisitor visitor(source, indent);
    getSpecification()->accept(&visitor);
}
<|endoftext|>


<commit_before>#include "dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent)
{
    init();
}

Dialog::~Dialog()
{

}

void Dialog::shuffle_animated(){
    //lock button
    btnRandomize->setDown(true);
    disconnect(btnRandomize,SIGNAL(clicked()),this,SLOT(shuffle_animated()));

    for(int i=0;i<animation_time;++i){
        shuffle();
        dieTime=QTime::currentTime().addMSecs(per_frame_ms);
        while( QTime::currentTime() < dieTime )
            QCoreApplication::processEvents(QEventLoop::AllEvents, per_frame_ms);
    }

    //enable button
    btnRandomize->setDown(false);
    connect(btnRandomize,SIGNAL(clicked()),this,SLOT(shuffle_animated()));
}

void Dialog::shuffle(){
    //shuffle
    srand(QTime::currentTime().msec());
    std::random_shuffle(male.begin(),male.end());
    std::random_shuffle(female.begin(),female.end());

    int male_iterator=0,female_iterator=0;
    for(int i=0;i<male_count+female_count;++i){
        if(seating_rule[i]==MALE) seating[i]->setText(male[male_iterator++]);
        else seating[i]->setText(female[female_iterator++]);
    }
}

void Dialog::init(){
    this->setWindowTitle("QTempatDuduk v1.4");
    this->resize(1000,500);

    btnChangePeople=new QPushButton(tr("&People..."),this);
    btnChangeRule=new QPushButton(tr("&Rule..."),this);
    btnUpdate=new QPushButton(tr("&Update!"),this);
    btnRandomize=new QPushButton(tr("&Shuffle!"),this);
    btnExit=new QPushButton(tr("E&xit"),this);

    mainLayout=new QVBoxLayout(this);
    buttonLayout=new QHBoxLayout(this);
    seatLayout=new QGridLayout(this);

    //default files
    db_people_filename="./people.txt";
    db_rule_filename="./seating.txt";

    init_data();
    init_seat();

    buttonLayout->addWidget(btnChangePeople);
    buttonLayout->addWidget(btnChangeRule);
    buttonLayout->addWidget(btnUpdate);
    buttonLayout->addStretch();
    buttonLayout->addWidget(btnRandomize);
    buttonLayout->addWidget(btnExit);

    connect(btnChangePeople,SIGNAL(clicked()),this,SLOT(change_people()));
    connect(btnChangeRule,SIGNAL(clicked()),this,SLOT(change_rule()));
    connect(btnUpdate,SIGNAL(clicked()),this,SLOT(update()));
    connect(btnExit,SIGNAL(clicked()),this,SLOT(accept()));
    connect(btnRandomize,SIGNAL(clicked()),this,SLOT(shuffle_animated()));

    mainLayout->addLayout(seatLayout);
    mainLayout->addLayout(buttonLayout);
    this->setLayout(mainLayout);
}

void Dialog::init_seat(){
    QBrush fontBrush(QColor(FONTCOLOR));
    fontBrush.setStyle(Qt::SolidPattern);

    QBrush seatBrush(QColor(SEATCOLOR));
    seatBrush.setStyle(Qt::SolidPattern);

    palette.setBrush(QPalette::Active, QPalette::WindowText, fontBrush);
    palette.setBrush(QPalette::Inactive, QPalette::WindowText, fontBrush);

    palette.setBrush(QPalette::Active, QPalette::Window, seatBrush);
    palette.setBrush(QPalette::Inactive, QPalette::Window, seatBrush);

    font.setPointSize(FONTSIZE);
    font.setBold(true);
    font.setFamily(FONTFAMILY);

    for(int i=0;i<rule_row;++i){
        for(int j=0;j<rule_column;++j){
            if(rule[i][j]=='.') seatLayout->addItem(new QSpacerItem(SPACERSIZE),i,j);
            else{
                init_seat_aux();
                seatLayout->addWidget(seat,i,j);
                seating.push_back(seat);
                seating_rule.push_back((rule[i][j]=='m'? MALE : FEMALE));
            }
        }
    }

}

void Dialog::init_seat_aux(){
    seat=new QLabel("-",this);
    seat->setPalette(palette);
    seat->setFont(font);
    seat->setAutoFillBackground(true);
    seat->setAlignment(Qt::AlignCenter);
    seat->setMinimumSize(SEATMINIMUMSIZE);
}

void Dialog::init_data(){
    //get data
    QString s;
    QFile db_people(db_people_filename),db_rule(db_rule_filename);
    if(!db_people.open(QIODevice::ReadOnly)) {
        QMessageBox::information(0, tr("Error"), db_people.errorString());
    }
    if(!db_rule.open(QIODevice::ReadOnly)) {
        QMessageBox::information(0, tr("Error"), db_rule.errorString());
    }

    QTextStream in_people(&db_people),in_rule(&db_rule);

    in_people>>male_count;
    in_people.readLine(); //clearing
    for(int i=0;i<male_count;++i){
        s = in_people.readLine();
        if(s.size())male.push_back(s);
    }

    in_people>>female_count;
    in_people.readLine();
    for(int i=0;i<female_count;++i) {
        s = in_people.readLine();
        if(s.size())female.push_back(s);
    }
    db_people.close();

    in_rule>>rule_male>>rule_female;
    if(rule_male!=male_count || rule_female!=female_count)
        QMessageBox::information(0, tr("Error"), tr("Mismatch number of person"));

    in_rule>>rule_row>>rule_column;
    for(int i=0;i<rule_row;++i){
        in_rule>>s;
        rule.push_back(s);
    }
    db_rule.close();

}

void Dialog::change_people(){
    db_people_filename=
            QFileDialog::getOpenFileName(this,
                                         tr("Select file..."),
                                         QDir::homePath(),
                                         tr("Text files (*.txt)"));
}

void Dialog::change_rule(){
    db_rule_filename=
            QFileDialog::getOpenFileName(this,
                                         tr("Select file..."),
                                         QDir::homePath(),
                                         tr("Text files (*.txt)"));

}

void Dialog::update(){
    //empty all
    male.clear();
    female.clear();
    seating_rule.clear();
    for(int i=0;i<rule_row;++i)
        for(int j=0;j<rule_column;++j)
            seatLayout->removeItem(seatLayout->itemAtPosition(i,j));
    for(int i=0;i<seating.size();++i)
        delete seating[i];
    seating.clear();
    rule.clear();

    //redo
    init_data();
    init_seat();

}
<commit_msg>Fixed #2<commit_after>#include "dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent)
{
    init();
}

Dialog::~Dialog()
{

}

void Dialog::shuffle_animated(){
    //lock button
    btnRandomize->setDown(true);
    disconnect(btnRandomize,SIGNAL(clicked()),this,SLOT(shuffle_animated()));

    for(int i=0;i<animation_time;++i){
        shuffle();
        dieTime=QTime::currentTime().addMSecs(per_frame_ms);
        while( QTime::currentTime() < dieTime )
            QCoreApplication::processEvents(QEventLoop::AllEvents, per_frame_ms);
    }

    //enable button
    btnRandomize->setDown(false);
    connect(btnRandomize,SIGNAL(clicked()),this,SLOT(shuffle_animated()));
}

void Dialog::shuffle(){
    //shuffle
    srand(QTime::currentTime().msec());
    std::random_shuffle(male.begin(),male.end());
    std::random_shuffle(female.begin(),female.end());

    int male_iterator=0,female_iterator=0;
    for(int i=0;i<male_count+female_count;++i){
        if(seating_rule[i]==MALE) seating[i]->setText(male[male_iterator++]);
        else seating[i]->setText(female[female_iterator++]);
    }
}

void Dialog::init(){
    this->setWindowTitle("QTempatDuduk v1.4");
    this->resize(1000,500);

    btnChangePeople=new QPushButton(tr("&People..."),this);
    btnChangeRule=new QPushButton(tr("&Rule..."),this);
    btnUpdate=new QPushButton(tr("&Update!"),this);
    btnRandomize=new QPushButton(tr("&Shuffle!"),this);
    btnExit=new QPushButton(tr("E&xit"),this);

    mainLayout=new QVBoxLayout(this);
    buttonLayout=new QHBoxLayout(this);
    seatLayout=new QGridLayout(this);

    //default files
    db_people_filename="./people.txt";
    db_rule_filename="./seating.txt";

    init_data();
    init_seat();

    buttonLayout->addWidget(btnChangePeople);
    buttonLayout->addWidget(btnChangeRule);
    buttonLayout->addWidget(btnUpdate);
    buttonLayout->addStretch();
    buttonLayout->addWidget(btnRandomize);
    buttonLayout->addWidget(btnExit);

    connect(btnChangePeople,SIGNAL(clicked()),this,SLOT(change_people()));
    connect(btnChangeRule,SIGNAL(clicked()),this,SLOT(change_rule()));
    connect(btnUpdate,SIGNAL(clicked()),this,SLOT(update()));
    connect(btnExit,SIGNAL(clicked()),this,SLOT(accept()));
    connect(btnRandomize,SIGNAL(clicked()),this,SLOT(shuffle_animated()));

    mainLayout->addLayout(seatLayout);
    mainLayout->addLayout(buttonLayout);
    this->setLayout(mainLayout);
}

void Dialog::init_seat(){
    QBrush fontBrush(QColor(FONTCOLOR));
    fontBrush.setStyle(Qt::SolidPattern);

    QBrush seatBrush(QColor(SEATCOLOR));
    seatBrush.setStyle(Qt::SolidPattern);

    palette.setBrush(QPalette::Active, QPalette::WindowText, fontBrush);
    palette.setBrush(QPalette::Inactive, QPalette::WindowText, fontBrush);

    palette.setBrush(QPalette::Active, QPalette::Window, seatBrush);
    palette.setBrush(QPalette::Inactive, QPalette::Window, seatBrush);

    font.setPointSize(FONTSIZE);
    font.setBold(true);
    font.setFamily(FONTFAMILY);

    for(int i=0;i<rule_row;++i){
        for(int j=0;j<rule_column;++j){
            if(rule[i][j]=='.') seatLayout->addItem(new QSpacerItem(SPACERSIZE),i,j);
            else{
                init_seat_aux();
                seatLayout->addWidget(seat,i,j);
                seating.push_back(seat);
                seating_rule.push_back((rule[i][j]=='m'? MALE : FEMALE));
            }
        }
    }

}

void Dialog::init_seat_aux(){
    seat=new QLabel("-",this);
    seat->setPalette(palette);
    seat->setFont(font);
    seat->setAutoFillBackground(true);
    seat->setAlignment(Qt::AlignCenter);
    seat->setMinimumSize(SEATMINIMUMSIZE);
}

void Dialog::init_data(){
    //get data
    QString s;
    QFile db_people(db_people_filename),db_rule(db_rule_filename);
    if(!db_people.open(QIODevice::ReadOnly)) {
        QMessageBox::information(0, tr("Error"), db_people.errorString());
    }
    if(!db_rule.open(QIODevice::ReadOnly)) {
        QMessageBox::information(0, tr("Error"), db_rule.errorString());
    }

    QTextStream in_people(&db_people),in_rule(&db_rule);

    in_people>>male_count;
    in_people.readLine(); //clearing
    for(int i=0;i<male_count;++i){
        s = in_people.readLine();
        if(s.size())male.push_back(s);
    }

    in_people>>female_count;
    in_people.readLine();
    for(int i=0;i<female_count;++i) {
        s = in_people.readLine();
        if(s.size())female.push_back(s);
    }
    db_people.close();

    in_rule>>rule_male>>rule_female;
    if(rule_male!=male_count || rule_female!=female_count)
        QMessageBox::information(0, tr("Error"), tr("Mismatch number of person"));

    in_rule>>rule_row>>rule_column;
    for(int i=0;i<rule_row;++i){
        in_rule>>s;
        rule.push_back(s);
    }
    db_rule.close();

}

void Dialog::change_people(){
    db_people_filename=
            QFileDialog::getOpenFileName(this,
                                         tr("Select file..."),
                                         QDir::homePath(),
                                         tr("Text files (*.txt)"));
    if(!QFile(db_people_filename).exists()){
        QMessageBox::information(0, tr("Error"), "File not found");
        db_people_filename="./people.txt";
    }
}

void Dialog::change_rule(){
    db_rule_filename=
            QFileDialog::getOpenFileName(this,
                                         tr("Select file..."),
                                         QDir::homePath(),
                                         tr("Text files (*.txt)"));
    if(!QFile(db_rule_filename).exists()){
        QMessageBox::information(0, tr("Error"), "File not found");
        db_rule_filename="./seating.txt";
    }
}

void Dialog::update(){
    //empty all
    male.clear();
    female.clear();
    seating_rule.clear();
    for(int i=0;i<rule_row;++i)
        for(int j=0;j<rule_column;++j)
            seatLayout->removeItem(seatLayout->itemAtPosition(i,j));
    for(int i=0;i<seating.size();++i)
        delete seating[i];
    seating.clear();
    rule.clear();

    //redo
    init_data();
    init_seat();

}
<|endoftext|>


<commit_before>#include "dbreader.h"

#define DEBUG if (0) qDebug() << __PRETTY_FUNCTION__

DbReader::DbReader(QObject *parent)
    : QObject(parent), m_stop(false)
{
    qRegisterMetaType<QList<QSqlRecord> >();
    qRegisterMetaType<QSqlDatabase>();
    qRegisterMetaType<QSqlQuery>();
    qRegisterMetaType<DbReader *>();
    qRegisterMetaType<void *>();
}

DbReader::~DbReader()
{
    QSqlDatabase::removeDatabase(m_db.connectionName());
}

void DbReader::stop()
{
    m_stop = true;
}

void DbReader::initialize(const QSqlDatabase &db)
{
    m_db = QSqlDatabase::cloneDatabase(db, QUuid::createUuid().toString());
    if (!m_db.open())
        qFatal("Erorr opening database: %s", qPrintable(m_db.lastError().text()));
}

void DbReader::execute(const QSqlQuery &q, void *userData)
{
    QSqlQuery query(q);
    query.setForwardOnly(true);
    query.exec();

    QList<QSqlRecord> data = readRecords(query);
    DEBUG << "Read " << data.count() << "records";

    if (!m_stop)
        emit dataReady(this, data, userData);
}

QList<QSqlRecord> DbReader::readRecords(QSqlQuery &query)
{
    QList<QSqlRecord> data;
    while (query.next() && !m_stop) {
        data.append(query.record());
    }
    return data;
}

<commit_msg>Print error when exec fails<commit_after>#include "dbreader.h"

#define DEBUG if (0) qDebug() << __PRETTY_FUNCTION__

DbReader::DbReader(QObject *parent)
    : QObject(parent), m_stop(false)
{
    qRegisterMetaType<QList<QSqlRecord> >();
    qRegisterMetaType<QSqlDatabase>();
    qRegisterMetaType<QSqlQuery>();
    qRegisterMetaType<DbReader *>();
    qRegisterMetaType<void *>();
}

DbReader::~DbReader()
{
    QSqlDatabase::removeDatabase(m_db.connectionName());
}

void DbReader::stop()
{
    m_stop = true;
}

void DbReader::initialize(const QSqlDatabase &db)
{
    m_db = QSqlDatabase::cloneDatabase(db, QUuid::createUuid().toString());
    if (!m_db.open())
        qFatal("Erorr opening database: %s", qPrintable(m_db.lastError().text()));
}

void DbReader::execute(const QSqlQuery &q, void *userData)
{
    QSqlQuery query(q);
    query.setForwardOnly(true);
    if (!query.exec())
        qFatal("Error executing query: %s", qPrintable(query.lastQuery()));

    QList<QSqlRecord> data = readRecords(query);
    DEBUG << "Read " << data.count() << "records";

    if (!m_stop)
        emit dataReady(this, data, userData);
}

QList<QSqlRecord> DbReader::readRecords(QSqlQuery &query)
{
    QList<QSqlRecord> data;
    while (query.next() && !m_stop) {
        data.append(query.record());
    }
    return data;
}

<|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2014, Balazs Racz
 * 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.
 *
 * \file dcc/Defs.hxx
 *
 * Definitions for DCC concepts.
 *
 * @author Balazs Racz
 * @date 27 Feb 2016
 */

#ifndef _DCC_DEFS_HXX_
#define _DCC_DEFS_HXX_

namespace dcc {

/// Which address type this legacy train node uses. These address types
/// translate to mutually independent packets on the track.
enum class TrainAddressType
{
    /// DCC packets with short address (1..127)
    DCC_SHORT_ADDRESS = 1,
    /// DCC packets with long address (128..~10000)
    DCC_LONG_ADDRESS,
    /// Marklin-motorola packets. Addresses 1..80 are supported.
    MM,
    /// Unsupported address type (e.g. a protocol we don't have an
    /// implementation for).
    UNSUPPORTED = 255,
    /// Unspecified address type (default / match any).
    UNSPECIFIED = 254,
};

}  // namespace dcc

#endif
<commit_msg>Makes TrainAddressType fit into a uint8.<commit_after>/** \copyright
 * Copyright (c) 2014, Balazs Racz
 * 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.
 *
 * \file dcc/Defs.hxx
 *
 * Definitions for DCC concepts.
 *
 * @author Balazs Racz
 * @date 27 Feb 2016
 */

#ifndef _DCC_DEFS_HXX_
#define _DCC_DEFS_HXX_

namespace dcc {

/// Which address type this legacy train node uses. These address types
/// translate to mutually independent packets on the track.
enum class TrainAddressType : uint8_t
{
    /// DCC packets with short address (1..127)
    DCC_SHORT_ADDRESS = 1,
    /// DCC packets with long address (128..~10000)
    DCC_LONG_ADDRESS,
    /// Marklin-motorola packets. Addresses 1..80 are supported.
    MM,
    /// Unsupported address type (e.g. a protocol we don't have an
    /// implementation for).
    UNSUPPORTED = 255,
    /// Unspecified address type (default / match any).
    UNSPECIFIED = 254,
};

}  // namespace dcc

#endif
<|endoftext|>


<commit_before>/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkFlags.h"

SkFlagInfo* SkFlags::gHead;
SkString SkFlags::gUsage;

void SkFlags::SetUsage(const char* usage) {
    gUsage.set(usage);
}

// Maximum line length for the help message.
#define LINE_LENGTH 80

static void print_help_for_flag(const SkFlagInfo* flag) {
    SkDebugf("\t--%s", flag->name().c_str());
    const SkString& shortName = flag->shortName();
    if (shortName.size() > 0) {
        SkDebugf(" or -%s", shortName.c_str());
    }
    SkDebugf(":\ttype: %s", flag->typeAsString().c_str());
    if (flag->defaultValue().size() > 0) {
        SkDebugf("\tdefault: %s", flag->defaultValue().c_str());
    }
    SkDebugf("\n");
    const SkString& help = flag->help();
    size_t length = help.size();
    const char* currLine = help.c_str();
    const char* stop = currLine + length;
    while (currLine < stop) {
        if (strlen(currLine) < LINE_LENGTH) {
            // Only one line length's worth of text left.
            SkDebugf("\t\t%s\n", currLine);
            break;
        }
        int lineBreak = SkStrFind(currLine, "\n");
        if (lineBreak < 0 || lineBreak > LINE_LENGTH) {
            // No line break within line length. Will need to insert one.
            // Find a space before the line break.
            int spaceIndex = LINE_LENGTH - 1;
            while (spaceIndex > 0 && currLine[spaceIndex] != ' ') {
                spaceIndex--;
            }
            int gap;
            if (0 == spaceIndex) {
                // No spaces on the entire line. Go ahead and break mid word.
                spaceIndex = LINE_LENGTH;
                gap = 0;
            } else {
                // Skip the space on the next line
                gap = 1;
            }
            SkDebugf("\t\t%.*s\n", spaceIndex, currLine);
            currLine += spaceIndex + gap;
        } else {
            // the line break is within the limit. Break there.
            lineBreak++;
            SkDebugf("\t\t%.*s", lineBreak, currLine);
            currLine += lineBreak;
        }
    }
    SkDebugf("\n");
}

void SkFlags::ParseCommandLine(int argc, char** argv) {
    // Only allow calling this function once.
    static bool gOnce;
    if (gOnce) {
        SkDebugf("ParseCommandLine should only be called once at the beginning"
                 " of main!\n");
        SkASSERT(false);
        return;
    }
    gOnce = true;

    bool helpPrinted = false;
    // Loop over argv, starting with 1, since the first is just the name of the program.
    for (int i = 1; i < argc; i++) {
        if (0 == strcmp("-h", argv[i]) || 0 == strcmp("--h", argv[i])
                || 0 == strcmp("-help", argv[i]) || 0 == strcmp("--help", argv[i])) {
            // Print help message.
            SkTDArray<const char*> helpFlags;
            for (int j = i + 1; j < argc; j++) {
                if (SkStrStartsWith(argv[j], '-')) {
                    break;
                }
                helpFlags.append(1, &argv[j]);
            }
            if (0 == helpFlags.count()) {
                // Only print general help message if help for specific flags is not requested.
                SkDebugf("%s\n%s\n", argv[0], gUsage.c_str());
            }
            SkDebugf("Flags:\n");
            SkFlagInfo* flag = SkFlags::gHead;
            while (flag != NULL) {
                // If no flags followed --help, print them all
                bool printFlag = 0 == helpFlags.count();
                if (!printFlag) {
                    for (int k = 0; k < helpFlags.count(); k++) {
                        if (flag->name().equals(helpFlags[k]) ||
                            flag->shortName().equals(helpFlags[k])) {
                            printFlag = true;
                            helpFlags.remove(k);
                            break;
                        }
                    }
                }
                if (printFlag) {
                    print_help_for_flag(flag);
                }
                flag = flag->next();
            }
            if (helpFlags.count() > 0) {
                SkDebugf("Requested help for unrecognized flags:\n");
                for (int k = 0; k < helpFlags.count(); k++) {
                    SkDebugf("\t--%s\n", helpFlags[k]);
                }
            }
            helpPrinted = true;
        }
        if (!helpPrinted) {
            bool flagMatched = false;
            SkFlagInfo* flag = gHead;
            while (flag != NULL) {
                if (flag->match(argv[i])) {
                    flagMatched = true;
                    switch (flag->getFlagType()) {
                        case SkFlagInfo::kBool_FlagType:
                            // Handled by match, above
                            break;
                        case SkFlagInfo::kString_FlagType:
                            flag->resetStrings();
                            // Add all arguments until another flag is reached.
                            while (i+1 < argc && !SkStrStartsWith(argv[i+1], '-')) {
                                i++;
                                flag->append(argv[i]);
                            }
                            break;
                        case SkFlagInfo::kInt_FlagType:
                            i++;
                            flag->setInt(atoi(argv[i]));
                            break;
                        case SkFlagInfo::kDouble_FlagType:
                            i++;
                            flag->setDouble(atof(argv[i]));
                            break;
                        default:
                            SkASSERT(!"Invalid flag type");
                    }
                    break;
                }
                flag = flag->next();
            }
            if (!flagMatched) {
                SkDebugf("skipping unknown flag %s\n", argv[i]);
            }
        }
    }
    // Since all of the flags have been set, release the memory used by each
    // flag. FLAGS_x can still be used after this.
    SkFlagInfo* flag = gHead;
    gHead = NULL;
    while (flag != NULL) {
        SkFlagInfo* next = flag->next();
        SkDELETE(flag);
        flag = next;
    }
    if (helpPrinted) {
        exit(0);
    }
}
<commit_msg>When SkFlags encounters an invalid flag, quit.<commit_after>/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkFlags.h"

SkFlagInfo* SkFlags::gHead;
SkString SkFlags::gUsage;

void SkFlags::SetUsage(const char* usage) {
    gUsage.set(usage);
}

// Maximum line length for the help message.
#define LINE_LENGTH 80

static void print_help_for_flag(const SkFlagInfo* flag) {
    SkDebugf("\t--%s", flag->name().c_str());
    const SkString& shortName = flag->shortName();
    if (shortName.size() > 0) {
        SkDebugf(" or -%s", shortName.c_str());
    }
    SkDebugf(":\ttype: %s", flag->typeAsString().c_str());
    if (flag->defaultValue().size() > 0) {
        SkDebugf("\tdefault: %s", flag->defaultValue().c_str());
    }
    SkDebugf("\n");
    const SkString& help = flag->help();
    size_t length = help.size();
    const char* currLine = help.c_str();
    const char* stop = currLine + length;
    while (currLine < stop) {
        if (strlen(currLine) < LINE_LENGTH) {
            // Only one line length's worth of text left.
            SkDebugf("\t\t%s\n", currLine);
            break;
        }
        int lineBreak = SkStrFind(currLine, "\n");
        if (lineBreak < 0 || lineBreak > LINE_LENGTH) {
            // No line break within line length. Will need to insert one.
            // Find a space before the line break.
            int spaceIndex = LINE_LENGTH - 1;
            while (spaceIndex > 0 && currLine[spaceIndex] != ' ') {
                spaceIndex--;
            }
            int gap;
            if (0 == spaceIndex) {
                // No spaces on the entire line. Go ahead and break mid word.
                spaceIndex = LINE_LENGTH;
                gap = 0;
            } else {
                // Skip the space on the next line
                gap = 1;
            }
            SkDebugf("\t\t%.*s\n", spaceIndex, currLine);
            currLine += spaceIndex + gap;
        } else {
            // the line break is within the limit. Break there.
            lineBreak++;
            SkDebugf("\t\t%.*s", lineBreak, currLine);
            currLine += lineBreak;
        }
    }
    SkDebugf("\n");
}

void SkFlags::ParseCommandLine(int argc, char** argv) {
    // Only allow calling this function once.
    static bool gOnce;
    if (gOnce) {
        SkDebugf("ParseCommandLine should only be called once at the beginning"
                 " of main!\n");
        SkASSERT(false);
        return;
    }
    gOnce = true;

    bool helpPrinted = false;
    // Loop over argv, starting with 1, since the first is just the name of the program.
    for (int i = 1; i < argc; i++) {
        if (0 == strcmp("-h", argv[i]) || 0 == strcmp("--h", argv[i])
                || 0 == strcmp("-help", argv[i]) || 0 == strcmp("--help", argv[i])) {
            // Print help message.
            SkTDArray<const char*> helpFlags;
            for (int j = i + 1; j < argc; j++) {
                if (SkStrStartsWith(argv[j], '-')) {
                    break;
                }
                helpFlags.append(1, &argv[j]);
            }
            if (0 == helpFlags.count()) {
                // Only print general help message if help for specific flags is not requested.
                SkDebugf("%s\n%s\n", argv[0], gUsage.c_str());
            }
            SkDebugf("Flags:\n");
            SkFlagInfo* flag = SkFlags::gHead;
            while (flag != NULL) {
                // If no flags followed --help, print them all
                bool printFlag = 0 == helpFlags.count();
                if (!printFlag) {
                    for (int k = 0; k < helpFlags.count(); k++) {
                        if (flag->name().equals(helpFlags[k]) ||
                            flag->shortName().equals(helpFlags[k])) {
                            printFlag = true;
                            helpFlags.remove(k);
                            break;
                        }
                    }
                }
                if (printFlag) {
                    print_help_for_flag(flag);
                }
                flag = flag->next();
            }
            if (helpFlags.count() > 0) {
                SkDebugf("Requested help for unrecognized flags:\n");
                for (int k = 0; k < helpFlags.count(); k++) {
                    SkDebugf("\t--%s\n", helpFlags[k]);
                }
            }
            helpPrinted = true;
        }
        if (!helpPrinted) {
            bool flagMatched = false;
            SkFlagInfo* flag = gHead;
            while (flag != NULL) {
                if (flag->match(argv[i])) {
                    flagMatched = true;
                    switch (flag->getFlagType()) {
                        case SkFlagInfo::kBool_FlagType:
                            // Handled by match, above
                            break;
                        case SkFlagInfo::kString_FlagType:
                            flag->resetStrings();
                            // Add all arguments until another flag is reached.
                            while (i+1 < argc && !SkStrStartsWith(argv[i+1], '-')) {
                                i++;
                                flag->append(argv[i]);
                            }
                            break;
                        case SkFlagInfo::kInt_FlagType:
                            i++;
                            flag->setInt(atoi(argv[i]));
                            break;
                        case SkFlagInfo::kDouble_FlagType:
                            i++;
                            flag->setDouble(atof(argv[i]));
                            break;
                        default:
                            SkASSERT(!"Invalid flag type");
                    }
                    break;
                }
                flag = flag->next();
            }
            if (!flagMatched) {
                SkDebugf("Got unknown flag \"%s\". Exiting.\n", argv[i]);
                exit(-1);
            }
        }
    }
    // Since all of the flags have been set, release the memory used by each
    // flag. FLAGS_x can still be used after this.
    SkFlagInfo* flag = gHead;
    gHead = NULL;
    while (flag != NULL) {
        SkFlagInfo* next = flag->next();
        SkDELETE(flag);
        flag = next;
    }
    if (helpPrinted) {
        exit(0);
    }
}
<|endoftext|>