<commit_before>#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>

#include <readline/readline.h>
#include <readline/history.h>

namespace {

enum Request {
  Execute,
  Complete
};

enum Response {
  RowSet,
  NewDatabase,
  CopySuccess,
  Success,
  Error
};

enum RowSetFlag {
  InsertedRow,
  DeletedRow,
  End,
  Item
};

class Buffer {
 public:
  Buffer(int capacity):
    array(static_cast<char*>(malloc(capacity))),
    capacity(capacity),
    position(0),
    limit(0)
  { }

  ~Buffer() {
    if (array) free(array);
  }

  char* array;
  int capacity;
  int position;
  int limit;
};

class Context {
 public:
  Context():
    buffer(8 * 1024),
    databaseName(0),
    socket(-1),
    completionCount(-1),
    trouble(false),
    exit(false),
    copying(false)
  { }

  ~Context() {
    if (databaseName) {
      free(databaseName);
    }
  }

  Buffer buffer;
  char* databaseName;
  int socket;
  int completionCount;
  bool trouble;
  bool exit;
  bool copying;
};

Context* globalContext = 0;

int
min(int a, int b)
{
  return a > b ? b : a;
}

int
connect(const char* host, int port)
{
  addrinfo hints;
  memset(&hints, 0, sizeof(addrinfo));
  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_STREAM;

  addrinfo* result;
  int r = getaddrinfo(host, 0, &hints, &result);
  if (r != 0) {
    fprintf(stderr, "unable to resolve localhost: %s\n", gai_strerror(r));
    return -1;
  }

  sockaddr_in address;
  memset(&address, 0, sizeof(sockaddr_in));
  address.sin_family = AF_INET;
  address.sin_port = htons(port);
  address.sin_addr = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr;

  freeaddrinfo(result);

  int socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (socket < 0) {
    perror("unable to open socket");
    return -1;
  }

  r = connect(socket, reinterpret_cast<sockaddr*>(&address),
              sizeof(sockaddr_in));
  if (r != 0) {
    perror("unable to connect");
    return -1;
  }

  return socket;
}

bool
flush(Context* context)
{
  int r = write
    (context->socket, context->buffer.array, context->buffer.position);
  if (r != context->buffer.position) {
    perror("\nunable to write");
    context->trouble = true;
    return false;
  }
  context->buffer.position = 0;
  return true;
}

int
writeBytes(Context* context, const char* src, int count)
{
  int total = 0;
  while (total < count) {
    if (context->buffer.limit == context->buffer.position) {
      if (not flush(context)) {
        return -1;
      }
    }

    int c = min
      (count - total, context->buffer.limit - context->buffer.position);
    memcpy(context->buffer.array + context->buffer.position, src + total, c);
    context->buffer.position += c;
    total += c;
  }
  return total;
}

bool
writeByte(Context* context, int v)
{
  char src[] = { v };
  return writeBytes(context, src, 1) == 1;
}

bool
writeInteger(Context* context, int v)
{
  char src[] = { (v >> 24) & 0xFF,
                 (v >> 16) & 0xFF,
                 (v >>  8) & 0xFF,
                 (v      ) & 0xFF };
  return writeBytes(context, src, 4) == 4;
}

bool
writeString(Context* context, const char* s, int length)
{
  if (writeInteger(context, length)) {
    return writeBytes(context, s, length) == length;
  } else {
    return false;
  }
}

int
readBytes(Context* context, char* dst, int count)
{
  int total = 0;
  while (total < count) {
    if (context->buffer.limit == context->buffer.position) {
      context->buffer.position = 0;
      int r = read
        (context->socket, context->buffer.array, context->buffer.capacity);
      if (r == 0) {
        fprintf(stderr, "\nunexpected end of stream from server\n");
        context->trouble = true;
        context->buffer.limit = 0;
        return -1;
      } else if (r < 0) {
        perror("\nunable to read");
        context->trouble = true;
        context->buffer.limit = 0;
        return -1;
      }
      context->buffer.limit = r;
    }

    int c = min
      (count - total, context->buffer.limit - context->buffer.position);
    memcpy(dst + total, context->buffer.array + context->buffer.position, c);
    context->buffer.position += c;
    total += c;
  }
  return total;
}

int
readByte(Context* context)
{
  char dst[1];
  int r = readBytes(context, dst, 1);
  return r < 1 ? -1 : dst[0];
}

int
readInteger(Context* context)
{
  char dst[4];
  int r = readBytes(context, dst, 4);
  return r < 4 ? -1 : (  (((int) dst[0]) << 24)
                       | (((int) dst[1]) << 16)
                       | (((int) dst[2]) <<  8)
                       | (((int) dst[3])      ));
}

char*
readString(Context* context)
{
  int length = readInteger(context);
  if (length < 0) {
    return 0;
  }

  char* string = static_cast<char*>(malloc(length + 1));
  if (string == 0) {
    fprintf(stderr, "\nunable to allocate memory\n");
    context->trouble = true;
    return 0;
  }

  int count = readBytes(context, string, length);
  if (count != length) {
    free(string);
    return 0;
  }

  string[length] = 0;

  return string;
}

int
startCompletion(Context* context, const char* text)
{
  context->buffer.position = 0;
  context->buffer.limit = context->buffer.capacity;

  if (not writeByte(context, Complete)) {
    return -1;
  }

  if (not writeString(context, text, strlen(text))) {
    return -1;
  }

  if (not flush(context)) {
    return -1;
  }

  context->buffer.limit = 0;

  int result = readByte(context);
  switch (result) {
  case -1:
    break;

  case Success: {
    return readInteger(context);
  } break;

  case Error: {
    char* message = readString(context);
    if (message == 0) {
      return -1;
    }

    free(message);
  } break;

  default:
    fprintf(stderr, "\nunexpected result from server: %d\n", result);
    context->trouble = true;
    break;
  }

  return -1;
}

char*
completionGenerator(const char*, int state)
{
  Context* context = globalContext;

  if (context->trouble) {
    return 0;
  }

  if (state == 0) {
    context->completionCount = startCompletion(context, rl_line_buffer);
  }

  if (context->completionCount <= 0) {
    return 0;
  } else {
    -- context->completionCount;

    return readString(context);
  }
}

char*
removeEdgeWhitespace(char* s)
{
  while (isspace(*s)) ++s;

  if (*s == 0) return s;

  char* p = s;
  char* lastNonSpace = p;
  while (*p) {
    if (not isspace(*p)) {
      lastNonSpace = p;
    }
    ++ p;
  }

  lastNonSpace[1] = 0;

  return s;
}

void
execute(Context* context, const char* command)
{
  if (strcmp(command, "exit") == 0
      || strcmp(command, "quit") == 0)
  {
    context->exit = true;
    return;
  }

  if (context->trouble) {
    return;
  }

  if (not context->copying) {
    context->buffer.position = 0;
    context->buffer.limit = context->buffer.capacity;
  }

  if (not writeByte(context, Execute)) {
    return;
  }

  if (not writeString(context, command, strlen(command))) {
    return;
  }

  if (context->copying && strcmp(command, "\\.") == 0) {
    if (not flush(context)) {
      return;
    }
    context->copying = false;
  }

  if (context->copying) {
    return;
  }

  if (not flush(context)) {
    return;
  }

  context->buffer.limit = 0;

  int result = readByte(context);
  switch (result) {
  case -1:
    break;

  case NewDatabase: {
    if (context->databaseName) {
      free(context->databaseName);
    }

    context->databaseName = readString(context);
    if (context->databaseName == 0) {
      return;
    }

    char* message = readString(context);
    if (message == 0) {
      return;
    }

    fprintf(stdout, "%s\n", message);

    free(message);
  } break;

  case CopySuccess: {
    char* message = readString(context);
    if (message == 0) {
      return;
    }

    fprintf(stdout, "%s\n", message);

    free(message);

    context->buffer.position = 0;
    context->buffer.limit = context->buffer.capacity;

    context->copying = true;
  } break;

  case Success: {
    char* message = readString(context);
    if (message == 0) {
      return;
    }

    fprintf(stdout, "%s\n", message);

    free(message);
  } break;

  case RowSet: {
    bool done = false;
    bool sawRow = false;
    while (not done) {
      int flag = readByte(context);
      switch (flag) {
      case -1:
        return;

      case InsertedRow:
        sawRow = true;
        fprintf(stdout, "\n inserted:");
        break;

      case DeletedRow:
        sawRow = true;
        fprintf(stdout, "\n  deleted:");
        break;

      case Item: {
        char* item = readString(context);
        if (item == 0) {
          return;
        }

        fprintf(stdout, " %s", item);

        free(item);
      } break;

      case End:
        if (not sawRow) {
          fprintf(stdout, "\n no matching rows found");
        }
        done = true;
        fprintf(stdout, "\n");
        break;

      default:
        fprintf(stderr, "\nunexpected flag from server: %d\n", flag);
        context->trouble = true;
        return;
      }
    }
  } break;

  case Error: {
    char* message = readString(context);
    if (message == 0) {
      return;
    }

    fprintf(stderr, "error: %s\n", message);

    free(message);
  } break;

  default:
    fprintf(stderr, "\nunexpected result from server: %d\n", result);
    context->trouble = true;
    break;
  }
}

} // namespace

int
main(int, const char**)
{
  Context context;
  globalContext = &context;

  if (context.buffer.array == 0) {
    fprintf(stderr, "\nunable to allocate memory\n");
    return -1;
  }

  context.socket = connect("localhost", 8017);
  if (context.socket < 0) {
    return -1;
  }

  fprintf(stdout, "Welcome to the DBMS SQL client interface.  "
          "Type \"help\" to get started.\n");

  rl_readline_name = "DBMSClient";

  rl_completion_entry_function = completionGenerator;

  while (not (context.trouble || context.exit)) {
    char* line;
    if (context.databaseName) {
      int length = strlen(context.databaseName) + 4;
      char* prompt = static_cast<char*>(malloc(length));
      if (prompt == 0) {
        fprintf(stderr, "\nunable to allocate memory\n");
        return -1;
      }

      snprintf(prompt, length, "%s > ", context.databaseName);
      line = readline(prompt);
      free(prompt);
    } else {
      line = readline("> ");
    }

    if (line == 0) {
      fprintf(stdout, "\n");
      break;
    }

    char* s = removeEdgeWhitespace(line);
    if (*s) {
      add_history(s);

      execute(&context, s);
      fprintf(stdout, "\n");
    }

    free(line);
  }

  close(context.socket);

  return context.trouble ? -1 : 0;
}
<commit_msg>add noninteractive mode for efficient batch operations<commit_after>#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>

#include <readline/readline.h>
#include <readline/history.h>

namespace {

enum Request {
  Execute,
  Complete
};

enum Response {
  RowSet,
  NewDatabase,
  CopySuccess,
  Success,
  Error
};

enum RowSetFlag {
  InsertedRow,
  DeletedRow,
  End,
  Item
};

class Buffer {
 public:
  Buffer(int capacity):
    array(static_cast<char*>(malloc(capacity))),
    capacity(capacity),
    position(0),
    limit(0)
  { }

  ~Buffer() {
    if (array) free(array);
  }

  char* array;
  int capacity;
  int position;
  int limit;
};

class Context {
 public:
  Context():
    buffer(8 * 1024),
    databaseName(0),
    socket(-1),
    completionCount(-1),
    trouble(false),
    exit(false),
    copying(false)
  { }

  ~Context() {
    if (databaseName) {
      free(databaseName);
    }
  }

  Buffer buffer;
  char* databaseName;
  int socket;
  int completionCount;
  bool trouble;
  bool exit;
  bool copying;
};

Context* globalContext = 0;

int
min(int a, int b)
{
  return a > b ? b : a;
}

int
connect(const char* host, int port)
{
  addrinfo hints;
  memset(&hints, 0, sizeof(addrinfo));
  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_STREAM;

  addrinfo* result;
  int r = getaddrinfo(host, 0, &hints, &result);
  if (r != 0) {
    fprintf(stderr, "unable to resolve localhost: %s\n", gai_strerror(r));
    return -1;
  }

  sockaddr_in address;
  memset(&address, 0, sizeof(sockaddr_in));
  address.sin_family = AF_INET;
  address.sin_port = htons(port);
  address.sin_addr = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr;

  freeaddrinfo(result);

  int socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (socket < 0) {
    perror("unable to open socket");
    return -1;
  }

  r = connect(socket, reinterpret_cast<sockaddr*>(&address),
              sizeof(sockaddr_in));
  if (r != 0) {
    perror("unable to connect");
    return -1;
  }

  return socket;
}

bool
flush(Context* context)
{
  int r = write
    (context->socket, context->buffer.array, context->buffer.position);
  if (r != context->buffer.position) {
    perror("\nunable to write");
    context->trouble = true;
    return false;
  }
  context->buffer.position = 0;
  return true;
}

int
writeBytes(Context* context, const char* src, int count)
{
  int total = 0;
  while (total < count) {
    if (context->buffer.limit == context->buffer.position) {
      if (not flush(context)) {
        return -1;
      }
    }

    int c = min
      (count - total, context->buffer.limit - context->buffer.position);
    memcpy(context->buffer.array + context->buffer.position, src + total, c);
    context->buffer.position += c;
    total += c;
  }
  return total;
}

bool
writeByte(Context* context, int v)
{
  char src[] = { v };
  return writeBytes(context, src, 1) == 1;
}

bool
writeInteger(Context* context, int v)
{
  char src[] = { (v >> 24) & 0xFF,
                 (v >> 16) & 0xFF,
                 (v >>  8) & 0xFF,
                 (v      ) & 0xFF };
  return writeBytes(context, src, 4) == 4;
}

bool
writeString(Context* context, const char* s, int length)
{
  if (writeInteger(context, length)) {
    return writeBytes(context, s, length) == length;
  } else {
    return false;
  }
}

int
readBytes(Context* context, char* dst, int count)
{
  int total = 0;
  while (total < count) {
    if (context->buffer.limit == context->buffer.position) {
      context->buffer.position = 0;
      int r = read
        (context->socket, context->buffer.array, context->buffer.capacity);
      if (r == 0) {
        fprintf(stderr, "\nunexpected end of stream from server\n");
        context->trouble = true;
        context->buffer.limit = 0;
        return -1;
      } else if (r < 0) {
        perror("\nunable to read");
        context->trouble = true;
        context->buffer.limit = 0;
        return -1;
      }
      context->buffer.limit = r;
    }

    int c = min
      (count - total, context->buffer.limit - context->buffer.position);
    memcpy(dst + total, context->buffer.array + context->buffer.position, c);
    context->buffer.position += c;
    total += c;
  }
  return total;
}

int
readByte(Context* context)
{
  char dst[1];
  int r = readBytes(context, dst, 1);
  return r < 1 ? -1 : dst[0];
}

int
readInteger(Context* context)
{
  char dst[4];
  int r = readBytes(context, dst, 4);
  return r < 4 ? -1 : (  (((int) dst[0]) << 24)
                       | (((int) dst[1]) << 16)
                       | (((int) dst[2]) <<  8)
                       | (((int) dst[3])      ));
}

char*
readString(Context* context)
{
  int length = readInteger(context);
  if (length < 0) {
    return 0;
  }

  char* string = static_cast<char*>(malloc(length + 1));
  if (string == 0) {
    fprintf(stderr, "\nunable to allocate memory\n");
    context->trouble = true;
    return 0;
  }

  int count = readBytes(context, string, length);
  if (count != length) {
    free(string);
    return 0;
  }

  string[length] = 0;

  return string;
}

int
startCompletion(Context* context, const char* text)
{
  context->buffer.position = 0;
  context->buffer.limit = context->buffer.capacity;

  if (not writeByte(context, Complete)) {
    return -1;
  }

  if (not writeString(context, text, strlen(text))) {
    return -1;
  }

  if (not flush(context)) {
    return -1;
  }

  context->buffer.limit = 0;

  int result = readByte(context);
  switch (result) {
  case -1:
    break;

  case Success: {
    return readInteger(context);
  } break;

  case Error: {
    char* message = readString(context);
    if (message == 0) {
      return -1;
    }

    free(message);
  } break;

  default:
    fprintf(stderr, "\nunexpected result from server: %d\n", result);
    context->trouble = true;
    break;
  }

  return -1;
}

char*
completionGenerator(const char*, int state)
{
  Context* context = globalContext;

  if (context->trouble) {
    return 0;
  }

  if (state == 0) {
    context->completionCount = startCompletion(context, rl_line_buffer);
  }

  if (context->completionCount <= 0) {
    return 0;
  } else {
    -- context->completionCount;

    return readString(context);
  }
}

char*
removeEdgeWhitespace(char* s)
{
  while (isspace(*s)) ++s;

  if (*s == 0) return s;

  char* p = s;
  char* lastNonSpace = p;
  while (*p) {
    if (not isspace(*p)) {
      lastNonSpace = p;
    }
    ++ p;
  }

  lastNonSpace[1] = 0;

  return s;
}

void
execute(Context* context, const char* command)
{
  if (strcmp(command, "exit") == 0
      || strcmp(command, "quit") == 0)
  {
    context->exit = true;
    return;
  }

  if (context->trouble) {
    return;
  }

  if (not context->copying) {
    context->buffer.position = 0;
    context->buffer.limit = context->buffer.capacity;
  }

  if (not writeByte(context, Execute)) {
    return;
  }

  if (not writeString(context, command, strlen(command))) {
    return;
  }

  if (context->copying && strcmp(command, "\\.") == 0) {
    if (not flush(context)) {
      return;
    }
    context->copying = false;
  }

  if (context->copying) {
    return;
  }

  if (not flush(context)) {
    return;
  }

  context->buffer.limit = 0;

  int result = readByte(context);
  switch (result) {
  case -1:
    break;

  case NewDatabase: {
    if (context->databaseName) {
      free(context->databaseName);
    }

    context->databaseName = readString(context);
    if (context->databaseName == 0) {
      return;
    }

    char* message = readString(context);
    if (message == 0) {
      return;
    }

    fprintf(stdout, "%s\n", message);

    free(message);
  } break;

  case CopySuccess: {
    char* message = readString(context);
    if (message == 0) {
      return;
    }

    fprintf(stdout, "%s\n", message);

    free(message);

    context->buffer.position = 0;
    context->buffer.limit = context->buffer.capacity;

    context->copying = true;
  } break;

  case Success: {
    char* message = readString(context);
    if (message == 0) {
      return;
    }

    fprintf(stdout, "%s\n", message);

    free(message);
  } break;

  case RowSet: {
    bool done = false;
    bool sawRow = false;
    while (not done) {
      int flag = readByte(context);
      switch (flag) {
      case -1:
        return;

      case InsertedRow:
        sawRow = true;
        fprintf(stdout, "\n inserted:");
        break;

      case DeletedRow:
        sawRow = true;
        fprintf(stdout, "\n  deleted:");
        break;

      case Item: {
        char* item = readString(context);
        if (item == 0) {
          return;
        }

        fprintf(stdout, " %s", item);

        free(item);
      } break;

      case End:
        if (not sawRow) {
          fprintf(stdout, "\n no matching rows found");
        }
        done = true;
        fprintf(stdout, "\n");
        break;

      default:
        fprintf(stderr, "\nunexpected flag from server: %d\n", flag);
        context->trouble = true;
        return;
      }
    }
  } break;

  case Error: {
    char* message = readString(context);
    if (message == 0) {
      return;
    }

    fprintf(stderr, "error: %s\n", message);

    free(message);
  } break;

  default:
    fprintf(stderr, "\nunexpected result from server: %d\n", result);
    context->trouble = true;
    break;
  }
}

void
usage(const char* name)
{
  fprintf(stderr, "usage: %s [batch]\n", name);
}

} // namespace

int
main(int argumentCount, const char** arguments)
{
  Context context;
  globalContext = &context;

  if (context.buffer.array == 0) {
    fprintf(stderr, "\nunable to allocate memory\n");
    return -1;
  }

  context.socket = connect("localhost", 8017);
  if (context.socket < 0) {
    return -1;
  }

  bool interactive;
  switch (argumentCount) {
  case 1:
    interactive = true;
    break;

  case 2:
    if (strcmp("batch", arguments[1]) == 0) {
      interactive = false;
    } else {
      usage(arguments[0]);
      return -1;
    }
    break;

  default:
    usage(arguments[0]);
    return -1;
  }

  if (interactive) {
    fprintf(stdout, "Welcome to the DBMS SQL client interface.  "
            "Type \"help\" to get started.\n");

    rl_readline_name = "DBMSClient";

    rl_completion_entry_function = completionGenerator;

    while (not (context.trouble || context.exit)) {
      char* line;
      if (context.databaseName) {
        int length = strlen(context.databaseName) + 4;
        char* prompt = static_cast<char*>(malloc(length));
        if (prompt == 0) {
          fprintf(stderr, "\nunable to allocate memory\n");
          return -1;
        }

        snprintf(prompt, length, "%s > ", context.databaseName);
        line = readline(prompt);
        free(prompt);
      } else {
        line = readline("> ");
      }

      if (line == 0) {
        fprintf(stdout, "\n");
        break;
      }

      if (context.copying) {
        execute(&context, line);
      } else {
        char* s = removeEdgeWhitespace(line);
        if (*s) {
          add_history(s);

          execute(&context, s);
          fprintf(stdout, "\n");
        }
      }

      free(line);
    }
  } else {
    const int BufferSize = 8096;
    char buffer[BufferSize];
    int i = 0;

    while (true) {
      int c = fgetc(stdin);
      switch (c) {
      case EOF:
        return 0;

      case '\n':
        buffer[i] = 0;
        execute(&context, buffer);
        i = 0;
        break;

      default:
        if (i < BufferSize - 1) {
          buffer[i++] = c;
        } else {
          fprintf(stderr, "buffer overflow\n");
          return -1;
        }
        break;
      }
    }
  }

  close(context.socket);

  return context.trouble ? -1 : 0;
}
<|endoftext|>


<commit_before>// -*-c++-*-

/*
 * $Id$
 *
 * Loader for DirectX .x files.
 * Copyright (c)2002-2006 Ulrich Hertlein <u.hertlein@sandbox.de>
 *
 * 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.1 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#if defined(_MSC_VER) && (_MSC_VER <= 1200)
#pragma warning (disable : 4786)
#endif

#include "types.h"

#include <iostream>
#include <string.h>
#include <stdlib.h>

using namespace std;

namespace DX {

    // Tokenize a string
    void tokenize(const string & str, vector<string> & tokens, const string & delimiters)
    {
        string::size_type lastPos = str.find_first_not_of(delimiters, 0);
        string::size_type pos     = str.find_first_of(delimiters, lastPos);

        while (string::npos != pos || string::npos != lastPos) {
            tokens.push_back(str.substr(lastPos, pos - lastPos));
            lastPos = str.find_first_not_of(delimiters, pos);
            pos = str.find_first_of(delimiters, lastPos);
        }
    }

    // Read 'TextureFilename'
    void readTexFilename(ifstream & fin, TextureFilename & texture)
    {
        char buf[256];
        vector<string> token;

        //cerr << "*** TexFilename\n";
        while (fin.getline(buf, sizeof(buf))) {

            // Tokenize
            token.clear();
            tokenize(buf, token);
            if (token.size() == 0)
                continue;
            if (token[0] == "}")
                break;

            // Strip " if present
            std::string line = buf;
            std::string::size_type pos = line.find('"');
            if (pos != string::npos) {
                std::string::size_type end = line.rfind('"');
                int len = (end != std::string::npos ? (end-pos-1) : (line.size()-pos));
                texture = line.substr(pos+1, len);
            }
            else
                texture = token[0];
            //cerr << "* tex='" << texture << "'" << endl;
        }
    }

    // Read 'Coords2d'
    void readCoords2d(ifstream & fin, vector<Coords2d> & v, unsigned int count)
    {
        char buf[256];
        vector<string> token;

        unsigned int i = 0;

        //cerr << "*** Coords2d\n";
        while (i < count && fin.getline(buf, sizeof(buf))) {

            // Tokenize
            token.clear();
            tokenize(buf, token);
            if (token.size() == 0)
                continue;

            Coords2d c;
            c.u = (float) atof(token[0].c_str());
            c.v = (float) atof(token[1].c_str());
            v.push_back(c);
            i++;
        }
    }

    // Read 'Vector'
    void readVector(ifstream & fin, vector<Vector> & v, unsigned int count)
    {
        char buf[256];
        vector<string> token;

        unsigned int i = 0;

        //cerr << "*** Vector\n";
        while (i < count && fin.getline(buf, sizeof(buf))) {

            // Tokenize
            token.clear();
            tokenize(buf, token);
            if (token.size() == 0)
                continue;

            Vector vec;
            vec.x = (float) atof(token[0].c_str());
            vec.y = (float) atof(token[1].c_str());
            vec.z = (float) atof(token[2].c_str());
            v.push_back(vec);
            i++;
        }
    }

    // Parse 'Material'
    void parseMaterial(ifstream & fin, Material & material)
    {
        char buf[256];
        vector<string> token;

        unsigned int i = 0;

        //cerr << "*** Material\n";
        while (fin.getline(buf, sizeof(buf))) {

            // Tokenize
            token.clear();
            tokenize(buf, token);
            if (token.size() == 0)
                continue;
            if (token[0] == "}")
                break;
            if (token[0] == "TextureFilename") {
                TextureFilename tf;
                readTexFilename(fin, tf);
                material.texture.push_back(tf);
                //cerr << "* num tex=" << material.texture.size() << endl;
            } else {
                switch (i) {
                    case 0: {
                                // ColorRGBA
                                material.faceColor.red = (float) atof(token[0].c_str());
                                material.faceColor.green = (float) atof(token[1].c_str());
                                material.faceColor.blue = (float) atof(token[2].c_str());
                                material.faceColor.alpha = (float) atof(token[3].c_str());
                                i++;
                            } break;
                    case 1: {
                                // Power
                                material.power = (float) atof(token[0].c_str());
                                i++;
                            } break;
                    case 2: {
                                // ColorRGB
                                material.specularColor.red = (float) atof(token[0].c_str());
                                material.specularColor.green = (float) atof(token[1].c_str());
                                material.specularColor.blue = (float) atof(token[2].c_str());
                                i++;
                            } break;
                    case 3: {
                                // ColorRGB
                                material.emissiveColor.red = (float) atof(token[0].c_str());
                                material.emissiveColor.green = (float) atof(token[1].c_str());
                                material.emissiveColor.blue = (float) atof(token[2].c_str());
                                i++;
                            } break;
                }
            }
        }
    }

    // Read index list
    void readIndexList(ifstream & fin, vector<unsigned int> & v, unsigned int count)
    {
        char buf[256];
        vector<string> token;

        unsigned int i = 0;

        //cerr << "*** IndexList\n";
        while (i < count && fin.getline(buf, sizeof(buf))) {

            // Tokenize
            token.clear();
            tokenize(buf, token);
            if (token.size() == 0)
                continue;

            unsigned int idx = atoi(token[0].c_str());
            v.push_back(idx);
            i++;
        }
    }

    // Read 'MeshFace'
    void readMeshFace(ifstream & fin, vector<MeshFace> & v, unsigned int count)
    {
        char buf[256];
        vector<string> token;

        unsigned int i = 0;

        //cerr << "*** MeshFace\n";
        while (i < count && fin.getline(buf, sizeof(buf))) {

            // Tokenize
            token.clear();
            tokenize(buf, token);
            if (token.size() == 0)
                continue;

            MeshFace mf;
            unsigned int n = atoi(token[0].c_str());

            for (unsigned int j = 0; j < n; j++) {
                unsigned int idx = atoi(token[j+1].c_str());
                mf.push_back(idx);
            }
            v.push_back(mf);
            i++;
        }
    }

}
<commit_msg>From Urlich Hertlein, "Attached is a patched version that replaces calls to atof() with osg::asciiToFloat()."<commit_after>// -*-c++-*-

/*
 * $Id$
 *
 * Loader for DirectX .x files.
 * Copyright (c)2002-2006 Ulrich Hertlein <u.hertlein@sandbox.de>
 *
 * 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.1 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#if defined(_MSC_VER) && (_MSC_VER <= 1200)
#pragma warning (disable : 4786)
#endif

#include "types.h"

#include <iostream>
#include <string.h>
#include <stdlib.h>

using namespace std;

namespace DX {

    // Tokenize a string
    void tokenize(const string & str, vector<string> & tokens, const string & delimiters)
    {
        string::size_type lastPos = str.find_first_not_of(delimiters, 0);
        string::size_type pos     = str.find_first_of(delimiters, lastPos);

        while (string::npos != pos || string::npos != lastPos) {
            tokens.push_back(str.substr(lastPos, pos - lastPos));
            lastPos = str.find_first_not_of(delimiters, pos);
            pos = str.find_first_of(delimiters, lastPos);
        }
    }

    // Read 'TextureFilename'
    void readTexFilename(ifstream & fin, TextureFilename & texture)
    {
        char buf[256];
        vector<string> token;

        //cerr << "*** TexFilename\n";
        while (fin.getline(buf, sizeof(buf))) {

            // Tokenize
            token.clear();
            tokenize(buf, token);
            if (token.size() == 0)
                continue;
            if (token[0] == "}")
                break;

            // Strip " if present
            std::string line = buf;
            std::string::size_type pos = line.find('"');
            if (pos != string::npos) {
                std::string::size_type end = line.rfind('"');
                int len = (end != std::string::npos ? (end-pos-1) : (line.size()-pos));
                texture = line.substr(pos+1, len);
            }
            else
                texture = token[0];
            //cerr << "* tex='" << texture << "'" << endl;
        }
    }

    // Read 'Coords2d'
    void readCoords2d(ifstream & fin, vector<Coords2d> & v, unsigned int count)
    {
        char buf[256];
        vector<string> token;

        unsigned int i = 0;

        //cerr << "*** Coords2d\n";
        while (i < count && fin.getline(buf, sizeof(buf))) {

            // Tokenize
            token.clear();
            tokenize(buf, token);
            if (token.size() == 0)
                continue;

            Coords2d c;
            c.u = osg::asciiToFloat(token[0].c_str());
            c.v = osg::asciiToFloat(token[1].c_str());
            v.push_back(c);
            i++;
        }
    }

    // Read 'Vector'
    void readVector(ifstream & fin, vector<Vector> & v, unsigned int count)
    {
        char buf[256];
        vector<string> token;

        unsigned int i = 0;

        //cerr << "*** Vector\n";
        while (i < count && fin.getline(buf, sizeof(buf))) {

            // Tokenize
            token.clear();
            tokenize(buf, token);
            if (token.size() == 0)
                continue;

            Vector vec;
            vec.x = osg::asciiToFloat(token[0].c_str());
            vec.y = osg::asciiToFloat(token[1].c_str());
            vec.z = osg::asciiToFloat(token[2].c_str());
            v.push_back(vec);
            i++;
        }
    }

    // Parse 'Material'
    void parseMaterial(ifstream & fin, Material & material)
    {
        char buf[256];
        vector<string> token;

        unsigned int i = 0;

        //cerr << "*** Material\n";
        while (fin.getline(buf, sizeof(buf))) {

            // Tokenize
            token.clear();
            tokenize(buf, token);
            if (token.size() == 0)
                continue;
            if (token[0] == "}")
                break;
            if (token[0] == "TextureFilename") {
                TextureFilename tf;
                readTexFilename(fin, tf);
                material.texture.push_back(tf);
                //cerr << "* num tex=" << material.texture.size() << endl;
            } else {
                switch (i) {
                    case 0: {
                                // ColorRGBA
                                material.faceColor.red = osg::asciiToFloat(token[0].c_str());
                                material.faceColor.green = osg::asciiToFloat(token[1].c_str());
                                material.faceColor.blue = osg::asciiToFloat(token[2].c_str());
                                material.faceColor.alpha = osg::asciiToFloat(token[3].c_str());
                                i++;
                            } break;
                    case 1: {
                                // Power
                                material.power = osg::asciiToFloat(token[0].c_str());
                                i++;
                            } break;
                    case 2: {
                                // ColorRGB
                                material.specularColor.red = osg::asciiToFloat(token[0].c_str());
                                material.specularColor.green = osg::asciiToFloat(token[1].c_str());
                                material.specularColor.blue = osg::asciiToFloat(token[2].c_str());
                                i++;
                            } break;
                    case 3: {
                                // ColorRGB
                                material.emissiveColor.red = osg::asciiToFloat(token[0].c_str());
                                material.emissiveColor.green = osg::asciiToFloat(token[1].c_str());
                                material.emissiveColor.blue = osg::asciiToFloat(token[2].c_str());
                                i++;
                            } break;
                }
            }
        }
    }

    // Read index list
    void readIndexList(ifstream & fin, vector<unsigned int> & v, unsigned int count)
    {
        char buf[256];
        vector<string> token;

        unsigned int i = 0;

        //cerr << "*** IndexList\n";
        while (i < count && fin.getline(buf, sizeof(buf))) {

            // Tokenize
            token.clear();
            tokenize(buf, token);
            if (token.size() == 0)
                continue;

            unsigned int idx = atoi(token[0].c_str());
            v.push_back(idx);
            i++;
        }
    }

    // Read 'MeshFace'
    void readMeshFace(ifstream & fin, vector<MeshFace> & v, unsigned int count)
    {
        char buf[256];
        vector<string> token;

        unsigned int i = 0;

        //cerr << "*** MeshFace\n";
        while (i < count && fin.getline(buf, sizeof(buf))) {

            // Tokenize
            token.clear();
            tokenize(buf, token);
            if (token.size() == 0)
                continue;

            MeshFace mf;
            unsigned int n = atoi(token[0].c_str());

            for (unsigned int j = 0; j < n; j++) {
                unsigned int idx = atoi(token[j+1].c_str());
                mf.push_back(idx);
            }
            v.push_back(mf);
            i++;
        }
    }

}
<|endoftext|>


<commit_before>#include "client.hpp"

/** For logging **/
#include "logger.hpp"

/** For event-handling **/
#include <SDL2/SDL.h>

/** For network **/
#include "messagetypes.hpp"
#include "packet.hpp"
#include "systemidentifiers.hpp"

#include "inputdata.hpp"

Client::Client(int argc, char** argv) :
        socket("swordbow-magic"),
        sequence(1),
        systemManager(&componentManager, &deltaTime),
        renderer(argc, argv),
        textureBoundingBox(&componentManager, &renderer),
        textureHashGridSystem(&textureBoundingBox),
        cameraSystem(&renderer),
        renderSystem(&renderer, &textureHashGridSystem, &cameraSystem) {

    Logger::log("Starting client", Log::INFO);

    //Default port
    short port = 47294;

    //Check if port is set
    for(int i = 0; i < argc; i++) {
		if(strcmp(argv[i], "port") == 0) {
			port = std::atoi(argv[i+1]);
		}
	}

    socket.open(port);

    systemManager.add(&textureHashGridSystem);
    systemManager.add(&renderSystem);
    systemManager.add(&cameraSystem);

    //Play some sweet music
	soundEngine.playMusic(Music::NATURE_SOUNDS);
}

Client::~Client() {
    socket.close();
    Logger::log("Destroying client", Log::INFO);
}

void Client::connect(const IpAddress& server) {
    //Start a thread that checks socket for any recieved data
    receiveThreadRunning = true;
    receiveThread = std::thread(&Client::receive, this);

    this->server = server;

    //Connect-request packet
    send<bool>(true, MESSAGE_TYPE::CONNECT);
    std::ostringstream oss;
    oss << "Sent connect request to " << server;
    Logger::log(oss, Log::INFO);
}

void Client::disconnect() {

    //Stop receiving data on socket
    receiveThreadRunning = false;
    receiveThread.join();

    //Disconnect-request packet
    send<bool>(true, MESSAGE_TYPE::DISCONNECT);

    std::ostringstream oss;
    oss << "Disconnected from " << server;
    Logger::log(oss, Log::INFO);

    //Indicate not connected to any server
    server = IpAddress(0, 0, 0, 0, 0);
}

void Client::receive() {
    while(receiveThreadRunning) {

        //Receive data from server...
        IpAddress server;
        unsigned char type;
        int bytesRead;
        socket.receive(server, type, bytesRead);

        //If any data was received, check its type and take appropiate action
        if(bytesRead > 0) {

            /** CRITICAL-SECTION **/
            componentsMutex.lock();

            switch(type) {
                case MESSAGE_TYPE::OUTDATED: {
                    Logger::log("This packet is outdated, to late! Sluggish!", Log::WARNING);
                } break;

                case MESSAGE_TYPE::CONNECT: {
                    Logger::log("Got camera ID from server", Log::INFO);

                    //Got my id. Tell camerasystem to follow that id.
                    auto typedPacket = socket.get<Packet<std::pair<ID, System::Identifier>>>(bytesRead);
                    const auto& pair = typedPacket.getData();
                    systemManager.getSystem(pair.second)->add(pair.first);
                } break;

                //Server will send this to client for a couple of reasons.
                //In any case the client shouldn't be connected to the server.
                case MESSAGE_TYPE::DISCONNECT: {
                    Logger::log("Received DISCONNECT packet", Log::INFO);
                    disconnect();
                } break;

                case MESSAGE_TYPE::INITIAL_COMPONENTS: {
                    Logger::log("Received INITIAL_COMPONENTS packet", Log::INFO);

                    using DataType = std::pair<Components<MoveComponent>, Components<RenderComponent>>;
                    using PacketType = Packet<DataType>;
                    auto typedPacket = socket.get<PacketType>(bytesRead);

                    for(auto& pair : typedPacket.getData().first) {
                        textureHashGridSystem.add(pair.first);
                        renderSystem.add(pair.first);
                    }
                } break;

                case MESSAGE_TYPE::MOVECOMPONENTS: {
                    Logger::log("Received MOVECOMPONENTS packet", Log::INFO);

                    //All movecomponents were received - handle it
                    auto typedPacket = socket.get<Packet<Components<MoveComponent>>>(bytesRead);
                    componentManager.moveComponents.sync(typedPacket.getData());

                    //It is assumed that any receieved movecomponent should
                    //be added to texturehashgridsystem and rendersystem,
                    //because if not, why would the server send them in the first
                    //place?
                    for(auto& pair : typedPacket.getData()) {
                        textureHashGridSystem.add(pair.first);
                        renderSystem.add(pair.first);
                    }

                } break;

                case MESSAGE_TYPE::RENDERCOMPONENTS: {
                    Logger::log("Received RENDERCOMPONENTS packet", Log::INFO);

                    //All rendercomponents were received - handle it
                    auto typedPacket = socket.get<Packet<Components<RenderComponent>>>(bytesRead);
                    componentManager.renderComponents.sync(typedPacket.getData());

                    for(auto& pair : typedPacket.getData()) {
                        textureHashGridSystem.add(pair.first);
                        renderSystem.add(pair.first);
                    }

                } break;

                case MESSAGE_TYPE::MOVECOMPONENTSDIFF: {
                    Logger::log("Received MOVECOMPONENTSDIFF packet", Log::INFO);

                    //Diff movecomponents were received - handle it
                    auto typedPacket = socket.get<Packet<Components<MoveComponent>>>(bytesRead);
                    componentManager.moveComponents.sync(typedPacket.getData());

                    //It makes sence to auto-activate newly received ids of the
                    //movecomponents in rendersystem, since the server only
                    //sends movecomponents on actual difference, the client
                    //should redraw that difference. So former ACTIVATE_ID message
                    //could be implicit with any component-message, which has the
                    //benefit of not mistakingly activating ids before components
                    //are received. Since system.add is a superset of system.activateId
                    //we might aswell assume adding received components to systems
                    //which makes REGISTER_ID_TO_SYSTEM-message obsolete
                    for(auto& pair : typedPacket.getData()) {
                        textureHashGridSystem.add(pair.first);
                        renderSystem.add(pair.first);
                    }

                } break;

                case MESSAGE_TYPE::RENDERCOMPONENTSDIFF: {
                    Logger::log("Received RENDERCOMPONENTSDIFF packet", Log::INFO);

                    //Diff rendercomponents were received - handle it
                    auto typedPacket = socket.get<Packet<Components<RenderComponent>>>(bytesRead);
                    componentManager.renderComponents.sync(typedPacket.getData());

                    for(auto& pair : typedPacket.getData()) {
                        textureHashGridSystem.add(pair.first);
                        renderSystem.add(pair.first);
                    }
                } break;

                case MESSAGE_TYPE::PLAY_SOUND: {
                    Logger::log("Received PLAY_SOUND packet", Log::INFO);

                    auto typedPacket = socket.get<Packet<SoundData>>(bytesRead);
                    soundEngine.playSound(typedPacket.getData());
                } break;

                case MESSAGE_TYPE::REGISTER_ID_TO_SYSTEM: {
                    Logger::log("Received REGISTER_ID_TO_SYSTEM packet", Log::INFO);

                    auto typedPacket = socket.get<Packet<std::pair<ID, System::Identifier>>>(bytesRead);
                    const auto& id = typedPacket.getData().first;
                    const auto& systemIdentifier = typedPacket.getData().second;
                    systemManager.getSystem(systemIdentifier)->add(id);
                } break;

                case MESSAGE_TYPE::REMOVE_ID: {
                    Logger::log("Received REMOVE_ID packet", Log::INFO);

                    auto typedPacket = socket.get<Packet<ID>>(bytesRead);
                    const auto& id = typedPacket.getData();
                    systemManager.getSystem(System::RENDER)->remove(id);
                    systemManager.getSystem(System::HASHGRID_TEXTURE)->remove(id);
                    componentManager.clearComponents(id);
                } break;

                case MESSAGE_TYPE::REMOVE_ID_FROM_SYSTEM: {
                    Logger::log("Received REMOVE_ID_FROM_SYSTEM packet", Log::INFO);

                    auto typedPacket = socket.get<Packet<std::pair<ID, System::Identifier>>>(bytesRead);
                    const auto& id = typedPacket.getData().first;
                    const auto& systemIdentifier = typedPacket.getData().second;
                    systemManager.getSystem(systemIdentifier)->remove(id);
                } break;

                case MESSAGE_TYPE::REMOVE_ID_FROM_SYSTEMS: {
                    Logger::log("Received REMOVE_ID_FROM_SYSTEMS packet", Log::INFO);

                    auto typedPacket = socket.get<Packet<ID>>(bytesRead);
                    const auto& id = typedPacket.getData();
                    systemManager.getSystem(System::RENDER)->remove(id);
                    systemManager.getSystem(System::HASHGRID_TEXTURE)->remove(id);
                } break;

                case MESSAGE_TYPE::ACTIVATE_ID: {
                    Logger::log("Received ACTIVATE_ID packet", Log::INFO);

                    auto typedPacket = socket.get<Packet<std::pair<ID, System::Identifier>>>(bytesRead);
                    const auto& id = typedPacket.getData().first;
                    const auto& systemIdentifier = typedPacket.getData().second;
                    systemManager.getSystem(systemIdentifier)->activateId(id);
                } break;

                default: {
                    const std::string logstr(
                        std::string("Message without proper type received. This is probably a bug.\n") +
                        std::string("Either client-side handling for that message isn't implemented") +
                        std::string(" or server sent a message with a bogus messagetype") +
                        std::string(" or the messagetype was wrongly altered somewhere\n")
                    );
                    Logger::log(logstr, Log::WARNING);
                };
            }

            /** END OF CRITICAL SECTION **/
            componentsMutex.unlock();
        }
    }
}

void Client::run() {
    while(running) {
        step();
    }
}

void Client::step() {
    deltaTime.start();

    /** Get input from client **/
    std::queue<int> presses;
    std::queue<int> releases;

    //Fetch all events that ocurred...
    while(SDL_PollEvent(&event) != 0) {
        //Dont consider keyrepeat as keypress
        if(event.key.repeat == 0) {
            //And take appropiate action!
            switch(event.type) {
                case SDL_QUIT: {
                    running = false;
                    break;
                }
                //If this event was a keydown...
                case SDL_KEYDOWN: {
                    presses.push(event.key.keysym.sym);
                } break;

                //If user released a key
                case SDL_KEYUP: {
                    releases.push(event.key.keysym.sym);

                } break;
            }
        }
    }

    //If user either pressed or released a key
    //then send keystrokes to server
    if( !(presses.empty() && releases.empty()) ) {
        send<InputData>({presses, releases}, MESSAGE_TYPE::INPUTDATA);
    }

    /** CRITICAL SECTION **/
    componentsMutex.lock();

    /** Update client-side ECS **/
    systemManager.update();

    /** END OF CRITICAL SECTION **/
    componentsMutex.unlock();

    deltaTime.stop();
}

int main(int argc, char** argv) {
    Logger::level = Log::INFO;
    Client client(argc, argv);
    client.connect({127, 0, 0, 1, 47293});
    client.run();
    client.disconnect();
}

//
<commit_msg>fixed client-main-thread locking out client-receive-thread, which were causing heavy stuttering<commit_after>#include "client.hpp"

/** For logging **/
#include "logger.hpp"

/** For event-handling **/
#include <SDL2/SDL.h>

/** For network **/
#include "messagetypes.hpp"
#include "packet.hpp"
#include "systemidentifiers.hpp"

#include "inputdata.hpp"

Client::Client(int argc, char** argv) :
        socket("swordbow-magic"),
        sequence(1),
        systemManager(&componentManager, &deltaTime),
        renderer(argc, argv),
        textureBoundingBox(&componentManager, &renderer),
        textureHashGridSystem(&textureBoundingBox),
        cameraSystem(&renderer),
        renderSystem(&renderer, &textureHashGridSystem, &cameraSystem) {

    Logger::log("Starting client", Log::INFO);

    //Default port
    short port = 47294;

    //Check if port is set
    for(int i = 0; i < argc; i++) {
		if(strcmp(argv[i], "port") == 0) {
			port = std::atoi(argv[i+1]);
		}
	}

    socket.open(port);

    systemManager.add(&textureHashGridSystem);
    systemManager.add(&renderSystem);
    systemManager.add(&cameraSystem);

    //Play some sweet music
	soundEngine.playMusic(Music::NATURE_SOUNDS);
}

Client::~Client() {
    socket.close();
    Logger::log("Destroying client", Log::INFO);
}

void Client::connect(const IpAddress& server) {
    //Start a thread that checks socket for any recieved data
    receiveThreadRunning = true;
    receiveThread = std::thread(&Client::receive, this);

    this->server = server;

    //Connect-request packet
    send<bool>(true, MESSAGE_TYPE::CONNECT);
    std::ostringstream oss;
    oss << "Sent connect request to " << server;
    Logger::log(oss, Log::INFO);
}

void Client::disconnect() {

    //Stop receiving data on socket
    receiveThreadRunning = false;
    receiveThread.join();

    //Disconnect-request packet
    send<bool>(true, MESSAGE_TYPE::DISCONNECT);

    std::ostringstream oss;
    oss << "Disconnected from " << server;
    Logger::log(oss, Log::INFO);

    //Indicate not connected to any server
    server = IpAddress(0, 0, 0, 0, 0);
}

void Client::receive() {
    while(receiveThreadRunning) {

        //Receive data from server...
        IpAddress server;
        unsigned char type;
        int bytesRead;
        socket.receive(server, type, bytesRead);

        //If any data was received, check its type and take appropiate action
        if(bytesRead > 0) {

            /** CRITICAL-SECTION **/
            componentsMutex.lock();

            switch(type) {
                case MESSAGE_TYPE::OUTDATED: {
                    Logger::log("This packet is outdated, to late! Sluggish!", Log::WARNING);
                } break;

                case MESSAGE_TYPE::CONNECT: {
                    Logger::log("Got camera ID from server", Log::INFO);

                    //Got my id. Tell camerasystem to follow that id.
                    auto typedPacket = socket.get<Packet<std::pair<ID, System::Identifier>>>(bytesRead);
                    const auto& pair = typedPacket.getData();
                    systemManager.getSystem(pair.second)->add(pair.first);
                } break;

                //Server will send this to client for a couple of reasons.
                //In any case the client shouldn't be connected to the server.
                case MESSAGE_TYPE::DISCONNECT: {
                    Logger::log("Received DISCONNECT packet", Log::INFO);
                    disconnect();
                } break;

                case MESSAGE_TYPE::INITIAL_COMPONENTS: {
                    Logger::log("Received INITIAL_COMPONENTS packet", Log::INFO);

                    using DataType = std::pair<Components<MoveComponent>, Components<RenderComponent>>;
                    using PacketType = Packet<DataType>;
                    auto typedPacket = socket.get<PacketType>(bytesRead);

                    for(auto& pair : typedPacket.getData().first) {
                        textureHashGridSystem.add(pair.first);
                        renderSystem.add(pair.first);
                    }
                } break;

                case MESSAGE_TYPE::MOVECOMPONENTS: {
                    Logger::log("Received MOVECOMPONENTS packet", Log::INFO);

                    //All movecomponents were received - handle it
                    auto typedPacket = socket.get<Packet<Components<MoveComponent>>>(bytesRead);
                    componentManager.moveComponents.sync(typedPacket.getData());

                    //It is assumed that any receieved movecomponent should
                    //be added to texturehashgridsystem and rendersystem,
                    //because if not, why would the server send them in the first
                    //place?
                    for(auto& pair : typedPacket.getData()) {
                        textureHashGridSystem.add(pair.first);
                        renderSystem.add(pair.first);
                    }

                } break;

                case MESSAGE_TYPE::RENDERCOMPONENTS: {
                    Logger::log("Received RENDERCOMPONENTS packet", Log::INFO);

                    //All rendercomponents were received - handle it
                    auto typedPacket = socket.get<Packet<Components<RenderComponent>>>(bytesRead);
                    componentManager.renderComponents.sync(typedPacket.getData());

                    for(auto& pair : typedPacket.getData()) {
                        textureHashGridSystem.add(pair.first);
                        renderSystem.add(pair.first);
                    }

                } break;

                case MESSAGE_TYPE::MOVECOMPONENTSDIFF: {
                    Logger::log("Received MOVECOMPONENTSDIFF packet", Log::INFO);

                    //Diff movecomponents were received - handle it
                    auto typedPacket = socket.get<Packet<Components<MoveComponent>>>(bytesRead);
                    componentManager.moveComponents.sync(typedPacket.getData());

                    //It makes sence to auto-activate newly received ids of the
                    //movecomponents in rendersystem, since the server only
                    //sends movecomponents on actual difference, the client
                    //should redraw that difference. So former ACTIVATE_ID message
                    //could be implicit with any component-message, which has the
                    //benefit of not mistakingly activating ids before components
                    //are received. Since system.add is a superset of system.activateId
                    //we might aswell assume adding received components to systems
                    //which makes REGISTER_ID_TO_SYSTEM-message obsolete
                    for(auto& pair : typedPacket.getData()) {
                        textureHashGridSystem.add(pair.first);
                        renderSystem.add(pair.first);
                    }

                } break;

                case MESSAGE_TYPE::RENDERCOMPONENTSDIFF: {
                    Logger::log("Received RENDERCOMPONENTSDIFF packet", Log::INFO);

                    //Diff rendercomponents were received - handle it
                    auto typedPacket = socket.get<Packet<Components<RenderComponent>>>(bytesRead);
                    componentManager.renderComponents.sync(typedPacket.getData());

                    for(auto& pair : typedPacket.getData()) {
                        textureHashGridSystem.add(pair.first);
                        renderSystem.add(pair.first);
                    }
                } break;

                case MESSAGE_TYPE::PLAY_SOUND: {
                    Logger::log("Received PLAY_SOUND packet", Log::INFO);

                    auto typedPacket = socket.get<Packet<SoundData>>(bytesRead);
                    soundEngine.playSound(typedPacket.getData());
                } break;

                case MESSAGE_TYPE::REGISTER_ID_TO_SYSTEM: {
                    Logger::log("Received REGISTER_ID_TO_SYSTEM packet", Log::INFO);

                    auto typedPacket = socket.get<Packet<std::pair<ID, System::Identifier>>>(bytesRead);
                    const auto& id = typedPacket.getData().first;
                    const auto& systemIdentifier = typedPacket.getData().second;
                    systemManager.getSystem(systemIdentifier)->add(id);
                } break;

                case MESSAGE_TYPE::REMOVE_ID: {
                    Logger::log("Received REMOVE_ID packet", Log::INFO);

                    auto typedPacket = socket.get<Packet<ID>>(bytesRead);
                    const auto& id = typedPacket.getData();
                    systemManager.getSystem(System::RENDER)->remove(id);
                    systemManager.getSystem(System::HASHGRID_TEXTURE)->remove(id);
                    componentManager.clearComponents(id);
                } break;

                case MESSAGE_TYPE::REMOVE_ID_FROM_SYSTEM: {
                    Logger::log("Received REMOVE_ID_FROM_SYSTEM packet", Log::INFO);

                    auto typedPacket = socket.get<Packet<std::pair<ID, System::Identifier>>>(bytesRead);
                    const auto& id = typedPacket.getData().first;
                    const auto& systemIdentifier = typedPacket.getData().second;
                    systemManager.getSystem(systemIdentifier)->remove(id);
                } break;

                case MESSAGE_TYPE::REMOVE_ID_FROM_SYSTEMS: {
                    Logger::log("Received REMOVE_ID_FROM_SYSTEMS packet", Log::INFO);

                    auto typedPacket = socket.get<Packet<ID>>(bytesRead);
                    const auto& id = typedPacket.getData();
                    systemManager.getSystem(System::RENDER)->remove(id);
                    systemManager.getSystem(System::HASHGRID_TEXTURE)->remove(id);
                } break;

                case MESSAGE_TYPE::ACTIVATE_ID: {
                    Logger::log("Received ACTIVATE_ID packet", Log::INFO);

                    auto typedPacket = socket.get<Packet<std::pair<ID, System::Identifier>>>(bytesRead);
                    const auto& id = typedPacket.getData().first;
                    const auto& systemIdentifier = typedPacket.getData().second;
                    systemManager.getSystem(systemIdentifier)->activateId(id);
                } break;

                default: {
                    const std::string logstr(
                        std::string("Message without proper type received. This is probably a bug.\n") +
                        std::string("Either client-side handling for that message isn't implemented") +
                        std::string(" or server sent a message with a bogus messagetype") +
                        std::string(" or the messagetype was wrongly altered somewhere\n")
                    );
                    Logger::log(logstr, Log::WARNING);
                };
            }

            /** END OF CRITICAL SECTION **/
            componentsMutex.unlock();
        }
    }
}

void Client::run() {
    while(running) {
        step();
    }
}

void Client::step() {
    deltaTime.start();

    /** Get input from client **/
    std::queue<int> presses;
    std::queue<int> releases;

    //Fetch all events that ocurred...
    while(SDL_PollEvent(&event) != 0) {
        //Dont consider keyrepeat as keypress
        if(event.key.repeat == 0) {
            //And take appropiate action!
            switch(event.type) {
                case SDL_QUIT: {
                    running = false;
                    break;
                }
                //If this event was a keydown...
                case SDL_KEYDOWN: {
                    presses.push(event.key.keysym.sym);
                } break;

                //If user released a key
                case SDL_KEYUP: {
                    releases.push(event.key.keysym.sym);

                } break;
            }
        }
    }

    //If user either pressed or released a key
    //then send keystrokes to server
    if( !(presses.empty() && releases.empty()) ) {
        send<InputData>({presses, releases}, MESSAGE_TYPE::INPUTDATA);
    }

    /** CRITICAL SECTION **/
    componentsMutex.lock();

    /** Update client-side ECS **/
    systemManager.update();

    /** END OF CRITICAL SECTION **/
    componentsMutex.unlock();

    //Limit client-speed to 60fps (rather 60 tick per second)
    //Check the elapsed time for the current step, if it is lower than
    //16.6666... then it's faster than 60fps so sleep until 16.666ms has passed
    using ms = std::chrono::milliseconds;
    using fdur = std::chrono::duration<float>;
    const float sleep_float = 1.0f/60 - deltaTime.elapsed();
    const ms sleep = std::chrono::duration_cast<ms>(fdur(sleep_float));
    std::this_thread::sleep_for(sleep);

    deltaTime.stop();
}

int main(int argc, char** argv) {
    Logger::level = Log::INFO;
    Client client(argc, argv);
    client.connect({127, 0, 0, 1, 47293});
    client.run();
    client.disconnect();
}

//
<|endoftext|>


<commit_before>// Copyright 2012 the V8 project authors. 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 Google Inc. 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.

#include "v8.h"

#include "bootstrapper.h"
#include "codegen.h"
#include "compiler.h"
#include "debug.h"
#include "prettyprinter.h"
#include "rewriter.h"
#include "runtime.h"
#include "stub-cache.h"

namespace v8 {
namespace internal {

#define __ ACCESS_MASM(masm_)

#ifdef DEBUG

Comment::Comment(MacroAssembler* masm, const char* msg)
    : masm_(masm), msg_(msg) {
  __ RecordComment(msg);
}

Comment::~Comment() {
  if (msg_[0] == '[') __ RecordComment("]");
}

#endif  // DEBUG

#undef __

void CodeGenerator::MakeCodePrologue(CompilationInfo* info) {
#ifdef DEBUG
  bool print_source = false;
  bool print_ast = false;
  const char* ftype;

  if (Isolate::Current()->bootstrapper()->IsActive()) {
    print_source = FLAG_print_builtin_source;
    print_ast = FLAG_print_builtin_ast;
    ftype = "builtin";
  } else {
    print_source = FLAG_print_source;
    print_ast = FLAG_print_ast;
    ftype = "user-defined";
  }

  if (FLAG_trace_codegen || print_source || print_ast) {
    PrintF("*** Generate code for %s function: ", ftype);
    if (info->IsStub()) {
      const char* name =
          CodeStub::MajorName(info->code_stub()->MajorKey(), true);
      PrintF("%s", name == NULL ? "<unknown>" : name);
    } else {
      info->function()->name()->ShortPrint();
    }
    PrintF(" ***\n");
  }

  if (!info->IsStub() && print_source) {
    PrintF("--- Source from AST ---\n%s\n",
           PrettyPrinter().PrintProgram(info->function()));
  }

  if (!info->IsStub() && print_ast) {
    PrintF("--- AST ---\n%s\n",
           AstPrinter().PrintProgram(info->function()));
  }
#endif  // DEBUG
}

Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
                                             Code::Flags flags,
                                             CompilationInfo* info) {
  Isolate* isolate = info->isolate();

  // Allocate and install the code.
  CodeDesc desc;
  masm->GetCode(&desc);
  Handle<Code> code =
      isolate->factory()->NewCode(desc, flags, masm->CodeObject());

  if (!code.is_null()) {
    isolate->counters()->total_compiled_code_size()->Increment(
        code->instruction_size());
    code->set_prologue_offset(info->prologue_offset());
  }
  return code;
}

void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
#ifdef ENABLE_DISASSEMBLER
  bool print_code = Isolate::Current()->bootstrapper()->IsActive()
      ? FLAG_print_builtin_code
      : (FLAG_print_code || (info->IsOptimizing() && FLAG_print_opt_code));
  if (print_code) {
    // Print the source code if available.
    FunctionLiteral* function = info->function();
    if (code->kind() != Code::COMPILED_STUB) {
      Handle<Script> script = info->script();
      if (!script->IsUndefined() && !script->source()->IsUndefined()) {
        PrintF("--- Raw source ---\n");
        ConsStringIteratorOp op;
        StringCharacterStream stream(String::cast(script->source()),
                                     &op,
                                     function->start_position());
        // fun->end_position() points to the last character in the stream. We
        // need to compensate by adding one to calculate the length.
        int source_len =
            function->end_position() - function->start_position() + 1;
        for (int i = 0; i < source_len; i++) {
          if (stream.HasMore()) PrintF("%c", stream.GetNext());
        }
        PrintF("\n\n");
      }
    }
    if (info->IsOptimizing()) {
      if (FLAG_print_unopt_code) {
        PrintF("--- Unoptimized code ---\n");
        info->closure()->shared()->code()->Disassemble(
            *function->debug_name()->ToCString());
      }
      PrintF("--- Optimized code ---\n");
    } else {
      PrintF("--- Code ---\n");
    }
    if (info->IsStub()) {
      CodeStub::Major major_key = info->code_stub()->MajorKey();
      code->Disassemble(CodeStub::MajorName(major_key, false));
    } else {
      code->Disassemble(*function->debug_name()->ToCString());
    }
  }
#endif  // ENABLE_DISASSEMBLER
}

bool CodeGenerator::ShouldGenerateLog(Expression* type) {
  ASSERT(type != NULL);
  Isolate* isolate = Isolate::Current();
  if (!isolate->logger()->is_logging() && !CpuProfiler::is_profiling(isolate)) {
    return false;
  }
  Handle<String> name = Handle<String>::cast(type->AsLiteral()->handle());
  if (FLAG_log_regexp) {
    if (name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("regexp")))
      return true;
  }
  return false;
}

bool CodeGenerator::RecordPositions(MacroAssembler* masm,
                                    int pos,
                                    bool right_here) {
  if (pos != RelocInfo::kNoPosition) {
    masm->positions_recorder()->RecordStatementPosition(pos);
    masm->positions_recorder()->RecordPosition(pos);
    if (right_here) {
      return masm->positions_recorder()->WriteRecordedPositions();
    }
  }
  return false;
}

void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
  switch (type_) {
    case READ_ELEMENT:
      GenerateReadElement(masm);
      break;
    case NEW_NON_STRICT_FAST:
      GenerateNewNonStrictFast(masm);
      break;
    case NEW_NON_STRICT_SLOW:
      GenerateNewNonStrictSlow(masm);
      break;
    case NEW_STRICT:
      GenerateNewStrict(masm);
      break;
  }
}

int CEntryStub::MinorKey() {
  int result = (save_doubles_ == kSaveFPRegs) ? 1 : 0;
  ASSERT(result_size_ == 1 || result_size_ == 2);
#ifdef _WIN64
  return result | ((result_size_ == 1) ? 0 : 2);
#else
  return result;
#endif
}

} }  // namespace v8::internal
<commit_msg>Print generated code for Crankshafted stubs with --print-code-stubs<commit_after>// Copyright 2012 the V8 project authors. 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 Google Inc. 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.

#include "v8.h"

#include "bootstrapper.h"
#include "codegen.h"
#include "compiler.h"
#include "debug.h"
#include "prettyprinter.h"
#include "rewriter.h"
#include "runtime.h"
#include "stub-cache.h"

namespace v8 {
namespace internal {

#define __ ACCESS_MASM(masm_)

#ifdef DEBUG

Comment::Comment(MacroAssembler* masm, const char* msg)
    : masm_(masm), msg_(msg) {
  __ RecordComment(msg);
}

Comment::~Comment() {
  if (msg_[0] == '[') __ RecordComment("]");
}

#endif  // DEBUG

#undef __

void CodeGenerator::MakeCodePrologue(CompilationInfo* info) {
#ifdef DEBUG
  bool print_source = false;
  bool print_ast = false;
  const char* ftype;

  if (Isolate::Current()->bootstrapper()->IsActive()) {
    print_source = FLAG_print_builtin_source;
    print_ast = FLAG_print_builtin_ast;
    ftype = "builtin";
  } else {
    print_source = FLAG_print_source;
    print_ast = FLAG_print_ast;
    ftype = "user-defined";
  }

  if (FLAG_trace_codegen || print_source || print_ast) {
    PrintF("*** Generate code for %s function: ", ftype);
    if (info->IsStub()) {
      const char* name =
          CodeStub::MajorName(info->code_stub()->MajorKey(), true);
      PrintF("%s", name == NULL ? "<unknown>" : name);
    } else {
      info->function()->name()->ShortPrint();
    }
    PrintF(" ***\n");
  }

  if (!info->IsStub() && print_source) {
    PrintF("--- Source from AST ---\n%s\n",
           PrettyPrinter().PrintProgram(info->function()));
  }

  if (!info->IsStub() && print_ast) {
    PrintF("--- AST ---\n%s\n",
           AstPrinter().PrintProgram(info->function()));
  }
#endif  // DEBUG
}

Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
                                             Code::Flags flags,
                                             CompilationInfo* info) {
  Isolate* isolate = info->isolate();

  // Allocate and install the code.
  CodeDesc desc;
  masm->GetCode(&desc);
  Handle<Code> code =
      isolate->factory()->NewCode(desc, flags, masm->CodeObject());

  if (!code.is_null()) {
    isolate->counters()->total_compiled_code_size()->Increment(
        code->instruction_size());
    code->set_prologue_offset(info->prologue_offset());
  }
  return code;
}

void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
#ifdef ENABLE_DISASSEMBLER
  bool print_code = Isolate::Current()->bootstrapper()->IsActive()
      ? FLAG_print_builtin_code
      : (FLAG_print_code ||
         (info->IsStub() && FLAG_print_code_stubs) ||
         (info->IsOptimizing() && FLAG_print_opt_code));
  if (print_code) {
    // Print the source code if available.
    FunctionLiteral* function = info->function();
    if (code->kind() != Code::COMPILED_STUB) {
      Handle<Script> script = info->script();
      if (!script->IsUndefined() && !script->source()->IsUndefined()) {
        PrintF("--- Raw source ---\n");
        ConsStringIteratorOp op;
        StringCharacterStream stream(String::cast(script->source()),
                                     &op,
                                     function->start_position());
        // fun->end_position() points to the last character in the stream. We
        // need to compensate by adding one to calculate the length.
        int source_len =
            function->end_position() - function->start_position() + 1;
        for (int i = 0; i < source_len; i++) {
          if (stream.HasMore()) PrintF("%c", stream.GetNext());
        }
        PrintF("\n\n");
      }
    }
    if (info->IsOptimizing()) {
      if (FLAG_print_unopt_code) {
        PrintF("--- Unoptimized code ---\n");
        info->closure()->shared()->code()->Disassemble(
            *function->debug_name()->ToCString());
      }
      PrintF("--- Optimized code ---\n");
    } else {
      PrintF("--- Code ---\n");
    }
    if (info->IsStub()) {
      CodeStub::Major major_key = info->code_stub()->MajorKey();
      code->Disassemble(CodeStub::MajorName(major_key, false));
    } else {
      code->Disassemble(*function->debug_name()->ToCString());
    }
  }
#endif  // ENABLE_DISASSEMBLER
}

bool CodeGenerator::ShouldGenerateLog(Expression* type) {
  ASSERT(type != NULL);
  Isolate* isolate = Isolate::Current();
  if (!isolate->logger()->is_logging() && !CpuProfiler::is_profiling(isolate)) {
    return false;
  }
  Handle<String> name = Handle<String>::cast(type->AsLiteral()->handle());
  if (FLAG_log_regexp) {
    if (name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("regexp")))
      return true;
  }
  return false;
}

bool CodeGenerator::RecordPositions(MacroAssembler* masm,
                                    int pos,
                                    bool right_here) {
  if (pos != RelocInfo::kNoPosition) {
    masm->positions_recorder()->RecordStatementPosition(pos);
    masm->positions_recorder()->RecordPosition(pos);
    if (right_here) {
      return masm->positions_recorder()->WriteRecordedPositions();
    }
  }
  return false;
}

void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
  switch (type_) {
    case READ_ELEMENT:
      GenerateReadElement(masm);
      break;
    case NEW_NON_STRICT_FAST:
      GenerateNewNonStrictFast(masm);
      break;
    case NEW_NON_STRICT_SLOW:
      GenerateNewNonStrictSlow(masm);
      break;
    case NEW_STRICT:
      GenerateNewStrict(masm);
      break;
  }
}

int CEntryStub::MinorKey() {
  int result = (save_doubles_ == kSaveFPRegs) ? 1 : 0;
  ASSERT(result_size_ == 1 || result_size_ == 2);
#ifdef _WIN64
  return result | ((result_size_ == 1) ? 0 : 2);
#else
  return result;
#endif
}

} }  // namespace v8::internal
<|endoftext|>


<commit_before>/***************************************************************************
        konsolekalendaradd.cpp  -  description
           -------------------
    begin                : Sun May 25 2003
    copyright            : (C) 2002 by Tuukka Pasanen
    email                : illuusio@mailcity.com
 ***************************************************************************/

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

#include <stdlib.h>
#include <iostream>

#include <qdatetime.h>

#include <kdebug.h>
#include <klocale.h>

#include "calendarlocal.h"
#include "calendar.h"
#include "event.h"

#include "konsolekalendaradd.h"

using namespace KCal;
using namespace std;

KonsoleKalendarAdd::KonsoleKalendarAdd( KonsoleKalendarVariables *variables )
{
  m_variables = variables;

}

KonsoleKalendarAdd::~KonsoleKalendarAdd()
{

}

/**
 * Adds event to Calendar
 */

bool KonsoleKalendarAdd::addEvent()
{
  Event *event = new Event();

  event->setDtStart( m_variables->getStartDate() );
  event->setDtEnd( m_variables->getStartDate() );
  event->setDescription( m_variables->getDescription() );
  event->setSummary( m_variables->getSummary() );

  if( m_variables->getCalendar()->addEvent( event ) == true ) {
    kdDebug() << "Event added!" << endl;
  } else {
    kdDebug() << "Can't add event" << endl;
  } // else

  m_variables->getCalendar()->save( m_variables->getCalendarFile() );

  delete event;

  return true;
}

bool KonsoleKalendarAdd::addImportedCalendar()
{

 CalendarLocal importCalendar;

 if( !importCalendar.load( m_variables->getImportFile() ) ){
   kdDebug() << "Can't open file: " << m_variables->getImportFile() << endl;
   return false;
 } else {
   kdDebug() << "Successfully opened file: " << m_variables->getImportFile() << endl;
 } // else

 Event::List eventList( importCalendar.rawEvents() );
 Event *singleEvent;

 if( eventList.count() ) {

   Event::List::ConstIterator it;
   for( it = eventList.begin(); it != eventList.end(); ++it ) {
     singleEvent = *it;

     kdDebug() << "Add event" << endl;
     m_variables->getCalendar()->addEvent( singleEvent );

   } // for

 } // if

 importCalendar.close();
 m_variables->getCalendar()->save( m_variables->getCalendarFile() );

 return true;
}

<commit_msg>Small bug fixed<commit_after>/***************************************************************************
        konsolekalendaradd.cpp  -  description
           -------------------
    begin                : Sun May 25 2003
    copyright            : (C) 2002 by Tuukka Pasanen
    email                : illuusio@mailcity.com
 ***************************************************************************/

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

#include <stdlib.h>
#include <iostream>

#include <qdatetime.h>

#include <kdebug.h>
#include <klocale.h>

#include "calendarlocal.h"
#include "calendar.h"
#include "event.h"

#include "konsolekalendaradd.h"

using namespace KCal;
using namespace std;

KonsoleKalendarAdd::KonsoleKalendarAdd( KonsoleKalendarVariables *variables )
{
  m_variables = variables;

}

KonsoleKalendarAdd::~KonsoleKalendarAdd()
{

}

/**
 * Adds event to Calendar
 */

bool KonsoleKalendarAdd::addEvent()
{
  Event *event = new Event();

  event->setDtStart( m_variables->getStartDate() );
  event->setDtEnd( m_variables->getEndDate() );
  event->setDescription( m_variables->getDescription() );
  event->setSummary( m_variables->getSummary() );

  if( m_variables->getCalendar()->addEvent( event ) == true ) {
    kdDebug() << "Event added!" << endl;
  } else {
    kdDebug() << "Can't add event" << endl;
  } // else

  m_variables->getCalendar()->save( m_variables->getCalendarFile() );

  delete event;

  return true;
}

bool KonsoleKalendarAdd::addImportedCalendar()
{

 CalendarLocal importCalendar;

 if( !importCalendar.load( m_variables->getImportFile() ) ){
   kdDebug() << "Can't open file: " << m_variables->getImportFile() << endl;
   return false;
 } else {
   kdDebug() << "Successfully opened file: " << m_variables->getImportFile() << endl;
 } // else

 Event::List eventList( importCalendar.rawEvents() );
 Event *singleEvent;

 if( eventList.count() ) {

   Event::List::ConstIterator it;
   for( it = eventList.begin(); it != eventList.end(); ++it ) {
     singleEvent = *it;

     kdDebug() << "Add event" << endl;
     m_variables->getCalendar()->addEvent( singleEvent );

   } // for

 } // if

 importCalendar.close();
 m_variables->getCalendar()->save( m_variables->getCalendarFile() );

 return true;
}

<|endoftext|>