<commit_before>//===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This implements support for bulk buffered stream output.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Format.h"
#include "llvm/System/Program.h"
#include "llvm/System/Process.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Compiler.h"
#include <ostream>

#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined(HAVE_FCNTL_H)
# include <fcntl.h>
#endif

#if defined(_MSC_VER)
#include <io.h>
#include <fcntl.h>
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
# define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
# define STDERR_FILENO 2
#endif
#endif

using namespace llvm;

// An out of line virtual method to provide a home for the class vtable.
void raw_ostream::handle() {}

raw_ostream &raw_ostream::operator<<(unsigned long N) {
  // Zero is a special case.
  if (N == 0)
    return *this << '0';

  char NumberBuffer[20];
  char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
  char *CurPtr = EndPtr;

  while (N) {
    *--CurPtr = '0' + char(N % 10);
    N /= 10;
  }
  return write(CurPtr, EndPtr-CurPtr);
}

raw_ostream &raw_ostream::operator<<(long N) {
  if (N <  0) {
    *this << '-';
    N = -N;
  }

  return this->operator<<(static_cast<unsigned long>(N));
}

raw_ostream &raw_ostream::operator<<(unsigned long long N) {
  // Zero is a special case.
  if (N == 0)
    return *this << '0';

  char NumberBuffer[20];
  char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
  char *CurPtr = EndPtr;

  while (N) {
    *--CurPtr = '0' + char(N % 10);
    N /= 10;
  }
  return write(CurPtr, EndPtr-CurPtr);
}

raw_ostream &raw_ostream::operator<<(long long N) {
  if (N <  0) {
    *this << '-';
    N = -N;
  }

  return this->operator<<(static_cast<unsigned long long>(N));
}

raw_ostream &raw_ostream::operator<<(const void *P) {
  uintptr_t N = (uintptr_t) P;
  *this << '0' << 'x';

  // Zero is a special case.
  if (N == 0)
    return *this << '0';

  char NumberBuffer[20];
  char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
  char *CurPtr = EndPtr;

  while (N) {
    unsigned x = N % 16;
    *--CurPtr = (x < 10 ? '0' + x : 'a' + x - 10);
    N /= 16;
  }

  return write(CurPtr, EndPtr-CurPtr);
}

void raw_ostream::flush_nonempty() {
  assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty.");
  write_impl(OutBufStart, OutBufCur - OutBufStart);
  OutBufCur = OutBufStart;
}

raw_ostream &raw_ostream::write(unsigned char C) {
  // Group exceptional cases into a single branch.
  if (OutBufCur >= OutBufEnd) {
    if (Unbuffered) {
      write_impl(reinterpret_cast<char*>(&C), 1);
      return *this;
    }

    if (!OutBufStart)
      SetBufferSize();
    else
      flush_nonempty();
  }

  *OutBufCur++ = C;
  return *this;
}

raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) {
  // Group exceptional cases into a single branch.
  if (BUILTIN_EXPECT(OutBufCur+Size > OutBufEnd, false)) {
    if (Unbuffered) {
      write_impl(Ptr, Size);
      return *this;
    }

    if (!OutBufStart)
      SetBufferSize();
    else
      flush_nonempty();
  }

  // Handle short strings specially, memcpy isn't very good at very short
  // strings.
  switch (Size) {
  case 4: OutBufCur[3] = Ptr[3]; // FALL THROUGH
  case 3: OutBufCur[2] = Ptr[2]; // FALL THROUGH
  case 2: OutBufCur[1] = Ptr[1]; // FALL THROUGH
  case 1: OutBufCur[0] = Ptr[0]; // FALL THROUGH
  case 0: break;
  default:
    // Normally the string to emit is shorter than the buffer.
    if (Size <= unsigned(OutBufEnd-OutBufCur)) {
      memcpy(OutBufCur, Ptr, Size);
      break;
    }

    // Otherwise we are emitting a string larger than our buffer. We
    // know we already flushed, so just write it out directly.
    write_impl(Ptr, Size);
    Size = 0;
    break;
  }
  OutBufCur += Size;

  return *this;
}

// Formatted output.
raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) {
  // If we have more than a few bytes left in our output buffer, try
  // formatting directly onto its end.
  //
  // FIXME: This test is a bit silly, since if we don't have enough
  // space in the buffer we will have to flush the formatted output
  // anyway. We should just flush upfront in such cases, and use the
  // whole buffer as our scratch pad. Note, however, that this case is
  // also necessary for correctness on unbuffered streams.
  unsigned NextBufferSize = 127;
  if (OutBufEnd-OutBufCur > 3) {
    unsigned BufferBytesLeft = OutBufEnd-OutBufCur;
    unsigned BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft);

    // Common case is that we have plenty of space.
    if (BytesUsed < BufferBytesLeft) {
      OutBufCur += BytesUsed;
      return *this;
    }

    // Otherwise, we overflowed and the return value tells us the size to try
    // again with.
    NextBufferSize = BytesUsed;
  }

  // If we got here, we didn't have enough space in the output buffer for the
  // string.  Try printing into a SmallVector that is resized to have enough
  // space.  Iterate until we win.
  SmallVector<char, 128> V;

  while (1) {
    V.resize(NextBufferSize);

    // Try formatting into the SmallVector.
    unsigned BytesUsed = Fmt.print(&V[0], NextBufferSize);

    // If BytesUsed fit into the vector, we win.
    if (BytesUsed <= NextBufferSize)
      return write(&V[0], BytesUsed);

    // Otherwise, try again with a new size.
    assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?");
    NextBufferSize = BytesUsed;
  }
}

//===----------------------------------------------------------------------===//
//  Formatted Output
//===----------------------------------------------------------------------===//

// Out of line virtual method.
void format_object_base::home() {
}

//===----------------------------------------------------------------------===//
//  raw_fd_ostream
//===----------------------------------------------------------------------===//

/// raw_fd_ostream - Open the specified file for writing. If an error
/// occurs, information about the error is put into ErrorInfo, and the
/// stream should be immediately destroyed; the string will be empty
/// if no error occurred.
raw_fd_ostream::raw_fd_ostream(const char *Filename, bool Binary,
                               std::string &ErrorInfo) : pos(0) {
  ErrorInfo.clear();

  // Handle "-" as stdout.
  if (Filename[0] == '-' && Filename[1] == 0) {
    FD = STDOUT_FILENO;
    // If user requested binary then put stdout into binary mode if
    // possible.
    if (Binary)
      sys::Program::ChangeStdoutToBinary();
    ShouldClose = false;
    return;
  }

  int Flags = O_WRONLY|O_CREAT|O_TRUNC;
#ifdef O_BINARY
  if (Binary)
    Flags |= O_BINARY;
#endif
  FD = open(Filename, Flags, 0644);
  if (FD < 0) {
    ErrorInfo = "Error opening output file '" + std::string(Filename) + "'";
    ShouldClose = false;
  } else {
    ShouldClose = true;
  }
}

raw_fd_ostream::~raw_fd_ostream() {
  if (FD >= 0) {
    flush();
    if (ShouldClose)
      ::close(FD);
  }
}

void raw_fd_ostream::write_impl(const char *Ptr, unsigned Size) {
  assert (FD >= 0 && "File already closed.");
  pos += Size;
  ::write(FD, Ptr, Size);
}

void raw_fd_ostream::close() {
  assert (ShouldClose);
  ShouldClose = false;
  flush();
  ::close(FD);
  FD = -1;
}

uint64_t raw_fd_ostream::seek(uint64_t off) {
  flush();
  pos = lseek(FD, off, SEEK_SET);
  return pos;
}

raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold,
                                         bool bg) {
  if (sys::Process::ColorNeedsFlush())
    flush();
  const char *colorcode =
    (colors == SAVEDCOLOR) ? sys::Process::OutputBold(bg)
    : sys::Process::OutputColor(colors, bold, bg);
  if (colorcode) {
    unsigned len = strlen(colorcode);
    write(colorcode, len);
    // don't account colors towards output characters
    pos -= len;
  }
  return *this;
}

raw_ostream &raw_fd_ostream::resetColor() {
  if (sys::Process::ColorNeedsFlush())
    flush();
  const char *colorcode = sys::Process::ResetColor();
  if (colorcode) {
    unsigned len = strlen(colorcode);
    write(colorcode, len);
    // don't account colors towards output characters
    pos -= len;
  }
  return *this;
}

//===----------------------------------------------------------------------===//
//  raw_stdout/err_ostream
//===----------------------------------------------------------------------===//

raw_stdout_ostream::raw_stdout_ostream():raw_fd_ostream(STDOUT_FILENO, false) {}
raw_stderr_ostream::raw_stderr_ostream():raw_fd_ostream(STDERR_FILENO, false,
                                                        true) {}

// An out of line virtual method to provide a home for the class vtable.
void raw_stdout_ostream::handle() {}
void raw_stderr_ostream::handle() {}

/// outs() - This returns a reference to a raw_ostream for standard output.
/// Use it like: outs() << "foo" << "bar";
raw_ostream &llvm::outs() {
  static raw_stdout_ostream S;
  return S;
}

/// errs() - This returns a reference to a raw_ostream for standard error.
/// Use it like: errs() << "foo" << "bar";
raw_ostream &llvm::errs() {
  static raw_stderr_ostream S;
  return S;
}

//===----------------------------------------------------------------------===//
//  raw_os_ostream
//===----------------------------------------------------------------------===//

raw_os_ostream::~raw_os_ostream() {
  flush();
}

void raw_os_ostream::write_impl(const char *Ptr, unsigned Size) {
  OS.write(Ptr, Size);
}

uint64_t raw_os_ostream::current_pos() { return OS.tellp(); }

uint64_t raw_os_ostream::tell() {
  return (uint64_t)OS.tellp() + GetNumBytesInBuffer();
}

//===----------------------------------------------------------------------===//
//  raw_string_ostream
//===----------------------------------------------------------------------===//

raw_string_ostream::~raw_string_ostream() {
  flush();
}

void raw_string_ostream::write_impl(const char *Ptr, unsigned Size) {
  OS.append(Ptr, Size);
}

//===----------------------------------------------------------------------===//
//  raw_svector_ostream
//===----------------------------------------------------------------------===//

raw_svector_ostream::~raw_svector_ostream() {
  flush();
}

void raw_svector_ostream::write_impl(const char *Ptr, unsigned Size) {
  OS.append(Ptr, Ptr + Size);
}

uint64_t raw_svector_ostream::current_pos() { return OS.size(); }

uint64_t raw_svector_ostream::tell() {
  return OS.size() + GetNumBytesInBuffer();
}
<commit_msg>Detect write failures on raw_fd_ostream.<commit_after>//===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This implements support for bulk buffered stream output.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Format.h"
#include "llvm/System/Program.h"
#include "llvm/System/Process.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <ostream>

#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined(HAVE_FCNTL_H)
# include <fcntl.h>
#endif

#if defined(_MSC_VER)
#include <io.h>
#include <fcntl.h>
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
# define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
# define STDERR_FILENO 2
#endif
#endif

using namespace llvm;

// An out of line virtual method to provide a home for the class vtable.
void raw_ostream::handle() {}

raw_ostream &raw_ostream::operator<<(unsigned long N) {
  // Zero is a special case.
  if (N == 0)
    return *this << '0';

  char NumberBuffer[20];
  char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
  char *CurPtr = EndPtr;

  while (N) {
    *--CurPtr = '0' + char(N % 10);
    N /= 10;
  }
  return write(CurPtr, EndPtr-CurPtr);
}

raw_ostream &raw_ostream::operator<<(long N) {
  if (N <  0) {
    *this << '-';
    N = -N;
  }

  return this->operator<<(static_cast<unsigned long>(N));
}

raw_ostream &raw_ostream::operator<<(unsigned long long N) {
  // Zero is a special case.
  if (N == 0)
    return *this << '0';

  char NumberBuffer[20];
  char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
  char *CurPtr = EndPtr;

  while (N) {
    *--CurPtr = '0' + char(N % 10);
    N /= 10;
  }
  return write(CurPtr, EndPtr-CurPtr);
}

raw_ostream &raw_ostream::operator<<(long long N) {
  if (N <  0) {
    *this << '-';
    N = -N;
  }

  return this->operator<<(static_cast<unsigned long long>(N));
}

raw_ostream &raw_ostream::operator<<(const void *P) {
  uintptr_t N = (uintptr_t) P;
  *this << '0' << 'x';

  // Zero is a special case.
  if (N == 0)
    return *this << '0';

  char NumberBuffer[20];
  char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
  char *CurPtr = EndPtr;

  while (N) {
    unsigned x = N % 16;
    *--CurPtr = (x < 10 ? '0' + x : 'a' + x - 10);
    N /= 16;
  }

  return write(CurPtr, EndPtr-CurPtr);
}

void raw_ostream::flush_nonempty() {
  assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty.");
  write_impl(OutBufStart, OutBufCur - OutBufStart);
  OutBufCur = OutBufStart;
}

raw_ostream &raw_ostream::write(unsigned char C) {
  // Group exceptional cases into a single branch.
  if (OutBufCur >= OutBufEnd) {
    if (Unbuffered) {
      write_impl(reinterpret_cast<char*>(&C), 1);
      return *this;
    }

    if (!OutBufStart)
      SetBufferSize();
    else
      flush_nonempty();
  }

  *OutBufCur++ = C;
  return *this;
}

raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) {
  // Group exceptional cases into a single branch.
  if (BUILTIN_EXPECT(OutBufCur+Size > OutBufEnd, false)) {
    if (Unbuffered) {
      write_impl(Ptr, Size);
      return *this;
    }

    if (!OutBufStart)
      SetBufferSize();
    else
      flush_nonempty();
  }

  // Handle short strings specially, memcpy isn't very good at very short
  // strings.
  switch (Size) {
  case 4: OutBufCur[3] = Ptr[3]; // FALL THROUGH
  case 3: OutBufCur[2] = Ptr[2]; // FALL THROUGH
  case 2: OutBufCur[1] = Ptr[1]; // FALL THROUGH
  case 1: OutBufCur[0] = Ptr[0]; // FALL THROUGH
  case 0: break;
  default:
    // Normally the string to emit is shorter than the buffer.
    if (Size <= unsigned(OutBufEnd-OutBufCur)) {
      memcpy(OutBufCur, Ptr, Size);
      break;
    }

    // Otherwise we are emitting a string larger than our buffer. We
    // know we already flushed, so just write it out directly.
    write_impl(Ptr, Size);
    Size = 0;
    break;
  }
  OutBufCur += Size;

  return *this;
}

// Formatted output.
raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) {
  // If we have more than a few bytes left in our output buffer, try
  // formatting directly onto its end.
  //
  // FIXME: This test is a bit silly, since if we don't have enough
  // space in the buffer we will have to flush the formatted output
  // anyway. We should just flush upfront in such cases, and use the
  // whole buffer as our scratch pad. Note, however, that this case is
  // also necessary for correctness on unbuffered streams.
  unsigned NextBufferSize = 127;
  if (OutBufEnd-OutBufCur > 3) {
    unsigned BufferBytesLeft = OutBufEnd-OutBufCur;
    unsigned BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft);

    // Common case is that we have plenty of space.
    if (BytesUsed < BufferBytesLeft) {
      OutBufCur += BytesUsed;
      return *this;
    }

    // Otherwise, we overflowed and the return value tells us the size to try
    // again with.
    NextBufferSize = BytesUsed;
  }

  // If we got here, we didn't have enough space in the output buffer for the
  // string.  Try printing into a SmallVector that is resized to have enough
  // space.  Iterate until we win.
  SmallVector<char, 128> V;

  while (1) {
    V.resize(NextBufferSize);

    // Try formatting into the SmallVector.
    unsigned BytesUsed = Fmt.print(&V[0], NextBufferSize);

    // If BytesUsed fit into the vector, we win.
    if (BytesUsed <= NextBufferSize)
      return write(&V[0], BytesUsed);

    // Otherwise, try again with a new size.
    assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?");
    NextBufferSize = BytesUsed;
  }
}

//===----------------------------------------------------------------------===//
//  Formatted Output
//===----------------------------------------------------------------------===//

// Out of line virtual method.
void format_object_base::home() {
}

//===----------------------------------------------------------------------===//
//  raw_fd_ostream
//===----------------------------------------------------------------------===//

/// raw_fd_ostream - Open the specified file for writing. If an error
/// occurs, information about the error is put into ErrorInfo, and the
/// stream should be immediately destroyed; the string will be empty
/// if no error occurred.
raw_fd_ostream::raw_fd_ostream(const char *Filename, bool Binary,
                               std::string &ErrorInfo) : pos(0) {
  ErrorInfo.clear();

  // Handle "-" as stdout.
  if (Filename[0] == '-' && Filename[1] == 0) {
    FD = STDOUT_FILENO;
    // If user requested binary then put stdout into binary mode if
    // possible.
    if (Binary)
      sys::Program::ChangeStdoutToBinary();
    ShouldClose = false;
    return;
  }

  int Flags = O_WRONLY|O_CREAT|O_TRUNC;
#ifdef O_BINARY
  if (Binary)
    Flags |= O_BINARY;
#endif
  FD = open(Filename, Flags, 0644);
  if (FD < 0) {
    ErrorInfo = "Error opening output file '" + std::string(Filename) + "'";
    ShouldClose = false;
  } else {
    ShouldClose = true;
  }
}

raw_fd_ostream::~raw_fd_ostream() {
  if (FD >= 0) {
    flush();
    if (ShouldClose)
      ::close(FD);
  }
}

void raw_fd_ostream::write_impl(const char *Ptr, unsigned Size) {
  assert (FD >= 0 && "File already closed.");
  pos += Size;
  if (::write(FD, Ptr, Size) != (ssize_t) Size)
    llvm_report_error("IO failure writing to output stream.");
}

void raw_fd_ostream::close() {
  assert (ShouldClose);
  ShouldClose = false;
  flush();
  ::close(FD);
  FD = -1;
}

uint64_t raw_fd_ostream::seek(uint64_t off) {
  flush();
  pos = ::lseek(FD, off, SEEK_SET);
  return pos;
}

raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold,
                                         bool bg) {
  if (sys::Process::ColorNeedsFlush())
    flush();
  const char *colorcode =
    (colors == SAVEDCOLOR) ? sys::Process::OutputBold(bg)
    : sys::Process::OutputColor(colors, bold, bg);
  if (colorcode) {
    unsigned len = strlen(colorcode);
    write(colorcode, len);
    // don't account colors towards output characters
    pos -= len;
  }
  return *this;
}

raw_ostream &raw_fd_ostream::resetColor() {
  if (sys::Process::ColorNeedsFlush())
    flush();
  const char *colorcode = sys::Process::ResetColor();
  if (colorcode) {
    unsigned len = strlen(colorcode);
    write(colorcode, len);
    // don't account colors towards output characters
    pos -= len;
  }
  return *this;
}

//===----------------------------------------------------------------------===//
//  raw_stdout/err_ostream
//===----------------------------------------------------------------------===//

raw_stdout_ostream::raw_stdout_ostream():raw_fd_ostream(STDOUT_FILENO, false) {}
raw_stderr_ostream::raw_stderr_ostream():raw_fd_ostream(STDERR_FILENO, false,
                                                        true) {}

// An out of line virtual method to provide a home for the class vtable.
void raw_stdout_ostream::handle() {}
void raw_stderr_ostream::handle() {}

/// outs() - This returns a reference to a raw_ostream for standard output.
/// Use it like: outs() << "foo" << "bar";
raw_ostream &llvm::outs() {
  static raw_stdout_ostream S;
  return S;
}

/// errs() - This returns a reference to a raw_ostream for standard error.
/// Use it like: errs() << "foo" << "bar";
raw_ostream &llvm::errs() {
  static raw_stderr_ostream S;
  return S;
}

//===----------------------------------------------------------------------===//
//  raw_os_ostream
//===----------------------------------------------------------------------===//

raw_os_ostream::~raw_os_ostream() {
  flush();
}

void raw_os_ostream::write_impl(const char *Ptr, unsigned Size) {
  OS.write(Ptr, Size);
}

uint64_t raw_os_ostream::current_pos() { return OS.tellp(); }

uint64_t raw_os_ostream::tell() {
  return (uint64_t)OS.tellp() + GetNumBytesInBuffer();
}

//===----------------------------------------------------------------------===//
//  raw_string_ostream
//===----------------------------------------------------------------------===//

raw_string_ostream::~raw_string_ostream() {
  flush();
}

void raw_string_ostream::write_impl(const char *Ptr, unsigned Size) {
  OS.append(Ptr, Size);
}

//===----------------------------------------------------------------------===//
//  raw_svector_ostream
//===----------------------------------------------------------------------===//

raw_svector_ostream::~raw_svector_ostream() {
  flush();
}

void raw_svector_ostream::write_impl(const char *Ptr, unsigned Size) {
  OS.append(Ptr, Ptr + Size);
}

uint64_t raw_svector_ostream::current_pos() { return OS.size(); }

uint64_t raw_svector_ostream::tell() {
  return OS.size() + GetNumBytesInBuffer();
}
<|endoftext|>


<commit_before>/*
* Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
* License for more details.
*
* $Id$
*/

#include "ircutil.h"

/*!
    \class Irc::Util ircutil.h
    \brief The Irc::Util class provides IRC related utility functions.
 */

namespace Irc
{
    /*!
        Parses and returns the nick part from \a target.
    */
    QString Irc::Util::nickFromTarget(const QString& target)
    {
        int index = target.indexOf(QLatin1Char('!'));
        return target.left(index);
    }

    /*!
        Parses and returns the host part from \a target.
    */
    QString Irc::Util::hostFromTarget(const QString& target)
    {
        int index = target.indexOf(QLatin1Char('!'));
        return target.mid(index + 1);
    }
}
<commit_msg>Added missing include.<commit_after>/*
* Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
* License for more details.
*
* $Id$
*/

#include "ircutil.h"
#include <QString>

/*!
    \class Irc::Util ircutil.h
    \brief The Irc::Util class provides IRC related utility functions.
 */

namespace Irc
{
    /*!
        Parses and returns the nick part from \a target.
    */
    QString Irc::Util::nickFromTarget(const QString& target)
    {
        int index = target.indexOf(QLatin1Char('!'));
        return target.left(index);
    }

    /*!
        Parses and returns the host part from \a target.
    */
    QString Irc::Util::hostFromTarget(const QString& target)
    {
        int index = target.indexOf(QLatin1Char('!'));
        return target.mid(index + 1);
    }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <unistd.h>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <cmath>
#include <utility>
#include <cassert>
#include <algorithm>
#include "Point.h"
#include "Strategy.h"
#include "Judge.h"
#define MAX_NODE 1000000
#define TIME_LIMIT 1
#define ROUND_MAC   0
#define ROUND_USR   1
#define THREAD_NUM 4
#define INFD 1e8
using namespace std;
struct Node {
  double score;
  long long tot;
  int nxt[12];

  void clear() {
    score = 0;
    tot = 1;
    memset(nxt, 255, sizeof(nxt));
  }
};
Node a[MAX_NODE];
int size, root;
time_t global_start;
void clear() {
  size = 1;
  root = 0;
  a[0].clear();
  global_start = time(0);
  srand(global_start);
}

int table1[12];
int table2[12];

int evaluate(int x, int y, int M, int N, int **board) {
  int cnt = 1;
  for (int dx = -1; dx <= 1; dx++)
    for (int dy = -1; dy <= 1; dy++)
      if (dx != 0 || dy != 0) {
        if (0 <= x + 2 * dx && x + 2 * dx < M && 0 <= y + 2 * dy && y + 2 * dy < N &&
            board[x + dx][y + dy] && board[x + 2 * dx][y + 2 * dy] == board[x + dx][y + dy])
            cnt += 4;
      }
  return cnt;
}

double Simulation(const int M, const int N, int *top, int **board,
                  const int lastX, const int lastY, const int noX, const int noY, const int dep) {

  if (dep == ROUND_MAC && userWin(lastX, lastY, M, N, board)) return 0;
  if (dep == ROUND_USR && machineWin(lastX, lastY, M, N, board)) return 1;
  if (isTie(N, top)) return 0.5;

  int posible = 0;
  for (int i = 0; i < N; i++)
    if (top[i]) {
      table1[posible] = evaluate(top[i] - 1, i, M, N, board) + (posible ? table1[posible - 1] : 0);
      table2[posible] = i;
      posible++;
    }

  assert(posible);
  assert(table1[posible - 1]);
  int idx = rand() % table1[posible - 1];
  int y = table2[lower_bound(table1, table1 + posible, idx) - table1];
//  printf("%d\n", y);
  assert(0 <= y && y < N);
  assert(top[y]);

  int x = top[y] - 1;
  assert(board[x][y] == 0);
  board[x][y] = 2 - dep;
  top[y]--;
  if (x - 1 == noX && y == noY) top[y]--;
  double score = Simulation(M, N, top, board, x, y, noX, noY, dep ^ 1);
  board[x][y] = 0;
  top[y] = x + 1;
  return score;
}
int SelectNode(int M, int N, int **board, int *top, int id, int dep) {
  int idx = -1;
  double best = -1;
  double tot = 2 * log(a[id].tot);
  assert(a[id].tot > 0);
  double tmp;
  for (int i = 0; i < N; i++) {
    if (a[id].nxt[i] == -1 && top[i]) {
      tmp = 1 + sqrt(tot);
      if (tmp > best) {
        best = tmp;
        idx = i;
      }
    }
    if (a[id].nxt[i] != -1 && top[i]) {
      if (a[a[id].nxt[i]].tot > 0) {
        tmp = a[a[id].nxt[i]].score / a[a[id].nxt[i]].tot + sqrt(tot / a[a[id].nxt[i]].tot);
      } else {
        assert(a[a[id].nxt[i]].tot == -1);
        tmp = a[a[id].nxt[i]].score;
        if (tmp == 1) tmp = INFD;
      }
      if (tmp > best) {
        best = tmp;
        idx = i;
      }
    }
  }
  assert(idx != -1);
  return idx;
}
double Select(const int M, const int N, int *top, int **board,
              const int lastX, const int lastY, const int noX, const int noY, int &id, const int dep) {

  if (id != -1 && a[id].tot < 0) {
    if (dep == ROUND_USR)
      return a[id].score;
    else
      return 1 - a[id].score;
  }

  double score;
  if (id == -1) {
    if (size < MAX_NODE) {
      id = size++;
      a[id].clear();

      if (dep == ROUND_MAC && userWin(lastX, lastY, M, N, board)) {
        a[id].tot = -1;
        a[id].score = 1;
        return 0;
      }
      if (dep == ROUND_USR && machineWin(lastX, lastY, M, N, board)) {
        a[id].tot = -1;
        a[id].score = 1;
        return 1;
      }
      if (isTie(N, top)) {
        a[id].tot = -1;
        a[id].score = 0.5;
        return 0.5;
      }
      score = Simulation(M, N, top, board, lastX, lastY, noX, noY, dep);
    } else {
      return Simulation(M, N, top, board, lastX, lastY, noX, noY, dep);
    }
  } else {
    int idx = SelectNode(M, N, board, top, id, dep);
    int x = top[idx] - 1, y = idx;
    top[idx]--;
    if (x - 1 == noX && y == noY) top[idx]--;
    assert(x >= 0 && x < M && y >= 0 && y < N);
    assert(board[x][y] == 0);
    board[x][y] = 2 - dep;
    score = Select(M, N, top, board, x, y, noX, noY, a[id].nxt[idx], dep ^ 1);
    top[idx] = x + 1;
    board[x][y] = 0;
  }
  if (dep == ROUND_USR)
    a[id].score += score;
  else
    a[id].score += 1 - score;

  a[id].tot += 1;
  return score;
}

int g_M, g_N;
const int *g_top;
const int *g_board;
int g_lastX, g_lastY, g_noX, g_noY;

void MC() {

  int** board = new int*[g_M];
  for(int i = 0; i < g_M; i++){
    board[i] = new int[g_N];
    for(int j = 0; j < g_N; j++){
      board[i][j] = g_board[i * g_N + j];
    }
  }
  int *top = new int[g_N];
  for (int i = 0; i < g_N; i++)
    top[i] = g_top[i];

  while (time(0) - global_start < TIME_LIMIT) {
    Select(g_M, g_N, top, board, g_lastX, g_lastY, g_noX, g_noY, root, ROUND_MAC);
  }

  clearArray(g_M, g_N, board);
  delete[] top;
}
extern "C" Point* getPoint(const int M, const int N, const int* top, const int* _board,
                           const int lastX, const int lastY, const int noX, const int noY){
  clear();
  g_M = M;
  g_N = N;
  g_board = _board;
  g_top = top;
  g_lastX = lastX;
  g_lastY = lastY;
  g_noX = noX;
  g_noY = noY;

  MC();
  double best = -1;
  int idx = -1;
  for (int i = 0; i < N; i++)
    if (a[0].nxt[i] != -1 && top[i]) {

      double tmp = 0;
      if (a[a[0].nxt[i]].tot == -1) {
        tmp = a[a[0].nxt[i]].score;
      } else {
        tmp = a[a[0].nxt[i]].score / a[a[0].nxt[i]].tot;
      }
      //      printf("%d %.4lf\n", i, tmp);
      if (tmp > best) {
        best = tmp;
        idx = i;
      }
    }
  assert(idx != -1 && top[idx]);
//  printf("%d\n", size);
  return new Point(top[idx] - 1, idx);
}
//external clear
extern "C" void clearPoint(Point* p){
  delete p;
  return;
}
void clearArray(int M, int N, int** board){
  for(int i = 0; i < M; i++){
    delete[] board[i];
  }
  delete[] board;
}
<commit_msg>determine win & lose<commit_after>#include <iostream>
#include <unistd.h>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <cmath>
#include <utility>
#include <cassert>
#include <algorithm>
#include "Point.h"
#include "Strategy.h"
#include "Judge.h"
#define MAX_NODE 1000000
#define TIME_LIMIT 4
#define ROUND_MAC   0
#define ROUND_USR   1
#define THREAD_NUM 4
#define INFD 1e8
using namespace std;
struct Node {
  double score;
  long long tot;
  int nxt[12];

  void clear() {
    score = 0;
    tot = 1;
    memset(nxt, 255, sizeof(nxt));
  }
};
Node a[MAX_NODE];
int size, root;
time_t global_start;
void clear() {
  size = 1;
  root = 0;
  a[0].clear();
  global_start = time(0);
  srand(global_start);
}

int table1[12];
int table2[12];

int evaluate(int x, int y, int M, int N, int **board) {
  int cnt = 1;
  for (int dx = -1; dx <= 1; dx++)
    for (int dy = -1; dy <= 1; dy++)
      if (dx != 0 || dy != 0) {
        if (0 <= x + 2 * dx && x + 2 * dx < M && 0 <= y + 2 * dy && y + 2 * dy < N &&
            board[x + dx][y + dy] && board[x + 2 * dx][y + 2 * dy] == board[x + dx][y + dy])
            cnt += 4;
      }
  return cnt;
}

double Simulation(const int M, const int N, int *top, int **board,
                  const int lastX, const int lastY, const int noX, const int noY, const int dep) {

  if (dep == ROUND_MAC && userWin(lastX, lastY, M, N, board)) return 0;
  if (dep == ROUND_USR && machineWin(lastX, lastY, M, N, board)) return 1;
  if (isTie(N, top)) return 0.5;

  int posible = 0;
  for (int i = 0; i < N; i++)
    if (top[i]) {
      table1[posible] = evaluate(top[i] - 1, i, M, N, board) + (posible ? table1[posible - 1] : 0);
      table2[posible] = i;
      posible++;
    }

  assert(posible);
  assert(table1[posible - 1]);
  int idx = rand() % table1[posible - 1];
  int y = table2[lower_bound(table1, table1 + posible, idx) - table1];
//  printf("%d\n", y);
  assert(0 <= y && y < N);
  assert(top[y]);

  int x = top[y] - 1;
  assert(board[x][y] == 0);
  board[x][y] = 2 - dep;
  top[y]--;
  if (x - 1 == noX && y == noY) top[y]--;
  double score = Simulation(M, N, top, board, x, y, noX, noY, dep ^ 1);
  board[x][y] = 0;
  top[y] = x + 1;
  return score;
}
int SelectNode(int M, int N, int **board, int *top, int id, int dep) {
  int idx = -1;
  double best = -1e8;
  double tot = 2 * log(a[id].tot);
  assert(a[id].tot > 0);
  double tmp;
  for (int i = 0; i < N; i++) {
    if (a[id].nxt[i] == -1 && top[i]) {
      tmp = 1 + sqrt(tot);
      if (tmp > best) {
        best = tmp;
        idx = i;
      }
    }
    if (a[id].nxt[i] != -1 && top[i]) {
      if (a[a[id].nxt[i]].tot > 0) {
        tmp = a[a[id].nxt[i]].score / a[a[id].nxt[i]].tot + sqrt(tot / a[a[id].nxt[i]].tot);
      } else {
        assert(a[a[id].nxt[i]].tot == -1);
        tmp = a[a[id].nxt[i]].score;
        if (tmp == 1) tmp = INFD;
        if (tmp == 0) tmp = -1;
      }
      if (tmp > best) {
        best = tmp;
        idx = i;
      }
    }
  }
  assert(idx != -1);
  if (tmp == INFD) return -1;
  if (tmp == -1) return -2;
  return idx;
}
double Select(const int M, const int N, int *top, int **board,
              const int lastX, const int lastY, const int noX, const int noY, int &id, const int dep) {

  if (id != -1 && a[id].tot < 0) {
    if (dep == ROUND_USR)
      return a[id].score;
    else
      return 1 - a[id].score;
  }

  double score;
  if (id == -1) {
    if (size < MAX_NODE) {
      id = size++;
      a[id].clear();

      if (dep == ROUND_MAC && userWin(lastX, lastY, M, N, board)) {
        a[id].tot = -1;
        a[id].score = 1;
        return 0;
      }
      if (dep == ROUND_USR && machineWin(lastX, lastY, M, N, board)) {
        a[id].tot = -1;
        a[id].score = 1;
        return 1;
      }
      if (isTie(N, top)) {
        a[id].tot = -1;
        a[id].score = 0.5;
        return 0.5;
      }
      score = Simulation(M, N, top, board, lastX, lastY, noX, noY, dep);
    } else {
      return Simulation(M, N, top, board, lastX, lastY, noX, noY, dep);
    }
  } else {
    int idx = SelectNode(M, N, board, top, id, dep);
    if (idx == -1) {
      a[id].score = 0;
      a[id].tot = -1;
      return (dep == ROUND_MAC) ? 1 : 0;
    } else if (idx == -2) {
      a[id].score = 1;
      a[id].tot = -1;
      return (dep == ROUND_MAC) ? 0 : 1;
    } else {
      int x = top[idx] - 1, y = idx;
      top[idx]--;
      if (x - 1 == noX && y == noY) top[idx]--;
      assert(x >= 0 && x < M && y >= 0 && y < N);
      assert(board[x][y] == 0);
      board[x][y] = 2 - dep;
      score = Select(M, N, top, board, x, y, noX, noY, a[id].nxt[idx], dep ^ 1);
      top[idx] = x + 1;
      board[x][y] = 0;
    }
  }
  if (dep == ROUND_USR)
    a[id].score += score;
  else
    a[id].score += 1 - score;

  a[id].tot += 1;
  return score;
}

int g_M, g_N;
const int *g_top;
const int *g_board;
int g_lastX, g_lastY, g_noX, g_noY;

void MC() {

  int** board = new int*[g_M];
  for(int i = 0; i < g_M; i++){
    board[i] = new int[g_N];
    for(int j = 0; j < g_N; j++){
      board[i][j] = g_board[i * g_N + j];
    }
  }
  int *top = new int[g_N];
  for (int i = 0; i < g_N; i++)
    top[i] = g_top[i];

  while (time(0) - global_start < TIME_LIMIT) {
    Select(g_M, g_N, top, board, g_lastX, g_lastY, g_noX, g_noY, root, ROUND_MAC);
  }

  clearArray(g_M, g_N, board);
  delete[] top;
}
extern "C" Point* getPoint(const int M, const int N, const int* top, const int* _board,
                           const int lastX, const int lastY, const int noX, const int noY){
  clear();
  g_M = M;
  g_N = N;
  g_board = _board;
  g_top = top;
  g_lastX = lastX;
  g_lastY = lastY;
  g_noX = noX;
  g_noY = noY;

  MC();
  double best = -1;
  int idx = -1;
  for (int i = 0; i < N; i++)
    if (a[0].nxt[i] != -1 && top[i]) {

      double tmp = 0;
      if (a[a[0].nxt[i]].tot == -1) {
        tmp = a[a[0].nxt[i]].score;
      } else {
        tmp = a[a[0].nxt[i]].score / a[a[0].nxt[i]].tot;
      }
      //      printf("%d %.4lf\n", i, tmp);
      if (tmp > best) {
        best = tmp;
        idx = i;
      }
    }
  assert(idx != -1 && top[idx]);
//  printf("%d\n", size);
  return new Point(top[idx] - 1, idx);
}
//external clear
extern "C" void clearPoint(Point* p){
  delete p;
  return;
}
void clearArray(int M, int N, int** board){
  for(int i = 0; i < M; i++){
    delete[] board[i];
  }
  delete[] board;
}
<|endoftext|>


<commit_before>#include <Supervisor/Monitor.hh>

#include <Time.hh>
#include <Power.hh>
#include <MemoryManager.hh>
#include <Kernel/Thread.hh>
#include <Interrupt.hh>

#include <string>
#include <list>
#include <cstdio>
#include <utility>
#include <functional>

using CommandPair = std::pair<MonitorCommand*, std::string>;

MonitorCommand::MonitorCommand()
{
}

MonitorCommand::~MonitorCommand()
{
}

class InterruptCommand : public MonitorCommand
{
public:
   void run(std::string)
   {
      printf("Interrupt statistics:\n");
      Interrupt::printStatistics();
   }
};

class UptimeCommand : public MonitorCommand
{
public:
   void run(std::string)
   {
      uint64_t uptime = Time::getUptime();
      printf("Uptime is: %lu.%lu\n",
             (unsigned long )uptime / 1000,
             (unsigned long )(uptime % 1000));
   }
};

class LambdaCommand : public MonitorCommand
{
public:
   using CommandFunction = std::function<void(std::string)>;

   LambdaCommand(CommandFunction lambda, std::string command)
      : lambdaM(lambda)
   {
      Monitor::registerCommand(this, command);
   }

   void run(std::string args)
   {
      lambdaM(args);
   }

private:
   CommandFunction lambdaM;
};

Monitor::Monitor()
{
//   static InterruptCommand interruptCommand;
   static UptimeCommand uptimeCommand;

//   Monitor::registerCommand(&interruptCommand, "interrupts");
   Monitor::registerCommand(&uptimeCommand, "uptime");

   static LambdaCommand interruptCommand([](std::string) {
         printf("Interrupt statistics:\n");
         Interrupt::printStatistics();
   }, "interrupts");
}

Monitor::~Monitor()
{
}

std::string
Monitor::getCommand()
{
   char buffer[128];

   printf("=> ");
   std::string command = gets_s(buffer, sizeof(buffer));

   return command;
}

namespace
{
   std::list<CommandPair> commands;
};

void
Monitor::registerCommand(MonitorCommand* command, std::string name)
{
   auto pair =  std::make_pair(command, name);

   commands.push_back(pair);
}

void
Monitor::enter()
{
   printf("\nEntering ESRTK Monitor\n\n");

   bool isRunning = true;
   while (isRunning)
   {
      std::string command = getCommand();

      if (command == "help")
      {
         printf("Available commands:\n");
         for (auto& handler : commands)
         {
            printf(" %s\n", handler.second.c_str());
         }
      }
      else
      {
         for (auto& handler : commands)
         {
            if (handler.second == command)
            {
               handler.first->run(command);
            }
         }
      }

      if (command == "memory")
      {
         putchar('\n');
         MemoryManager::get().printStatistics();
      }
      else if (command == "threads")
      {
         putchar('\n');
         Kernel::Thread::printAll();
      }
      else if (command == "reboot")
      {
         Power::reboot();
      }
      else if (command == "deadlock")
      {
         printf("Simulating a dead-lock!\n");
         for (;;)
         {
            asm volatile("cli");
         }
      }
      else if (command == "exit")
      {
         isRunning = false;
      }
   }
}
<commit_msg>Convert all existing debug commands<commit_after>#include <Supervisor/Monitor.hh>

#include <Time.hh>
#include <Power.hh>
#include <MemoryManager.hh>
#include <Kernel/Thread.hh>
#include <Interrupt.hh>

#include <string>
#include <list>
#include <cstdio>
#include <utility>
#include <functional>

using CommandPair = std::pair<MonitorCommand*, std::string>;

MonitorCommand::MonitorCommand()
{
}

MonitorCommand::~MonitorCommand()
{
}

class InterruptCommand : public MonitorCommand
{
public:
   void run(std::string)
   {
      printf("Interrupt statistics:\n");
      Interrupt::printStatistics();
   }
};

class LambdaCommand : public MonitorCommand
{
public:
   using CommandFunction = std::function<void(std::string)>;

   LambdaCommand(CommandFunction lambda, std::string command)
      : lambdaM(lambda)
   {
      Monitor::registerCommand(this, command);
   }

   void run(std::string args)
   {
      lambdaM(args);
   }

private:
   CommandFunction lambdaM;
};

Monitor::Monitor()
{
   static LambdaCommand interruptCommand([](std::string) {
         printf("Interrupt statistics:\n");
         Interrupt::printStatistics();
   }, "interrupts");

   static LambdaCommand uptimeCommand([](std::string) {
         uint64_t uptime = Time::getUptime();
         printf("Uptime is: %lu.%lu\n",
                (unsigned long )uptime / 1000,
                (unsigned long )(uptime % 1000));
   }, "uptime");

   static LambdaCommand memoryCommand([](std::string) {
         MemoryManager::get().printStatistics();
   }, "memory");

   static LambdaCommand threadsCommand([](std::string) {
         Kernel::Thread::printAll();
   }, "threads");

   static LambdaCommand rebootCommand([](std::string) {
         Power::reboot();
   }, "reboot");

   static LambdaCommand deadlockCommand([](std::string) {
         printf("Simulating a dead-lock!\n");
         for (;;)
         {
            asm volatile("cli");
         }
   }, "deadlock");
}

Monitor::~Monitor()
{
}

std::string
Monitor::getCommand()
{
   char buffer[128];

   printf("=> ");
   std::string command = gets_s(buffer, sizeof(buffer));

   return command;
}

namespace
{
   std::list<CommandPair> commands;
};

void
Monitor::registerCommand(MonitorCommand* command, std::string name)
{
   auto pair =  std::make_pair(command, name);

   commands.push_back(pair);
}

void
Monitor::enter()
{
   printf("\nEntering ESRTK Monitor\n\n");

   bool isRunning = true;
   while (isRunning)
   {
      std::string command = getCommand();

      if (command == "help")
      {
         printf("Available commands:\n");
         for (auto& handler : commands)
         {
            printf(" %s\n", handler.second.c_str());
         }
      }
      else if (command == "exit")
      {
         isRunning = false;
      }
      else
      {
         for (auto& handler : commands)
         {
            if (handler.second == command)
            {
               handler.first->run(command);
            }
         }
      }
   }
}
<|endoftext|>


<commit_before>#include <cfloat>
#include <stack>

#include "mpi.h"

#include "kd_tree.hpp"
#include "kd_mesh.hpp"
#include "mesh.hpp"

#define EPSILON 0.00001

Kd_tree::Kd_tree(char dim, int np, int rank) {
    root = new Kd_tree_node;
    root->split_dim = 0;
    root->is_leaf = false;
    if (np > 1) {
        this->local_root_dim = (int)log2(np - 1);
        std::cout << local_root_dim << std::endl;
    } else {
        this->local_root_dim = 2;
    }

    this->dim = dim;
    this->np  = np;
    this->rank = rank;
}

void Kd_tree::add(Mesh* m) {
    meshes.push_back(m);
}

void Kd_tree::build() {
    std::vector<Kd_mesh>* kd_meshes = new std::vector<Kd_mesh>;
    for (Mesh* mesh : meshes) {
        kd_meshes->push_back(Kd_mesh(*mesh));
    }
    build_tree(root, kd_meshes);
    if (rank == 0)
        local_root = root;
}

void Kd_tree::build_tree(Kd_tree_node * node, std::vector<Kd_mesh>* meshes) {

    if (node->split_dim == local_root_dim) {
        if (local_roots.size() == (rank - 1)) {
            local_root = node;
        }
        local_roots.push_back(node);
    }
    int split_dim = node->split_dim % dim;

    std::cout << "Building tree" << std::endl;
    std::cout << "Dim = " << (int)split_dim << std::endl;
    int t = 0;
    for (Kd_mesh& kdm : *meshes) {
        t += kdm.tris.size();
    }
    std::cout << "Tri count = " << t << std::endl << std::endl;

    node->bbox = Bounding_box(*meshes);
    // Stop Criteria
    if (t < 150 || node->split_dim == 255) {
    //if (split_dim == 2) {
        node->is_leaf = true;
        node->kd_meshes = meshes;
        return;
    }

    // Find Split Plane (Median distance (replace with SA heuristic))
    node->split_dist = (0.5) *
                   (node->bbox.min[split_dim] + node->bbox.max[split_dim]);
    std::cout << "Split_dist = " << node->split_dist << std::endl;
//    std::cin.get();

    node->left  = new Kd_tree_node;
    node->left->split_dim = (node->split_dim + 1);
    node->left->is_leaf = false;
    node->left->bbox = node->bbox;
    node->left->bbox.max[split_dim] = node->split_dist;
    node->right = new Kd_tree_node;
    node->right->split_dim = (node->split_dim + 1);
    node->right->is_leaf = false;
    node->right->bbox = node->bbox;
    node->right->bbox.min[split_dim] = node->split_dist;

    // Partition the meshes onto either side of the splitting plane
    std::vector<Kd_mesh>* right_kd_meshes = new std::vector<Kd_mesh>;
    for (auto itr = meshes->begin(); itr != meshes->end(); ++itr) {
        // Case 1 - Right side of splitting plane
        if (itr->bbox.min[split_dim] > node->split_dist) {

            // Move to right
            right_kd_meshes->push_back(*itr);

            // Remove from left
            itr = meshes->erase(itr);
            if (itr == meshes->end())
               break;
            --itr;

        // Case 2 - Mesh straddles splitting plane
        } else if (itr->bbox.max[split_dim] > node->split_dist &&
                    itr->bbox.min[split_dim] <= node->split_dist){

            Kd_mesh right;
            bool left_changed = false;

            for (auto tri = itr->tris.begin(); tri != itr->tris.end(); tri++) {

                // If the triangle is solely to the right of splitting plane
                if (tri->m->verts[tri->inds[0]][split_dim] > node->split_dist &&
                    tri->m->verts[tri->inds[1]][split_dim] > node->split_dist &&
                    tri->m->verts[tri->inds[2]][split_dim] > node->split_dist) {

                    // Move triangle from left to right
                    right.add_tri(*tri);
                    itr->tris.erase(tri);
                    left_changed = true;
                    if (tri == itr->tris.end())
                        break;
                    --tri;

                // If the triangle straddle the splitting plane, duplicate it
                } else if(!(tri->m->verts[tri->inds[0]][split_dim] < node->split_dist
                    && tri->m->verts[tri->inds[1]][split_dim] < node->split_dist
                    && tri->m->verts[tri->inds[2]][split_dim] < node->split_dist)) {
                    right.add_tri(*tri);
                }
            }

            // Update the bounding box
            if (left_changed) {
                itr->bbox = Bounding_box(itr->tris);
            }
            right_kd_meshes->push_back(right);
        }
    }

    // Build
    build_tree(node->left, meshes);
    build_tree(node->right, right_kd_meshes);
}

/*
1.
If we reach the stopping criteria then mark this as a leaf node

2.
Find the splitting plane for the current dimension

3.
Make left and right children, assign their dimensions, default to non-leaf

4.
Assign shapes left of the splitting plane to left and shapes right of the splitting plane to
the right. Split up meshs that straddle plane.

5.
call on children

*/

bool Kd_tree_node::hit(Ray& ray, const Ray_Tracer* rt, float t_min, float t_max,
            Ray_Hit& rh, bool shadow) {

    bool hit = false;
    if (shadow) {
        for (const Kd_mesh& kd_mesh : *kd_meshes) {
            for (const Triangle& t : kd_mesh.tris) {
                if (t.hit(ray, rt, t_min, t_max, rh, true))
                    return true;
            }
        }
    } else {
        for (const Kd_mesh& kd_mesh : *kd_meshes) {
            for (const Triangle& t : kd_mesh.tris) {
                if (t.hit(ray, rt, t_min, t_max, rh, false)) {
                    t_max = rh.t;
                    hit = true;
                }
            }
        }
    }
    return hit;
}

// What a fucking nightmare
bool Kd_tree::hit_helper(bool is_local, Kd_tree_node* node, Ray& ray, const Ray_Tracer* rt,
                         float t_min, float t_max, Ray_Hit& rh,
                         bool shadow, unsigned int ray_id) {

    // Bounding box intersection
    V3 v0;
    v0[0] = node->bbox.min[0] - EPSILON;
    v0[1] = node->bbox.min[1] - EPSILON;
    v0[2] = node->bbox.min[2] - EPSILON;
    V3 v1;
    v1[0] = node->bbox.max[0] + EPSILON;
    v1[1] = node->bbox.max[1] + EPSILON;
    v1[2] = node->bbox.max[2] + EPSILON;

    float min = EPSILON;
    float max = FLT_MAX;

    /*
    std::cout<< " yo " << std::endl;
    std::cout<< ray.s << std::endl;
    std::cin.get();
    */
    for (int i = 0; i < 3; ++i) {
        if (fabs(ray.s[i]) > EPSILON) {
            float inv_slope = 1.0f / ray.s[i];
            if (inv_slope >= 0) {
                min = (v0[i] - ray.o[i]) * inv_slope;
                max = (v1[i] - ray.o[i]) * inv_slope;
            } else {
                min = (v1[i] - ray.o[i]) * inv_slope;
                max = (v0[i] - ray.o[i]) * inv_slope;
            }
        }
        if (min > t_min)
            t_min = min;
        if (max < t_max)
            t_max = max;
    }

    // Quit early if we don't even hit the bounding box
    if (t_min > t_max) {
        return false;
    }

    // Havran's stack-based traversal
    int num_remote = 0;
    std::stack<Kd_tree_node*> node_stack;
    std::stack<float> t_stack;
    node_stack.push(node);
    t_stack.push(t_min);
    t_stack.push(t_max);
    bool hit_once = false;
    rh.t = FLT_MAX;

    while (!node_stack.empty() || num_remote > 0) {
        //std::cout << "dim: " << cur_node->split_dim << "  lrd: " << local_root_dim <<std::endl;

/*
        if (num_remote > 0) {
            MPI_Status status;
            int flag;
            MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag, &status);
            if (flag) {
                Ray_Hit_Remote rhr_temp;
                MPI_Recv(&rhr_temp, sizeof(Ray_Hit_Remote), MPI_BYTE, status.MPI_SOURCE,
                            status.MPI_TAG, MPI_COMM_WORLD, &status);
                //std::cout<< "Got a response" <<std::endl;
                if (rh.t > rhr_temp.t) {
                    rh.t = rhr_temp.t;
                    rh.col = rhr_temp.col;
                    hit_once = true;
                    if (shadow)
                        return true;
                }
                num_remote--;
            }
        }
        */

        Kd_tree_node* cur_node;
        float curr_t_max;
        float curr_t_min;
        if (!node_stack.empty()) {
            cur_node = node_stack.top();
            node_stack.pop();
            curr_t_max = t_stack.top();
            t_stack.pop();
            curr_t_min = t_stack.top();
            t_stack.pop();
        } else {
            continue;
        }

        if (!is_local) {
            if (cur_node->split_dim == local_root_dim) {
                int pos = find(local_roots.begin(), local_roots.end(), cur_node)
                                - local_roots.begin();
                Ray_Trace ray_trace;
                ray_trace.r = ray;
                ray_trace.t_min = curr_t_min;
                ray_trace.t_max = curr_t_max;
                ray_trace.ray_id = ray_id;
                //num_remote++;
                MPI_Bsend(&ray_trace, sizeof(Ray_Trace), MPI_BYTE,
                            pos + 1, pos, MPI_COMM_WORLD);
                continue;
            }
        }

        // If we hit a leaf just checking the primitives inside
        if (cur_node->is_leaf) {
            if (cur_node->hit(ray, rt, curr_t_min, curr_t_max, rh, shadow)){
                // TODO: Could this cause a problem?
                curr_t_max = rh.t;
                hit_once = true;
                if (shadow)
                    return true;
            }
        } else {

            int a = cur_node->split_dim % dim; // This we be used to index various vectors
            float entry = ray.o[a] + curr_t_min*ray.s[a];
            float exit  = ray.o[a] + curr_t_max*ray.s[a];
            float s     = cur_node->split_dist;

            if (entry <= s) {
                if (exit <= s) {
                    node_stack.push(cur_node->left);
                    t_stack.push(curr_t_min);
                    t_stack.push(curr_t_max);
                } else {
                    float t = (s - ray.o[a]) / ray.s[a];
                    node_stack.push(cur_node->left);
                    t_stack.push(curr_t_min);
                    t_stack.push(t);
                    node_stack.push(cur_node->right);
                    t_stack.push(t);
                    t_stack.push(curr_t_max);
                }
            } else {
                if (exit >= s) {
                    node_stack.push(cur_node->right);
                    t_stack.push(curr_t_min);
                    t_stack.push(curr_t_max);
                } else {
                    float t = (s - ray.o[a]) / ray.s[a];
                    node_stack.push(cur_node->right);
                    t_stack.push(curr_t_min);
                    t_stack.push(t);
                    node_stack.push(cur_node->left);
                    t_stack.push(t);
                    t_stack.push(curr_t_max);
                }
            }
        }
    }

    return hit_once;
}

bool Kd_tree::hit(Ray& ray, const Ray_Tracer* rt, float t_min, float t_max,
                    Ray_Hit& rh, bool shadow, unsigned int ray_id) {

    return hit_helper(false, root, ray, rt, t_min, t_max, rh, shadow, ray_id);
}

bool Kd_tree::hit_local(Ray& ray, const Ray_Tracer* rt, float t_min, float t_max,
                    Ray_Hit& rh, bool shadow) {

    return hit_helper(true, local_root, ray, rt, t_min, t_max, rh, shadow, 0);
}

<commit_msg>commented out couts<commit_after>#include <cfloat>
#include <stack>

#include "mpi.h"

#include "kd_tree.hpp"
#include "kd_mesh.hpp"
#include "mesh.hpp"

#define EPSILON 0.00001

Kd_tree::Kd_tree(char dim, int np, int rank) {
    root = new Kd_tree_node;
    root->split_dim = 0;
    root->is_leaf = false;
    if (np > 1) {
        this->local_root_dim = (int)log2(np - 1);
        std::cout << local_root_dim << std::endl;
    } else {
        this->local_root_dim = 2;
    }

    this->dim = dim;
    this->np  = np;
    this->rank = rank;
}

void Kd_tree::add(Mesh* m) {
    meshes.push_back(m);
}

void Kd_tree::build() {
    std::vector<Kd_mesh>* kd_meshes = new std::vector<Kd_mesh>;
    for (Mesh* mesh : meshes) {
        kd_meshes->push_back(Kd_mesh(*mesh));
    }
    build_tree(root, kd_meshes);
    if (rank == 0)
        local_root = root;
}

#define DEBUG
void Kd_tree::build_tree(Kd_tree_node * node, std::vector<Kd_mesh>* meshes) {

    if (node->split_dim == local_root_dim) {
        if (local_roots.size() == (rank - 1)) {
            local_root = node;
        }
        local_roots.push_back(node);
    }
    int split_dim = node->split_dim % dim;

    #ifdef DEBUG
    std::cout << "Building tree" << std::endl;
    std::cout << "Dim = " << (int)split_dim << std::endl;
    #endif

    int t = 0;
    for (Kd_mesh& kdm : *meshes) {
        t += kdm.tris.size();
    }

    #ifdef DEBUG
    std::cout << "Tri count = " << t << std::endl << std::endl;
    #endif

    node->bbox = Bounding_box(*meshes);
    // Stop Criteria
    if (t < 350 || node->split_dim == 50) {
    //if (split_dim == 2) {
        node->is_leaf = true;
        node->kd_meshes = meshes;
        return;
    }

    // Find Split Plane (Median distance (replace with SA heuristic))
    node->split_dist = (0.5) *
                   (node->bbox.min[split_dim] + node->bbox.max[split_dim]);
    #ifdef DEBUG
    std::cout << "Split_dist = " << node->split_dist << std::endl;
    #endif

    node->left  = new Kd_tree_node;
    node->left->split_dim = (node->split_dim + 1);
    node->left->is_leaf = false;
    node->left->bbox = node->bbox;
    node->left->bbox.max[split_dim] = node->split_dist;
    node->right = new Kd_tree_node;
    node->right->split_dim = (node->split_dim + 1);
    node->right->is_leaf = false;
    node->right->bbox = node->bbox;
    node->right->bbox.min[split_dim] = node->split_dist;

    // Partition the meshes onto either side of the splitting plane
    std::vector<Kd_mesh>* right_kd_meshes = new std::vector<Kd_mesh>;
    for (auto itr = meshes->begin(); itr != meshes->end(); ++itr) {
        // Case 1 - Right side of splitting plane
        if (itr->bbox.min[split_dim] > node->split_dist) {

            // Move to right
            right_kd_meshes->push_back(*itr);

            // Remove from left
            itr = meshes->erase(itr);
            if (itr == meshes->end())
               break;
            --itr;

        // Case 2 - Mesh straddles splitting plane
        } else if (itr->bbox.max[split_dim] > node->split_dist &&
                    itr->bbox.min[split_dim] <= node->split_dist){

            Kd_mesh right;
            bool left_changed = false;

            for (auto tri = itr->tris.begin(); tri != itr->tris.end(); tri++) {

                // If the triangle is solely to the right of splitting plane
                if (tri->m->verts[tri->inds[0]][split_dim] > node->split_dist &&
                    tri->m->verts[tri->inds[1]][split_dim] > node->split_dist &&
                    tri->m->verts[tri->inds[2]][split_dim] > node->split_dist) {

                    // Move triangle from left to right
                    right.add_tri(*tri);
                    itr->tris.erase(tri);
                    left_changed = true;
                    if (tri == itr->tris.end())
                        break;
                    --tri;

                // If the triangle straddle the splitting plane, duplicate it
                } else if(!(tri->m->verts[tri->inds[0]][split_dim] < node->split_dist
                    && tri->m->verts[tri->inds[1]][split_dim] < node->split_dist
                    && tri->m->verts[tri->inds[2]][split_dim] < node->split_dist)) {
                    right.add_tri(*tri);
                }
            }

            // Update the bounding box
            if (left_changed) {
                itr->bbox = Bounding_box(itr->tris);
            }
            right_kd_meshes->push_back(right);
        }
    }

    // Build
    build_tree(node->left, meshes);
    build_tree(node->right, right_kd_meshes);
}

/*
1.
If we reach the stopping criteria then mark this as a leaf node

2.
Find the splitting plane for the current dimension

3.
Make left and right children, assign their dimensions, default to non-leaf

4.
Assign shapes left of the splitting plane to left and shapes right of the splitting plane to
the right. Split up meshs that straddle plane.

5.
call on children

*/

bool Kd_tree_node::hit(Ray& ray, const Ray_Tracer* rt, float t_min, float t_max,
            Ray_Hit& rh, bool shadow) {

    bool hit = false;
    if (shadow) {
        for (const Kd_mesh& kd_mesh : *kd_meshes) {
            for (const Triangle& t : kd_mesh.tris) {
                if (t.hit(ray, rt, t_min, t_max, rh, true))
                    return true;
            }
        }
    } else {
        for (const Kd_mesh& kd_mesh : *kd_meshes) {
            for (const Triangle& t : kd_mesh.tris) {
                if (t.hit(ray, rt, t_min, t_max, rh, false)) {
                    t_max = rh.t;
                    hit = true;
                }
            }
        }
    }
    return hit;
}

// What a fucking nightmare
bool Kd_tree::hit_helper(bool is_local, Kd_tree_node* node, Ray& ray, const Ray_Tracer* rt,
                         float t_min, float t_max, Ray_Hit& rh,
                         bool shadow, unsigned int ray_id) {

    // Bounding box intersection
    V3 v0;
    v0[0] = node->bbox.min[0] - EPSILON;
    v0[1] = node->bbox.min[1] - EPSILON;
    v0[2] = node->bbox.min[2] - EPSILON;
    V3 v1;
    v1[0] = node->bbox.max[0] + EPSILON;
    v1[1] = node->bbox.max[1] + EPSILON;
    v1[2] = node->bbox.max[2] + EPSILON;

    float min = EPSILON;
    float max = FLT_MAX;

    /*
    std::cout<< " yo " << std::endl;
    std::cout<< ray.s << std::endl;
    std::cin.get();
    */
    for (int i = 0; i < 3; ++i) {
        if (fabs(ray.s[i]) > EPSILON) {
            float inv_slope = 1.0f / ray.s[i];
            if (inv_slope >= 0) {
                min = (v0[i] - ray.o[i]) * inv_slope;
                max = (v1[i] - ray.o[i]) * inv_slope;
            } else {
                min = (v1[i] - ray.o[i]) * inv_slope;
                max = (v0[i] - ray.o[i]) * inv_slope;
            }
        }
        if (min > t_min)
            t_min = min;
        if (max < t_max)
            t_max = max;
    }

    // Quit early if we don't even hit the bounding box
    if (t_min > t_max) {
        return false;
    }

    // Havran's stack-based traversal
    int num_remote = 0;
    std::stack<Kd_tree_node*> node_stack;
    std::stack<float> t_stack;
    node_stack.push(node);
    t_stack.push(t_min);
    t_stack.push(t_max);
    bool hit_once = false;
    rh.t = FLT_MAX;

    while (!node_stack.empty() || num_remote > 0) {
        //std::cout << "dim: " << cur_node->split_dim << "  lrd: " << local_root_dim <<std::endl;

/*
        if (num_remote > 0) {
            MPI_Status status;
            int flag;
            MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag, &status);
            if (flag) {
                Ray_Hit_Remote rhr_temp;
                MPI_Recv(&rhr_temp, sizeof(Ray_Hit_Remote), MPI_BYTE, status.MPI_SOURCE,
                            status.MPI_TAG, MPI_COMM_WORLD, &status);
                //std::cout<< "Got a response" <<std::endl;
                if (rh.t > rhr_temp.t) {
                    rh.t = rhr_temp.t;
                    rh.col = rhr_temp.col;
                    hit_once = true;
                    if (shadow)
                        return true;
                }
                num_remote--;
            }
        }
        */

        Kd_tree_node* cur_node;
        float curr_t_max;
        float curr_t_min;
        if (!node_stack.empty()) {
            cur_node = node_stack.top();
            node_stack.pop();
            curr_t_max = t_stack.top();
            t_stack.pop();
            curr_t_min = t_stack.top();
            t_stack.pop();
        } else {
            continue;
        }

        if (!is_local) {
            if (cur_node->split_dim == local_root_dim) {
                int pos = find(local_roots.begin(), local_roots.end(), cur_node)
                                - local_roots.begin();
                Ray_Trace ray_trace;
                ray_trace.r = ray;
                ray_trace.t_min = curr_t_min;
                ray_trace.t_max = curr_t_max;
                ray_trace.ray_id = ray_id;
                //num_remote++;
                MPI_Bsend(&ray_trace, sizeof(Ray_Trace), MPI_BYTE,
                            pos + 1, pos, MPI_COMM_WORLD);
                continue;
            }
        }

        // If we hit a leaf just checking the primitives inside
        if (cur_node->is_leaf) {
            if (cur_node->hit(ray, rt, curr_t_min, curr_t_max, rh, shadow)){
                // TODO: Could this cause a problem?
                curr_t_max = rh.t;
                hit_once = true;
                if (shadow)
                    return true;
            }
        } else {

            int a = cur_node->split_dim % dim; // This we be used to index various vectors
            float entry = ray.o[a] + curr_t_min*ray.s[a];
            float exit  = ray.o[a] + curr_t_max*ray.s[a];
            float s     = cur_node->split_dist;

            if (entry <= s) {
                if (exit <= s) {
                    node_stack.push(cur_node->left);
                    t_stack.push(curr_t_min);
                    t_stack.push(curr_t_max);
                } else {
                    float t = (s - ray.o[a]) / ray.s[a];
                    node_stack.push(cur_node->left);
                    t_stack.push(curr_t_min);
                    t_stack.push(t);
                    node_stack.push(cur_node->right);
                    t_stack.push(t);
                    t_stack.push(curr_t_max);
                }
            } else {
                if (exit >= s) {
                    node_stack.push(cur_node->right);
                    t_stack.push(curr_t_min);
                    t_stack.push(curr_t_max);
                } else {
                    float t = (s - ray.o[a]) / ray.s[a];
                    node_stack.push(cur_node->right);
                    t_stack.push(curr_t_min);
                    t_stack.push(t);
                    node_stack.push(cur_node->left);
                    t_stack.push(t);
                    t_stack.push(curr_t_max);
                }
            }
        }
    }

    return hit_once;
}

bool Kd_tree::hit(Ray& ray, const Ray_Tracer* rt, float t_min, float t_max,
                    Ray_Hit& rh, bool shadow, unsigned int ray_id) {

    return hit_helper(false, root, ray, rt, t_min, t_max, rh, shadow, ray_id);
}

bool Kd_tree::hit_local(Ray& ray, const Ray_Tracer* rt, float t_min, float t_max,
                    Ray_Hit& rh, bool shadow) {

    return hit_helper(true, local_root, ray, rt, t_min, t_max, rh, shadow, 0);
}

<|endoftext|>


<commit_before>#include "util/bitmap.h"
#include "util/trans-bitmap.h"
#include <math.h>
#include <iostream>

#include "level/utils.h"
#include "network/messages.h"
#include "loading.h"
#include "util/file-system.h"
#include "util/font.h"
#include "util/funcs.h"
#include "util/gradient.h"
#include "util/thread.h"
#include "globals.h"
#include <vector>
#include "util/thread.h"
#include "util/message-queue.h"
#include "init.h"

using namespace std;

namespace Loader{

Util::Thread::Lock loading_screen_mutex;
volatile bool done_loading = true;

typedef struct pair{
	int x, y;
} ppair;

class Info{
public:
    Info(){
        Global::registerInfo(&messages);
    }

    bool transferMessages(Messages & box){
        bool did = false;
        while (messages.hasAny()){
            const string & str = messages.get();
            box.addMessage(str);
            did = true;
        }
        return did;
    }

    ~Info(){
        Global::unregisterInfo(&messages);
    }

private:
    MessageQueue messages;
};

void * loadingScreenSimple1(void * arg);

void startLoading(Util::Thread::Id * thread, void * arg, Kind kind){
    bool create = false;
    Util::Thread::acquireLock(&loading_screen_mutex);
    create = done_loading;
    done_loading = false;
    Util::Thread::releaseLock(&loading_screen_mutex);

    /* prevent multiple loading threads from being made */
    if (create){
        switch (kind){
            case Default: Util::Thread::createThread(thread, NULL, (Util::Thread::ThreadFunction) loadingScreen, arg); break;
            case SimpleCircle: Util::Thread::createThread(thread, NULL, (Util::Thread::ThreadFunction) loadingScreenSimple1, arg); break;
        }
    }
}

void stopLoading(Util::Thread::Id thread){
    bool needJoin = false;
    Util::Thread::acquireLock( &loading_screen_mutex );
    needJoin = ! done_loading;
    done_loading = true;
    Util::Thread::releaseLock( &loading_screen_mutex );
    if (needJoin){
        Util::Thread::joinThread(thread);
    }
}

static void setupBackground(const Bitmap & background, int load_x, int load_y, int load_width, int load_height, int infobox_x, int infobox_y, int infoWidth, int infoHeight, const Bitmap & infoBackground, const Bitmap & work){
    background.Blit(load_x, load_y, load_width, load_height, 0, 0, work);
    Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2 - Font::getDefaultFont().getHeight(), Bitmap::makeColor( 192, 192, 192 ), background, "Paintown version %s", 0, Global::getVersionString().c_str());
    Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2, Bitmap::makeColor( 192, 192, 192 ), background, "Made by Jon Rafkind", 0 );
    background.BlitToScreen();
    background.Blit(infobox_x, infobox_y, infoWidth, infoHeight, 0, 0, infoBackground);
}

static vector<ppair> generateFontPixels(const Font & myFont, const string & message, int width, int height){
    Bitmap letters(width, height);
    letters.fill( Bitmap::MaskColor() );
    myFont.printf( 0, 0, Bitmap::makeColor(255, 255, 255), letters, message.c_str(), 0 );

    vector< ppair > pairs;
    /* store every pixel we need to draw */
    for ( int x = 0; x < letters.getWidth(); x++ ){
        for ( int y = 0; y < letters.getHeight(); y++ ){
            int pixel = letters.getPixel(x, y);
            if (pixel != Bitmap::MaskColor()){
                ppair p;
                p.x = x;
                p.y = y;
                pairs.push_back( p );
            }
        }
    }

    return pairs;
}

/* shows time elapsed */
class TimeCounter{
public:
    TimeCounter():
    work(200, 40){
        start = Global::second_counter;
        last = 0;
    }

    void draw(int x, int y){
        const Font & font = Font::getDefaultFont(24, 24);
        if (Global::second_counter != last){
            work.clear();
            last = Global::second_counter;
            font.printf(0, 0, Bitmap::makeColor(192, 192, 192), work, "Waiting.. %d", 0, last - start);
            work.BlitAreaToScreen(x, y);
        }
    }

    Bitmap work;
    unsigned int start;
    unsigned int last;
};

void * loadingScreen(void * arg){
    int load_x = 80;
    int load_y = 220;
    const int infobox_width = 300;
    const int infobox_height = 150;
    Info info;
    const Font & myFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
    const Font & infoFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
    Level::LevelInfo levelInfo;
    if (arg != NULL){
        levelInfo = *(Level::LevelInfo*) arg;
    }

    if (levelInfo.getPositionX() != -1){
        load_x = levelInfo.getPositionX();
    }

    if (levelInfo.getPositionY() != -1){
        load_y = levelInfo.getPositionY();
    }

    // const char * the_string = (arg != NULL) ? (const char *) arg : "Loading...";
    int load_width = myFont.textLength(levelInfo.loadingMessage().c_str());
    int load_height = myFont.getHeight(levelInfo.loadingMessage().c_str());

    const int infobox_x = load_x;
    const int infobox_y = load_y + load_height * 2;

    Global::debug( 2 ) << "loading screen" << endl;

    Bitmap work( load_width, load_height );

    vector<ppair> pairs = generateFontPixels(myFont, levelInfo.loadingMessage(), load_width, load_height);

    Messages infobox(infobox_width, infobox_height);
    Bitmap infoWork(infobox_width, infobox_height);
    Bitmap infoBackground(infobox_width, infobox_height);

    const int MAX_COLOR = 200;

    /* blend from dark grey to light red */
    Effects::Gradient gradient(MAX_COLOR, Bitmap::makeColor(16, 16, 16), Bitmap::makeColor(192, 8, 8));

    Global::speed_counter = 0;

    if (levelInfo.getBackground() != 0){
        setupBackground(*levelInfo.getBackground(), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
    } else {
        setupBackground(Bitmap(levelInfo.loadingBackground().path()), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
    }

    Util::ThreadBoolean quit(done_loading, loading_screen_mutex);

    TimeCounter counter;

    bool firstDraw = true;

    while ( ! quit.get() ){

        /* true if a logic loop has passed */
        bool draw = firstDraw;

        /* will be true if any new info messages appeared */
        bool drawInfo = firstDraw;
        firstDraw = false;
        if ( Global::speed_counter > 0 ){
            double think = Global::speed_counter;
            Global::speed_counter = 0;
            draw = true;

            while ( think > 0 ){
                gradient.backward();
                think -= 1;
            }

            /* if no new messages appeared this will be false */
            drawInfo = info.transferMessages(infobox);
        } else {
            Util::rest( 1 );
        }

        if (draw){
            for ( vector< ppair >::iterator it = pairs.begin(); it != pairs.end(); it++ ){
                int color = gradient.current(it->x);
                work.putPixel(it->x, it->y, color);
            }

            // counter.draw(200, 100);

            /* we might not have to draw the whole info box again if no new
             * messages appeared.
             */
            if (drawInfo){
                infoBackground.Blit(infoWork);

                /* cheesy hack to change the font size. the font
                 * should store the size and change it on its own
                 */
                Font::getFont(Global::DEFAULT_FONT, 13, 13);
                infobox.draw(0, 0, infoWork, infoFont);
                Font::getFont(Global::DEFAULT_FONT, 24, 24);
                infoWork.BlitAreaToScreen(infobox_x, infobox_y);
            }
            /* work already contains the correct background */
            // work.Blit( load_x, load_y, *Bitmap::Screen );
            work.BlitAreaToScreen(load_x, load_y);
        }
    }

    return NULL;
}

/* shows two circles rotating around a center point */
void * loadingScreenSimple1(void * arg){
    Bitmap work(40, 40);
    Bitmap original(40, 40);
    original.BlitFromScreen(0, 0);
    Util::ThreadBoolean quit(done_loading, loading_screen_mutex);
    Global::speed_counter = 0;
    bool firstDraw = true;
    int angle = 0;
    int color1 = Bitmap::makeColor(0, 0, 0);
    int color2 = Bitmap::makeColor(0x00, 0x99, 0xff);
    int color3 = Bitmap::makeColor(0xff, 0x22, 0x33);
    int color4 = Bitmap::makeColor(0x44, 0x77, 0x33);
    int colors[4] = {color1, color2, color3, color4};
    Bitmap::transBlender(0, 0, 0, 64);
    int speed = 7;
    while (! quit.get()){
        bool draw = firstDraw;

        /* will be true if any new info messages appeared */
        bool drawInfo = firstDraw;
        firstDraw = false;
        if (Global::speed_counter > 0){
            double think = Global::speed_counter;
            Global::speed_counter = 0;
            draw = true;

            while (think > 0){
                angle += speed;
                think -= 1;
            }
        } else {
            Util::rest(1);
        }

        if (draw){
            int max = sizeof(colors) / sizeof(int);
            double middleX = work.getWidth() / 2;
            double middleY = work.getHeight() / 2;
            original.Blit(work);
            for (int i = 0; i < max; i++){
                double x = cos(Util::radians(angle + 360 / max * i)) * 15;
                double y = sin(Util::radians(angle + 360 / max * i)) * 15;
                work.translucent().circleFill(middleX + x, middleY + y, 2, colors[i]);
                x = cos(Util::radians(angle + speed + 360 / max * i)) * 15;
                y = sin(Util::radians(angle + speed + 360 / max * i)) * 15;
                work.circleFill(middleX + x, middleY + y, 2, colors[i]);
            }
            work.BlitAreaToScreen(0, 0);
        }
    }

    return NULL;
}

}
<commit_msg>dont need to draw loader immediately<commit_after>#include "util/bitmap.h"
#include "util/trans-bitmap.h"
#include <math.h>
#include <iostream>

#include "level/utils.h"
#include "network/messages.h"
#include "loading.h"
#include "util/file-system.h"
#include "util/font.h"
#include "util/funcs.h"
#include "util/gradient.h"
#include "util/thread.h"
#include "globals.h"
#include <vector>
#include "util/thread.h"
#include "util/message-queue.h"
#include "init.h"

using namespace std;

namespace Loader{

Util::Thread::Lock loading_screen_mutex;
volatile bool done_loading = true;

typedef struct pair{
	int x, y;
} ppair;

class Info{
public:
    Info(){
        Global::registerInfo(&messages);
    }

    bool transferMessages(Messages & box){
        bool did = false;
        while (messages.hasAny()){
            const string & str = messages.get();
            box.addMessage(str);
            did = true;
        }
        return did;
    }

    ~Info(){
        Global::unregisterInfo(&messages);
    }

private:
    MessageQueue messages;
};

void * loadingScreenSimple1(void * arg);

void startLoading(Util::Thread::Id * thread, void * arg, Kind kind){
    bool create = false;
    Util::Thread::acquireLock(&loading_screen_mutex);
    create = done_loading;
    done_loading = false;
    Util::Thread::releaseLock(&loading_screen_mutex);

    /* prevent multiple loading threads from being made */
    if (create){
        switch (kind){
            case Default: Util::Thread::createThread(thread, NULL, (Util::Thread::ThreadFunction) loadingScreen, arg); break;
            case SimpleCircle: Util::Thread::createThread(thread, NULL, (Util::Thread::ThreadFunction) loadingScreenSimple1, arg); break;
        }
    }
}

void stopLoading(Util::Thread::Id thread){
    bool needJoin = false;
    Util::Thread::acquireLock( &loading_screen_mutex );
    needJoin = ! done_loading;
    done_loading = true;
    Util::Thread::releaseLock( &loading_screen_mutex );
    if (needJoin){
        Util::Thread::joinThread(thread);
    }
}

static void setupBackground(const Bitmap & background, int load_x, int load_y, int load_width, int load_height, int infobox_x, int infobox_y, int infoWidth, int infoHeight, const Bitmap & infoBackground, const Bitmap & work){
    background.Blit(load_x, load_y, load_width, load_height, 0, 0, work);
    Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2 - Font::getDefaultFont().getHeight(), Bitmap::makeColor( 192, 192, 192 ), background, "Paintown version %s", 0, Global::getVersionString().c_str());
    Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2, Bitmap::makeColor( 192, 192, 192 ), background, "Made by Jon Rafkind", 0 );
    background.BlitToScreen();
    background.Blit(infobox_x, infobox_y, infoWidth, infoHeight, 0, 0, infoBackground);
}

static vector<ppair> generateFontPixels(const Font & myFont, const string & message, int width, int height){
    Bitmap letters(width, height);
    letters.fill( Bitmap::MaskColor() );
    myFont.printf( 0, 0, Bitmap::makeColor(255, 255, 255), letters, message.c_str(), 0 );

    vector< ppair > pairs;
    /* store every pixel we need to draw */
    for ( int x = 0; x < letters.getWidth(); x++ ){
        for ( int y = 0; y < letters.getHeight(); y++ ){
            int pixel = letters.getPixel(x, y);
            if (pixel != Bitmap::MaskColor()){
                ppair p;
                p.x = x;
                p.y = y;
                pairs.push_back( p );
            }
        }
    }

    return pairs;
}

/* shows time elapsed */
class TimeCounter{
public:
    TimeCounter():
    work(200, 40){
        start = Global::second_counter;
        last = 0;
    }

    void draw(int x, int y){
        const Font & font = Font::getDefaultFont(24, 24);
        if (Global::second_counter != last){
            work.clear();
            last = Global::second_counter;
            font.printf(0, 0, Bitmap::makeColor(192, 192, 192), work, "Waiting.. %d", 0, last - start);
            work.BlitAreaToScreen(x, y);
        }
    }

    Bitmap work;
    unsigned int start;
    unsigned int last;
};

void * loadingScreen(void * arg){
    int load_x = 80;
    int load_y = 220;
    const int infobox_width = 300;
    const int infobox_height = 150;
    Info info;
    const Font & myFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
    const Font & infoFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
    Level::LevelInfo levelInfo;
    if (arg != NULL){
        levelInfo = *(Level::LevelInfo*) arg;
    }

    if (levelInfo.getPositionX() != -1){
        load_x = levelInfo.getPositionX();
    }

    if (levelInfo.getPositionY() != -1){
        load_y = levelInfo.getPositionY();
    }

    // const char * the_string = (arg != NULL) ? (const char *) arg : "Loading...";
    int load_width = myFont.textLength(levelInfo.loadingMessage().c_str());
    int load_height = myFont.getHeight(levelInfo.loadingMessage().c_str());

    const int infobox_x = load_x;
    const int infobox_y = load_y + load_height * 2;

    Global::debug( 2 ) << "loading screen" << endl;

    Bitmap work( load_width, load_height );

    vector<ppair> pairs = generateFontPixels(myFont, levelInfo.loadingMessage(), load_width, load_height);

    Messages infobox(infobox_width, infobox_height);
    Bitmap infoWork(infobox_width, infobox_height);
    Bitmap infoBackground(infobox_width, infobox_height);

    const int MAX_COLOR = 200;

    /* blend from dark grey to light red */
    Effects::Gradient gradient(MAX_COLOR, Bitmap::makeColor(16, 16, 16), Bitmap::makeColor(192, 8, 8));

    Global::speed_counter = 0;

    if (levelInfo.getBackground() != 0){
        setupBackground(*levelInfo.getBackground(), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
    } else {
        setupBackground(Bitmap(levelInfo.loadingBackground().path()), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
    }

    Util::ThreadBoolean quit(done_loading, loading_screen_mutex);

    TimeCounter counter;

    bool firstDraw = true;

    while ( ! quit.get() ){

        /* true if a logic loop has passed */
        bool draw = firstDraw;

        /* will be true if any new info messages appeared */
        bool drawInfo = firstDraw;
        firstDraw = false;
        if ( Global::speed_counter > 0 ){
            double think = Global::speed_counter;
            Global::speed_counter = 0;
            draw = true;

            while ( think > 0 ){
                gradient.backward();
                think -= 1;
            }

            /* if no new messages appeared this will be false */
            drawInfo = info.transferMessages(infobox);
        } else {
            Util::rest( 1 );
        }

        if (draw){
            for ( vector< ppair >::iterator it = pairs.begin(); it != pairs.end(); it++ ){
                int color = gradient.current(it->x);
                work.putPixel(it->x, it->y, color);
            }

            // counter.draw(200, 100);

            /* we might not have to draw the whole info box again if no new
             * messages appeared.
             */
            if (drawInfo){
                infoBackground.Blit(infoWork);

                /* cheesy hack to change the font size. the font
                 * should store the size and change it on its own
                 */
                Font::getFont(Global::DEFAULT_FONT, 13, 13);
                infobox.draw(0, 0, infoWork, infoFont);
                Font::getFont(Global::DEFAULT_FONT, 24, 24);
                infoWork.BlitAreaToScreen(infobox_x, infobox_y);
            }
            /* work already contains the correct background */
            // work.Blit( load_x, load_y, *Bitmap::Screen );
            work.BlitAreaToScreen(load_x, load_y);
        }
    }

    return NULL;
}

/* shows two circles rotating around a center point */
void * loadingScreenSimple1(void * arg){
    Bitmap work(40, 40);
    Bitmap original(40, 40);
    original.BlitFromScreen(0, 0);
    Util::ThreadBoolean quit(done_loading, loading_screen_mutex);
    Global::speed_counter = 0;
    int angle = 0;
    int color1 = Bitmap::makeColor(0, 0, 0);
    int color2 = Bitmap::makeColor(0x00, 0x99, 0xff);
    int color3 = Bitmap::makeColor(0xff, 0x22, 0x33);
    int color4 = Bitmap::makeColor(0x44, 0x77, 0x33);
    int colors[4] = {color1, color2, color3, color4};
    Bitmap::transBlender(0, 0, 0, 64);
    int speed = 7;
    while (! quit.get()){
        bool draw = false;

        /* will be true if any new info messages appeared */
        if (Global::speed_counter > 0){
            double think = Global::speed_counter;
            Global::speed_counter = 0;
            draw = true;

            while (think > 0){
                angle += speed;
                think -= 1;
            }
        } else {
            Util::rest(1);
        }

        if (draw){
            int max = sizeof(colors) / sizeof(int);
            double middleX = work.getWidth() / 2;
            double middleY = work.getHeight() / 2;
            original.Blit(work);
            for (int i = 0; i < max; i++){
                double x = cos(Util::radians(angle + 360 / max * i)) * 15;
                double y = sin(Util::radians(angle + 360 / max * i)) * 15;
                work.translucent().circleFill(middleX + x, middleY + y, 2, colors[i]);
                x = cos(Util::radians(angle + speed + 360 / max * i)) * 15;
                y = sin(Util::radians(angle + speed + 360 / max * i)) * 15;
                work.circleFill(middleX + x, middleY + y, 2, colors[i]);
            }
            work.BlitAreaToScreen(0, 0);
        }
    }

    return NULL;
}

}
<|endoftext|>