<commit_before>/*
* (C) 2006,2011,2012,2014 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*
* Code to run the X.509v3 processing tests described in "Conformance
*  Testing of Relying Party Client Certificate Path Proccessing Logic",
*  which is available on NIST's web site.
*
* Known Failures/Problems:
*  - Policy extensions are not implemented, so we skip tests #34-#53.
*  - Tests #75 and #76 are skipped as they make use of relatively
*    obscure CRL extensions which are not supported.
*/

#include "tests.h"

#if defined(BOTAN_HAS_X509_CERTIFICATES)

#include <botan/x509path.h>
#include <botan/fs.h>

#include <algorithm>
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <map>
#include <cstdlib>

using namespace Botan;

std::map<size_t, Path_Validation_Result::Code> get_expected();

size_t test_nist_x509()
   {
   const std::string root_test_dir = "src/tests/data/nist_x509/";
   const size_t total_tests = 76;

   size_t unexp_failure = 0;
   size_t unexp_success = 0;
   size_t wrong_error = 0;
   size_t skipped = 0;
   size_t ran = 0;

   auto expected_results = get_expected();

   try {

   for(size_t test_no = 1; test_no <= total_tests; ++test_no)
      {
      const std::string test_dir = root_test_dir + "/test" + (test_no <= 9 ? "0" : "") + std::to_string(test_no);
      const std::vector<std::string> all_files = list_all_readable_files_in_or_under(test_dir);

      std::vector<std::string> certs, crls;
      std::string root_cert, to_verify;

      for(size_t k = 0; k != all_files.size(); k++)
         {
         const std::string current = all_files[k];

         if(current.find("int") != std::string::npos &&
            current.find(".crt") != std::string::npos)
            certs.push_back(current);
         else if(current.find("root.crt") != std::string::npos)
            root_cert = current;
         else if(current.find("end.crt") != std::string::npos)
            to_verify = current;
         else if(current.find(".crl") != std::string::npos)
            crls.push_back(current);
         }

      if(expected_results.find(test_no) == expected_results.end())
         {
         skipped++;
         continue;
         }

      ++ran;

      Certificate_Store_In_Memory store;

      store.add_certificate(X509_Certificate(root_cert));

      X509_Certificate end_user(to_verify);

      for(size_t i = 0; i != certs.size(); i++)
         store.add_certificate(X509_Certificate(certs[i]));

      for(size_t i = 0; i != crls.size(); i++)
         {
         DataSource_Stream in(crls[i]);
         X509_CRL crl(in);
         store.add_crl(crl);
         }

      Path_Validation_Restrictions restrictions(true);

      Path_Validation_Result validation_result =
         x509_path_validate(end_user,
                            restrictions,
                            store);

      auto expected = expected_results[test_no];

      Path_Validation_Result::Code result = validation_result.result();

      if(result != expected)
         {
         std::cout << "NIST X.509 test #" << test_no << ": ";

         const std::string result_str = Path_Validation_Result::status_string(result);
         const std::string exp_str = Path_Validation_Result::status_string(expected);

         if(expected == Certificate_Status_Code::VERIFIED)
            {
            std::cout << "unexpected failure: " << result_str << std::endl;
            unexp_failure++;
            }
         else if(result == Certificate_Status_Code::VERIFIED)
            {
            std::cout << "unexpected success, expected " << exp_str << std::endl;
            unexp_success++;
            }
         else
            {
            std::cout << "wrong error, got '" << result_str << "' expected '" << exp_str << "'" << std::endl;
            wrong_error++;
            }
         }
      }
   }
   catch(std::exception& e)
      {
      std::cout << e.what() << std::endl;
      return 1;
      }

   const size_t all_failures = unexp_failure + unexp_success + wrong_error;

   test_report("NIST X.509 path validation", ran, all_failures);

   return all_failures;
   }

/*
  The expected results are essentially the error codes that best coorespond
  to the problem described in the testing documentation.

  There are a few cases where the tests say there should or should not be an
  error, and I disagree. A few of the tests have test results different from
  what they "should" be: these changes are marked as such, and have comments
  explaining the problem at hand.
*/
std::map<size_t, Path_Validation_Result::Code> get_expected()
   {
   std::map<size_t, Path_Validation_Result::Code> expected_results;

   /* OK, not a super great way of doing this... */
   expected_results[1] = Certificate_Status_Code::VERIFIED;
   expected_results[2] = Certificate_Status_Code::SIGNATURE_ERROR;
   expected_results[3] = Certificate_Status_Code::SIGNATURE_ERROR;
   expected_results[4] = Certificate_Status_Code::VERIFIED;
   expected_results[5] = Certificate_Status_Code::CERT_NOT_YET_VALID;
   expected_results[6] = Certificate_Status_Code::CERT_NOT_YET_VALID;
   expected_results[7] = Certificate_Status_Code::VERIFIED;
   expected_results[8] = Certificate_Status_Code::CERT_NOT_YET_VALID;
   expected_results[9] = Certificate_Status_Code::CERT_HAS_EXPIRED;
   expected_results[10] = Certificate_Status_Code::CERT_HAS_EXPIRED;
   expected_results[11] = Certificate_Status_Code::CERT_HAS_EXPIRED;
   expected_results[12] = Certificate_Status_Code::VERIFIED;
   expected_results[13] = Certificate_Status_Code::CERT_ISSUER_NOT_FOUND;

   expected_results[14] = Certificate_Status_Code::CERT_ISSUER_NOT_FOUND;
   expected_results[15] = Certificate_Status_Code::VERIFIED;
   expected_results[16] = Certificate_Status_Code::VERIFIED;
   expected_results[17] = Certificate_Status_Code::VERIFIED;
   expected_results[18] = Certificate_Status_Code::VERIFIED;

   expected_results[19] = Certificate_Status_Code::NO_REVOCATION_DATA;
   expected_results[20] = Certificate_Status_Code::CERT_IS_REVOKED;
   expected_results[21] = Certificate_Status_Code::CERT_IS_REVOKED;

   expected_results[22] = Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER;
   expected_results[23] = Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER;
   expected_results[24] = Certificate_Status_Code::VERIFIED;
   expected_results[25] = Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER;
   expected_results[26] = Certificate_Status_Code::VERIFIED;
   expected_results[27] = Certificate_Status_Code::VERIFIED;
   expected_results[28] = Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER;
   expected_results[29] = Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER;
   expected_results[30] = Certificate_Status_Code::VERIFIED;

   expected_results[31] = Certificate_Status_Code::CA_CERT_NOT_FOR_CRL_ISSUER;
   expected_results[32] = Certificate_Status_Code::CA_CERT_NOT_FOR_CRL_ISSUER;
   expected_results[33] = Certificate_Status_Code::VERIFIED;

   /*
    Policy tests: a little trickier because there are other inputs
    which affect the result.

    In the case of the tests currently in the suite, the default
    method (with acceptable policy being "any-policy" and with no
    explict policy required), will almost always result in a verified
    status. This is not particularly helpful. So, we should do several
    different tests for each test set:

       1) With the user policy as any-policy and no explicit policy
       2) With the user policy as any-policy and an explicit policy required
       3) With the user policy as test-policy-1 (2.16.840.1.101.3.1.48.1) and
          an explict policy required
       4) With the user policy as either test-policy-1 or test-policy-2 and an
          explicit policy required

     This provides reasonably good coverage of the possible outcomes.
   */

   expected_results[34] = Certificate_Status_Code::VERIFIED;
   expected_results[35] = Certificate_Status_Code::VERIFIED;
   expected_results[36] = Certificate_Status_Code::VERIFIED;
   expected_results[37] = Certificate_Status_Code::VERIFIED;
   expected_results[38] = Certificate_Status_Code::VERIFIED;
   expected_results[39] = Certificate_Status_Code::VERIFIED;
   expected_results[40] = Certificate_Status_Code::VERIFIED;
   expected_results[41] = Certificate_Status_Code::VERIFIED;
   expected_results[42] = Certificate_Status_Code::VERIFIED;
   expected_results[43] = Certificate_Status_Code::VERIFIED;
   expected_results[44] = Certificate_Status_Code::VERIFIED;

   //expected_results[45] = Certificate_Status_Code::EXPLICT_POLICY_REQUIRED;
   //expected_results[46] = Certificate_Status_Code::ACCEPT;
   //expected_results[47] = Certificate_Status_Code::EXPLICT_POLICY_REQUIRED;

   expected_results[48] = Certificate_Status_Code::VERIFIED;
   expected_results[49] = Certificate_Status_Code::VERIFIED;
   expected_results[50] = Certificate_Status_Code::VERIFIED;
   expected_results[51] = Certificate_Status_Code::VERIFIED;
   expected_results[52] = Certificate_Status_Code::VERIFIED;
   expected_results[53] = Certificate_Status_Code::VERIFIED;

   expected_results[54] = Certificate_Status_Code::CERT_CHAIN_TOO_LONG;
   expected_results[55] = Certificate_Status_Code::CERT_CHAIN_TOO_LONG;
   expected_results[56] = Certificate_Status_Code::VERIFIED;
   expected_results[57] = Certificate_Status_Code::VERIFIED;
   expected_results[58] = Certificate_Status_Code::CERT_CHAIN_TOO_LONG;
   expected_results[59] = Certificate_Status_Code::CERT_CHAIN_TOO_LONG;
   expected_results[60] = Certificate_Status_Code::CERT_CHAIN_TOO_LONG;
   expected_results[61] = Certificate_Status_Code::CERT_CHAIN_TOO_LONG;
   expected_results[62] = Certificate_Status_Code::VERIFIED;
   expected_results[63] = Certificate_Status_Code::VERIFIED;

   expected_results[64] = Certificate_Status_Code::CRL_BAD_SIGNATURE;

   expected_results[65] = Certificate_Status_Code::NO_REVOCATION_DATA;
   expected_results[66] = Certificate_Status_Code::NO_REVOCATION_DATA;

   expected_results[67] = Certificate_Status_Code::VERIFIED;

   expected_results[68] = Certificate_Status_Code::CERT_IS_REVOKED;
   expected_results[69] = Certificate_Status_Code::CERT_IS_REVOKED;
   expected_results[70] = Certificate_Status_Code::CERT_IS_REVOKED;
   expected_results[71] = Certificate_Status_Code::CERT_IS_REVOKED;
   expected_results[72] = Certificate_Status_Code::CRL_HAS_EXPIRED;
   expected_results[73] = Certificate_Status_Code::CRL_HAS_EXPIRED;
   expected_results[74] = Certificate_Status_Code::VERIFIED;

   /* These tests use weird CRL extensions which aren't supported yet */
   //expected_results[75] = ;
   //expected_results[76] = ;

   return expected_results;
   }

#else

size_t test_nist_x509() { return 0; }

#endif
<commit_msg>Skip the NIST X.509 tests if the FS code is not available. Previously would fail with a very unhelpful message.<commit_after>/*
* (C) 2006,2011,2012,2014 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*
* Code to run the X.509v3 processing tests described in "Conformance
*  Testing of Relying Party Client Certificate Path Proccessing Logic",
*  which is available on NIST's web site.
*
* Known Failures/Problems:
*  - Policy extensions are not implemented, so we skip tests #34-#53.
*  - Tests #75 and #76 are skipped as they make use of relatively
*    obscure CRL extensions which are not supported.
*/

#include "tests.h"

#if defined(BOTAN_HAS_X509_CERTIFICATES)

#include <botan/x509path.h>
#include <botan/fs.h>

#include <algorithm>
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <map>
#include <cstdlib>

using namespace Botan;

std::map<size_t, Path_Validation_Result::Code> get_expected();

size_t test_nist_x509()
   {
   const std::string root_test_dir = "src/tests/data/nist_x509/";
   const size_t total_tests = 76;

   if(list_all_readable_files_in_or_under(root_test_dir).empty())
      {
      std::cout << "No FS access, skipping NIST X.509 validation tests\n";
      test_report("NIST X.509 path validation", 0, 0);
      return;
      }

   size_t unexp_failure = 0;
   size_t unexp_success = 0;
   size_t wrong_error = 0;
   size_t skipped = 0;
   size_t ran = 0;

   auto expected_results = get_expected();

   try {

   for(size_t test_no = 1; test_no <= total_tests; ++test_no)
      {
      const std::string test_dir = root_test_dir + "/test" + (test_no <= 9 ? "0" : "") + std::to_string(test_no);
      const std::vector<std::string> all_files = list_all_readable_files_in_or_under(test_dir);

      std::vector<std::string> certs, crls;
      std::string root_cert, to_verify;

      for(size_t k = 0; k != all_files.size(); k++)
         {
         const std::string current = all_files[k];

         if(current.find("int") != std::string::npos &&
            current.find(".crt") != std::string::npos)
            certs.push_back(current);
         else if(current.find("root.crt") != std::string::npos)
            root_cert = current;
         else if(current.find("end.crt") != std::string::npos)
            to_verify = current;
         else if(current.find(".crl") != std::string::npos)
            crls.push_back(current);
         }

      if(expected_results.find(test_no) == expected_results.end())
         {
         skipped++;
         continue;
         }

      ++ran;

      Certificate_Store_In_Memory store;

      store.add_certificate(X509_Certificate(root_cert));

      X509_Certificate end_user(to_verify);

      for(size_t i = 0; i != certs.size(); i++)
         store.add_certificate(X509_Certificate(certs[i]));

      for(size_t i = 0; i != crls.size(); i++)
         {
         DataSource_Stream in(crls[i]);
         X509_CRL crl(in);
         store.add_crl(crl);
         }

      Path_Validation_Restrictions restrictions(true);

      Path_Validation_Result validation_result =
         x509_path_validate(end_user,
                            restrictions,
                            store);

      auto expected = expected_results[test_no];

      Path_Validation_Result::Code result = validation_result.result();

      if(result != expected)
         {
         std::cout << "NIST X.509 test #" << test_no << ": ";

         const std::string result_str = Path_Validation_Result::status_string(result);
         const std::string exp_str = Path_Validation_Result::status_string(expected);

         if(expected == Certificate_Status_Code::VERIFIED)
            {
            std::cout << "unexpected failure: " << result_str << std::endl;
            unexp_failure++;
            }
         else if(result == Certificate_Status_Code::VERIFIED)
            {
            std::cout << "unexpected success, expected " << exp_str << std::endl;
            unexp_success++;
            }
         else
            {
            std::cout << "wrong error, got '" << result_str << "' expected '" << exp_str << "'" << std::endl;
            wrong_error++;
            }
         }
      }
   }
   catch(std::exception& e)
      {
      std::cout << e.what() << std::endl;
      ++unexp_failures;
      }

   const size_t all_failures = unexp_failure + unexp_success + wrong_error;

   test_report("NIST X.509 path validation", ran, all_failures);

   return all_failures;
   }

/*
  The expected results are essentially the error codes that best coorespond
  to the problem described in the testing documentation.

  There are a few cases where the tests say there should or should not be an
  error, and I disagree. A few of the tests have test results different from
  what they "should" be: these changes are marked as such, and have comments
  explaining the problem at hand.
*/
std::map<size_t, Path_Validation_Result::Code> get_expected()
   {
   std::map<size_t, Path_Validation_Result::Code> expected_results;

   /* OK, not a super great way of doing this... */
   expected_results[1] = Certificate_Status_Code::VERIFIED;
   expected_results[2] = Certificate_Status_Code::SIGNATURE_ERROR;
   expected_results[3] = Certificate_Status_Code::SIGNATURE_ERROR;
   expected_results[4] = Certificate_Status_Code::VERIFIED;
   expected_results[5] = Certificate_Status_Code::CERT_NOT_YET_VALID;
   expected_results[6] = Certificate_Status_Code::CERT_NOT_YET_VALID;
   expected_results[7] = Certificate_Status_Code::VERIFIED;
   expected_results[8] = Certificate_Status_Code::CERT_NOT_YET_VALID;
   expected_results[9] = Certificate_Status_Code::CERT_HAS_EXPIRED;
   expected_results[10] = Certificate_Status_Code::CERT_HAS_EXPIRED;
   expected_results[11] = Certificate_Status_Code::CERT_HAS_EXPIRED;
   expected_results[12] = Certificate_Status_Code::VERIFIED;
   expected_results[13] = Certificate_Status_Code::CERT_ISSUER_NOT_FOUND;

   expected_results[14] = Certificate_Status_Code::CERT_ISSUER_NOT_FOUND;
   expected_results[15] = Certificate_Status_Code::VERIFIED;
   expected_results[16] = Certificate_Status_Code::VERIFIED;
   expected_results[17] = Certificate_Status_Code::VERIFIED;
   expected_results[18] = Certificate_Status_Code::VERIFIED;

   expected_results[19] = Certificate_Status_Code::NO_REVOCATION_DATA;
   expected_results[20] = Certificate_Status_Code::CERT_IS_REVOKED;
   expected_results[21] = Certificate_Status_Code::CERT_IS_REVOKED;

   expected_results[22] = Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER;
   expected_results[23] = Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER;
   expected_results[24] = Certificate_Status_Code::VERIFIED;
   expected_results[25] = Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER;
   expected_results[26] = Certificate_Status_Code::VERIFIED;
   expected_results[27] = Certificate_Status_Code::VERIFIED;
   expected_results[28] = Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER;
   expected_results[29] = Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER;
   expected_results[30] = Certificate_Status_Code::VERIFIED;

   expected_results[31] = Certificate_Status_Code::CA_CERT_NOT_FOR_CRL_ISSUER;
   expected_results[32] = Certificate_Status_Code::CA_CERT_NOT_FOR_CRL_ISSUER;
   expected_results[33] = Certificate_Status_Code::VERIFIED;

   /*
    Policy tests: a little trickier because there are other inputs
    which affect the result.

    In the case of the tests currently in the suite, the default
    method (with acceptable policy being "any-policy" and with no
    explict policy required), will almost always result in a verified
    status. This is not particularly helpful. So, we should do several
    different tests for each test set:

       1) With the user policy as any-policy and no explicit policy
       2) With the user policy as any-policy and an explicit policy required
       3) With the user policy as test-policy-1 (2.16.840.1.101.3.1.48.1) and
          an explict policy required
       4) With the user policy as either test-policy-1 or test-policy-2 and an
          explicit policy required

     This provides reasonably good coverage of the possible outcomes.
   */

   expected_results[34] = Certificate_Status_Code::VERIFIED;
   expected_results[35] = Certificate_Status_Code::VERIFIED;
   expected_results[36] = Certificate_Status_Code::VERIFIED;
   expected_results[37] = Certificate_Status_Code::VERIFIED;
   expected_results[38] = Certificate_Status_Code::VERIFIED;
   expected_results[39] = Certificate_Status_Code::VERIFIED;
   expected_results[40] = Certificate_Status_Code::VERIFIED;
   expected_results[41] = Certificate_Status_Code::VERIFIED;
   expected_results[42] = Certificate_Status_Code::VERIFIED;
   expected_results[43] = Certificate_Status_Code::VERIFIED;
   expected_results[44] = Certificate_Status_Code::VERIFIED;

   //expected_results[45] = Certificate_Status_Code::EXPLICT_POLICY_REQUIRED;
   //expected_results[46] = Certificate_Status_Code::ACCEPT;
   //expected_results[47] = Certificate_Status_Code::EXPLICT_POLICY_REQUIRED;

   expected_results[48] = Certificate_Status_Code::VERIFIED;
   expected_results[49] = Certificate_Status_Code::VERIFIED;
   expected_results[50] = Certificate_Status_Code::VERIFIED;
   expected_results[51] = Certificate_Status_Code::VERIFIED;
   expected_results[52] = Certificate_Status_Code::VERIFIED;
   expected_results[53] = Certificate_Status_Code::VERIFIED;

   expected_results[54] = Certificate_Status_Code::CERT_CHAIN_TOO_LONG;
   expected_results[55] = Certificate_Status_Code::CERT_CHAIN_TOO_LONG;
   expected_results[56] = Certificate_Status_Code::VERIFIED;
   expected_results[57] = Certificate_Status_Code::VERIFIED;
   expected_results[58] = Certificate_Status_Code::CERT_CHAIN_TOO_LONG;
   expected_results[59] = Certificate_Status_Code::CERT_CHAIN_TOO_LONG;
   expected_results[60] = Certificate_Status_Code::CERT_CHAIN_TOO_LONG;
   expected_results[61] = Certificate_Status_Code::CERT_CHAIN_TOO_LONG;
   expected_results[62] = Certificate_Status_Code::VERIFIED;
   expected_results[63] = Certificate_Status_Code::VERIFIED;

   expected_results[64] = Certificate_Status_Code::CRL_BAD_SIGNATURE;

   expected_results[65] = Certificate_Status_Code::NO_REVOCATION_DATA;
   expected_results[66] = Certificate_Status_Code::NO_REVOCATION_DATA;

   expected_results[67] = Certificate_Status_Code::VERIFIED;

   expected_results[68] = Certificate_Status_Code::CERT_IS_REVOKED;
   expected_results[69] = Certificate_Status_Code::CERT_IS_REVOKED;
   expected_results[70] = Certificate_Status_Code::CERT_IS_REVOKED;
   expected_results[71] = Certificate_Status_Code::CERT_IS_REVOKED;
   expected_results[72] = Certificate_Status_Code::CRL_HAS_EXPIRED;
   expected_results[73] = Certificate_Status_Code::CRL_HAS_EXPIRED;
   expected_results[74] = Certificate_Status_Code::VERIFIED;

   /* These tests use weird CRL extensions which aren't supported yet */
   //expected_results[75] = ;
   //expected_results[76] = ;

   return expected_results;
   }

#else

size_t test_nist_x509() { return 0; }

#endif
<|endoftext|>


<commit_before>#include <taichi/visual/gui.h>
#include "../tlang.h"

TLANG_NAMESPACE_BEGIN

auto ray_march = [] {
  CoreState::set_trigger_gdb_when_crash(true);
  int n = 512;
  Program prog(Arch::gpu);
  prog.config.print_ir = true;

  Global(color_r, f32);
  Global(color_g, f32);
  Global(color_b, f32);

  layout([&]() { root.dense(0, n * n * 2).place(color_r, color_g, color_b); });

  auto sdf = [&](Vector p_) {
    float alpha = -0.7f;
    Vector p(3);
    p(0) = (cos(alpha) * p_(0) + sin(alpha) * p_(2) + 1.0_f) % 2.0_f - 1.0_f;
    p(1) = p_(1);
    p(2) = -sin(alpha) * p_(0) + cos(alpha) * p_(2);

    auto dist_sphere = p.norm() - 0.5_f;
    auto dist_walls = min(p(2) + 6.0f, p(1) + 1.0f);
    Vector d(3);
    d(0) = abs(p(0) - 1.0_f) - 0.3_f;
    d(1) = abs(p(1) + 0.5_f) - 1.2_f;
    d(2) = abs(p(2) - 1.0_f) - 0.2_f;
    auto dist_cube = norm(d.map([](const Expr &v) { return max(v, 0.0f); })) +
                     min(max(max(d(0), d(1)), d(2)), 0.0_f);
    return min(dist_sphere, min(dist_walls, dist_cube));
  };

  float32 eps = 1e-5f;
  float32 dist_limit = 1e2;
  int limit = 200;

  auto ray_march = [&](Vector p, Vector dir) {
    auto j = Var(0);
    auto dist = Var(0.0f);

    While(j < limit && sdf(p + dist * dir) > eps && dist < dist_limit, [&] {
      dist += sdf(p + dist * dir);
      j += 1;
    });
    return dist;
  };

  auto normal = [&](Vector p) {
    float d = 1e-3f;
    Vector n(3);
    for (int i = 0; i < 3; i++) {
      auto inc = Var(p), dec = Var(p);
      inc(i) += d;
      dec(i) -= d;
      n(i) = (0.5f / d) * (sdf(inc) - sdf(dec));
    }
    return normalized(n);
  };

  auto out_dir = [&](Vector n) {
    auto u = Var(Vector({1.0f, 0.0f, 0.0f})), v = Var(Vector(3));
    If(abs(n(1)) < 1 - 1e-3f, [&] {
      u = normalized(cross(n, Vector({0.0f, 1.0f, 0.0f})));
    });
    v = cross(n, u);
    auto phi = Var(2 * pi * Rand<float>());
    auto r = Var(Rand<float>());
    auto alpha = Var(0.5_f * pi * (r * r));
    return sin(alpha) * (cos(phi) * u + sin(phi) * v) + cos(alpha) * n;
  };

  auto background = [](Vector dir) {
    return 1.0f * max(dir(1) + dir(0), 0.0f);
  };

  float fov = 0.3;

  auto &main = kernel([&]() {
    Parallelize(8);
    Vectorize(8);
    For(0, n * n * 2, [&](Expr i) {
      auto orig = Var(Vector({0.0f, 0.0f, 12.0f}));

      auto c = Var(Vector(
          {fov * (cast<float>(i / n) / float(n / 2) - 2.0f),
           fov * (cast<float>(i % n) / float(n / 2) - 1.0f), Expr(-1.0f)}));

      c = normalized(c);

      auto color = Var(Vector({1.0f, 1.0f, 1.0f}));
      int depth_limit = 4;
      auto depth = Var(0);

      While(depth < depth_limit, [&] {
        depth += 1;
        auto _dist = Var(ray_march(orig, c));
        If(_dist < dist_limit,
           [&] {
             orig += _dist * c;
             Vector nor;
             nor = normal(orig);
             c = normalized(out_dir(nor));
             orig += 0.01f * c;
             color *= 0.7_f;
           })
            .Else([&] {
              color = color * background(c);
              depth = depth_limit;
            });
      });

      color_r[i] += color(0);
      color_g[i] += color(1);
      color_b[i] += color(2);
    });
  });

  /// TC_P(measure_cpe(func, 1));

  GUI gui("ray march", Vector2i(n * 2, n));

  auto tone_map = [](real x) { return x; };
  constexpr int N = 1;
  for (int frame = 0;; frame++) {
    for (int i = 0; i < N; i++)
      main();
    real scale = 1.0_f / ((frame + 1) * N);
    for (int i = 0; i < n * n * 2; i++) {
      gui.buffer[i / n][i % n] =
          Vector4(tone_map(scale * color_r.val<float>(i)),
                  tone_map(scale * color_g.val<float>(i)),
                  tone_map(scale * color_b.val<float>(i)), 1);
    }
    gui.update();
  }
};
TC_REGISTER_TASK(ray_march);

TLANG_NAMESPACE_END
<commit_msg>simplify ray_march<commit_after>#include <taichi/visual/gui.h>
#include "../tlang.h"

TLANG_NAMESPACE_BEGIN

auto ray_march = [] {
  CoreState::set_trigger_gdb_when_crash(true);
  int n = 512;
  Program prog(Arch::gpu);
  prog.config.print_ir = true;

  Vector buffer(DataType::f32, 3);

  layout([&]() {
    root.dense(0, n * n * 2).place(buffer(0), buffer(1), buffer(2));
  });

  auto sdf = [&](Vector p_) {
    float alpha = -0.7f;
    Vector p(3);
    p(0) = (cos(alpha) * p_(0) + sin(alpha) * p_(2) + 1.0_f) % 2.0_f - 1.0_f;
    p(1) = p_(1);
    p(2) = -sin(alpha) * p_(0) + cos(alpha) * p_(2);

    auto dist_sphere = p.norm() - 0.5_f;
    auto dist_walls = min(p(2) + 6.0f, p(1) + 1.0f);
    Vector d =
        Var(abs(p + Vector({-1.0f, 0.5f, -1.0f})) - Vector({0.3f, 1.2f, 0.2f}));
    auto dist_cube = norm(d.map([](const Expr &v) { return max(v, 0.0f); })) +
                     min(max(max(d(0), d(1)), d(2)), 0.0_f);
    return min(dist_sphere, min(dist_walls, dist_cube));
  };

  float32 eps = 1e-5f;
  float32 dist_limit = 1e2;
  int limit = 200;

  auto ray_march = [&](Vector p, Vector dir) {
    auto j = Var(0);
    auto dist = Var(0.0f);

    While(j < limit && sdf(p + dist * dir) > eps && dist < dist_limit, [&] {
      dist += sdf(p + dist * dir);
      j += 1;
    });
    return dist;
  };

  auto normal = [&](Vector p) {
    float d = 1e-3f;
    Vector n(3);
    for (int i = 0; i < 3; i++) {
      auto inc = Var(p), dec = Var(p);
      inc(i) += d;
      dec(i) -= d;
      n(i) = (0.5f / d) * (sdf(inc) - sdf(dec));
    }
    return normalized(n);
  };

  auto out_dir = [&](Vector n) {
    auto u = Var(Vector({1.0f, 0.0f, 0.0f})), v = Var(Vector(3));
    If(abs(n(1)) < 1 - 1e-3f, [&] {
      u = normalized(cross(n, Vector({0.0f, 1.0f, 0.0f})));
    });
    v = cross(n, u);
    auto phi = Var(2 * pi * Rand<float>());
    auto r = Var(Rand<float>());
    auto alpha = Var(0.5_f * pi * (r * r));
    return sin(alpha) * (cos(phi) * u + sin(phi) * v) + cos(alpha) * n;
  };

  auto background = [](Vector dir) {
    return 1.0f * max(dir(1) + dir(0), 0.0f);
  };

  float fov = 0.3;

  auto &main = kernel([&]() {
    Parallelize(8);
    Vectorize(8);
    For(0, n * n * 2, [&](Expr i) {
      auto orig = Var(Vector({0.0f, 0.0f, 12.0f}));

      auto c = Var(
          Vector({fov * (cast<float>(i / n) / float(n / 2) - 2.0f),
                  fov * (cast<float>(i % n) / float(n / 2) - 1.0f), -1.0f}));

      c = normalized(c);

      auto color = Var(Vector({1.0f, 1.0f, 1.0f}));
      int depth_limit = 4;
      auto depth = Var(0);

      While(depth < depth_limit, [&] {
        depth += 1;
        auto _dist = Var(ray_march(orig, c));
        If(_dist < dist_limit,
           [&] {
             orig += _dist * c;
             Vector nor;
             nor = normal(orig);
             c = normalized(out_dir(nor));
             orig += 0.01f * c;
             color *= 0.7_f;
           })
            .Else([&] {
              color = color * background(c);
              depth = depth_limit;
            });
      });

      buffer[i] += color;
    });
  });

  /// TC_P(measure_cpe(func, 1));

  GUI gui("ray march", Vector2i(n * 2, n));

  auto tone_map = [](real x) { return x; };
  constexpr int N = 1;
  for (int frame = 0;; frame++) {
    for (int i = 0; i < N; i++)
      main();
    real scale = 1.0_f / ((frame + 1) * N);
    for (int i = 0; i < n * n * 2; i++) {
      gui.buffer[i / n][i % n] =
          Vector4(tone_map(scale * buffer(0).val<float>(i)),
                  tone_map(scale * buffer(1).val<float>(i)),
                  tone_map(scale * buffer(2).val<float>(i)), 1);
    }
    gui.update();
  }
};
TC_REGISTER_TASK(ray_march);

TLANG_NAMESPACE_END
<|endoftext|>


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

#include <memory>

#include "ngraph/runtime/aligned_buffer.hpp"
#include "ngraph/runtime/allocator.hpp"
#include "ngraph/util.hpp"

using namespace ngraph;

runtime::AlignedBuffer::AlignedBuffer()
    : m_allocator(nullptr)
    , m_allocated_buffer(nullptr)
    , m_aligned_buffer(nullptr)
    , m_byte_size(0)
{
}

runtime::AlignedBuffer::AlignedBuffer(size_t byte_size,
                                      size_t alignment,
                                      std::shared_ptr<ngraph::runtime::Allocator> allocator)
{
    m_byte_size = byte_size;
    if (m_byte_size > 0)
    {
        size_t allocation_size = m_byte_size + alignment;
        m_allocated_buffer = static_cast<char*>(m_allocator->Malloc(allocation_size, alignment));
        m_aligned_buffer = m_allocated_buffer;
        size_t mod = size_t(m_aligned_buffer) % alignment;

        if (mod != 0)
        {
            m_aligned_buffer += (alignment - mod);
        }
    }
    else
    {
        m_allocated_buffer = nullptr;
        m_aligned_buffer = nullptr;
    }
}

runtime::AlignedBuffer::~AlignedBuffer()
{
    if (m_allocated_buffer != nullptr)
    {
        m_allocator->Free(m_allocated_buffer);
    }
}
<commit_msg>fix unit test<commit_after>//*****************************************************************************
// Copyright 2017-2019 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//*****************************************************************************

#include <memory>

#include "ngraph/runtime/aligned_buffer.hpp"
#include "ngraph/runtime/allocator.hpp"
#include "ngraph/util.hpp"

using namespace ngraph;

runtime::AlignedBuffer::AlignedBuffer()
    : m_allocator(nullptr)
    , m_allocated_buffer(nullptr)
    , m_aligned_buffer(nullptr)
    , m_byte_size(0)
{
}

runtime::AlignedBuffer::AlignedBuffer(size_t byte_size,
                                      size_t alignment,
                                      std::shared_ptr<ngraph::runtime::Allocator> allocator)
{
    m_byte_size = byte_size;
    m_allocator = allocator;
    if (m_byte_size > 0)
    {
        size_t allocation_size = m_byte_size + alignment;
        m_allocated_buffer = static_cast<char*>(m_allocator->Malloc(allocation_size, alignment));
        m_aligned_buffer = m_allocated_buffer;
        size_t mod = size_t(m_aligned_buffer) % alignment;

        if (mod != 0)
        {
            m_aligned_buffer += (alignment - mod);
        }
    }
    else
    {
        m_allocated_buffer = nullptr;
        m_aligned_buffer = nullptr;
    }
}

runtime::AlignedBuffer::~AlignedBuffer()
{
    if (m_allocated_buffer != nullptr)
    {
        m_allocator->Free(m_allocated_buffer);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2018 The Dash Core developers
// Copyright (c) 2014-2018 The Machinecoin Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <governance-validators.h>

#include <base58.h>
#include <utilstrencodings.h>

#include <algorithm>

CProposalValidator::CProposalValidator(const std::string& strDataHexIn)
    : strData(),
      objJSON(UniValue::VOBJ),
      fJSONValid(false),
      strErrorMessages()
{
    if(!strDataHexIn.empty()) {
        SetHexData(strDataHexIn);
    }
}

void CProposalValidator::Clear()
{
    strData = std::string();
    objJSON = UniValue(UniValue::VOBJ);
    fJSONValid = false;
    strErrorMessages = std::string();
}

void CProposalValidator::SetHexData(const std::string& strDataHexIn)
{
    std::vector<unsigned char> v = ParseHex(strDataHexIn);
    strData = std::string(v.begin(), v.end());
    ParseJSONData();
}

bool CProposalValidator::Validate()
{
    if(!ValidateJSON()) {
        strErrorMessages += "JSON parsing error;";
        return false;
    }
    if(!ValidateName()) {
        strErrorMessages += "Invalid name;";
        return false;
    }
    if(!ValidateStartEndEpoch()) {
        strErrorMessages += "Invalid start:end range;";
        return false;
    }
    if(!ValidatePaymentAmount()) {
        strErrorMessages += "Invalid payment amount;";
        return false;
    }
    if(!ValidatePaymentAddress()) {
        strErrorMessages += "Invalid payment address;";
        return false;
    }
    if(!ValidateURL()) {
        strErrorMessages += "Invalid URL;";
        return false;
    }
    return true;
}

bool CProposalValidator::ValidateJSON()
{
    return fJSONValid;
}

bool CProposalValidator::ValidateName()
{
    std::string strName;
    if(!GetDataValue("name", strName)) {
        strErrorMessages += "name field not found;";
        return false;
    }

    if(strName.size() > 40) {
        strErrorMessages += "name exceeds 40 characters;";
        return false;
    }

    std::string strNameStripped = StripWhitespace(strName);

    if(strNameStripped.empty()) {
        strErrorMessages += "name is empty;";
        return false;
    }

    static const std::string strAllowedChars = "-_abcdefghijklmnopqrstuvwxyz0123456789";

    std::transform(strName.begin(), strName.end(), strName.begin(), ::tolower);

    if(strName.find_first_not_of(strAllowedChars) != std::string::npos) {
        strErrorMessages += "name contains invalid characters;";
        return false;
    }

    return true;
}

bool CProposalValidator::ValidateStartEndEpoch()
{
    int64_t nStartEpoch = 0;
    int64_t nEndEpoch = 0;

    if(!GetDataValue("start_epoch", nStartEpoch)) {
        strErrorMessages += "start_epoch field not found;";
        return false;
    }

    if(!GetDataValue("end_epoch", nEndEpoch)) {
        strErrorMessages += "end_epoch field not found;";
        return false;
    }

    if(nEndEpoch <= nStartEpoch) {
        strErrorMessages += "end_epoch <= start_epoch;";
        return false;
    }

    return true;
}

bool CProposalValidator::ValidatePaymentAmount()
{
    double dValue = 0.0;

    if(!GetDataValue("payment_amount", dValue)) {
        strErrorMessages += "payment_amount field not found;";
        return false;
    }

    if(dValue <= 0.0) {
        strErrorMessages += "payment_amount is negative;";
        return false;
    }

    // TODO: Should check for an amount which exceeds the budget but this is
    // currently difficult because start and end epochs are defined in terms of
    // clock time instead of block height.

    return true;
}

bool CProposalValidator::ValidatePaymentAddress()
{
    std::string strPaymentAddress;

    if(!GetDataValue("payment_address", strPaymentAddress)) {
        strErrorMessages += "payment_address field not found;";
        return false;
    }

    if(IsValidDestinationString(strPaymentAddress)) {
        strErrorMessages += "payment_address is invalid;";
        return false;
    }

    return true;
}

bool CProposalValidator::ValidateURL()
{
    std::string strURL;
    if(!GetDataValue("url", strURL)) {
        strErrorMessages += "url field not found;";
        return false;
    }

    std::string strURLStripped = StripWhitespace(strURL);

    if(strURLStripped.size() < 4U) {
        strErrorMessages += "url too short;";
        return false;
    }

    if(!CheckURL(strURL)) {
        strErrorMessages += "url invalid;";
        return false;
    }

    return true;
}

void CProposalValidator::ParseJSONData()
{
    fJSONValid = false;

    if(strData.empty()) {
        return;
    }

    try {
        UniValue obj(UniValue::VOBJ);
        obj.read(strData);
        std::vector<UniValue> arr1 = obj.getValues();
        std::vector<UniValue> arr2 = arr1.at(0).getValues();
        objJSON = arr2.at(1);
        fJSONValid = true;
    }
    catch(std::exception& e) {
        strErrorMessages += std::string(e.what()) + std::string(";");
    }
    catch(...) {
        strErrorMessages += "Unknown exception;";
    }
}

bool CProposalValidator::GetDataValue(const std::string& strKey, std::string& strValue)
{
    bool fOK = false;
    try  {
        strValue = objJSON[strKey].get_str();
        fOK = true;
    }
    catch(std::exception& e) {
        strErrorMessages += std::string(e.what()) + std::string(";");
    }
    catch(...) {
        strErrorMessages += "Unknown exception;";
    }
    return fOK;
}

bool CProposalValidator::GetDataValue(const std::string& strKey, int64_t& nValue)
{
    bool fOK = false;
    try  {
        const UniValue uValue = objJSON[strKey];
        switch(uValue.getType()) {
        case UniValue::VNUM:
            nValue = uValue.get_int64();
            fOK = true;
            break;
        default:
            break;
        }
    }
    catch(std::exception& e) {
        strErrorMessages += std::string(e.what()) + std::string(";");
    }
    catch(...) {
        strErrorMessages += "Unknown exception;";
    }
    return fOK;
}

bool CProposalValidator::GetDataValue(const std::string& strKey, double& dValue)
{
    bool fOK = false;
    try  {
        const UniValue uValue = objJSON[strKey];
        switch(uValue.getType()) {
        case UniValue::VNUM:
            dValue = uValue.get_real();
            fOK = true;
            break;
        default:
            break;
        }
    }
    catch(std::exception& e) {
        strErrorMessages += std::string(e.what()) + std::string(";");
    }
    catch(...) {
        strErrorMessages += "Unknown exception;";
    }
    return fOK;
}

std::string CProposalValidator::StripWhitespace(const std::string& strIn)
{
    static const std::string strWhitespace = " \f\n\r\t\v";

    std::string::size_type nStart = strIn.find_first_not_of(strWhitespace);
    std::string::size_type nEnd = strIn.find_last_not_of(strWhitespace);

    if((nStart == std::string::npos) || (nEnd == std::string::npos)) {
        return std::string();
    }

    return strIn.substr(nStart, nEnd - nStart + 1);
}

/*
  The purpose of this function is to replicate the behavior of the
  Python urlparse function used by sentinel (urlparse.py).  This function
  should return false whenever urlparse raises an exception and true
  otherwise.
 */
bool CProposalValidator::CheckURL(const std::string& strURLIn)
{
    std::string strRest(strURLIn);
    std::string::size_type nPos = strRest.find(':');

    if(nPos != std::string::npos) {
        //std::string strSchema = strRest.substr(0,nPos);

        if(nPos < strRest.size()) {
            strRest = strRest.substr(nPos + 1);
        }
        else {
            strRest = "";
        }
    }

    // Process netloc
    if((strRest.size() > 2) && (strRest.substr(0,2) == "//")) {
        static const std::string strNetlocDelimiters = "/?#";

        strRest = strRest.substr(2);

        std::string::size_type nPos2 = strRest.find_first_of(strNetlocDelimiters);

        std::string strNetloc = strRest.substr(0,nPos2);

        if((strNetloc.find('[') != std::string::npos) && (strNetloc.find(']') == std::string::npos)) {
            return false;
        }

        if((strNetloc.find(']') != std::string::npos) && (strNetloc.find('[') == std::string::npos)) {
            return false;
        }
    }

    return true;
}
<commit_msg>no message<commit_after>// Copyright (c) 2014-2018 The Dash Core developers
// Copyright (c) 2014-2018 The Machinecoin Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <governance-validators.h>

#include <base58.h>
#include <utilstrencodings.h>

#include <algorithm>

CProposalValidator::CProposalValidator(const std::string& strDataHexIn)
    : strData(),
      objJSON(UniValue::VOBJ),
      fJSONValid(false),
      strErrorMessages()
{
    if(!strDataHexIn.empty()) {
        SetHexData(strDataHexIn);
    }
}

void CProposalValidator::Clear()
{
    strData = std::string();
    objJSON = UniValue(UniValue::VOBJ);
    fJSONValid = false;
    strErrorMessages = std::string();
}

void CProposalValidator::SetHexData(const std::string& strDataHexIn)
{
    std::vector<unsigned char> v = ParseHex(strDataHexIn);
    strData = std::string(v.begin(), v.end());
    ParseJSONData();
}

bool CProposalValidator::Validate()
{
    if(!ValidateJSON()) {
        strErrorMessages += "JSON parsing error;";
        return false;
    }
    if(!ValidateName()) {
        strErrorMessages += "Invalid name;";
        return false;
    }
    if(!ValidateStartEndEpoch()) {
        strErrorMessages += "Invalid start:end range;";
        return false;
    }
    if(!ValidatePaymentAmount()) {
        strErrorMessages += "Invalid payment amount;";
        return false;
    }
    if(!ValidatePaymentAddress()) {
        strErrorMessages += "Invalid payment address;";
        return false;
    }
    if(!ValidateURL()) {
        strErrorMessages += "Invalid URL;";
        return false;
    }
    return true;
}

bool CProposalValidator::ValidateJSON()
{
    return fJSONValid;
}

bool CProposalValidator::ValidateName()
{
    std::string strName;
    if(!GetDataValue("name", strName)) {
        strErrorMessages += "name field not found;";
        return false;
    }

    if(strName.size() > 40) {
        strErrorMessages += "name exceeds 40 characters;";
        return false;
    }

    std::string strNameStripped = StripWhitespace(strName);

    if(strNameStripped.empty()) {
        strErrorMessages += "name is empty;";
        return false;
    }

    static const std::string strAllowedChars = "-_abcdefghijklmnopqrstuvwxyz0123456789";

    std::transform(strName.begin(), strName.end(), strName.begin(), ::tolower);

    if(strName.find_first_not_of(strAllowedChars) != std::string::npos) {
        strErrorMessages += "name contains invalid characters;";
        return false;
    }

    return true;
}

bool CProposalValidator::ValidateStartEndEpoch()
{
    int64_t nStartEpoch = 0;
    int64_t nEndEpoch = 0;

    if(!GetDataValue("start_epoch", nStartEpoch)) {
        strErrorMessages += "start_epoch field not found;";
        return false;
    }

    if(!GetDataValue("end_epoch", nEndEpoch)) {
        strErrorMessages += "end_epoch field not found;";
        return false;
    }

    if(nEndEpoch <= nStartEpoch) {
        strErrorMessages += "end_epoch <= start_epoch;";
        return false;
    }

    return true;
}

bool CProposalValidator::ValidatePaymentAmount()
{
    double dValue = 0.0;

    if(!GetDataValue("payment_amount", dValue)) {
        strErrorMessages += "payment_amount field not found;";
        return false;
    }

    if(dValue <= 0.0) {
        strErrorMessages += "payment_amount is negative;";
        return false;
    }

    // TODO: Should check for an amount which exceeds the budget but this is
    // currently difficult because start and end epochs are defined in terms of
    // clock time instead of block height.

    return true;
}

bool CProposalValidator::ValidatePaymentAddress()
{
    std::string strPaymentAddress;

    if(!GetDataValue("payment_address", strPaymentAddress)) {
        strErrorMessages += "payment_address field not found;";
        return false;
    }

    CTxDestination destination = DecodeDestination(strPaymentAddress);
    if (!IsValidDestination(destination)) {
        strErrorMessages += "payment_address is invalid;";
        return false;
    }

    return true;
}

bool CProposalValidator::ValidateURL()
{
    std::string strURL;
    if(!GetDataValue("url", strURL)) {
        strErrorMessages += "url field not found;";
        return false;
    }

    std::string strURLStripped = StripWhitespace(strURL);

    if(strURLStripped.size() < 4U) {
        strErrorMessages += "url too short;";
        return false;
    }

    if(!CheckURL(strURL)) {
        strErrorMessages += "url invalid;";
        return false;
    }

    return true;
}

void CProposalValidator::ParseJSONData()
{
    fJSONValid = false;

    if(strData.empty()) {
        return;
    }

    try {
        UniValue obj(UniValue::VOBJ);
        obj.read(strData);
        std::vector<UniValue> arr1 = obj.getValues();
        std::vector<UniValue> arr2 = arr1.at(0).getValues();
        objJSON = arr2.at(1);
        fJSONValid = true;
    }
    catch(std::exception& e) {
        strErrorMessages += std::string(e.what()) + std::string(";");
    }
    catch(...) {
        strErrorMessages += "Unknown exception;";
    }
}

bool CProposalValidator::GetDataValue(const std::string& strKey, std::string& strValue)
{
    bool fOK = false;
    try  {
        strValue = objJSON[strKey].get_str();
        fOK = true;
    }
    catch(std::exception& e) {
        strErrorMessages += std::string(e.what()) + std::string(";");
    }
    catch(...) {
        strErrorMessages += "Unknown exception;";
    }
    return fOK;
}

bool CProposalValidator::GetDataValue(const std::string& strKey, int64_t& nValue)
{
    bool fOK = false;
    try  {
        const UniValue uValue = objJSON[strKey];
        switch(uValue.getType()) {
        case UniValue::VNUM:
            nValue = uValue.get_int64();
            fOK = true;
            break;
        default:
            break;
        }
    }
    catch(std::exception& e) {
        strErrorMessages += std::string(e.what()) + std::string(";");
    }
    catch(...) {
        strErrorMessages += "Unknown exception;";
    }
    return fOK;
}

bool CProposalValidator::GetDataValue(const std::string& strKey, double& dValue)
{
    bool fOK = false;
    try  {
        const UniValue uValue = objJSON[strKey];
        switch(uValue.getType()) {
        case UniValue::VNUM:
            dValue = uValue.get_real();
            fOK = true;
            break;
        default:
            break;
        }
    }
    catch(std::exception& e) {
        strErrorMessages += std::string(e.what()) + std::string(";");
    }
    catch(...) {
        strErrorMessages += "Unknown exception;";
    }
    return fOK;
}

std::string CProposalValidator::StripWhitespace(const std::string& strIn)
{
    static const std::string strWhitespace = " \f\n\r\t\v";

    std::string::size_type nStart = strIn.find_first_not_of(strWhitespace);
    std::string::size_type nEnd = strIn.find_last_not_of(strWhitespace);

    if((nStart == std::string::npos) || (nEnd == std::string::npos)) {
        return std::string();
    }

    return strIn.substr(nStart, nEnd - nStart + 1);
}

/*
  The purpose of this function is to replicate the behavior of the
  Python urlparse function used by sentinel (urlparse.py).  This function
  should return false whenever urlparse raises an exception and true
  otherwise.
 */
bool CProposalValidator::CheckURL(const std::string& strURLIn)
{
    std::string strRest(strURLIn);
    std::string::size_type nPos = strRest.find(':');

    if(nPos != std::string::npos) {
        //std::string strSchema = strRest.substr(0,nPos);

        if(nPos < strRest.size()) {
            strRest = strRest.substr(nPos + 1);
        }
        else {
            strRest = "";
        }
    }

    // Process netloc
    if((strRest.size() > 2) && (strRest.substr(0,2) == "//")) {
        static const std::string strNetlocDelimiters = "/?#";

        strRest = strRest.substr(2);

        std::string::size_type nPos2 = strRest.find_first_of(strNetlocDelimiters);

        std::string strNetloc = strRest.substr(0,nPos2);

        if((strNetloc.find('[') != std::string::npos) && (strNetloc.find(']') == std::string::npos)) {
            return false;
        }

        if((strNetloc.find(']') != std::string::npos) && (strNetloc.find('[') == std::string::npos)) {
            return false;
        }
    }

    return true;
}
<|endoftext|>


<commit_before>#include "Chan.h"
#include "znc.h"
#include "User.h"
#include "Utils.h"

void CChan::Reset() {
	m_bWhoDone = false;
	m_bIsOn = false;
	m_uOpCount = 0;
	m_uVoiceCount =	0;
	m_uModes = 0;
	m_uLimit = 0;
	m_uClientRequests = 0;
	ClearNicks();
}

void CChan::Joined() {
}

void CChan::Cycle() const {
	m_pUser->PutIRC("PART " + GetName() + "\r\nJOIN " + GetName() + " " + GetKey());
}

string CChan::GetModeString() const {
	string sRet;

	if (m_uModes & Secret) { sRet += "s"; }
	if (m_uModes & Private) { sRet += "p"; }
	if (m_uModes & OpTopic) { sRet += "t"; }
	if (m_uModes & InviteOnly) { sRet += "i"; }
	if (m_uModes & NoMessages) { sRet += "n"; }
	if (m_uModes & Moderated) { sRet += "m"; }
	if (m_uLimit) { sRet += "l"; }
	if (m_uModes & Key) { sRet += "k"; }

	return (sRet.empty()) ? sRet : ("+" + sRet);
}

void CChan::SetModes(const string& sModes) {
	m_uModes = 0;
	m_uLimit = 0;
	m_sKey = "";
	ModeChange(sModes);
}

void CChan::IncClientRequests() {
	m_uClientRequests++;
}

bool CChan::DecClientRequests() {
	if (!m_uClientRequests) {
		return false;
	}

	m_uClientRequests--;
	return true;
}

bool CChan::Who() {
	if (m_bWhoDone) {
		return false;
	}

	m_pUser->PutIRC("WHO " + GetName());
	return true;
}

void CChan::OnWho(const string& sNick, const string& sIdent, const string& sHost) {
	CNick* pNick = FindNick(sNick);

	if (pNick) {
		pNick->SetIdent(sIdent);
		pNick->SetHost(sHost);
	}
}

void CChan::ModeChange(const string& sModes, const string& sOpNick) {
	string sModeArg = CUtils::Token(sModes, 0);
	string sArgs = CUtils::Token(sModes, 1, true);
	bool bAdd = true;

#ifdef _MODULES
	CNick* pNick = FindNick(sOpNick);
	if (pNick) {
		m_pUser->GetModules().OnRawMode(*pNick, *this, sModeArg, sArgs);
	}
#endif

	for (unsigned int a = 0; a < sModeArg.size(); a++) {
		switch (sModeArg[a]) {
			case '+': bAdd = true; break;
			case '-': bAdd = false; break;
			case 's': if (bAdd) { m_uModes |= Secret; } else { m_uModes &= ~Secret; } break;
			case 'p': if (bAdd) { m_uModes |= Private; } else { m_uModes &= ~Private; }  break;
			case 'm': if (bAdd) { m_uModes |= Moderated; } else { m_uModes &= ~Moderated; }  break;
			case 'i': if (bAdd) { m_uModes |= InviteOnly; } else { m_uModes &= ~InviteOnly; }  break;
			case 'n': if (bAdd) { m_uModes |= NoMessages; } else { m_uModes &= ~NoMessages; }  break;
			case 't': if (bAdd) { m_uModes |= OpTopic; } else { m_uModes &= ~OpTopic; }  break;
			case 'l': if (bAdd) { m_uLimit = strtoul(GetModeArg(sArgs).c_str(), NULL, 10); } else { m_uLimit = 0; }  break;
			case 'k': if (bAdd) { m_uModes |= Key; SetKey(GetModeArg(sArgs)); } else { m_uModes &= ~Key; GetModeArg(sArgs); }  break;
			case 'o': OnOp(sOpNick, GetModeArg(sArgs), bAdd); break;
			case 'v': OnVoice(sOpNick, GetModeArg(sArgs), bAdd); break;
			case 'b': // Don't do anything with bans yet
			case 'e': // Don't do anything with excepts yet
			default: GetModeArg(sArgs); // Pop off an arg, assume new modes will have an argument
		}
	}
}

string CChan::GetModeArg(string& sArgs) const {
	string sRet = sArgs.substr(0, sArgs.find(' '));
	sArgs = (sRet.size() < sArgs.size()) ? sArgs.substr(sRet.size() +1) : "";
	return sRet;
}

void CChan::ClearNicks() {
	for (map<string,CNick*>::iterator a = m_msNicks.begin(); a != m_msNicks.end(); a++) {
		delete a->second;
	}

	m_msNicks.clear();
}

int CChan::AddNicks(const string& sNicks) {
	if (IsOn()) {
		return 0;
	}

	int iRet = 0;
	string sCurNick;

	for (unsigned int a = 0; a < sNicks.size(); a++) {
		switch (sNicks[a]) {
			case ' ':
				if (AddNick(sCurNick)) {
					iRet++;
				}

				sCurNick = "";

				break;
			default:
				sCurNick += sNicks[a];
				break;
		}
	}

	if (!sCurNick.empty()) {
		if (AddNick(sCurNick)) {
			iRet++;
		}
	}

	return iRet;
}

bool CChan::AddNick(const string& sNick) {
	const char* p = sNick.c_str();
	bool bIsOp = false;
	bool bIsVoice = false;

	switch (*p) {
		case '\0':
			return false;
		case '@':
			bIsOp = true;
		case '+':
			if (!*++p) {
				return false;
			}

			bIsVoice = !bIsOp;
	}

	CNick* pNick = FindNick(p);
	if (!pNick) {
		pNick = new CNick(p);
	}

	if ((bIsOp) && (!pNick->IsOp())) {
		IncOpCount();
		pNick->SetOp(true);
	} else if ((bIsVoice) && (!pNick->IsVoice())) {
		IncVoiceCount();
		pNick->SetVoice(true);
	}

	m_msNicks[pNick->GetNick()] = pNick;

	return true;
}

bool CChan::RemNick(const string& sNick) {
	map<string,CNick*>::iterator it = m_msNicks.find(sNick);
	if (it == m_msNicks.end()) {
		return false;
	}

	if (it->second->IsOp()) {
		DecOpCount();
	}

	if (it->second->IsVoice()) {
		DecVoiceCount();
	}

	delete it->second;
	m_msNicks.erase(it);

	if ((m_msNicks.size() == 1) && (!m_msNicks.begin()->second->IsOp())) {
		Cycle();
	}

	return true;
}

bool CChan::ChangeNick(const string& sOldNick, const string& sNewNick) {
	map<string,CNick*>::iterator it = m_msNicks.find(sOldNick);

	if (it == m_msNicks.end()) {
		return false;
	}

	// Rename this nick
	it->second->SetNick(sNewNick);

	// Insert a new element into the map then erase the old one, do this to change the key
	m_msNicks[sNewNick] = it->second;
	m_msNicks.erase(it);

	return true;
}

void CChan::OnOp(const string& sOpNick, const string& sNick, bool bOpped) {
	CNick* pNick = FindNick(sNick);

	if (pNick) {
		bool bNoChange = (pNick->IsOp() == bOpped);
#ifdef _MODULES
	CNick* pOpNick = FindNick(sOpNick);

	if (pOpNick) {
		if (bOpped) {
			m_pUser->GetModules().OnOp(*pOpNick, *pNick, *this, bNoChange);
		} else {
			m_pUser->GetModules().OnDeop(*pOpNick, *pNick, *this, bNoChange);
		}
	}
#endif

		if (bNoChange) {
			// If no change, return
			return;
		}

		pNick->SetOp(bOpped);
		(bOpped) ? IncOpCount() : DecOpCount();
	}
}

void CChan::OnVoice(const string& sOpNick, const string& sNick, bool bVoiced) {
	CNick* pNick = FindNick(sNick);

	if (pNick) {
		bool bNoChange = (pNick->IsVoice() == bVoiced);

#ifdef _MODULES
		CNick* pOpNick = FindNick(sOpNick);

		if (pOpNick) {
			if (bVoiced) {
				m_pUser->GetModules().OnVoice(*pOpNick, *pNick, *this, bNoChange);
			} else {
				m_pUser->GetModules().OnDevoice(*pOpNick, *pNick, *this, bNoChange);
			}
		}
#endif

		if (bNoChange) {
			// If no change, return
			return;
		}

		pNick->SetVoice(bVoiced);
		(bVoiced) ? IncVoiceCount() : DecVoiceCount();
	}
}

CNick* CChan::FindNick(const string& sNick) const {
	map<string,CNick*>::const_iterator it = m_msNicks.find(sNick);
	return (it != m_msNicks.end()) ? it->second : NULL;
}

int CChan::AddBuffer(const string& sLine) {
	// Todo: revisit the buffering
	if (!m_uBufferCount) {
		return 0;
	}

	if (m_vsBuffer.size() >= m_uBufferCount) {
		m_vsBuffer.erase(m_vsBuffer.begin());
	}

	m_vsBuffer.push_back(sLine);
	return m_vsBuffer.size();
}

void CChan::ClearBuffer() {
	m_vsBuffer.clear();
}

<commit_msg>Make sure the last nick in the chan is us before we auto-cycle<commit_after>#include "Chan.h"
#include "znc.h"
#include "User.h"
#include "Utils.h"

void CChan::Reset() {
	m_bWhoDone = false;
	m_bIsOn = false;
	m_uOpCount = 0;
	m_uVoiceCount =	0;
	m_uModes = 0;
	m_uLimit = 0;
	m_uClientRequests = 0;
	ClearNicks();
}

void CChan::Joined() {
}

void CChan::Cycle() const {
	m_pUser->PutIRC("PART " + GetName() + "\r\nJOIN " + GetName() + " " + GetKey());
}

string CChan::GetModeString() const {
	string sRet;

	if (m_uModes & Secret) { sRet += "s"; }
	if (m_uModes & Private) { sRet += "p"; }
	if (m_uModes & OpTopic) { sRet += "t"; }
	if (m_uModes & InviteOnly) { sRet += "i"; }
	if (m_uModes & NoMessages) { sRet += "n"; }
	if (m_uModes & Moderated) { sRet += "m"; }
	if (m_uLimit) { sRet += "l"; }
	if (m_uModes & Key) { sRet += "k"; }

	return (sRet.empty()) ? sRet : ("+" + sRet);
}

void CChan::SetModes(const string& sModes) {
	m_uModes = 0;
	m_uLimit = 0;
	m_sKey = "";
	ModeChange(sModes);
}

void CChan::IncClientRequests() {
	m_uClientRequests++;
}

bool CChan::DecClientRequests() {
	if (!m_uClientRequests) {
		return false;
	}

	m_uClientRequests--;
	return true;
}

bool CChan::Who() {
	if (m_bWhoDone) {
		return false;
	}

	m_pUser->PutIRC("WHO " + GetName());
	return true;
}

void CChan::OnWho(const string& sNick, const string& sIdent, const string& sHost) {
	CNick* pNick = FindNick(sNick);

	if (pNick) {
		pNick->SetIdent(sIdent);
		pNick->SetHost(sHost);
	}
}

void CChan::ModeChange(const string& sModes, const string& sOpNick) {
	string sModeArg = CUtils::Token(sModes, 0);
	string sArgs = CUtils::Token(sModes, 1, true);
	bool bAdd = true;

#ifdef _MODULES
	CNick* pNick = FindNick(sOpNick);
	if (pNick) {
		m_pUser->GetModules().OnRawMode(*pNick, *this, sModeArg, sArgs);
	}
#endif

	for (unsigned int a = 0; a < sModeArg.size(); a++) {
		switch (sModeArg[a]) {
			case '+': bAdd = true; break;
			case '-': bAdd = false; break;
			case 's': if (bAdd) { m_uModes |= Secret; } else { m_uModes &= ~Secret; } break;
			case 'p': if (bAdd) { m_uModes |= Private; } else { m_uModes &= ~Private; }  break;
			case 'm': if (bAdd) { m_uModes |= Moderated; } else { m_uModes &= ~Moderated; }  break;
			case 'i': if (bAdd) { m_uModes |= InviteOnly; } else { m_uModes &= ~InviteOnly; }  break;
			case 'n': if (bAdd) { m_uModes |= NoMessages; } else { m_uModes &= ~NoMessages; }  break;
			case 't': if (bAdd) { m_uModes |= OpTopic; } else { m_uModes &= ~OpTopic; }  break;
			case 'l': if (bAdd) { m_uLimit = strtoul(GetModeArg(sArgs).c_str(), NULL, 10); } else { m_uLimit = 0; }  break;
			case 'k': if (bAdd) { m_uModes |= Key; SetKey(GetModeArg(sArgs)); } else { m_uModes &= ~Key; GetModeArg(sArgs); }  break;
			case 'o': OnOp(sOpNick, GetModeArg(sArgs), bAdd); break;
			case 'v': OnVoice(sOpNick, GetModeArg(sArgs), bAdd); break;
			case 'b': // Don't do anything with bans yet
			case 'e': // Don't do anything with excepts yet
			default: GetModeArg(sArgs); // Pop off an arg, assume new modes will have an argument
		}
	}
}

string CChan::GetModeArg(string& sArgs) const {
	string sRet = sArgs.substr(0, sArgs.find(' '));
	sArgs = (sRet.size() < sArgs.size()) ? sArgs.substr(sRet.size() +1) : "";
	return sRet;
}

void CChan::ClearNicks() {
	for (map<string,CNick*>::iterator a = m_msNicks.begin(); a != m_msNicks.end(); a++) {
		delete a->second;
	}

	m_msNicks.clear();
}

int CChan::AddNicks(const string& sNicks) {
	if (IsOn()) {
		return 0;
	}

	int iRet = 0;
	string sCurNick;

	for (unsigned int a = 0; a < sNicks.size(); a++) {
		switch (sNicks[a]) {
			case ' ':
				if (AddNick(sCurNick)) {
					iRet++;
				}

				sCurNick = "";

				break;
			default:
				sCurNick += sNicks[a];
				break;
		}
	}

	if (!sCurNick.empty()) {
		if (AddNick(sCurNick)) {
			iRet++;
		}
	}

	return iRet;
}

bool CChan::AddNick(const string& sNick) {
	const char* p = sNick.c_str();
	bool bIsOp = false;
	bool bIsVoice = false;

	switch (*p) {
		case '\0':
			return false;
		case '@':
			bIsOp = true;
		case '+':
			if (!*++p) {
				return false;
			}

			bIsVoice = !bIsOp;
	}

	CNick* pNick = FindNick(p);
	if (!pNick) {
		pNick = new CNick(p);
	}

	if ((bIsOp) && (!pNick->IsOp())) {
		IncOpCount();
		pNick->SetOp(true);
	} else if ((bIsVoice) && (!pNick->IsVoice())) {
		IncVoiceCount();
		pNick->SetVoice(true);
	}

	m_msNicks[pNick->GetNick()] = pNick;

	return true;
}

bool CChan::RemNick(const string& sNick) {
	map<string,CNick*>::iterator it = m_msNicks.find(sNick);
	if (it == m_msNicks.end()) {
		return false;
	}

	if (it->second->IsOp()) {
		DecOpCount();
	}

	if (it->second->IsVoice()) {
		DecVoiceCount();
	}

	delete it->second;
	m_msNicks.erase(it);
	CNick* pNick = m_msNicks.begin()->second;

	if ((m_msNicks.size() == 1) && (!pNick->IsOp()) && (strcasecmp(pNick->GetNick().c_str(), m_pUser->GetCurNick().c_str()) == 0)) {
		Cycle();
	}

	return true;
}

bool CChan::ChangeNick(const string& sOldNick, const string& sNewNick) {
	map<string,CNick*>::iterator it = m_msNicks.find(sOldNick);

	if (it == m_msNicks.end()) {
		return false;
	}

	// Rename this nick
	it->second->SetNick(sNewNick);

	// Insert a new element into the map then erase the old one, do this to change the key
	m_msNicks[sNewNick] = it->second;
	m_msNicks.erase(it);

	return true;
}

void CChan::OnOp(const string& sOpNick, const string& sNick, bool bOpped) {
	CNick* pNick = FindNick(sNick);

	if (pNick) {
		bool bNoChange = (pNick->IsOp() == bOpped);
#ifdef _MODULES
	CNick* pOpNick = FindNick(sOpNick);

	if (pOpNick) {
		if (bOpped) {
			m_pUser->GetModules().OnOp(*pOpNick, *pNick, *this, bNoChange);
		} else {
			m_pUser->GetModules().OnDeop(*pOpNick, *pNick, *this, bNoChange);
		}
	}
#endif

		if (bNoChange) {
			// If no change, return
			return;
		}

		pNick->SetOp(bOpped);
		(bOpped) ? IncOpCount() : DecOpCount();
	}
}

void CChan::OnVoice(const string& sOpNick, const string& sNick, bool bVoiced) {
	CNick* pNick = FindNick(sNick);

	if (pNick) {
		bool bNoChange = (pNick->IsVoice() == bVoiced);

#ifdef _MODULES
		CNick* pOpNick = FindNick(sOpNick);

		if (pOpNick) {
			if (bVoiced) {
				m_pUser->GetModules().OnVoice(*pOpNick, *pNick, *this, bNoChange);
			} else {
				m_pUser->GetModules().OnDevoice(*pOpNick, *pNick, *this, bNoChange);
			}
		}
#endif

		if (bNoChange) {
			// If no change, return
			return;
		}

		pNick->SetVoice(bVoiced);
		(bVoiced) ? IncVoiceCount() : DecVoiceCount();
	}
}

CNick* CChan::FindNick(const string& sNick) const {
	map<string,CNick*>::const_iterator it = m_msNicks.find(sNick);
	return (it != m_msNicks.end()) ? it->second : NULL;
}

int CChan::AddBuffer(const string& sLine) {
	// Todo: revisit the buffering
	if (!m_uBufferCount) {
		return 0;
	}

	if (m_vsBuffer.size() >= m_uBufferCount) {
		m_vsBuffer.erase(m_vsBuffer.begin());
	}

	m_vsBuffer.push_back(sLine);
	return m_vsBuffer.size();
}

void CChan::ClearBuffer() {
	m_vsBuffer.clear();
}

<|endoftext|>


<commit_before>#include "Chan.h"
#include "znc.h"
#include "User.h"
#include "Utils.h"

CChan::CChan(const string& sName, CUser* pUser) {
	m_sName = sName;

	if (CUtils::Left(m_sName, 1) != "#" && CUtils::Left(m_sName, 1) != "&") {
		m_sName = "#" + m_sName;
	}

	m_pUser = pUser;
	m_bAutoCycle = true;
	m_bDetached = false;
	m_uBufferCount = m_pUser->GetBufferCount();
	m_bKeepBuffer = m_pUser->KeepBuffer();
	Reset();
}
CChan::~CChan() {
	ClearNicks();
}

void CChan::Reset() {
	m_bWhoDone = false;
	m_bIsOn = false;
	m_bIsOp = false;
	m_bIsVoice = false;
	m_uOpCount = 0;
	m_uVoiceCount =	0;
	m_uModes = 0;
	m_uLimit = 0;
	m_uClientRequests = 0;
	ClearNicks();
}

void CChan::Joined() {
}

void CChan::Cycle() const {
	m_pUser->PutIRC("PART " + GetName() + "\r\nJOIN " + GetName() + " " + GetKey());
}

void CChan::JoinUser() {
	if (!IsOn()) {
		IncClientRequests();
		m_pUser->PutIRC("JOIN " + GetName());
		return;
	}

	m_pUser->PutUser(":" + m_pUser->GetIRCNick().GetNickMask() + " JOIN :" + GetName());

	if (!GetTopic().empty()) {
		m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 332 " + m_pUser->GetIRCNick().GetNick() + " " + GetName() + " :" + GetTopic());
		m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 333 " + m_pUser->GetIRCNick().GetNick() + " " + GetName() + " " + GetTopicOwner() + " " + CUtils::ToString(GetTopicDate()));
	}

	string sPre = ":" + m_pUser->GetIRCServer() + " 353 " + m_pUser->GetIRCNick().GetNick() + " = " + GetName() + " :";
	string sLine = sPre;

	for (map<string,CNick*>::iterator a = m_msNicks.begin(); a != m_msNicks.end(); a++) {
		if (a->second->IsOp()) {
			sLine += "@";
		} else if (a->second->IsVoice()) {
			sLine += "+";
		}

		sLine += a->first;

		if (sLine.size() >= 490 || a == (--m_msNicks.end())) {
			m_pUser->PutUser(sLine);
			sLine = sPre;
		} else {
			sLine += " ";
		}
	}

	m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 366 " + m_pUser->GetIRCNick().GetNick() + " " + GetName() + " :End of /NAMES list.");
	SendBuffer();

	m_bDetached = false;
}

void CChan::SendBuffer() {
	if (m_pUser->IsUserAttached()) {
		const vector<string>& vsBuffer = GetBuffer();

		if (vsBuffer.size()) {
			m_pUser->PutUser(":***!znc@znc.com PRIVMSG " + GetName() + " :Buffer Playback...");

			for (unsigned int a = 0; a < vsBuffer.size(); a++) {
				m_pUser->PutUser(vsBuffer[a]);
			}

			if (!KeepBuffer()) {
				ClearBuffer();
			}

			m_pUser->PutUser(":***!znc@znc.com PRIVMSG " + GetName() + " :Playback Complete.");
		}
	}
}

void CChan::DetachUser() {
	m_pUser->PutUser(":" + m_pUser->GetIRCNick().GetNickMask() + " PART " + GetName());
	m_bDetached = true;
}

string CChan::GetModeString() const {
	string sRet;

	if (m_uModes & Secret) { sRet += "s"; }
	if (m_uModes & Private) { sRet += "p"; }
	if (m_uModes & OpTopic) { sRet += "t"; }
	if (m_uModes & InviteOnly) { sRet += "i"; }
	if (m_uModes & NoMessages) { sRet += "n"; }
	if (m_uModes & Moderated) { sRet += "m"; }
	if (m_uLimit) { sRet += "l"; }
	if (m_uModes & Key) { sRet += "k"; }

	return (sRet.empty()) ? sRet : ("+" + sRet);
}

void CChan::SetModes(const string& sModes) {
	m_uModes = 0;
	m_uLimit = 0;
	m_sKey = "";
	ModeChange(sModes);
}

void CChan::IncClientRequests() {
	m_uClientRequests++;
}

bool CChan::DecClientRequests() {
	if (!m_uClientRequests) {
		return false;
	}

	m_uClientRequests--;
	return true;
}

bool CChan::Who() {
	if (m_bWhoDone) {
		return false;
	}

	m_pUser->PutIRC("WHO " + GetName());
	return true;
}

void CChan::OnWho(const string& sNick, const string& sIdent, const string& sHost) {
	CNick* pNick = FindNick(sNick);

	if (pNick) {
		pNick->SetIdent(sIdent);
		pNick->SetHost(sHost);
	}
}

void CChan::ModeChange(const string& sModes, const string& sOpNick) {
	string sModeArg = CUtils::Token(sModes, 0);
	string sArgs = CUtils::Token(sModes, 1, true);
	bool bAdd = true;

#ifdef _MODULES
	CNick* pNick = FindNick(sOpNick);
	if (pNick) {
		m_pUser->GetModules().OnRawMode(*pNick, *this, sModeArg, sArgs);
	}
#endif

	for (unsigned int a = 0; a < sModeArg.size(); a++) {
		switch (sModeArg[a]) {
			case '+': bAdd = true; break;
			case '-': bAdd = false; break;
			case 's': if (bAdd) { m_uModes |= Secret; } else { m_uModes &= ~Secret; } break;
			case 'p': if (bAdd) { m_uModes |= Private; } else { m_uModes &= ~Private; }  break;
			case 'm': if (bAdd) { m_uModes |= Moderated; } else { m_uModes &= ~Moderated; }  break;
			case 'i': if (bAdd) { m_uModes |= InviteOnly; } else { m_uModes &= ~InviteOnly; }  break;
			case 'n': if (bAdd) { m_uModes |= NoMessages; } else { m_uModes &= ~NoMessages; }  break;
			case 't': if (bAdd) { m_uModes |= OpTopic; } else { m_uModes &= ~OpTopic; }  break;
			case 'l': if (bAdd) { m_uLimit = strtoul(GetModeArg(sArgs).c_str(), NULL, 10); } else { m_uLimit = 0; }  break;
			case 'k': if (bAdd) { m_uModes |= Key; SetKey(GetModeArg(sArgs)); } else { m_uModes &= ~Key; GetModeArg(sArgs); }  break;
			case 'o': OnOp(sOpNick, GetModeArg(sArgs), bAdd); break;
			case 'v': OnVoice(sOpNick, GetModeArg(sArgs), bAdd); break;
			case 'b': // Don't do anything with bans yet
			case 'e': // Don't do anything with excepts yet
			default: GetModeArg(sArgs); // Pop off an arg, assume new modes will have an argument
		}
	}
}

string CChan::GetModeArg(string& sArgs) const {
	string sRet = sArgs.substr(0, sArgs.find(' '));
	sArgs = (sRet.size() < sArgs.size()) ? sArgs.substr(sRet.size() +1) : "";
	return sRet;
}

void CChan::ClearNicks() {
	for (map<string,CNick*>::iterator a = m_msNicks.begin(); a != m_msNicks.end(); a++) {
		delete a->second;
	}

	m_msNicks.clear();
}

int CChan::AddNicks(const string& sNicks) {
	if (IsOn()) {
		return 0;
	}

	int iRet = 0;
	string sCurNick;

	for (unsigned int a = 0; a < sNicks.size(); a++) {
		switch (sNicks[a]) {
			case ' ':
				if (AddNick(sCurNick)) {
					iRet++;
				}

				sCurNick = "";

				break;
			default:
				sCurNick += sNicks[a];
				break;
		}
	}

	if (!sCurNick.empty()) {
		if (AddNick(sCurNick)) {
			iRet++;
		}
	}

	return iRet;
}

bool CChan::AddNick(const string& sNick) {
	const char* p = sNick.c_str();
	bool bIsOp = false;
	bool bIsVoice = false;

	switch (*p) {
		case '\0':
			return false;
		case '@':
			bIsOp = true;
		case '+':
			if (!*++p) {
				return false;
			}

			bIsVoice = !bIsOp;
	}

	CNick* pNick = FindNick(p);
	if (!pNick) {
		pNick = new CNick(p);
	}

	if ((bIsOp) && (!pNick->IsOp())) {
		IncOpCount();
		pNick->SetOp(true);

		if (strcasecmp(pNick->GetNick().c_str(), m_pUser->GetCurNick().c_str()) == 0) {
			SetOpped(true);
		}
	} else if ((bIsVoice) && (!pNick->IsVoice())) {
		IncVoiceCount();
		pNick->SetVoice(true);

		if (strcasecmp(pNick->GetNick().c_str(), m_pUser->GetCurNick().c_str()) == 0) {
			SetVoiced(true);
		}
	}

	m_msNicks[pNick->GetNick()] = pNick;

	return true;
}

bool CChan::RemNick(const string& sNick) {
	map<string,CNick*>::iterator it = m_msNicks.find(sNick);
	if (it == m_msNicks.end()) {
		return false;
	}

	if (it->second->IsOp()) {
		DecOpCount();
	}

	if (it->second->IsVoice()) {
		DecVoiceCount();
	}

	delete it->second;
	m_msNicks.erase(it);
	CNick* pNick = m_msNicks.begin()->second;

	if ((m_msNicks.size() == 1) && (!pNick->IsOp()) && (strcasecmp(pNick->GetNick().c_str(), m_pUser->GetCurNick().c_str()) == 0)) {
		if (AutoCycle()) {
			Cycle();
		}
	}

	return true;
}

bool CChan::ChangeNick(const string& sOldNick, const string& sNewNick) {
	map<string,CNick*>::iterator it = m_msNicks.find(sOldNick);

	if (it == m_msNicks.end()) {
		return false;
	}

	// Rename this nick
	it->second->SetNick(sNewNick);

	// Insert a new element into the map then erase the old one, do this to change the key
	m_msNicks[sNewNick] = it->second;
	m_msNicks.erase(it);

	return true;
}

void CChan::OnOp(const string& sOpNick, const string& sNick, bool bOpped) {
	CNick* pNick = FindNick(sNick);

	if (pNick) {
		bool bNoChange = (pNick->IsOp() == bOpped);
#ifdef _MODULES
		CNick* pOpNick = FindNick(sOpNick);

		if (pOpNick) {
			if (bOpped) {
				m_pUser->GetModules().OnOp(*pOpNick, *pNick, *this, bNoChange);
			} else {
				m_pUser->GetModules().OnDeop(*pOpNick, *pNick, *this, bNoChange);
			}
		}
#endif

		if (strcasecmp(sNick.c_str(), m_pUser->GetCurNick().c_str()) == 0) {
			SetOpped(bOpped);
		}

		if (bNoChange) {
			// If no change, return
			return;
		}

		pNick->SetOp(bOpped);
		(bOpped) ? IncOpCount() : DecOpCount();
	}
}

void CChan::OnVoice(const string& sOpNick, const string& sNick, bool bVoiced) {
	CNick* pNick = FindNick(sNick);

	if (pNick) {
		bool bNoChange = (pNick->IsVoice() == bVoiced);

#ifdef _MODULES
		CNick* pOpNick = FindNick(sOpNick);

		if (pOpNick) {
			if (bVoiced) {
				m_pUser->GetModules().OnVoice(*pOpNick, *pNick, *this, bNoChange);
			} else {
				m_pUser->GetModules().OnDevoice(*pOpNick, *pNick, *this, bNoChange);
			}
		}
#endif

		if (strcasecmp(sNick.c_str(), m_pUser->GetCurNick().c_str()) == 0) {
			SetVoiced(bVoiced);
		}

		if (bNoChange) {
			// If no change, return
			return;
		}

		pNick->SetVoice(bVoiced);
		(bVoiced) ? IncVoiceCount() : DecVoiceCount();
	}
}

CNick* CChan::FindNick(const string& sNick) const {
	map<string,CNick*>::const_iterator it = m_msNicks.find(sNick);
	return (it != m_msNicks.end()) ? it->second : NULL;
}

int CChan::AddBuffer(const string& sLine) {
	// Todo: revisit the buffering
	if (!m_uBufferCount) {
		return 0;
	}

	if (m_vsBuffer.size() >= m_uBufferCount) {
		m_vsBuffer.erase(m_vsBuffer.begin());
	}

	m_vsBuffer.push_back(sLine);
	return m_vsBuffer.size();
}

void CChan::ClearBuffer() {
	m_vsBuffer.clear();
}
<commit_msg>Split constructor channel argument into chan/key<commit_after>#include "Chan.h"
#include "znc.h"
#include "User.h"
#include "Utils.h"

CChan::CChan(const string& sName, CUser* pUser) {
	m_sName = CUtils::Token(sName, 0);
	m_sKey = CUtils::Token(sName, 1);

	if (CUtils::Left(m_sName, 1) != "#" && CUtils::Left(m_sName, 1) != "&") {
		m_sName = "#" + m_sName;
	}

	m_pUser = pUser;
	m_bAutoCycle = true;
	m_bDetached = false;
	m_uBufferCount = m_pUser->GetBufferCount();
	m_bKeepBuffer = m_pUser->KeepBuffer();
	Reset();
}
CChan::~CChan() {
	ClearNicks();
}

void CChan::Reset() {
	m_bWhoDone = false;
	m_bIsOn = false;
	m_bIsOp = false;
	m_bIsVoice = false;
	m_uOpCount = 0;
	m_uVoiceCount =	0;
	m_uModes = 0;
	m_uLimit = 0;
	m_uClientRequests = 0;
	ClearNicks();
}

void CChan::Joined() {
}

void CChan::Cycle() const {
	m_pUser->PutIRC("PART " + GetName() + "\r\nJOIN " + GetName() + " " + GetKey());
}

void CChan::JoinUser() {
	if (!IsOn()) {
		IncClientRequests();
		m_pUser->PutIRC("JOIN " + GetName());
		return;
	}

	m_pUser->PutUser(":" + m_pUser->GetIRCNick().GetNickMask() + " JOIN :" + GetName());

	if (!GetTopic().empty()) {
		m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 332 " + m_pUser->GetIRCNick().GetNick() + " " + GetName() + " :" + GetTopic());
		m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 333 " + m_pUser->GetIRCNick().GetNick() + " " + GetName() + " " + GetTopicOwner() + " " + CUtils::ToString(GetTopicDate()));
	}

	string sPre = ":" + m_pUser->GetIRCServer() + " 353 " + m_pUser->GetIRCNick().GetNick() + " = " + GetName() + " :";
	string sLine = sPre;

	for (map<string,CNick*>::iterator a = m_msNicks.begin(); a != m_msNicks.end(); a++) {
		if (a->second->IsOp()) {
			sLine += "@";
		} else if (a->second->IsVoice()) {
			sLine += "+";
		}

		sLine += a->first;

		if (sLine.size() >= 490 || a == (--m_msNicks.end())) {
			m_pUser->PutUser(sLine);
			sLine = sPre;
		} else {
			sLine += " ";
		}
	}

	m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 366 " + m_pUser->GetIRCNick().GetNick() + " " + GetName() + " :End of /NAMES list.");
	SendBuffer();

	m_bDetached = false;
}

void CChan::SendBuffer() {
	if (m_pUser->IsUserAttached()) {
		const vector<string>& vsBuffer = GetBuffer();

		if (vsBuffer.size()) {
			m_pUser->PutUser(":***!znc@znc.com PRIVMSG " + GetName() + " :Buffer Playback...");

			for (unsigned int a = 0; a < vsBuffer.size(); a++) {
				m_pUser->PutUser(vsBuffer[a]);
			}

			if (!KeepBuffer()) {
				ClearBuffer();
			}

			m_pUser->PutUser(":***!znc@znc.com PRIVMSG " + GetName() + " :Playback Complete.");
		}
	}
}

void CChan::DetachUser() {
	m_pUser->PutUser(":" + m_pUser->GetIRCNick().GetNickMask() + " PART " + GetName());
	m_bDetached = true;
}

string CChan::GetModeString() const {
	string sRet;

	if (m_uModes & Secret) { sRet += "s"; }
	if (m_uModes & Private) { sRet += "p"; }
	if (m_uModes & OpTopic) { sRet += "t"; }
	if (m_uModes & InviteOnly) { sRet += "i"; }
	if (m_uModes & NoMessages) { sRet += "n"; }
	if (m_uModes & Moderated) { sRet += "m"; }
	if (m_uLimit) { sRet += "l"; }
	if (m_uModes & Key) { sRet += "k"; }

	return (sRet.empty()) ? sRet : ("+" + sRet);
}

void CChan::SetModes(const string& sModes) {
	m_uModes = 0;
	m_uLimit = 0;
	m_sKey = "";
	ModeChange(sModes);
}

void CChan::IncClientRequests() {
	m_uClientRequests++;
}

bool CChan::DecClientRequests() {
	if (!m_uClientRequests) {
		return false;
	}

	m_uClientRequests--;
	return true;
}

bool CChan::Who() {
	if (m_bWhoDone) {
		return false;
	}

	m_pUser->PutIRC("WHO " + GetName());
	return true;
}

void CChan::OnWho(const string& sNick, const string& sIdent, const string& sHost) {
	CNick* pNick = FindNick(sNick);

	if (pNick) {
		pNick->SetIdent(sIdent);
		pNick->SetHost(sHost);
	}
}

void CChan::ModeChange(const string& sModes, const string& sOpNick) {
	string sModeArg = CUtils::Token(sModes, 0);
	string sArgs = CUtils::Token(sModes, 1, true);
	bool bAdd = true;

#ifdef _MODULES
	CNick* pNick = FindNick(sOpNick);
	if (pNick) {
		m_pUser->GetModules().OnRawMode(*pNick, *this, sModeArg, sArgs);
	}
#endif

	for (unsigned int a = 0; a < sModeArg.size(); a++) {
		switch (sModeArg[a]) {
			case '+': bAdd = true; break;
			case '-': bAdd = false; break;
			case 's': if (bAdd) { m_uModes |= Secret; } else { m_uModes &= ~Secret; } break;
			case 'p': if (bAdd) { m_uModes |= Private; } else { m_uModes &= ~Private; }  break;
			case 'm': if (bAdd) { m_uModes |= Moderated; } else { m_uModes &= ~Moderated; }  break;
			case 'i': if (bAdd) { m_uModes |= InviteOnly; } else { m_uModes &= ~InviteOnly; }  break;
			case 'n': if (bAdd) { m_uModes |= NoMessages; } else { m_uModes &= ~NoMessages; }  break;
			case 't': if (bAdd) { m_uModes |= OpTopic; } else { m_uModes &= ~OpTopic; }  break;
			case 'l': if (bAdd) { m_uLimit = strtoul(GetModeArg(sArgs).c_str(), NULL, 10); } else { m_uLimit = 0; }  break;
			case 'k': if (bAdd) { m_uModes |= Key; SetKey(GetModeArg(sArgs)); } else { m_uModes &= ~Key; GetModeArg(sArgs); }  break;
			case 'o': OnOp(sOpNick, GetModeArg(sArgs), bAdd); break;
			case 'v': OnVoice(sOpNick, GetModeArg(sArgs), bAdd); break;
			case 'b': // Don't do anything with bans yet
			case 'e': // Don't do anything with excepts yet
			default: GetModeArg(sArgs); // Pop off an arg, assume new modes will have an argument
		}
	}
}

string CChan::GetModeArg(string& sArgs) const {
	string sRet = sArgs.substr(0, sArgs.find(' '));
	sArgs = (sRet.size() < sArgs.size()) ? sArgs.substr(sRet.size() +1) : "";
	return sRet;
}

void CChan::ClearNicks() {
	for (map<string,CNick*>::iterator a = m_msNicks.begin(); a != m_msNicks.end(); a++) {
		delete a->second;
	}

	m_msNicks.clear();
}

int CChan::AddNicks(const string& sNicks) {
	if (IsOn()) {
		return 0;
	}

	int iRet = 0;
	string sCurNick;

	for (unsigned int a = 0; a < sNicks.size(); a++) {
		switch (sNicks[a]) {
			case ' ':
				if (AddNick(sCurNick)) {
					iRet++;
				}

				sCurNick = "";

				break;
			default:
				sCurNick += sNicks[a];
				break;
		}
	}

	if (!sCurNick.empty()) {
		if (AddNick(sCurNick)) {
			iRet++;
		}
	}

	return iRet;
}

bool CChan::AddNick(const string& sNick) {
	const char* p = sNick.c_str();
	bool bIsOp = false;
	bool bIsVoice = false;

	switch (*p) {
		case '\0':
			return false;
		case '@':
			bIsOp = true;
		case '+':
			if (!*++p) {
				return false;
			}

			bIsVoice = !bIsOp;
	}

	CNick* pNick = FindNick(p);
	if (!pNick) {
		pNick = new CNick(p);
	}

	if ((bIsOp) && (!pNick->IsOp())) {
		IncOpCount();
		pNick->SetOp(true);

		if (strcasecmp(pNick->GetNick().c_str(), m_pUser->GetCurNick().c_str()) == 0) {
			SetOpped(true);
		}
	} else if ((bIsVoice) && (!pNick->IsVoice())) {
		IncVoiceCount();
		pNick->SetVoice(true);

		if (strcasecmp(pNick->GetNick().c_str(), m_pUser->GetCurNick().c_str()) == 0) {
			SetVoiced(true);
		}
	}

	m_msNicks[pNick->GetNick()] = pNick;

	return true;
}

bool CChan::RemNick(const string& sNick) {
	map<string,CNick*>::iterator it = m_msNicks.find(sNick);
	if (it == m_msNicks.end()) {
		return false;
	}

	if (it->second->IsOp()) {
		DecOpCount();
	}

	if (it->second->IsVoice()) {
		DecVoiceCount();
	}

	delete it->second;
	m_msNicks.erase(it);
	CNick* pNick = m_msNicks.begin()->second;

	if ((m_msNicks.size() == 1) && (!pNick->IsOp()) && (strcasecmp(pNick->GetNick().c_str(), m_pUser->GetCurNick().c_str()) == 0)) {
		if (AutoCycle()) {
			Cycle();
		}
	}

	return true;
}

bool CChan::ChangeNick(const string& sOldNick, const string& sNewNick) {
	map<string,CNick*>::iterator it = m_msNicks.find(sOldNick);

	if (it == m_msNicks.end()) {
		return false;
	}

	// Rename this nick
	it->second->SetNick(sNewNick);

	// Insert a new element into the map then erase the old one, do this to change the key
	m_msNicks[sNewNick] = it->second;
	m_msNicks.erase(it);

	return true;
}

void CChan::OnOp(const string& sOpNick, const string& sNick, bool bOpped) {
	CNick* pNick = FindNick(sNick);

	if (pNick) {
		bool bNoChange = (pNick->IsOp() == bOpped);
#ifdef _MODULES
		CNick* pOpNick = FindNick(sOpNick);

		if (pOpNick) {
			if (bOpped) {
				m_pUser->GetModules().OnOp(*pOpNick, *pNick, *this, bNoChange);
			} else {
				m_pUser->GetModules().OnDeop(*pOpNick, *pNick, *this, bNoChange);
			}
		}
#endif

		if (strcasecmp(sNick.c_str(), m_pUser->GetCurNick().c_str()) == 0) {
			SetOpped(bOpped);
		}

		if (bNoChange) {
			// If no change, return
			return;
		}

		pNick->SetOp(bOpped);
		(bOpped) ? IncOpCount() : DecOpCount();
	}
}

void CChan::OnVoice(const string& sOpNick, const string& sNick, bool bVoiced) {
	CNick* pNick = FindNick(sNick);

	if (pNick) {
		bool bNoChange = (pNick->IsVoice() == bVoiced);

#ifdef _MODULES
		CNick* pOpNick = FindNick(sOpNick);

		if (pOpNick) {
			if (bVoiced) {
				m_pUser->GetModules().OnVoice(*pOpNick, *pNick, *this, bNoChange);
			} else {
				m_pUser->GetModules().OnDevoice(*pOpNick, *pNick, *this, bNoChange);
			}
		}
#endif

		if (strcasecmp(sNick.c_str(), m_pUser->GetCurNick().c_str()) == 0) {
			SetVoiced(bVoiced);
		}

		if (bNoChange) {
			// If no change, return
			return;
		}

		pNick->SetVoice(bVoiced);
		(bVoiced) ? IncVoiceCount() : DecVoiceCount();
	}
}

CNick* CChan::FindNick(const string& sNick) const {
	map<string,CNick*>::const_iterator it = m_msNicks.find(sNick);
	return (it != m_msNicks.end()) ? it->second : NULL;
}

int CChan::AddBuffer(const string& sLine) {
	// Todo: revisit the buffering
	if (!m_uBufferCount) {
		return 0;
	}

	if (m_vsBuffer.size() >= m_uBufferCount) {
		m_vsBuffer.erase(m_vsBuffer.begin());
	}

	m_vsBuffer.push_back(sLine);
	return m_vsBuffer.size();
}

void CChan::ClearBuffer() {
	m_vsBuffer.clear();
}
<|endoftext|>


<commit_before>#include <iostream>

using std::cout;
using std::cin;
using std::endl;

int factorial(int x);

int main(int argc, char*argv[]){
	int opcion;

cout << "Ingrese el programa al que quiere ingresar: ";
cout << endl;
cout << "1.- Ejercicio 1(Funcion de factorial)" << endl;
cout << "2.- Ejercicio 2(Trapezoide)" << endl;
cin >> opcion;

if (opcion == 1){

}

	return 0;
}
<commit_msg>factorial<commit_after>#include <iostream>
#include <stdio.h>
#include <math.h>

using std::cout;
using std::cin;
using std::endl;

int factorial(int x);
double div(int x);

int main(int argc, char*argv[]){
	int opcion;
	int limite_fact;

	cout << "Ingrese el programa al que quiere ingresar: ";
	cout << endl;
	cout << "1.- Ejercicio 1(Funcion de factorial)" << endl;
	cout << "2.- Ejercicio 2(Trapezoide)" << endl;
	cin >> opcion;

	if (opcion == 1){
		cout << "Ingrese el numero x: " << endl;
		cin >> limite_fact;

		cout << div(limite_fact) + 1;
	}else if (){

	}

	return 0;
}//fin del main

//metodos
int factorial(int x){
	int sum_acum = 1;
	for (int i = 1; i <= x; ++i){
		sum_acum = sum_acum * i;
	}

	return sum_acum;
}

double div(int x){
	double acum_total = 0;
	for (int i = 1; i < 16; i++){
		acum_total += (pow(x, i))/(factorial(i));
	}
	return acum_total;
}
<|endoftext|>