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

// Little program to read lines of sample text, calculate score per 1024 bytes
// per language-script4 combination
// Possible input file /export/hda3/cld/pre2010/b0_samp_prune_20100722.utf8

#include <stdio.h>
#include <string.h>
#include <string>

#include "compact_lang_det_impl.h"
#include "lang_script.h"

using namespace CLD2;

double bytes[NUM_LANGUAGES][4];
double scores[NUM_LANGUAGES][4];

// Return score per 1024 bytes for top language
Language ScoreOneLine(const char* buffer, int buffer_length,
                    int* bytes, double* score_per_1kb) {
  bool is_plain_text = true;
  const CLDHints* cld_hints = NULL;
  bool allow_extended_lang = true;
  int flags = 0;
  Language plus_one = UNKNOWN_LANGUAGE;
  Language language3[3];
  int percent3[3];
  double normalized_score3[3];
  ResultChunkVector* resultchunkvector = NULL;
  int text_bytes;
  bool is_reliable;
  Language summary_lang;

  summary_lang = DetectLanguageSummaryV2(
                        buffer,
                        buffer_length,
                        is_plain_text,
                        cld_hints,
                        allow_extended_lang,
                        flags,
                        plus_one,
                        language3,
                        percent3,
                        normalized_score3,
                        resultchunkvector,
                        &text_bytes,
                        &is_reliable);
  *bytes = text_bytes;
  *score_per_1kb = normalized_score3[0];
  return language3[0];
}

#define LF 0x0a
#define CR 0x0d
const int kMaxBuffer = 5 * 1024;

bool ReadLine(FILE* infile, char* buffer, size_t maxlen) {
  char* p = fgets(buffer, maxlen, infile);
  if (p == NULL) {
    return false;
  }
  int len = strlen(buffer);

  // trim CR LF
  if (buffer[len-1] == LF) {buffer[--len] = '\0';}
  if (buffer[len-1] == CR) {buffer[--len] = '\0';}
  return true;
}

bool IsComment(const char* buffer) {
  int len = strlen(buffer);
  if (len == 0) {return true;}
  if (buffer[0] == '#') {return true;}
  if (buffer[0] == ' ') {return true;}    // Any leading space is comment
  return false;
}

// Skips over xxxxx_ where _ is one or more spaces/tabs
// Returns string::npos if no more fields
int SkipOneField(const string& src, int pos) {
  if (pos == string::npos) {return pos;}

  int lpos = pos;
  lpos = src.find_first_of(" \t", lpos);
  if (lpos == string::npos) {return lpos;}
  lpos = src.find_first_not_of(" \t", lpos);
  if (lpos == string::npos) {return lpos;}
  return lpos;
}

// Return language and script from parsed line or defaults
void GetLangScript(const string& src,
                   Language default_lang, ULScript default_lscript,
                   Language* target_lang, ULScript* target_lscript,
                   string* tld) {
  *target_lang = default_lang;
  *target_lscript = default_lscript;
  *tld = "";
  int pos = 0;
  int pos2 = 0;
  if (src.substr(0,7) == "SAMPLE ") {
    // SAMPLE ll-Ssss
    pos = SkipOneField(src, pos);
  } else if (src.substr(0,5) == "SAMP ") {
    // SAMP ll-Ssss /tld2.tld/
    pos = SkipOneField(src, pos);
    pos2 = SkipOneField(src, pos);
  } else if (src.substr(0,5) == "Samp ") {
    // Samp ll-Ssss /tld2.tld/
    pos = SkipOneField(src, pos);
    pos2 = SkipOneField(src, pos);
  }
  if (pos == 0) {return;}
  if (pos == string::npos) {return;}

  // Pos is at the first letter of language-script combination
  int end = src.find_first_of(" \t", pos);    // find end of lang-script
  if (end == string::npos) {return;}
  *target_lang = GetLanguageFromName(src.substr(pos, end - pos).c_str());
  *target_lscript = GetULScriptFromName(src.substr(pos, end - pos).c_str());

  // Pos2 is 0 or at the first letter of the tld string
  if (pos2 == 0) {return;}
  if (pos2 == string::npos) {return;}
  end = src.find_first_of(" \t", pos2);
  if (end == string::npos) {return;}
  *tld = src.substr(pos2, end - pos2);
}

// Return position of start of text
int GetTextBeginPos(const string& src) {
  int pos = 0;
  if (src.size() < 8) {return pos;}

  if (src.substr(0,7) == "SAMPLE ") {
    // Skip SAMPLE ll-Ssss
    pos = SkipOneField(src, pos);
    pos = SkipOneField(src, pos);
  } else if (src.substr(0,5) == "SAMP ") {
    // Skip SAMP ll-Ssss /tld2.tld/
    pos = SkipOneField(src, pos);
    pos = SkipOneField(src, pos);
    pos = SkipOneField(src, pos);
  } else if (src.substr(0,5) == "Samp ") {
    // Skip Samp ll-Ssss /tld2.tld/
    pos = SkipOneField(src, pos);
    pos = SkipOneField(src, pos);
    pos = SkipOneField(src, pos);
  }
  return pos;
}

// Avoid zdiv
inline double Divisor(double x) {
   return (x > 0.0 ? x : 1.0);
}

void Flush(Language cur_lang, ULScript ulscript,
           double total_score_cur_lang,
           double total_bytes_cur_lang, double total_bad_bytes_cur_lang) {
  if (cur_lang == UNKNOWN_LANGUAGE) {return;}

  bytes[cur_lang][LScript4(ulscript)] += total_bytes_cur_lang;
  scores[cur_lang][LScript4(ulscript)] += total_score_cur_lang;

  double score = total_score_cur_lang * 1024.0 / Divisor(total_bytes_cur_lang);
  double percent_bad = 100.0 * total_bad_bytes_cur_lang /
     Divisor(total_bytes_cur_lang + total_bad_bytes_cur_lang);
  fprintf(stdout, "%s-%s    %7.0f %6.1f, %2.0f%% bad SUMMARY\n\n",
          LanguageCode(cur_lang),
          ULScriptCode(ulscript),
          total_bytes_cur_lang,
          score,
          percent_bad);
}

int BytesPer1KB(int i, int j) {
   int bytes_per_1kb = ((scores[i][j] * 1024.0) / Divisor(bytes[i][j])) + 0.5;
   return bytes_per_1kb;
}

int main(int argc, char *argv[]) {
  Language cur_lang = UNKNOWN_LANGUAGE;
  ULScript cur_ulscript = ULScript_Common;
  double total_score_cur_lang = 0.0;
  double total_bytes_cur_lang = 0.0;
  double total_bad_bytes_cur_lang = 0.0;
  memset(bytes, 0, sizeof(bytes));
  memset(scores, 0, sizeof(bytes));

  char buffer[kMaxBuffer];
  int buffer_length;
  const char* filename = NULL;
  FILE* infile = stdin;
  for (int i = 1; i < argc; ++i) {
     if (argv[i][0] != '-') {
        filename = argv[i];
     }
  }

  if (filename != NULL) {
     infile = fopen(filename, "r");
     if (infile == NULL) {
        fprintf(stderr, "%s did not open\n", filename);
        return 0;
     }
  }

  while (ReadLine(infile, buffer, kMaxBuffer)) {
    if (IsComment(buffer)) {continue;}

    buffer_length = strlen(buffer);
    int bytes;
    double score_per_1kb;
    Language toplang;
    Language target_lang;
    ULScript target_ulscript;

    string src(buffer, buffer_length);
    string tld("");
    int pos = GetTextBeginPos(src);
    GetLangScript(src, UNKNOWN_LANGUAGE, ULScript_Common,
                   &target_lang, &target_ulscript, &tld);
    if ((cur_lang != target_lang) || (cur_ulscript != target_ulscript)) {
      Flush(cur_lang, cur_ulscript, total_score_cur_lang,
            total_bytes_cur_lang, total_bad_bytes_cur_lang);
      cur_lang = target_lang;
      cur_ulscript = target_ulscript;
      total_score_cur_lang = 0.0;
      total_bytes_cur_lang = 0.0;
      total_bad_bytes_cur_lang = 0.0;
    }

    toplang = ScoreOneLine(&src[pos], src.size() - pos, &bytes, &score_per_1kb);

    fprintf(stdout, "%s%c %d %4.1f %s\n",
            LanguageCode(toplang),
            (toplang == target_lang) ? ' ' : '*',
            bytes, score_per_1kb, buffer);
    // Only count when detected lang matches the claimed target lang
    if (toplang == target_lang) {
      total_bytes_cur_lang += bytes;
      total_score_cur_lang += (score_per_1kb * bytes) / 1024.0;
    } else {
      total_bad_bytes_cur_lang += bytes;
    }
  }
  Flush(cur_lang, cur_ulscript, total_score_cur_lang,
        total_bytes_cur_lang, total_bad_bytes_cur_lang);

  for (int i = 0; i < NUM_LANGUAGES; ++i) {
     Language ilang = static_cast<Language>(i);
     fprintf(stdout, "  {%4d, %4d, %4d, %4d},  // %d %s %s\n",
             BytesPer1KB(i, 0), BytesPer1KB(i, 1),
             BytesPer1KB(i, 2), BytesPer1KB(i, 3),
             i, LanguageName(ilang), LanguageCode(ilang));
  }

  if (infile != stdin) {
     fclose(infile);
  }
}
<commit_msg>Add namespace std<commit_after>// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Little program to read lines of sample text, calculate score per 1024 bytes
// per language-script4 combination
// Possible input file /export/hda3/cld/pre2010/b0_samp_prune_20100722.utf8

#include <stdio.h>
#include <string.h>
#include <string>

#include "compact_lang_det_impl.h"
#include "lang_script.h"

using namespace std;
using namespace CLD2;

double bytes[NUM_LANGUAGES][4];
double scores[NUM_LANGUAGES][4];

// Return score per 1024 bytes for top language
Language ScoreOneLine(const char* buffer, int buffer_length,
                    int* bytes, double* score_per_1kb) {
  bool is_plain_text = true;
  const CLDHints* cld_hints = NULL;
  bool allow_extended_lang = true;
  int flags = 0;
  Language plus_one = UNKNOWN_LANGUAGE;
  Language language3[3];
  int percent3[3];
  double normalized_score3[3];
  ResultChunkVector* resultchunkvector = NULL;
  int text_bytes;
  bool is_reliable;
  Language summary_lang;

  summary_lang = DetectLanguageSummaryV2(
                        buffer,
                        buffer_length,
                        is_plain_text,
                        cld_hints,
                        allow_extended_lang,
                        flags,
                        plus_one,
                        language3,
                        percent3,
                        normalized_score3,
                        resultchunkvector,
                        &text_bytes,
                        &is_reliable);
  *bytes = text_bytes;
  *score_per_1kb = normalized_score3[0];
  return language3[0];
}

#define LF 0x0a
#define CR 0x0d
const int kMaxBuffer = 5 * 1024;

bool ReadLine(FILE* infile, char* buffer, size_t maxlen) {
  char* p = fgets(buffer, maxlen, infile);
  if (p == NULL) {
    return false;
  }
  int len = strlen(buffer);

  // trim CR LF
  if (buffer[len-1] == LF) {buffer[--len] = '\0';}
  if (buffer[len-1] == CR) {buffer[--len] = '\0';}
  return true;
}

bool IsComment(const char* buffer) {
  int len = strlen(buffer);
  if (len == 0) {return true;}
  if (buffer[0] == '#') {return true;}
  if (buffer[0] == ' ') {return true;}    // Any leading space is comment
  return false;
}

// Skips over xxxxx_ where _ is one or more spaces/tabs
// Returns string::npos if no more fields
int SkipOneField(const string& src, int pos) {
  if (pos == string::npos) {return pos;}

  int lpos = pos;
  lpos = src.find_first_of(" \t", lpos);
  if (lpos == string::npos) {return lpos;}
  lpos = src.find_first_not_of(" \t", lpos);
  if (lpos == string::npos) {return lpos;}
  return lpos;
}

// Return language and script from parsed line or defaults
void GetLangScript(const string& src,
                   Language default_lang, ULScript default_lscript,
                   Language* target_lang, ULScript* target_lscript,
                   string* tld) {
  *target_lang = default_lang;
  *target_lscript = default_lscript;
  *tld = "";
  int pos = 0;
  int pos2 = 0;
  if (src.substr(0,7) == "SAMPLE ") {
    // SAMPLE ll-Ssss
    pos = SkipOneField(src, pos);
  } else if (src.substr(0,5) == "SAMP ") {
    // SAMP ll-Ssss /tld2.tld/
    pos = SkipOneField(src, pos);
    pos2 = SkipOneField(src, pos);
  } else if (src.substr(0,5) == "Samp ") {
    // Samp ll-Ssss /tld2.tld/
    pos = SkipOneField(src, pos);
    pos2 = SkipOneField(src, pos);
  }
  if (pos == 0) {return;}
  if (pos == string::npos) {return;}

  // Pos is at the first letter of language-script combination
  int end = src.find_first_of(" \t", pos);    // find end of lang-script
  if (end == string::npos) {return;}
  *target_lang = GetLanguageFromName(src.substr(pos, end - pos).c_str());
  *target_lscript = GetULScriptFromName(src.substr(pos, end - pos).c_str());

  // Pos2 is 0 or at the first letter of the tld string
  if (pos2 == 0) {return;}
  if (pos2 == string::npos) {return;}
  end = src.find_first_of(" \t", pos2);
  if (end == string::npos) {return;}
  *tld = src.substr(pos2, end - pos2);
}

// Return position of start of text
int GetTextBeginPos(const string& src) {
  int pos = 0;
  if (src.size() < 8) {return pos;}

  if (src.substr(0,7) == "SAMPLE ") {
    // Skip SAMPLE ll-Ssss
    pos = SkipOneField(src, pos);
    pos = SkipOneField(src, pos);
  } else if (src.substr(0,5) == "SAMP ") {
    // Skip SAMP ll-Ssss /tld2.tld/
    pos = SkipOneField(src, pos);
    pos = SkipOneField(src, pos);
    pos = SkipOneField(src, pos);
  } else if (src.substr(0,5) == "Samp ") {
    // Skip Samp ll-Ssss /tld2.tld/
    pos = SkipOneField(src, pos);
    pos = SkipOneField(src, pos);
    pos = SkipOneField(src, pos);
  }
  return pos;
}

// Avoid zdiv
inline double Divisor(double x) {
   return (x > 0.0 ? x : 1.0);
}

void Flush(Language cur_lang, ULScript ulscript,
           double total_score_cur_lang,
           double total_bytes_cur_lang, double total_bad_bytes_cur_lang) {
  if (cur_lang == UNKNOWN_LANGUAGE) {return;}

  bytes[cur_lang][LScript4(ulscript)] += total_bytes_cur_lang;
  scores[cur_lang][LScript4(ulscript)] += total_score_cur_lang;

  double score = total_score_cur_lang * 1024.0 / Divisor(total_bytes_cur_lang);
  double percent_bad = 100.0 * total_bad_bytes_cur_lang /
     Divisor(total_bytes_cur_lang + total_bad_bytes_cur_lang);
  fprintf(stdout, "%s-%s    %7.0f %6.1f, %2.0f%% bad SUMMARY\n\n",
          LanguageCode(cur_lang),
          ULScriptCode(ulscript),
          total_bytes_cur_lang,
          score,
          percent_bad);
}

int BytesPer1KB(int i, int j) {
   int bytes_per_1kb = ((scores[i][j] * 1024.0) / Divisor(bytes[i][j])) + 0.5;
   return bytes_per_1kb;
}

int main(int argc, char *argv[]) {
  Language cur_lang = UNKNOWN_LANGUAGE;
  ULScript cur_ulscript = ULScript_Common;
  double total_score_cur_lang = 0.0;
  double total_bytes_cur_lang = 0.0;
  double total_bad_bytes_cur_lang = 0.0;
  memset(bytes, 0, sizeof(bytes));
  memset(scores, 0, sizeof(bytes));

  char buffer[kMaxBuffer];
  int buffer_length;
  const char* filename = NULL;
  FILE* infile = stdin;
  for (int i = 1; i < argc; ++i) {
     if (argv[i][0] != '-') {
        filename = argv[i];
     }
  }

  if (filename != NULL) {
     infile = fopen(filename, "r");
     if (infile == NULL) {
        fprintf(stderr, "%s did not open\n", filename);
        return 0;
     }
  }

  while (ReadLine(infile, buffer, kMaxBuffer)) {
    if (IsComment(buffer)) {continue;}

    buffer_length = strlen(buffer);
    int bytes;
    double score_per_1kb;
    Language toplang;
    Language target_lang;
    ULScript target_ulscript;

    string src(buffer, buffer_length);
    string tld("");
    int pos = GetTextBeginPos(src);
    GetLangScript(src, UNKNOWN_LANGUAGE, ULScript_Common,
                   &target_lang, &target_ulscript, &tld);
    if ((cur_lang != target_lang) || (cur_ulscript != target_ulscript)) {
      Flush(cur_lang, cur_ulscript, total_score_cur_lang,
            total_bytes_cur_lang, total_bad_bytes_cur_lang);
      cur_lang = target_lang;
      cur_ulscript = target_ulscript;
      total_score_cur_lang = 0.0;
      total_bytes_cur_lang = 0.0;
      total_bad_bytes_cur_lang = 0.0;
    }

    toplang = ScoreOneLine(&src[pos], src.size() - pos, &bytes, &score_per_1kb);

    fprintf(stdout, "%s%c %d %4.1f %s\n",
            LanguageCode(toplang),
            (toplang == target_lang) ? ' ' : '*',
            bytes, score_per_1kb, buffer);
    // Only count when detected lang matches the claimed target lang
    if (toplang == target_lang) {
      total_bytes_cur_lang += bytes;
      total_score_cur_lang += (score_per_1kb * bytes) / 1024.0;
    } else {
      total_bad_bytes_cur_lang += bytes;
    }
  }
  Flush(cur_lang, cur_ulscript, total_score_cur_lang,
        total_bytes_cur_lang, total_bad_bytes_cur_lang);

  for (int i = 0; i < NUM_LANGUAGES; ++i) {
     Language ilang = static_cast<Language>(i);
     fprintf(stdout, "  {%4d, %4d, %4d, %4d},  // %d %s %s\n",
             BytesPer1KB(i, 0), BytesPer1KB(i, 1),
             BytesPer1KB(i, 2), BytesPer1KB(i, 3),
             i, LanguageName(ilang), LanguageCode(ilang));
  }

  if (infile != stdin) {
     fclose(infile);
  }
}
<|endoftext|>


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

//
// Author: dsites@google.com (Dick Sites)
//
// Unit test compact language detector, CLD2
//  Compile with -Davoid_utf8_string_constants if your compiler cannot
//  handle UTF-8 string constants
//

#include <stdio.h>
#include <string.h>

#include "../public/compact_lang_det.h"
#include "../public/encodings.h"
#include "unittest_data.h"

namespace CLD2 {

// Test strings.
const char* kTeststr_en =
  "confiscation of goods is assigned as the penalty part most of the courts "
  "consist of members and when it is necessary to bring public cases before a "
  "jury of members two courts combine for the purpose the most important cases "
  "of all are brought jurors or";

typedef struct {
  Language lang;
  const char* text;
} TestPair;

static const TestPair kTestPair[] = {
// A simple case to begin
  {ENGLISH, kTeststr_en},

// 20 languages recognized via Unicode script
  {ARMENIAN, kTeststr_hy_Armn},
  {CHEROKEE, kTeststr_chr_Cher},
  {DHIVEHI, kTeststr_dv_Thaa},
  {GEORGIAN, kTeststr_ka_Geor},
  {GREEK, kTeststr_el_Grek},
  {GUJARATI, kTeststr_gu_Gujr},
  {INUKTITUT, kTeststr_iu_Cans},
  {KANNADA, kTeststr_kn_Knda},
  {KHMER, kTeststr_km_Khmr},
  {LAOTHIAN, kTeststr_lo_Laoo},
  {LIMBU, kTeststr_lif_Limb},
  {MALAYALAM, kTeststr_ml_Mlym},
  {ORIYA, kTeststr_or_Orya},
  {PUNJABI, kTeststr_pa_Guru},
  {SINHALESE, kTeststr_si_Sinh},
  {SYRIAC, kTeststr_syr_Syrc},
  {TAGALOG, kTeststr_tl_Tglg},      // Also in quadgram list below
  {TAMIL, kTeststr_ta_Taml},
  {TELUGU, kTeststr_te_Telu},
  {THAI, kTeststr_th_Thai},

// 4 languages regognized via single letters
  {CHINESE, kTeststr_zh_Hans},
  {CHINESE_T, kTeststr_zh_Hant},
  {JAPANESE, kTeststr_ja_Hani},
  {KOREAN, kTeststr_ko_Hani},

// 60 languages recognized via combinations of four letters
  {AFRIKAANS, kTeststr_af_Latn},
  {ALBANIAN, kTeststr_sq_Latn},
  {ARABIC, kTeststr_ar_Arab},
  {AZERBAIJANI, kTeststr_az_Latn},
  {BASQUE, kTeststr_eu_Latn},
  {BELARUSIAN, kTeststr_be_Cyrl},
  {BENGALI, kTeststr_bn_Beng},      // No Assamese in subset
  {BIHARI, kTeststr_bh_Deva},
  {BULGARIAN, kTeststr_bg_Cyrl},
  {CATALAN, kTeststr_ca_Latn},
  {CEBUANO, kTeststr_ceb_Latn},
  {CROATIAN, kTeststr_hr_Latn},
  {CZECH, kTeststr_cs_Latn},
  {DANISH, kTeststr_da_Latn},
  {DUTCH, kTeststr_nl_Latn},
  {ENGLISH, kTeststr_en_Latn},
  {ESTONIAN, kTeststr_et_Latn},
  {FINNISH, kTeststr_fi_Latn},
  {FRENCH, kTeststr_fr_Latn},
  {GALICIAN, kTeststr_gl_Latn},
  {GANDA, kTeststr_lg_Latn},
  {GERMAN, kTeststr_de_Latn},
  {HAITIAN_CREOLE, kTeststr_ht_Latn},
  {HEBREW, kTeststr_iw_Hebr},
  {HINDI, kTeststr_hi_Deva},
  {HMONG, kTeststr_blu_Latn},
  {HUNGARIAN, kTeststr_hu_Latn},
  {ICELANDIC, kTeststr_is_Latn},
  {INDONESIAN, kTeststr_id_Latn},
  {IRISH, kTeststr_ga_Latn},
  {ITALIAN, kTeststr_it_Latn},
  {JAVANESE, kTeststr_jw_Latn},
  {KINYARWANDA, kTeststr_rw_Latn},
  {LATVIAN, kTeststr_lv_Latn},
  {LITHUANIAN, kTeststr_lt_Latn},
  {MACEDONIAN, kTeststr_mk_Cyrl},
  {MALAY, kTeststr_ms_Latn},
  {MALTESE, kTeststr_mt_Latn},
  {MARATHI, kTeststr_mr_Deva},
  {NEPALI, kTeststr_ne_Deva},
  {NORWEGIAN, kTeststr_no_Latn},
  {PERSIAN, kTeststr_fa_Arab},
  {POLISH, kTeststr_pl_Latn},
  {PORTUGUESE, kTeststr_pt_Latn},
  {ROMANIAN, kTeststr_ro_Latn},
  {ROMANIAN, kTeststr_ro_Cyrl},
  {RUSSIAN, kTeststr_ru_Cyrl},
  {SCOTS_GAELIC,  kTeststr_gd_Latn},
  {SERBIAN, kTeststr_sr_Cyrl},
  {SERBIAN, kTeststr_sr_Latn},
  {SLOVAK, kTeststr_sk_Latn},
  {SLOVENIAN, kTeststr_sl_Latn},
  {SPANISH,  kTeststr_es_Latn},
  {SWAHILI, kTeststr_sw_Latn},
  {SWEDISH, kTeststr_sv_Latn},
  {TAGALOG, kTeststr_tl_Latn},
  {TURKISH, kTeststr_tr_Latn},
  {UKRAINIAN, kTeststr_uk_Cyrl},
  {URDU, kTeststr_ur_Arab},
  {VIETNAMESE, kTeststr_vi_Latn},
  {WELSH, kTeststr_cy_Latn},
  {YIDDISH, kTeststr_yi_Hebr},

// 2 statistically-close languages
  {INDONESIAN, kTeststr_id_close},
  {MALAY, kTeststr_ms_close},

// Simple intermixed French/English text
  {FRENCH, kTeststr_fr_en_Latn},

// Cross-check the main quadgram table build date
// Change the expected language each time it is rebuilt
  {WELSH, kTeststr_version},

  {UNKNOWN_LANGUAGE, NULL},     // Must be last
};

bool OneTest(int flags, bool get_vector,
             Language lang_expected, const char* buffer, int buffer_length) {
  bool is_plain_text = true;
  const char* tldhint = "";
  const Encoding enchint = UNKNOWN_ENCODING;
  const Language langhint = UNKNOWN_LANGUAGE;
  const CLDHints cldhints = {NULL, tldhint, enchint, langhint};
  Language language3[3];
  int percent3[3];
  double normalized_score3[3];
  ResultChunkVector resultchunkvector;
  int text_bytes;
  bool is_reliable;

  Language lang_detected = ExtDetectLanguageSummary(
                          buffer,
                          buffer_length,
                          is_plain_text,
                          &cldhints,
                          flags,
                          language3,
                          percent3,
                          normalized_score3,
                          get_vector ? &resultchunkvector : NULL,
                          &text_bytes,
                          &is_reliable);
// expose DumpExtLang DumpLanguages

  bool ok = (lang_detected == lang_expected);

  if (!ok) {
    if ((flags & kCLDFlagHtml) != 0) {
      fprintf(stderr, "*** Wrong result. expected %s, detected %s
\n",
              LanguageName(lang_expected), LanguageName(lang_detected));
    }
    fprintf(stdout, "*** Wrong result. expected %s, detected %s\n",
            LanguageName(lang_expected), LanguageName(lang_detected));
    fprintf(stdout, "%s\n\n", buffer);
  }

  if (get_vector) {
    DumpResultChunkVector(stderr, buffer, &resultchunkvector);
  }

#if 0
  DumpExtLang(flags, summary_lang, language3, percent3, normalized_score3,
              text_bytes, is_reliable, n);

  if ((flags & kCLDFlagHtml) != 0) {
    DumpLanguages(summary_lang,
                  language3, percent3, text_bytes, is_reliable, n);
  }

  fprintf(stdout, "  SummaryLanguage %s%s at %u of %d, %s\n",
         LanguageName(summary_lang),
         is_reliable ? "" : "(un-reliable)",
         bytes_consumed,
         n,
         argv[1]);
#endif

  return ok;
}

void InitHtmlOut(int flags) {
#if 1
  if ((flags & kCLDFlagHtml) != 0) {
    // Begin HTML file
    fprintf(stderr, "<meta charset=\"UTF-8\">\n");
    // Encourage browsers to print background colors
    fprintf(stderr, "\n");
    fprintf(stderr, "\n");
    fprintf(stderr, "file = %s
\n", "cld2_unittest");
  }
#endif
}

void FinishHtmlOut(int flags) {
#if 1
  if ((flags & kCLDFlagHtml) != 0) {
    fprintf(stderr, "\n\n");
  }
#endif
}

int RunTests (int flags, bool get_vector) {
  fprintf(stdout, "CLD2 version: %s\n", CLD2::DetectLanguageVersion());
  InitHtmlOut(flags);
  bool any_fail = false;
  int i = 0;
  while (kTestPair[i].text != NULL) {
    Language lang_expected = kTestPair[i].lang;
    const char* buffer = kTestPair[i].text;
    int buffer_length = strlen(buffer);
    bool ok = OneTest(flags, get_vector, lang_expected, buffer, buffer_length);
    any_fail |= (!ok);
    ++i;
  }
  if (any_fail) {
    fprintf(stderr, "FAIL\n");
    fprintf(stdout, "FAIL\n");
  } else {
    fprintf(stderr, "PASS\n");
    fprintf(stdout, "PASS\n");
  }

  FinishHtmlOut(flags);
  return 0;
}

}       // End namespace CLD2

int main(int argc, char** argv) {
  // Get command-line flags
  int flags = 0;
  bool get_vector = false;
  for (int i = 1; i < argc; ++i) {
    if (strcmp(argv[i], "--html") == 0) {flags |= CLD2::kCLDFlagHtml;}
    if (strcmp(argv[i], "--cr") == 0) {flags |= CLD2::kCLDFlagCr;}
    if (strcmp(argv[i], "--verbose") == 0) {flags |= CLD2::kCLDFlagVerbose;}
    if (strcmp(argv[i], "--quiet") == 0) {flags |= CLD2::kCLDFlagQuiet;}
    if (strcmp(argv[i], "--echo") == 0) {flags |= CLD2::kCLDFlagEcho;}
    if (strcmp(argv[i], "--vector") == 0) {get_vector = true;}
  }

  return CLD2::RunTests(flags, get_vector);
}

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

//
// Author: dsites@google.com (Dick Sites)
//
// Unit test compact language detector, CLD2
//  Compile with -Davoid_utf8_string_constants if your compiler cannot
//  handle UTF-8 string constants
//

#include <stdio.h>
#include <string.h>

#include "../public/compact_lang_det.h"
#include "../public/encodings.h"
#include "unittest_data.h"

namespace CLD2 {

// Test strings.
const char* kTeststr_en =
  "confiscation of goods is assigned as the penalty part most of the courts "
  "consist of members and when it is necessary to bring public cases before a "
  "jury of members two courts combine for the purpose the most important cases "
  "of all are brought jurors or";

typedef struct {
  Language lang;
  const char* text;
} TestPair;

static const TestPair kTestPair[] = {
// A simple case to begin
  {ENGLISH, kTeststr_en},

// 20 languages recognized via Unicode script
  {ARMENIAN, kTeststr_hy_Armn},
  {CHEROKEE, kTeststr_chr_Cher},
  {DHIVEHI, kTeststr_dv_Thaa},
  {GEORGIAN, kTeststr_ka_Geor},
  {GREEK, kTeststr_el_Grek},
  {GUJARATI, kTeststr_gu_Gujr},
  {INUKTITUT, kTeststr_iu_Cans},
  {KANNADA, kTeststr_kn_Knda},
  {KHMER, kTeststr_km_Khmr},
  {LAOTHIAN, kTeststr_lo_Laoo},
  {LIMBU, kTeststr_lif_Limb},
  {MALAYALAM, kTeststr_ml_Mlym},
  {ORIYA, kTeststr_or_Orya},
  {PUNJABI, kTeststr_pa_Guru},
  {SINHALESE, kTeststr_si_Sinh},
  {SYRIAC, kTeststr_syr_Syrc},
  {TAGALOG, kTeststr_tl_Tglg},      // Also in quadgram list below
  {TAMIL, kTeststr_ta_Taml},
  {TELUGU, kTeststr_te_Telu},
  {THAI, kTeststr_th_Thai},

// 4 languages regognized via single letters
  {CHINESE, kTeststr_zh_Hans},
  {CHINESE_T, kTeststr_zh_Hant},
  {JAPANESE, kTeststr_ja_Hani},
  {KOREAN, kTeststr_ko_Hani},

// 60 languages recognized via combinations of four letters
  {AFRIKAANS, kTeststr_af_Latn},
  {ALBANIAN, kTeststr_sq_Latn},
  {ARABIC, kTeststr_ar_Arab},
  {AZERBAIJANI, kTeststr_az_Latn},
  {BASQUE, kTeststr_eu_Latn},
  {BELARUSIAN, kTeststr_be_Cyrl},
  {BENGALI, kTeststr_bn_Beng},      // No Assamese in subset
  {BIHARI, kTeststr_bh_Deva},
  {BULGARIAN, kTeststr_bg_Cyrl},
  {CATALAN, kTeststr_ca_Latn},
  {CEBUANO, kTeststr_ceb_Latn},
  {CROATIAN, kTeststr_hr_Latn},
  {CZECH, kTeststr_cs_Latn},
  {DANISH, kTeststr_da_Latn},
  {DUTCH, kTeststr_nl_Latn},
  {ENGLISH, kTeststr_en_Latn},
  {ESTONIAN, kTeststr_et_Latn},
  {FINNISH, kTeststr_fi_Latn},
  {FRENCH, kTeststr_fr_Latn},
  {GALICIAN, kTeststr_gl_Latn},
  {GANDA, kTeststr_lg_Latn},
  {GERMAN, kTeststr_de_Latn},
  {HAITIAN_CREOLE, kTeststr_ht_Latn},
  {HEBREW, kTeststr_iw_Hebr},
  {HINDI, kTeststr_hi_Deva},
  {HMONG, kTeststr_blu_Latn},
  {HUNGARIAN, kTeststr_hu_Latn},
  {ICELANDIC, kTeststr_is_Latn},
  {INDONESIAN, kTeststr_id_Latn},
  {IRISH, kTeststr_ga_Latn},
  {ITALIAN, kTeststr_it_Latn},
  {JAVANESE, kTeststr_jw_Latn},
  {KINYARWANDA, kTeststr_rw_Latn},
  {LATVIAN, kTeststr_lv_Latn},
  {LITHUANIAN, kTeststr_lt_Latn},
  {MACEDONIAN, kTeststr_mk_Cyrl},
  {MALAY, kTeststr_ms_Latn},
  {MALTESE, kTeststr_mt_Latn},
  {MARATHI, kTeststr_mr_Deva},
  {NEPALI, kTeststr_ne_Deva},
  {NORWEGIAN, kTeststr_no_Latn},
  {PERSIAN, kTeststr_fa_Arab},
  {POLISH, kTeststr_pl_Latn},
  {PORTUGUESE, kTeststr_pt_Latn},
  {ROMANIAN, kTeststr_ro_Latn},
  {ROMANIAN, kTeststr_ro_Cyrl},
  {RUSSIAN, kTeststr_ru_Cyrl},
  {SCOTS_GAELIC,  kTeststr_gd_Latn},
  {SERBIAN, kTeststr_sr_Cyrl},
  {SERBIAN, kTeststr_sr_Latn},
  {SLOVAK, kTeststr_sk_Latn},
  {SLOVENIAN, kTeststr_sl_Latn},
  {SPANISH,  kTeststr_es_Latn},
  {SWAHILI, kTeststr_sw_Latn},
  {SWEDISH, kTeststr_sv_Latn},
  {TAGALOG, kTeststr_tl_Latn},
  {TURKISH, kTeststr_tr_Latn},
  {UKRAINIAN, kTeststr_uk_Cyrl},
  {URDU, kTeststr_ur_Arab},
  {VIETNAMESE, kTeststr_vi_Latn},
  {WELSH, kTeststr_cy_Latn},
  {YIDDISH, kTeststr_yi_Hebr},

  // Added 2013.08.31 so-Latn ig-Latn ha-Latn yo-Latn zu-Latn
  {SOMALI,  kTeststr_so_Latn},
  {IGBO,  kTeststr_ig_Latn},
  {HAUSA,  kTeststr_ha_Latn},
  {YORUBA,  kTeststr_yo_Latn},
  {ZULU,  kTeststr_zu_Latn},
  // Added 2014.01.22 bs-Latn
  {BOSNIAN,  kTeststr_bs_Latn},

// 2 statistically-close languages
  {INDONESIAN, kTeststr_id_close},
  {MALAY, kTeststr_ms_close},

// Simple intermixed French/English text
  {FRENCH, kTeststr_fr_en_Latn},

// Cross-check the main quadgram table build date
// Change the expected language each time it is rebuilt
  //{WELSH, kTeststr_version},   // 2013.07.15
  {AZERBAIJANI, kTeststr_version},   // 2014.01.31

  {UNKNOWN_LANGUAGE, NULL},     // Must be last
};

bool OneTest(int flags, bool get_vector,
             Language lang_expected, const char* buffer, int buffer_length) {
  bool is_plain_text = true;
  const char* tldhint = "";
  const Encoding enchint = UNKNOWN_ENCODING;
  const Language langhint = UNKNOWN_LANGUAGE;
  const CLDHints cldhints = {NULL, tldhint, enchint, langhint};
  Language language3[3];
  int percent3[3];
  double normalized_score3[3];
  ResultChunkVector resultchunkvector;
  int text_bytes;
  bool is_reliable;

  Language lang_detected = ExtDetectLanguageSummary(
                          buffer,
                          buffer_length,
                          is_plain_text,
                          &cldhints,
                          flags,
                          language3,
                          percent3,
                          normalized_score3,
                          get_vector ? &resultchunkvector : NULL,
                          &text_bytes,
                          &is_reliable);
// expose DumpExtLang DumpLanguages

  bool ok = (lang_detected == lang_expected);

  if (!ok) {
    if ((flags & kCLDFlagHtml) != 0) {
      fprintf(stderr, "*** Wrong result. expected %s, detected %s
\n",
              LanguageName(lang_expected), LanguageName(lang_detected));
    }
    fprintf(stdout, "*** Wrong result. expected %s, detected %s\n",
            LanguageName(lang_expected), LanguageName(lang_detected));
    fprintf(stdout, "%s\n\n", buffer);
  }

  if (get_vector) {
    DumpResultChunkVector(stderr, buffer, &resultchunkvector);
  }

#if 0
  DumpExtLang(flags, summary_lang, language3, percent3, normalized_score3,
              text_bytes, is_reliable, n);

  if ((flags & kCLDFlagHtml) != 0) {
    DumpLanguages(summary_lang,
                  language3, percent3, text_bytes, is_reliable, n);
  }

  fprintf(stdout, "  SummaryLanguage %s%s at %u of %d, %s\n",
         LanguageName(summary_lang),
         is_reliable ? "" : "(un-reliable)",
         bytes_consumed,
         n,
         argv[1]);
#endif

  return ok;
}

void InitHtmlOut(int flags) {
#if 1
  if ((flags & kCLDFlagHtml) != 0) {
    // Begin HTML file
    fprintf(stderr, "<meta charset=\"UTF-8\">\n");
    // Encourage browsers to print background colors
    fprintf(stderr, "\n");
    fprintf(stderr, "\n");
    fprintf(stderr, "file = %s
\n", "cld2_unittest");
  }
#endif
}

void FinishHtmlOut(int flags) {
#if 1
  if ((flags & kCLDFlagHtml) != 0) {
    fprintf(stderr, "\n\n");
  }
#endif
}

int RunTests (int flags, bool get_vector) {
  fprintf(stdout, "CLD2 version: %s\n", CLD2::DetectLanguageVersion());
  InitHtmlOut(flags);
  bool any_fail = false;
  int i = 0;
  while (kTestPair[i].text != NULL) {
    Language lang_expected = kTestPair[i].lang;
    const char* buffer = kTestPair[i].text;
    int buffer_length = strlen(buffer);
    bool ok = OneTest(flags, get_vector, lang_expected, buffer, buffer_length);
    any_fail |= (!ok);
    ++i;
  }
  if (any_fail) {
    fprintf(stderr, "FAIL\n");
    fprintf(stdout, "FAIL\n");
  } else {
    fprintf(stderr, "PASS\n");
    fprintf(stdout, "PASS\n");
  }

  FinishHtmlOut(flags);
  return 0;
}

}       // End namespace CLD2

int main(int argc, char** argv) {
  // Get command-line flags
  int flags = 0;
  bool get_vector = false;
  for (int i = 1; i < argc; ++i) {
    if (strcmp(argv[i], "--html") == 0) {flags |= CLD2::kCLDFlagHtml;}
    if (strcmp(argv[i], "--cr") == 0) {flags |= CLD2::kCLDFlagCr;}
    if (strcmp(argv[i], "--verbose") == 0) {flags |= CLD2::kCLDFlagVerbose;}
    if (strcmp(argv[i], "--quiet") == 0) {flags |= CLD2::kCLDFlagQuiet;}
    if (strcmp(argv[i], "--echo") == 0) {flags |= CLD2::kCLDFlagEcho;}
    if (strcmp(argv[i], "--vector") == 0) {get_vector = true;}
  }

  return CLD2::RunTests(flags, get_vector);
}

<|endoftext|>


<commit_before>#include <iostream>
#include <SFML/Graphics.hpp>
#include <ctime>
#include <vector>

class Game
{
public:
    class Square
    {
    public:
        Square(bool isOccupied=false, sf::Color color=sf::Color(0, 128, 200))
          : IsOccupied(isOccupied)
          , Color(color)
        {}

        void Draw(sf::RenderWindow& window, int x, int y)
        {
            if (IsOccupied) {
                int fieldHeight = squareSize * FIELD_HEIGHT;
                int fieldWidth = squareSize * FIELD_WIDTH;
                sf::RectangleShape shape(sf::Vector2f(squareSize - 2 * outlineThickness, squareSize - 2 * outlineThickness));
                shape.setPosition(fieldPositionX + x * squareSize, fieldPositionY + fieldHeight - (y + 1) * squareSize);
                shape.setFillColor(Color);
                shape.setOutlineThickness(outlineThickness);
                window.draw(shape);
            }
        }

        bool IsOccupied;
        sf::Color Color;
    };

    class Figure
    {
    public:
        Figure()
          : CurrentStateIndex(0)
        {
            int states[2][4][4] = {
                {{0, 0, 1, 0},
                {0, 1, 1, 0},
                {0, 1, 0, 0},
                {0, 0, 0, 0}},

                {{0, 1, 1, 0},
                {0, 0, 1, 1},
                {0, 0, 0, 0},
                {0, 0, 0, 0}}
            };

            // TODO: refactor out of this class
            // TODO: remove constants
            for (int s = 0; s < 2; ++s) {
                States.push_back(std::vector< std::vector<Square> >(4, std::vector<Square>(4)));
                for (int i = 0; i < 4; ++i)
                    for(int j = 0; j < 4; ++j)
                        States[s][i][j] = states[s][i][j];
            }
        }

        void Rotate()
        {
            CurrentStateIndex = (CurrentStateIndex + 1) % States.size();
        }

        Square GetSquare(int i, int j)
        {
            return States[CurrentStateIndex][i][j];
        }

        std::vector< std::vector<Square> > GetCurrentState()
        {
            return States[CurrentStateIndex];
        }
    private:
        std::vector< std::vector< std::vector<Square> > > States;
        int CurrentStateIndex;
    };

public:
    Game()
      : field(FIELD_WIDTH, std::vector<Square>(FIELD_HEIGHT, Square()))
      , figX(0)
      , figY(FIELD_HEIGHT - 4)
    {
        // TODO ugly, handle it i a better way
        field[0][0] = true;
        field[0][1] = true;
        field[1][0] = true;
        field[1][1] = true;

        field[5][5] = true;
        field[5][5] = true;
        field[5][6] = true;
        field[5][6] = true;
    }

    void DrawField(sf::RenderWindow& window)
    {
        int fieldHeight = squareSize * FIELD_HEIGHT;
        int fieldWidth = squareSize * FIELD_WIDTH;
        DrawMatrix(window, field);
        sf::RectangleShape border(sf::Vector2f(fieldWidth, fieldHeight));
        border.setPosition(fieldPositionX, fieldPositionY);
        border.setOutlineThickness(outlineThickness);
        border.setFillColor(sf::Color::Transparent);
        window.draw(border);
    }

    void DrawMatrix(sf::RenderWindow& window, std::vector< std::vector<Square> > matrix, int offsetX = 0, int offsetY = 0)
    {
        int matrixHeight = squareSize * field.size();
        int matrixWidth = squareSize * field[0].size();
        for (int i = 0; i < matrix.size(); ++i) {
            for (int j = 0; j < matrix[i].size(); ++j) {
                matrix[i][j].Draw(window, i + offsetX, j + offsetY);
            }
        }
    }

    void Draw(sf::RenderWindow& window)
    {
        DrawField(window);
        DrawMatrix(window, fig.GetCurrentState(), figX, figY);
    }

    void MoveFigureRight()
    {
        if (IsCorrectFigurePosition(figX + 1, figY))
            figX++;
    }

    void MoveFigureLeft()
    {
        if (IsCorrectFigurePosition(figX - 1, figY))
            figX--;
    }

    void MoveFigureDown()
    {
        if (IsCorrectFigurePosition(figX, figY - 1))
            figY--;
    }

    void RotateFigure()
    {
        /* TODO: collision checking */
        fig.Rotate();
    }

    bool IsCorrectFigurePosition(int x, int y)
    {
        for (int i = 0; i < FIG_SIZE; ++i) {
            for (int j = 0; j < FIG_SIZE; ++j) {
                if (fig.GetSquare(i, j).IsOccupied && ((x + i) >= FIELD_WIDTH || (x + i) < 0 || (y+j) >= FIELD_HEIGHT || (y + j) < 0 || field[x + i][y + j].IsOccupied)) {
                    return false;
                }
            }
        }

        return true;
    }

private:
    static const int FIELD_WIDTH = 10;
    static const int FIELD_HEIGHT = 20;
    static const int FIG_SIZE = 4;
    std::vector< std::vector<Square> > field;
    Figure fig;
    int figX;
    int figY;
    enum {
        fieldPositionX = 50,
        fieldPositionY = 100,
    };
    enum {
        squareSize = 20,
        outlineThickness = 2,
        matrixPositionX = 50,
        matrixPositionY = 100,
    };
};

void init()
{
}

int main()
{
    Game game;

    const int windowWidth = 800;
    const int windowHeight = 600;

    sf::ContextSettings settings;
    settings.antialiasingLevel = 8;

    sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight), "My window", sf::Style::Default,  settings);

    while (window.isOpen())
    {
        window.clear();
        // check all the window's events that were triggered since the last iteration of the loop
        sf::Event event;
        while (window.pollEvent(event))
        {
            // "close requested" event: we close the window
            switch (event.type) {
                case sf::Event::Closed:
                    window.close();
                    break;
                case sf::Event::KeyPressed:
                    switch (event.key.code) {
                        case sf::Keyboard::Left:
                            game.MoveFigureLeft();
                            break;
                        case sf::Keyboard::Right:
                            game.MoveFigureRight();
                            break;
                        case sf::Keyboard::Down:
                            game.MoveFigureDown();
                            break;
                        case sf::Keyboard::Space:
                            game.RotateFigure();
                            break;
                        default:
                            break;
                    };
                default:
                    break;
            };
        }
        game.Draw(window);
        window.display();
    }
}
<commit_msg>simple clock handling, figure moves down every 1s<commit_after>#include <iostream>
#include <SFML/Graphics.hpp>
#include <ctime>
#include <vector>

class Game
{
public:
    class Square
    {
    public:
        Square(bool isOccupied=false, sf::Color color=sf::Color(0, 128, 200))
          : IsOccupied(isOccupied)
          , Color(color)
        {}

        void Draw(sf::RenderWindow& window, int x, int y)
        {
            if (IsOccupied) {
                int fieldHeight = squareSize * FIELD_HEIGHT;
                int fieldWidth = squareSize * FIELD_WIDTH;
                sf::RectangleShape shape(sf::Vector2f(squareSize - 2 * outlineThickness, squareSize - 2 * outlineThickness));
                shape.setPosition(fieldPositionX + x * squareSize, fieldPositionY + fieldHeight - (y + 1) * squareSize);
                shape.setFillColor(Color);
                shape.setOutlineThickness(outlineThickness);
                window.draw(shape);
            }
        }

        bool IsOccupied;
        sf::Color Color;
    };

    class Figure
    {
    public:
        Figure()
          : CurrentStateIndex(0)
        {
            int states[2][4][4] = {
                {{0, 0, 1, 0},
                {0, 1, 1, 0},
                {0, 1, 0, 0},
                {0, 0, 0, 0}},

                {{0, 1, 1, 0},
                {0, 0, 1, 1},
                {0, 0, 0, 0},
                {0, 0, 0, 0}}
            };

            // TODO: refactor out of this class
            // TODO: remove constants
            for (int s = 0; s < 2; ++s) {
                States.push_back(std::vector< std::vector<Square> >(4, std::vector<Square>(4)));
                for (int i = 0; i < 4; ++i)
                    for(int j = 0; j < 4; ++j)
                        States[s][i][j] = states[s][i][j];
            }
        }

        void Rotate()
        {
            CurrentStateIndex = (CurrentStateIndex + 1) % States.size();
        }

        Square GetSquare(int i, int j)
        {
            return States[CurrentStateIndex][i][j];
        }

        std::vector< std::vector<Square> > GetCurrentState()
        {
            return States[CurrentStateIndex];
        }
    private:
        std::vector< std::vector< std::vector<Square> > > States;
        int CurrentStateIndex;
    };

public:
    Game()
      : field(FIELD_WIDTH, std::vector<Square>(FIELD_HEIGHT, Square()))
      , figX(0)
      , figY(FIELD_HEIGHT - 4)
    {
        // TODO ugly, handle it i a better way
        field[0][0] = true;
        field[0][1] = true;
        field[1][0] = true;
        field[1][1] = true;

        field[5][5] = true;
        field[5][5] = true;
        field[5][6] = true;
        field[5][6] = true;
    }

    void DrawField(sf::RenderWindow& window)
    {
        int fieldHeight = squareSize * FIELD_HEIGHT;
        int fieldWidth = squareSize * FIELD_WIDTH;
        DrawMatrix(window, field);
        sf::RectangleShape border(sf::Vector2f(fieldWidth, fieldHeight));
        border.setPosition(fieldPositionX, fieldPositionY);
        border.setOutlineThickness(outlineThickness);
        border.setFillColor(sf::Color::Transparent);
        window.draw(border);
    }

    void DrawMatrix(sf::RenderWindow& window, std::vector< std::vector<Square> > matrix, int offsetX = 0, int offsetY = 0)
    {
        int matrixHeight = squareSize * field.size();
        int matrixWidth = squareSize * field[0].size();
        for (int i = 0; i < matrix.size(); ++i) {
            for (int j = 0; j < matrix[i].size(); ++j) {
                matrix[i][j].Draw(window, i + offsetX, j + offsetY);
            }
        }
    }

    void Draw(sf::RenderWindow& window)
    {
        DrawField(window);
        DrawMatrix(window, fig.GetCurrentState(), figX, figY);
    }

    void MoveFigureRight()
    {
        if (IsCorrectFigurePosition(figX + 1, figY))
            figX++;
    }

    void MoveFigureLeft()
    {
        if (IsCorrectFigurePosition(figX - 1, figY))
            figX--;
    }

    void MoveFigureDown()
    {
        if (IsCorrectFigurePosition(figX, figY - 1))
            figY--;
    }

    void ForceFigureDown()
    {
        MoveFigureDown();
    }

    void RotateFigure()
    {
        /* TODO: collision checking */
        fig.Rotate();
    }

    bool IsCorrectFigurePosition(int x, int y)
    {
        for (int i = 0; i < FIG_SIZE; ++i) {
            for (int j = 0; j < FIG_SIZE; ++j) {
                if (fig.GetSquare(i, j).IsOccupied && ((x + i) >= FIELD_WIDTH || (x + i) < 0 || (y+j) >= FIELD_HEIGHT || (y + j) < 0 || field[x + i][y + j].IsOccupied)) {
                    return false;
                }
            }
        }

        return true;
    }

private:
    static const int FIELD_WIDTH = 10;
    static const int FIELD_HEIGHT = 20;
    static const int FIG_SIZE = 4;
    std::vector< std::vector<Square> > field;
    Figure fig;
    int figX;
    int figY;
    enum {
        fieldPositionX = 50,
        fieldPositionY = 100,
    };
    enum {
        squareSize = 20,
        outlineThickness = 2,
        matrixPositionX = 50,
        matrixPositionY = 100,
    };
};

void init()
{
}

int main()
{
    Game game;

    const int windowWidth = 800;
    const int windowHeight = 600;

    sf::ContextSettings settings;
    settings.antialiasingLevel = 8;

    sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight), "My window", sf::Style::Default,  settings);

    sf::Clock clock;
    const int tickSize = 1000;
    while (window.isOpen())
    {
        window.clear();
        // check all the window's events that were triggered since the last iteration of the loop
        sf::Event event;
        while (window.pollEvent(event))
        {
            // "close requested" event: we close the window
            switch (event.type) {
                case sf::Event::Closed:
                    window.close();
                    break;
                case sf::Event::KeyPressed:
                    switch (event.key.code) {
                        case sf::Keyboard::Left:
                            game.MoveFigureLeft();
                            break;
                        case sf::Keyboard::Right:
                            game.MoveFigureRight();
                            break;
                        case sf::Keyboard::Down:
                            game.MoveFigureDown();
                            break;
                        case sf::Keyboard::Space:
                            game.RotateFigure();
                            break;
                        default:
                            break;
                    };
                default:
                    break;
            };
        }
        if (clock.getElapsedTime().asMilliseconds() > tickSize) {
            game.ForceFigureDown();
            clock.restart();
        }
        game.Draw(window);
        window.display();
    }
}
<|endoftext|>


<commit_before>//=============================================================================================================
/**
 * @file     pluginmanager.cpp
 * @author   Christoph Dinh <chdinh@nmr.mgh.harvard.edu>;
 *           Lorenz Esch <lesch@mgh.harvard.edu>;
 *           Lars Debor <Lars.Debor@tu-ilmenau.de>;
 *           Simon Heinke <Simon.Heinke@tu-ilmenau.de>
 * @since    0.1.0
 * @date     February, 2017
 *
 * @section  LICENSE
 *
Copyright (C) 2017, Christoph Dinh, Lars Debor, Simon Heinke and Matti Hamalainen. 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 MNE-CPP authors 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.
 *
 *
 * @brief    Definition of the PluginManager class.
 *
 */

//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "pluginmanager.h"
#include "../Plugins/abstractplugin.h"
#include "communicator.h"

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QDir>
#include <QDebug>

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace ANSHAREDLIB;

//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

PluginManager::PluginManager(QObject *parent)
: QPluginLoader(parent)
{

}

//=============================================================================================================

PluginManager::~PluginManager()
{
    for(AbstractPlugin*& plugin : m_qVecPlugins)
    {
        delete plugin;
    }
}

//=============================================================================================================

void PluginManager::loadPluginsFromDirectory(const QString& dir)
{
#ifdef STATICBUILD
    Q_UNUSED(dir);

    const auto staticInstances = QPluginLoader::staticInstances();
    for(QObject *plugin : staticInstances) {
        // AbstractPlugin
        if(AbstractPlugin* pPlugin = qobject_cast<AbstractPlugin*>(plugin)) {
            m_qVecPlugins.push_back(qobject_cast<AbstractPlugin*>(pPlugin));
        }
    }
#else
    QDir pluginsDir(dir);
    pluginsDir.setNameFilters((QStringList()<<"*.exp"<<"*.lib"));// Exclude .exp and .lib files (only relevant for windows builds)
    foreach(const QString &file, pluginsDir.entryList(QDir::NoDotAndDotDot | QDir::Files)) {
        loadPlugin(pluginsDir.absoluteFilePath(file));
    }
#endif
}

//=============================================================================================================

void PluginManager::loadPlugin(const QString& file)
{
    this->setFileName(file);
    AbstractPlugin *pPlugin = qobject_cast<AbstractPlugin*>(this->instance());
    if(pPlugin) {
        if(findByName(pPlugin->getName())==-1)
        {
            qDebug() << "[PluginManager::loadPlugin] Loading Plugin " << file.toUtf8().constData() << " succeeded.";
            m_qVecPlugins.push_back(qobject_cast<AbstractPlugin*>(pPlugin));
        } else {
            qDebug() << "[PluginManager::loadPlugin] Loading Plugin " << file.toUtf8().constData() << ". Plugin already loaded.";
        }
    } else {
        qDebug() << "[PluginManager::loadPlugin] Loading Plugin " << file.toUtf8().constData() << " failed.";
    }
}

//=============================================================================================================

void PluginManager::initPlugins(QSharedPointer<AnalyzeData> data)
{
    for(AbstractPlugin*& plugin : m_qVecPlugins)
    {
        plugin->setGlobalData(data);
        plugin->init();
    }

    // tell everyone that INIT-phase is finished
    Communicator con;
    con.publishEvent(EVENT_TYPE::PLUGIN_INIT_FINISHED);
}

//=============================================================================================================

int PluginManager::findByName(const QString& name)
{
    QVector<AbstractPlugin*>::const_iterator it = m_qVecPlugins.cbegin();
    for(int i = 0; it != m_qVecPlugins.cend(); ++i, ++it)
    {
        if((*it)->getName() == name)
        {
            return i;
        }
    }
    return -1;
}

//=============================================================================================================

void PluginManager::shutdown()
{
    for(AbstractPlugin*& plugin : m_qVecPlugins)
    {
        plugin->unload();
    }
}
<commit_msg>object cast repeated<commit_after>//=============================================================================================================
/**
 * @file     pluginmanager.cpp
 * @author   Christoph Dinh <chdinh@nmr.mgh.harvard.edu>;
 *           Lorenz Esch <lesch@mgh.harvard.edu>;
 *           Lars Debor <Lars.Debor@tu-ilmenau.de>;
 *           Simon Heinke <Simon.Heinke@tu-ilmenau.de>
 * @since    0.1.0
 * @date     February, 2017
 *
 * @section  LICENSE
 *
Copyright (C) 2017, Christoph Dinh, Lars Debor, Simon Heinke and Matti Hamalainen. 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 MNE-CPP authors 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.
 *
 *
 * @brief    Definition of the PluginManager class.
 *
 */

//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "pluginmanager.h"
#include "../Plugins/abstractplugin.h"
#include "communicator.h"

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QDir>
#include <QDebug>

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace ANSHAREDLIB;

//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

PluginManager::PluginManager(QObject *parent)
: QPluginLoader(parent)
{

}

//=============================================================================================================

PluginManager::~PluginManager()
{
    for(AbstractPlugin*& plugin : m_qVecPlugins)
    {
        delete plugin;
    }
}

//=============================================================================================================

void PluginManager::loadPluginsFromDirectory(const QString& dir)
{
#ifdef STATICBUILD
    Q_UNUSED(dir);

    const auto staticInstances = QPluginLoader::staticInstances();
    for(QObject *plugin : staticInstances) {
        // AbstractPlugin
        if(AbstractPlugin* pPlugin = qobject_cast<AbstractPlugin*>(plugin)) {
            m_qVecPlugins.push_back(qobject_cast<AbstractPlugin*>(pPlugin));
        }
    }
#else
    QDir pluginsDir(dir);
    pluginsDir.setNameFilters((QStringList()<<"*.exp"<<"*.lib"));
    foreach(const QString &file, pluginsDir.entryList(QDir::NoDotAndDotDot | QDir::Files)) {
        loadPlugin(pluginsDir.absoluteFilePath(file));
    }
#endif
}

//=============================================================================================================

void PluginManager::loadPlugin(const QString& file)
{
    if(!file.contains(".exp") && !file.contains(".lib"))
    {
        this->setFileName(file);
        AbstractPlugin* pPlugin = qobject_cast<AbstractPlugin*>(this->instance());
        if(pPlugin) {
            if(findByName(pPlugin->getName())==-1)
            {
                qDebug() << "[PluginManager::loadPlugin] Loading Plugin " << file.toUtf8().constData() << " succeeded.";
                m_qVecPlugins.push_back(pPlugin);
            } else {
                qDebug() << "[PluginManager::loadPlugin] Loading Plugin " << file.toUtf8().constData() << ". Plugin already loaded.";
            }
        } else {
            qDebug() << "[PluginManager::loadPlugin] Loading Plugin " << file.toUtf8().constData() << " failed.";
        }
    }
}

//=============================================================================================================

void PluginManager::initPlugins(QSharedPointer<AnalyzeData> data)
{
    for(AbstractPlugin*& plugin : m_qVecPlugins)
    {
        plugin->setGlobalData(data);
        plugin->init();
    }

    // tell everyone that INIT-phase is finished
    Communicator con;
    con.publishEvent(EVENT_TYPE::PLUGIN_INIT_FINISHED);
}

//=============================================================================================================

int PluginManager::findByName(const QString& name)
{
    QVector<AbstractPlugin*>::const_iterator it = m_qVecPlugins.cbegin();
    for(int i = 0; it != m_qVecPlugins.cend(); ++i, ++it)
    {
        if((*it)->getName() == name)
        {
            return i;
        }
    }
    return -1;
}

//=============================================================================================================

void PluginManager::shutdown()
{
    for(AbstractPlugin*& plugin : m_qVecPlugins)
    {
        plugin->unload();
    }
}
<|endoftext|>


<commit_before>/*******************************************************************************
Copyright (c) 2014, Jan Koester jan.koester@gmx.net
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> 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 <COPYRIGHT HOLDER> 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 <fcntl.h>
#include <sys/sysinfo.h>
#include <cstdlib>
#include <config.h>
#include <errno.h>
#include <signal.h>
#include "os/os.h"

#define READEVENT 0
#define SENDEVENT 1

#include "../event.h"

libhttppp::Event::Event(ServerSocket *serversocket) {
    _ServerSocket=serversocket;
    _ServerSocket->setnonblocking();
    _ServerSocket->listenSocket();
    _EventEndloop =true;
    _Cpool= new ConnectionPool(_ServerSocket);
    _Events = new epoll_event[(_ServerSocket->getMaxconnections())];
    _Mutex = new Mutex;
    _firstConnectionContext=NULL;
    _lastConnectionContext=NULL;
}

libhttppp::Event::~Event() {
  delete   _Cpool;
  delete[] _Events;
  delete _firstConnectionContext;
  delete _Mutex;
  _lastConnectionContext=NULL;
}

libhttppp::Event* _EventIns=NULL;

void libhttppp::Event::CtrlHandler(int signum) {
    _EventIns->_EventEndloop=false;
}

void libhttppp::Event::runEventloop() {
    _setEvent = (struct epoll_event){0};
    for(int i=0; i<_ServerSocket->getMaxconnections(); i++)
        _Events[i].data.fd = -1;
    _epollFD = epoll_create1(0);

    if (_epollFD == -1) {
        _httpexception.Critical("can't create epoll");
        throw _httpexception;
    }

    _setEvent.events = EPOLLIN;
    _setEvent.data.fd = _ServerSocket->getSocket();

    if (epoll_ctl(_epollFD, EPOLL_CTL_ADD, _ServerSocket->getSocket(), &_setEvent) < 0) {
        _httpexception.Critical("can't create epoll");
        throw _httpexception;
    }

    int srvssocket=_ServerSocket->getSocket();
    int maxconnets=_ServerSocket->getMaxconnections();
    while(_EventEndloop) {
        int n = epoll_wait(_epollFD,_Events,maxconnets, EPOLLWAIT);
        if(n<0){
            if(errno== EINTR){
                continue;
            }else{
                 _httpexception.Critical("epoll wait failure");
                 throw _httpexception;
            }

        }
        for(int i=0; i<n; i++) {
            ConnectionContext *curct=NULL;
            if(_Events[i].data.fd == srvssocket) {
              try {
              /*will create warning debug mode that normally because the check already connection
               * with this socket if getconnection throw they will be create a new one
               */
                _Mutex->lock();
                curct=addConnection();
                _Mutex->unlock();
                curct->_Mutex->lock();
                ClientSocket *clientsocket=curct->_CurConnection->getClientSocket();
                int fd=_ServerSocket->acceptEvent(clientsocket);
                clientsocket->setnonblocking();
                if(fd>0) {
                  _setEvent.data.ptr = (void*) curct;
                  _setEvent.events = EPOLLIN|EPOLLET;
                  if(epoll_ctl(_epollFD, EPOLL_CTL_ADD, fd, &_setEvent)==-1 && errno==EEXIST)
                    epoll_ctl(_epollFD, EPOLL_CTL_MOD,fd, &_setEvent);
                  curct->_Mutex->unlock();
                  ConnectEvent(curct->_CurConnection);
                } else {
                   curct->_Mutex->unlock();
                  _Mutex->lock();
                  delConnection(curct->_CurConnection);
                  _Mutex->unlock();
                }

              } catch(HTTPException &e) {
                _Mutex->lock();
                curct->_Mutex->unlock();
                delConnection(curct->_CurConnection);
                _Mutex->unlock();
                if(e.isCritical())
                  throw e;
              }
            } else {
                curct=(ConnectionContext*)_Events[i].data.ptr;
                if(_Events[i].events & EPOLLIN) {
                    Thread(ReadEvent,curct);
                }else{
                    _Mutex->lock();
                    CloseEvent(curct);
                    _Mutex->unlock();
                }
            }
        }
        _EventIns=this;
        signal(SIGINT, CtrlHandler);
    }
}

libhttppp::Event::ConnectionContext::ConnectionContext(){
  _CurConnection=NULL;
  _CurCPool=NULL;
  _CurEvent=NULL;
  _Mutex=new Mutex;
  _nextConnectionContext=NULL;
}

libhttppp::Event::ConnectionContext::~ConnectionContext(){
  delete _Mutex;
  delete _nextConnectionContext;
}

libhttppp::Event::ConnectionContext * libhttppp::Event::ConnectionContext::nextConnectionContext(){
  return _nextConnectionContext;
}

libhttppp::Event::ConnectionContext * libhttppp::Event::addConnection(){
  if(!_firstConnectionContext){
    _firstConnectionContext=new ConnectionContext();
    _firstConnectionContext->_Mutex->lock();
    _lastConnectionContext=_firstConnectionContext;
    _firstConnectionContext->_Mutex->unlock();
  }else{
    _lastConnectionContext->_Mutex->lock();
    _lastConnectionContext->_nextConnectionContext=new ConnectionContext();
    _lastConnectionContext=_lastConnectionContext->_nextConnectionContext;
    _lastConnectionContext->_Mutex->unlock();
  }
  _lastConnectionContext->_CurConnection=_Cpool->addConnection();
  _lastConnectionContext->_CurCPool=_Cpool;
  _lastConnectionContext->_CurEvent=this;

  return _lastConnectionContext;
}

libhttppp::Event::ConnectionContext * libhttppp::Event::delConnection(libhttppp::Connection* delcon){
  ConnectionContext *prevcontext=NULL;
  for(ConnectionContext *curcontext=_firstConnectionContext; curcontext;
      curcontext=curcontext->nextConnectionContext()){
    if(curcontext->_CurConnection==delcon){
      curcontext->_Mutex->lock();
      _Cpool->delConnection(delcon);
      if(prevcontext){
        prevcontext->_Mutex->lock();
        prevcontext->_nextConnectionContext=curcontext->_nextConnectionContext;
        if(_lastConnectionContext->_CurConnection==delcon){
          _lastConnectionContext->_Mutex->lock();
          _lastConnectionContext=prevcontext;
          _lastConnectionContext->_Mutex->unlock();
        }
        prevcontext->_Mutex->unlock();
      }else{
        _firstConnectionContext->_Mutex->lock();
        _lastConnectionContext->_Mutex->lock();
        _firstConnectionContext=curcontext->_nextConnectionContext;
        if(_lastConnectionContext->_CurConnection==delcon)
          _lastConnectionContext=_firstConnectionContext;
        if(_firstConnectionContext)
        _firstConnectionContext->_Mutex->unlock();
        if(_lastConnectionContext)
        _lastConnectionContext->_Mutex->unlock();
      }
      curcontext->_nextConnectionContext=NULL;
      delete curcontext;
      break;
    }
    prevcontext=curcontext;
  }
  if(prevcontext && prevcontext->_nextConnectionContext){
    return prevcontext->_nextConnectionContext;
  }else{
    ConnectionContext *fcontext=_firstConnectionContext;
    return fcontext;
  }
}

/*Workers*/
void *libhttppp::Event::ReadEvent(void *curcon){
  ConnectionContext *ccon=(ConnectionContext*)curcon;
  ccon->_Mutex->lock();
  Event *eventins=ccon->_CurEvent;
  Connection *con=(Connection*)ccon->_CurConnection;
  try {
    char buf[BLOCKSIZE];
    int rcvsize=0;
    do{
      rcvsize=eventins->_ServerSocket->recvData(con->getClientSocket(),buf,BLOCKSIZE);
      if(rcvsize>0)
        con->addRecvQueue(buf,rcvsize);
    }while(rcvsize>0);
    eventins->RequestEvent(con);
    ccon->_Mutex->unlock();
    WriteEvent(ccon);
  } catch(HTTPException &e) {
      ccon->_Mutex->unlock();
       if(e.isCritical()) {
         throw e;
       }
       if(e.isError()){
          CloseEvent(ccon);
       }
  }
  return NULL;
}

void *libhttppp::Event::WriteEvent(void* curcon){
  ConnectionContext *ccon=(ConnectionContext*)curcon;
  ccon->_Mutex->lock();
  Event *eventins=ccon->_CurEvent;
  Connection *con=(Connection*)ccon->_CurConnection;
  try {
    ssize_t sended=0;
    while(con->getSendData()){
      sended=eventins->_ServerSocket->sendData(con->getClientSocket(),
                                    (void*)con->getSendData()->getData(),
                                    con->getSendData()->getDataSize());
      if(sended>0)
        con->resizeSendQueue(sended);
      eventins->ResponseEvent(con);
    };
  } catch(HTTPException &e) {
    con->cleanSendData();
    ccon->_Mutex->unlock();
    CloseEvent(ccon);
  }
  ccon->_Mutex->unlock();
  return NULL;
}

void *libhttppp::Event::CloseEvent(void *curcon){
  ConnectionContext *ccon=(ConnectionContext*)curcon;
  Event *eventins=ccon->_CurEvent;
  Connection *con=(Connection*)ccon->_CurConnection;
  eventins->DisconnectEvent(con);
  try {
    epoll_ctl(eventins->_epollFD, EPOLL_CTL_DEL, con->getClientSocket()->getSocket(), &eventins->_setEvent);
    eventins->delConnection(con);
    curcon=NULL;
    eventins->_httpexception.Note("Connection shutdown!");
  } catch(HTTPException &e) {
    eventins->_httpexception.Note("Can't do Connection shutdown!");
  }
  return NULL;
}

/*Event Handlers*/
void libhttppp::Event::RequestEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::ResponseEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::ConnectEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::DisconnectEvent(libhttppp::Connection *curcon) {
    return;
}
<commit_msg>added mutex debbugging<commit_after>/*******************************************************************************
Copyright (c) 2014, Jan Koester jan.koester@gmx.net
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> 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 <COPYRIGHT HOLDER> 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 <fcntl.h>
#include <sys/sysinfo.h>
#include <cstdlib>
#include <config.h>
#include <errno.h>
#include <signal.h>
#include "os/os.h"

#define READEVENT 0
#define SENDEVENT 1

#define DEBUG_MUTEX

#include "../event.h"

libhttppp::Event::Event(ServerSocket *serversocket) {
    _ServerSocket=serversocket;
    _ServerSocket->setnonblocking();
    _ServerSocket->listenSocket();
    _EventEndloop =true;
    _Cpool= new ConnectionPool(_ServerSocket);
    _Events = new epoll_event[(_ServerSocket->getMaxconnections())];
    _Mutex = new Mutex;
    _firstConnectionContext=NULL;
    _lastConnectionContext=NULL;
}

libhttppp::Event::~Event() {
  delete   _Cpool;
  delete[] _Events;
  delete _firstConnectionContext;
  delete _Mutex;
  _lastConnectionContext=NULL;
}

libhttppp::Event* _EventIns=NULL;

void libhttppp::Event::CtrlHandler(int signum) {
    _EventIns->_EventEndloop=false;
}

void libhttppp::Event::runEventloop() {
    _setEvent = (struct epoll_event){0};
    for(int i=0; i<_ServerSocket->getMaxconnections(); i++)
        _Events[i].data.fd = -1;
    _epollFD = epoll_create1(0);

    if (_epollFD == -1) {
        _httpexception.Critical("can't create epoll");
        throw _httpexception;
    }

    _setEvent.events = EPOLLIN;
    _setEvent.data.fd = _ServerSocket->getSocket();

    if (epoll_ctl(_epollFD, EPOLL_CTL_ADD, _ServerSocket->getSocket(), &_setEvent) < 0) {
        _httpexception.Critical("can't create epoll");
        throw _httpexception;
    }

    int srvssocket=_ServerSocket->getSocket();
    int maxconnets=_ServerSocket->getMaxconnections();
    while(_EventEndloop) {
        int n = epoll_wait(_epollFD,_Events,maxconnets, EPOLLWAIT);
        if(n<0){
            if(errno== EINTR){
                continue;
            }else{
                 _httpexception.Critical("epoll wait failure");
                 throw _httpexception;
            }

        }
        for(int i=0; i<n; i++) {
            ConnectionContext *curct=NULL;
            if(_Events[i].data.fd == srvssocket) {
              try {
              /*will create warning debug mode that normally because the check already connection
               * with this socket if getconnection throw they will be create a new one
               */
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Lock MainMutex");
#endif
                _Mutex->lock();
                curct=addConnection();
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock MainMutex");
#endif
                _Mutex->unlock();
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Lock ConnectionMutex");
#endif
                curct->_Mutex->lock();
                ClientSocket *clientsocket=curct->_CurConnection->getClientSocket();
                int fd=_ServerSocket->acceptEvent(clientsocket);
                clientsocket->setnonblocking();
                if(fd>0) {
                  _setEvent.data.ptr = (void*) curct;
                  _setEvent.events = EPOLLIN|EPOLLET;
                  if(epoll_ctl(_epollFD, EPOLL_CTL_ADD, fd, &_setEvent)==-1 && errno==EEXIST)
                    epoll_ctl(_epollFD, EPOLL_CTL_MOD,fd, &_setEvent);
                  ConnectEvent(curct->_CurConnection);
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock ConnectionMutex");
#endif
                  curct->_Mutex->unlock();
                } else {
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock ConnectionMutex");
#endif
                   curct->_Mutex->unlock();
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Lock MainMutex");
#endif
                  _Mutex->lock();
                  delConnection(curct->_CurConnection);
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock MainMutex");
#endif
                  _Mutex->unlock();
                }

              } catch(HTTPException &e) {
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Lock MainMutex");
#endif
                _Mutex->lock();
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock ConnectionMutex");
#endif
                curct->_Mutex->unlock();
                delConnection(curct->_CurConnection);
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock MainMutex");
#endif
                _Mutex->unlock();
                if(e.isCritical())
                  throw e;
              }
            } else {
                curct=(ConnectionContext*)_Events[i].data.ptr;
                if(_Events[i].events & EPOLLIN) {
                    Thread(ReadEvent,curct);
                }else{
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Lock MainMutex");
#endif
                    _Mutex->lock();
                    CloseEvent(curct);
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock MainMutex");
#endif
                    _Mutex->unlock();
                }
            }
        }
        _EventIns=this;
        signal(SIGINT, CtrlHandler);
    }
}

libhttppp::Event::ConnectionContext::ConnectionContext(){
  _CurConnection=NULL;
  _CurCPool=NULL;
  _CurEvent=NULL;
  _Mutex=new Mutex;
  _nextConnectionContext=NULL;
}

libhttppp::Event::ConnectionContext::~ConnectionContext(){
  delete _Mutex;
  delete _nextConnectionContext;
}

libhttppp::Event::ConnectionContext * libhttppp::Event::ConnectionContext::nextConnectionContext(){
  return _nextConnectionContext;
}

libhttppp::Event::ConnectionContext * libhttppp::Event::addConnection(){
  if(!_firstConnectionContext){
    _firstConnectionContext=new ConnectionContext();
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Lock ConnectionMutex");
#endif
    _firstConnectionContext->_Mutex->lock();
    _lastConnectionContext=_firstConnectionContext;
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Unlock ConnectionMutex");
#endif
    _firstConnectionContext->_Mutex->unlock();
  }else{
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Lock ConnectionMutex");
#endif
    _lastConnectionContext->_Mutex->lock();
    _lastConnectionContext->_nextConnectionContext=new ConnectionContext();
    _lastConnectionContext=_lastConnectionContext->_nextConnectionContext;
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Unlock ConnectionMutex");
#endif
    _lastConnectionContext->_Mutex->unlock();
  }
  _lastConnectionContext->_CurConnection=_Cpool->addConnection();
  _lastConnectionContext->_CurCPool=_Cpool;
  _lastConnectionContext->_CurEvent=this;

  return _lastConnectionContext;
}

libhttppp::Event::ConnectionContext * libhttppp::Event::delConnection(libhttppp::Connection* delcon){
  ConnectionContext *prevcontext=NULL;
  for(ConnectionContext *curcontext=_firstConnectionContext; curcontext;
      curcontext=curcontext->nextConnectionContext()){
    if(curcontext->_CurConnection==delcon){
#ifdef DEBUG_MUTEX
      _httpexception.Note("delConnection","Lock ConnectionMutex");
#endif
      curcontext->_Mutex->lock();
      _Cpool->delConnection(delcon);
      if(prevcontext){
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","Lock prevConnectionMutex");
#endif
        prevcontext->_Mutex->lock();
        prevcontext->_nextConnectionContext=curcontext->_nextConnectionContext;
        if(_lastConnectionContext==curcontext){
          _lastConnectionContext=prevcontext;
        }
#ifdef DEBUG_MUTEX
     _httpexception.Note("delConnection","unlock prevConnectionMutex");
#endif
        prevcontext->_Mutex->unlock();
      }else{
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","lock firstConnectionMutex");
#endif
        _firstConnectionContext->_Mutex->lock();
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","lock lastConnectionMutex");
#endif
        _lastConnectionContext->_Mutex->lock();
        _firstConnectionContext=curcontext->_nextConnectionContext;
        if(_lastConnectionContext->_CurConnection==delcon)
          _lastConnectionContext=_firstConnectionContext;
        if(_firstConnectionContext){
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","unlock firstConnectionMutex");
#endif
        _firstConnectionContext->_Mutex->unlock();
        }
        if(_lastConnectionContext){
#ifdef DEBUG_MUTEX
     _httpexception.Note("delConnection","unlock lastConnectionMutex");
#endif
        _lastConnectionContext->_Mutex->unlock();
        }
      }
      curcontext->_nextConnectionContext=NULL;
      delete curcontext;
      break;
    }
    prevcontext=curcontext;
  }
  if(prevcontext && prevcontext->_nextConnectionContext){
    return prevcontext->_nextConnectionContext;
  }else{
    ConnectionContext *fcontext=_firstConnectionContext;
    return fcontext;
  }
}

/*Workers*/
void *libhttppp::Event::ReadEvent(void *curcon){
  ConnectionContext *ccon=(ConnectionContext*)curcon;
  Event *eventins=ccon->_CurEvent;
#ifdef DEBUG_MUTEX
  eventins->_httpexception.Note("ReadEvent","lock ConnectionMutex");
#endif
  ccon->_Mutex->lock();
  Connection *con=(Connection*)ccon->_CurConnection;
  try {
    char buf[BLOCKSIZE];
    int rcvsize=0;
    do{
      rcvsize=eventins->_ServerSocket->recvData(con->getClientSocket(),buf,BLOCKSIZE);
      if(rcvsize>0)
        con->addRecvQueue(buf,rcvsize);
    }while(rcvsize>0);
    eventins->RequestEvent(con);
#ifdef DEBUG_MUTEX
  eventins->_httpexception.Note("ReadEvent","unlock ConnectionMutex");
#endif
    ccon->_Mutex->unlock();
    WriteEvent(ccon);
  } catch(HTTPException &e) {
#ifdef DEBUG_MUTEX
      eventins->_httpexception.Note("ReadEvent","unlock ConnectionMutex");
#endif
      ccon->_Mutex->unlock();
       if(e.isCritical()) {
         throw e;
       }
       if(e.isError()){
          CloseEvent(ccon);
       }
  }
  return NULL;
}

void *libhttppp::Event::WriteEvent(void* curcon){
  ConnectionContext *ccon=(ConnectionContext*)curcon;
  Event *eventins=ccon->_CurEvent;
#ifdef DEBUG_MUTEX
  eventins->_httpexception.Note("WriteEvent","lock ConnectionMutex");
#endif
  ccon->_Mutex->lock();
  Connection *con=(Connection*)ccon->_CurConnection;
  try {
    ssize_t sended=0;
    while(con->getSendData()){
      sended=eventins->_ServerSocket->sendData(con->getClientSocket(),
                                    (void*)con->getSendData()->getData(),
                                    con->getSendData()->getDataSize());
      if(sended>0)
        con->resizeSendQueue(sended);
      eventins->ResponseEvent(con);
    }
  } catch(HTTPException &e) {
    con->cleanSendData();
    CloseEvent(ccon);
  }
#ifdef DEBUG_MUTEX
  eventins->_httpexception.Note("WriteEvent","unlock ConnectionMutex");
#endif
  ccon->_Mutex->unlock();
  return NULL;
}

void *libhttppp::Event::CloseEvent(void *curcon){
  ConnectionContext *ccon=(ConnectionContext*)curcon;
  Event *eventins=ccon->_CurEvent;
#ifdef DEBUG_MUTEX
  eventins->_httpexception.Note("CloseEvent","MainMutex");
#endif
  ccon->_Mutex->lock();
  Connection *con=(Connection*)ccon->_CurConnection;
  eventins->DisconnectEvent(con);
#ifdef DEBUG_MUTEX
  eventins->_httpexception.Note("CloseEvent","unlock MainMutex");
#endif
  ccon->_Mutex->unlock();
  try {
    epoll_ctl(eventins->_epollFD, EPOLL_CTL_DEL, con->getClientSocket()->getSocket(), &eventins->_setEvent);
    eventins->delConnection(con);
    curcon=NULL;
    eventins->_httpexception.Note("Connection shutdown!");
  } catch(HTTPException &e) {
    eventins->_httpexception.Note("Can't do Connection shutdown!");
  }
  return NULL;
}

/*Event Handlers*/
void libhttppp::Event::RequestEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::ResponseEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::ConnectEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::DisconnectEvent(libhttppp::Connection *curcon) {
    return;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <client/dbclient.h>
#include <client/gridfs.h>

extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM < 501)
#include <compat-5.1.h>
#endif
};

#include "utils.h"
#include "common.h"

using namespace mongo;

extern void bson_to_lua(lua_State *L, const BSONObj &obj);
extern int gridfile_create(lua_State *L, GridFile gf);

namespace {
    inline GridFS* userdata_to_gridfs(lua_State* L, int index) {
        void *ud = 0;

        ud = luaL_checkudata(L, index, LUAMONGO_GRIDFS);
        GridFS *gridfs = *((GridFS **)ud);

        return gridfs;
    }
}

/*
 * gridfs, err = mongo.GridFS.New(connection, dbname[, prefix])
 */
static int gridfs_new(lua_State *L) {
    int n = lua_gettop(L);
    int resultcount = 1;

    try {
        void *ud = 0;

        ud = luaL_checkudata(L, 1, LUAMONGO_CONNECTION);
        DBClientConnection *connection = *((DBClientConnection **)ud);

        const char *dbname = lua_tostring(L, 2);

        GridFS **gridfs = (GridFS **)lua_newuserdata(L, sizeof(GridFS *));

        if (n >= 3) {
            const char *prefix = luaL_checkstring(L, 3);

            *gridfs = new GridFS(*connection, dbname, prefix);
        } else {
            *gridfs = new GridFS(*connection, dbname);
        }

        luaL_getmetatable(L, LUAMONGO_GRIDFS);
        lua_setmetatable(L, -2);
    } catch (std::exception &e) {
        lua_pushnil(L);
        lua_pushfstring(L, LUAMONGO_ERR_GRIDFS_FAILED, e.what());
        resultcount = 2;
    }

    return resultcount;
}

/*
 * gridfile, err = gridfs:find_file(filename)
 */
static int gridfs_find_file(lua_State *L) {
    GridFS *gridfs = userdata_to_gridfs(L, 1);
    int resultcount = 1;

    try {
        GridFile gridfile = gridfs->findFile(luaL_checkstring(L, 2));
        resultcount = gridfile_create(L, gridfile);
    } catch (std::exception &e) {
        lua_pushboolean(L, 0);
        lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_GRIDFS, "find_file", e.what());
        resultcount = 2;
    }

    return resultcount;
}

/*
 * cursor = gridfs:list()
 */
static int gridfs_list(lua_State *L) {
    GridFS *gridfs = userdata_to_gridfs(L, 1);

    DBClientCursor **cursor = (DBClientCursor **)lua_newuserdata(L, sizeof(DBClientCursor *));
    auto_ptr<DBClientCursor> autocursor = gridfs->list();
    *cursor = autocursor.get();
    autocursor.release();

    luaL_getmetatable(L, LUAMONGO_CURSOR);
    lua_setmetatable(L, -2);

    return 1;
}

/*
 * ok, err = gridfs:remove_file(filename)
 */
static int gridfs_remove_file(lua_State *L) {
    int resultcount = 1;

    GridFS *gridfs = userdata_to_gridfs(L, 1);

    const char *filename = luaL_checkstring(L, 2);

    try {
        gridfs->removeFile(filename);
        lua_pushboolean(L, 1);
    } catch (std::exception &e) {
        lua_pushboolean(L, 0);
        lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_GRIDFS, "remove_file", e.what());
        resultcount = 2;
    }

    return resultcount;
}

/*
 * gridfile, err = gridfs:store_file(filename[, remote_file], content_type]])
 */
static int gridfs_store_file(lua_State *L) {
    int resultcount = 1;

    GridFS *gridfs = userdata_to_gridfs(L, 1);

    const char *filename = luaL_checkstring(L, 2);
    const char *remote = luaL_optstring(L, 3, "");
    const char *content_type = luaL_optstring(L, 4, "");

    try {
        BSONObj res = gridfs->storeFile(filename, remote, content_type);
        bson_to_lua(L, res);
    } catch (std::exception &e) {
        lua_pushnil(L);
        lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_GRIDFS, "store_file", e.what());
        resultcount = 2;
    }

    return resultcount;
}

/*
 * gridfile, err = gridfs:store_data(data[, remote_file], content_type]])
 * puts the file represented by data into the db
 */
static int gridfs_store_data(lua_State *L) {
    int resultcount = 1;

    GridFS *gridfs = userdata_to_gridfs(L, 1);

    size_t length = 0;
    const char *data = luaL_checklstring(L, 2, &length);
    const char *remote = luaL_optstring(L, 3, "");
    const char *content_type = luaL_optstring(L, 4, "");

    try {
        BSONObj res = gridfs->storeFile(data, length, remote, content_type);
        bson_to_lua(L, res);
    } catch (std::exception &e) {
        lua_pushnil(L);
        lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_GRIDFS, "store_data", e.what());
        resultcount = 2;
    }

    return resultcount;
}

/*
 * __gc
 */
static int gridfs_gc(lua_State *L) {
    GridFS *gridfs = userdata_to_gridfs(L, 1);

    delete gridfs;

    return 0;
}

/*
 * __tostring
 */
static int gridfs_tostring(lua_State *L) {
    GridFS *gridfs = userdata_to_gridfs(L, 1);

    lua_pushfstring(L, "%s: %p", LUAMONGO_GRIDFS, gridfs);

    return 1;
}

int mongo_gridfs_register(lua_State *L) {
    static const luaL_Reg gridfs_methods[] = {
        {"find_file", gridfs_find_file},
        {"list", gridfs_list},
        {"remove_file", gridfs_remove_file},
        {"store_file", gridfs_store_file},
        {"store_data", gridfs_store_data},
        {NULL, NULL}
    };

    static const luaL_Reg gridfs_class_methods[] = {
        {"New", gridfs_new},
        {NULL, NULL}
    };

    luaL_newmetatable(L, LUAMONGO_GRIDFS);
    luaL_register(L, 0, gridfs_methods);
    lua_pushvalue(L,-1);
    lua_setfield(L, -2, "__index");

    lua_pushcfunction(L, gridfs_gc);
    lua_setfield(L, -2, "__gc");

    lua_pushcfunction(L, gridfs_tostring);
    lua_setfield(L, -2, "__tostring");

    luaL_register(L, LUAMONGO_GRIDFS, gridfs_class_methods);

    return 1;
}
<commit_msg>Adds BSON object compatibility to gridfs_find_file<commit_after>#include <iostream>
#include <client/dbclient.h>
#include <client/gridfs.h>

extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM < 501)
#include <compat-5.1.h>
#endif
};

#include "utils.h"
#include "common.h"

using namespace mongo;

extern void lua_to_bson(lua_State *L, int stackpos, BSONObj &obj);
extern void bson_to_lua(lua_State *L, const BSONObj &obj);
extern int gridfile_create(lua_State *L, GridFile gf);

namespace {
    inline GridFS* userdata_to_gridfs(lua_State* L, int index) {
        void *ud = 0;

        ud = luaL_checkudata(L, index, LUAMONGO_GRIDFS);
        GridFS *gridfs = *((GridFS **)ud);

        return gridfs;
    }
}

/*
 * gridfs, err = mongo.GridFS.New(connection, dbname[, prefix])
 */
static int gridfs_new(lua_State *L) {
    int n = lua_gettop(L);
    int resultcount = 1;

    try {
        void *ud = 0;

        ud = luaL_checkudata(L, 1, LUAMONGO_CONNECTION);
        DBClientConnection *connection = *((DBClientConnection **)ud);

        const char *dbname = lua_tostring(L, 2);

        GridFS **gridfs = (GridFS **)lua_newuserdata(L, sizeof(GridFS *));

        if (n >= 3) {
            const char *prefix = luaL_checkstring(L, 3);

            *gridfs = new GridFS(*connection, dbname, prefix);
        } else {
            *gridfs = new GridFS(*connection, dbname);
        }

        luaL_getmetatable(L, LUAMONGO_GRIDFS);
        lua_setmetatable(L, -2);
    } catch (std::exception &e) {
        lua_pushnil(L);
        lua_pushfstring(L, LUAMONGO_ERR_GRIDFS_FAILED, e.what());
        resultcount = 2;
    }

    return resultcount;
}

/*
 * gridfile, err = gridfs:find_file(filename)
 */
static int gridfs_find_file(lua_State *L) {
    GridFS *gridfs = userdata_to_gridfs(L, 1);
    int resultcount = 1;

    if (!lua_isnoneornil(L, 2)) {
    	try {
    		int type = lua_type(L, 2);
    		if (type == LUA_TTABLE) {
    			BSONObj obj;
    			lua_to_bson(L, 2, obj);
    			GridFile gridfile = gridfs->findFile(obj);
    			resultcount = gridfile_create(L, gridfile);
    		} else {
    			GridFile gridfile = gridfs->findFile(luaL_checkstring(L, 2));
    			resultcount = gridfile_create(L, gridfile);
    		}

    	} catch (std::exception &e) {
    		lua_pushboolean(L, 0);
    		lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_GRIDFS, "find_file", e.what());
    		resultcount = 2;
    	}
    }

    return resultcount;

}

/*
 * cursor = gridfs:list()
 */
static int gridfs_list(lua_State *L) {
    GridFS *gridfs = userdata_to_gridfs(L, 1);

    DBClientCursor **cursor = (DBClientCursor **)lua_newuserdata(L, sizeof(DBClientCursor *));
    auto_ptr<DBClientCursor> autocursor = gridfs->list();
    *cursor = autocursor.get();
    autocursor.release();

    luaL_getmetatable(L, LUAMONGO_CURSOR);
    lua_setmetatable(L, -2);

    return 1;
}

/*
 * ok, err = gridfs:remove_file(filename)
 */
static int gridfs_remove_file(lua_State *L) {
    int resultcount = 1;

    GridFS *gridfs = userdata_to_gridfs(L, 1);

    const char *filename = luaL_checkstring(L, 2);

    try {
        gridfs->removeFile(filename);
        lua_pushboolean(L, 1);
    } catch (std::exception &e) {
        lua_pushboolean(L, 0);
        lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_GRIDFS, "remove_file", e.what());
        resultcount = 2;
    }

    return resultcount;
}

/*
 * gridfile, err = gridfs:store_file(filename[, remote_file], content_type]])
 */
static int gridfs_store_file(lua_State *L) {
    int resultcount = 1;

    GridFS *gridfs = userdata_to_gridfs(L, 1);

    const char *filename = luaL_checkstring(L, 2);
    const char *remote = luaL_optstring(L, 3, "");
    const char *content_type = luaL_optstring(L, 4, "");

    try {
        BSONObj res = gridfs->storeFile(filename, remote, content_type);
        bson_to_lua(L, res);
    } catch (std::exception &e) {
        lua_pushnil(L);
        lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_GRIDFS, "store_file", e.what());
        resultcount = 2;
    }

    return resultcount;
}

/*
 * gridfile, err = gridfs:store_data(data[, remote_file], content_type]])
 * puts the file represented by data into the db
 */
static int gridfs_store_data(lua_State *L) {
    int resultcount = 1;

    GridFS *gridfs = userdata_to_gridfs(L, 1);

    size_t length = 0;
    const char *data = luaL_checklstring(L, 2, &length);
    const char *remote = luaL_optstring(L, 3, "");
    const char *content_type = luaL_optstring(L, 4, "");

    try {
        BSONObj res = gridfs->storeFile(data, length, remote, content_type);
        bson_to_lua(L, res);
    } catch (std::exception &e) {
        lua_pushnil(L);
        lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_GRIDFS, "store_data", e.what());
        resultcount = 2;
    }

    return resultcount;
}

/*
 * __gc
 */
static int gridfs_gc(lua_State *L) {
    GridFS *gridfs = userdata_to_gridfs(L, 1);

    delete gridfs;

    return 0;
}

/*
 * __tostring
 */
static int gridfs_tostring(lua_State *L) {
    GridFS *gridfs = userdata_to_gridfs(L, 1);

    lua_pushfstring(L, "%s: %p", LUAMONGO_GRIDFS, gridfs);

    return 1;
}

int mongo_gridfs_register(lua_State *L) {
    static const luaL_Reg gridfs_methods[] = {
        {"find_file", gridfs_find_file},
        {"list", gridfs_list},
        {"remove_file", gridfs_remove_file},
        {"store_file", gridfs_store_file},
        {"store_data", gridfs_store_data},
        {NULL, NULL}
    };

    static const luaL_Reg gridfs_class_methods[] = {
        {"New", gridfs_new},
        {NULL, NULL}
    };

    luaL_newmetatable(L, LUAMONGO_GRIDFS);
    luaL_register(L, 0, gridfs_methods);
    lua_pushvalue(L,-1);
    lua_setfield(L, -2, "__index");

    lua_pushcfunction(L, gridfs_gc);
    lua_setfield(L, -2, "__gc");

    lua_pushcfunction(L, gridfs_tostring);
    lua_setfield(L, -2, "__tostring");

    luaL_register(L, LUAMONGO_GRIDFS, gridfs_class_methods);

    return 1;
}
<|endoftext|>