<commit_before>/*************************************************
* X.509 Certificate Extensions Source File       *
* (C) 1999-2006 The Botan Project                *
*************************************************/

#include <botan/x509_ext.h>
#include <botan/x509cert.h>
#include <botan/x509stat.h>
#include <botan/libstate.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>
#include <botan/lookup.h>
#include <botan/oids.h>
#include <botan/config.h>
#include <botan/bit_ops.h>
#include <algorithm>
#include <memory>

namespace Botan {

/*************************************************
* Return the OID of this extension               *
*************************************************/
OID Certificate_Extension::oid_of() const
   {
   return OIDS::lookup(oid_name());
   }

/*************************************************
* Encode an Extensions list                      *
*************************************************/
void Extensions::encode_into(DER_Encoder& to_object) const
   {
   for(u32bit j = 0; j != extensions.size(); ++j)
      {
      const Certificate_Extension* ext = extensions[j];

      std::string setting;

      if(ext->config_id() != "")
         setting = global_config().option("x509/exts/" + ext->config_id());

      if(setting == "")
         setting = "yes";

      if(setting != "yes" && setting != "no" && setting != "critical")
         throw Invalid_Argument("X509_CA:: Invalid value for option "
                                "x509/exts/" + ext->config_id() + " of " +
                                setting);

      bool is_critical = (setting == "critical");
      bool should_encode = ext->should_encode() && (setting != "no");

      if(should_encode)
         {
         to_object.start_cons(SEQUENCE)
               .encode(ext->oid_of())
               .encode_optional(is_critical, false)
               .encode(ext->encode_inner(), OCTET_STRING)
            .end_cons();
         }
      }
   }

/*************************************************
* Decode a list of Extensions                    *
*************************************************/
void Extensions::decode_from(BER_Decoder& from_source)
   {
   for(u32bit j = 0; j != extensions.size(); ++j)
      delete extensions[j];
   extensions.clear();

   BER_Decoder sequence = from_source.start_cons(SEQUENCE);
   while(sequence.more_items())
      {
      OID oid;
      MemoryVector<byte> value;
      bool critical;

      sequence.start_cons(SEQUENCE)
            .decode(oid)
            .decode_optional(critical, BOOLEAN, UNIVERSAL, false)
            .decode(value, OCTET_STRING)
            .verify_end()
         .end_cons();

      Certificate_Extension* ext =
         global_state().x509_state().get_extension(oid);

      if(!ext)
         {
         if(!critical || !should_throw)
            continue;

         throw Decoding_Error("Encountered unknown X.509 extension marked "
                              "as critical; OID = " + oid.as_string());
         }

      ext->decode_inner(value);

      extensions.push_back(ext);
      }
   sequence.verify_end();
   }

/*************************************************
* Write the extensions to an info store          *
*************************************************/
void Extensions::contents_to(Data_Store& subject_info,
                             Data_Store& issuer_info) const
   {
   for(u32bit j = 0; j != extensions.size(); ++j)
      extensions[j]->contents_to(subject_info, issuer_info);
   }

/*************************************************
* Copy another extensions list                   *
*************************************************/
Extensions& Extensions::copy_this(const Extensions& other)
   {
   for(u32bit j = 0; j != extensions.size(); ++j)
      delete extensions[j];
   extensions.clear();

   for(u32bit j = 0; j != other.extensions.size(); ++j)
      extensions.push_back(other.extensions[j]->copy());

   return (*this);
   }

/*************************************************
* Delete an Extensions list                      *
*************************************************/
Extensions::~Extensions()
   {
   for(u32bit j = 0; j != extensions.size(); ++j)
      delete extensions[j];
   }

namespace Cert_Extension {

/*************************************************
* Checked accessor for the path_limit member     *
*************************************************/
bool Basic_Constraints::get_path_limit() const
   {
   if(!is_ca)
      throw Invalid_State("Basic_Constraints::get_path_limit: Not a CA");
   return path_limit;
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> Basic_Constraints::encode_inner() const
   {
   return DER_Encoder()
      .start_cons(SEQUENCE)
      .encode_if(is_ca,
                 DER_Encoder()
                    .encode(is_ca)
                    .encode_optional(path_limit, NO_CERT_PATH_LIMIT)
         )
      .end_cons()
   .get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void Basic_Constraints::decode_inner(const MemoryRegion<byte>& in)
   {
   BER_Decoder(in)
      .start_cons(SEQUENCE)
         .decode_optional(is_ca, BOOLEAN, UNIVERSAL, false)
         .decode_optional(path_limit, INTEGER, UNIVERSAL, NO_CERT_PATH_LIMIT)
         .verify_end()
      .end_cons();

   if(is_ca == false)
      path_limit = 0;
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void Basic_Constraints::contents_to(Data_Store& subject, Data_Store&) const
   {
   subject.add("X509v3.BasicConstraints.is_ca", (is_ca ? 1 : 0));
   subject.add("X509v3.BasicConstraints.path_constraint", path_limit);
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> Key_Usage::encode_inner() const
   {
   if(constraints == NO_CONSTRAINTS)
      throw Encoding_Error("Cannot encode zero usage constraints");

   const u32bit unused_bits = low_bit(constraints) - 1;

   SecureVector<byte> der;
   der.append(BIT_STRING);
   der.append(2 + ((unused_bits < 8) ? 1 : 0));
   der.append(unused_bits % 8);
   der.append((constraints >> 8) & 0xFF);
   if(constraints & 0xFF)
      der.append(constraints & 0xFF);

   return der;
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void Key_Usage::decode_inner(const MemoryRegion<byte>& in)
   {
   BER_Decoder ber(in);

   BER_Object obj = ber.get_next_object();

   if(obj.type_tag != BIT_STRING || obj.class_tag != UNIVERSAL)
      throw BER_Bad_Tag("Bad tag for usage constraint",
                        obj.type_tag, obj.class_tag);

   if(obj.value.size() != 2 && obj.value.size() != 3)
      throw BER_Decoding_Error("Bad size for BITSTRING in usage constraint");

   if(obj.value[0] >= 8)
      throw BER_Decoding_Error("Invalid unused bits in usage constraint");

   obj.value[obj.value.size()-1] &= (0xFF << obj.value[0]);

   u16bit usage = 0;
   for(u32bit j = 1; j != obj.value.size(); ++j)
      usage = (obj.value[j] << 8) | usage;

   constraints = Key_Constraints(usage);
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void Key_Usage::contents_to(Data_Store& subject, Data_Store&) const
   {
   subject.add("X509v3.KeyUsage", constraints);
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> Subject_Key_ID::encode_inner() const
   {
   return DER_Encoder().encode(key_id, OCTET_STRING).get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void Subject_Key_ID::decode_inner(const MemoryRegion<byte>& in)
   {
   BER_Decoder(in).decode(key_id, OCTET_STRING).verify_end();
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void Subject_Key_ID::contents_to(Data_Store& subject, Data_Store&) const
   {
   subject.add("X509v3.SubjectKeyIdentifier", key_id);
   }

/*************************************************
* Subject_Key_ID Constructor                     *
*************************************************/
Subject_Key_ID::Subject_Key_ID(const MemoryRegion<byte>& pub_key)
   {
   std::auto_ptr<HashFunction> hash(get_hash("SHA-1"));
   key_id = hash->process(pub_key);
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> Authority_Key_ID::encode_inner() const
   {
   return DER_Encoder()
         .start_cons(SEQUENCE)
            .encode(key_id, OCTET_STRING, ASN1_Tag(0), CONTEXT_SPECIFIC)
         .end_cons()
      .get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void Authority_Key_ID::decode_inner(const MemoryRegion<byte>& in)
   {
   BER_Decoder(in)
      .start_cons(SEQUENCE)
      .decode_optional_string(key_id, OCTET_STRING, 0);
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void Authority_Key_ID::contents_to(Data_Store&, Data_Store& issuer) const
   {
   if(key_id.size())
      issuer.add("X509v3.AuthorityKeyIdentifier", key_id);
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> Alternative_Name::encode_inner() const
   {
   return DER_Encoder().encode(alt_name).get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void Alternative_Name::decode_inner(const MemoryRegion<byte>& in)
   {
   BER_Decoder(in).decode(alt_name);
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void Alternative_Name::contents_to(Data_Store& subject_info,
                                   Data_Store& issuer_info) const
   {
   std::multimap<std::string, std::string> contents =
      get_alt_name().contents();

   if(oid_name_str == "subject_alternative_name")
      subject_info.add(contents);
   else
      issuer_info.add(contents);
   }

/*************************************************
* Alternative_Name Constructor                   *
*************************************************/
Alternative_Name::Alternative_Name(const AlternativeName& alt_name,
                                   const std::string& oid_name_str,
                                   const std::string& config_name_str)
   {
   this->alt_name = alt_name;
   this->oid_name_str = oid_name_str;
   this->config_name_str = config_name_str;
   }

/*************************************************
* Subject_Alternative_Name Constructor           *
*************************************************/
Subject_Alternative_Name::Subject_Alternative_Name(
   const AlternativeName& name) :

   Alternative_Name(name, "X509v3.SubjectAlternativeName",
                    "subject_alternative_name")
   {
   }

/*************************************************
* Issuer_Alternative_Name Constructor           *
*************************************************/
Issuer_Alternative_Name::Issuer_Alternative_Name(const AlternativeName& name) :
   Alternative_Name(name, "X509v3.IssuerAlternativeName",
                    "issuer_alternative_name")
   {
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> Extended_Key_Usage::encode_inner() const
   {
   return DER_Encoder()
      .start_cons(SEQUENCE)
         .encode_list(oids)
      .end_cons()
   .get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void Extended_Key_Usage::decode_inner(const MemoryRegion<byte>& in)
   {
   BER_Decoder(in)
      .start_cons(SEQUENCE)
         .decode_list(oids)
      .end_cons();
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void Extended_Key_Usage::contents_to(Data_Store& subject, Data_Store&) const
   {
   for(u32bit j = 0; j != oids.size(); ++j)
      subject.add("X509v3.ExtendedKeyUsage", oids[j].as_string());
   }

namespace {

/*************************************************
* A policy specifier                             *
*************************************************/
class Policy_Information : public ASN1_Object
   {
   public:
      OID oid;

      void encode_into(DER_Encoder& codec) const
         {
         codec.start_cons(SEQUENCE)
            .encode(oid)
            .end_cons();
         }

      void decode_from(BER_Decoder& codec)
         {
         codec.start_cons(SEQUENCE)
            .decode(oid)
            .discard_remaining()
            .end_cons();
         }
   };

}

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> Certificate_Policies::encode_inner() const
   {
   throw Exception("Certificate_Policies::encode_inner: Bugged");

   std::vector<Policy_Information> policies;

   return DER_Encoder()
      .start_cons(SEQUENCE)
         .encode_list(policies)
      .end_cons()
   .get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void Certificate_Policies::decode_inner(const MemoryRegion<byte>& in)
   {
   std::vector<Policy_Information> policies;

   BER_Decoder(in)
      .start_cons(SEQUENCE)
         .decode_list(policies)
      .end_cons();
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void Certificate_Policies::contents_to(Data_Store& info, Data_Store&) const
   {
   for(u32bit j = 0; j != oids.size(); ++j)
      info.add("X509v3.ExtendedKeyUsage", oids[j].as_string());
   }

/*************************************************
* Checked accessor for the crl_number member     *
*************************************************/
u32bit CRL_Number::get_crl_number() const
   {
   if(!has_value)
      throw Invalid_State("CRL_Number::get_crl_number: Not set");
   return crl_number;
   }

/*************************************************
* Copy a CRL_Number extension                    *
*************************************************/
CRL_Number* CRL_Number::copy() const
   {
   if(!has_value)
      throw Invalid_State("CRL_Number::copy: Not set");
   return new CRL_Number(crl_number);
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> CRL_Number::encode_inner() const
   {
   return DER_Encoder().encode(crl_number).get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void CRL_Number::decode_inner(const MemoryRegion<byte>& in)
   {
   BER_Decoder(in).decode(crl_number);
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void CRL_Number::contents_to(Data_Store& info, Data_Store&) const
   {
   info.add("X509v3.CRLNumber", crl_number);
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> CRL_ReasonCode::encode_inner() const
   {
   return DER_Encoder()
      .encode((u32bit)reason, ENUMERATED, UNIVERSAL)
   .get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void CRL_ReasonCode::decode_inner(const MemoryRegion<byte>& in)
   {
   u32bit reason_code = 0;
   BER_Decoder(in).decode(reason_code, ENUMERATED, UNIVERSAL);
   reason = (CRL_Code)reason_code;
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void CRL_ReasonCode::contents_to(Data_Store& info, Data_Store&) const
   {
   info.add("X509v3.CRLReasonCode", reason);
   }

}

}
<commit_msg>Fix a bug that caused subject alternative name information to be saved as issuer names.<commit_after>/*************************************************
* X.509 Certificate Extensions Source File       *
* (C) 1999-2006 The Botan Project                *
*************************************************/

#include <botan/x509_ext.h>
#include <botan/x509cert.h>
#include <botan/x509stat.h>
#include <botan/libstate.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>
#include <botan/lookup.h>
#include <botan/oids.h>
#include <botan/config.h>
#include <botan/bit_ops.h>
#include <algorithm>
#include <memory>

namespace Botan {

/*************************************************
* Return the OID of this extension               *
*************************************************/
OID Certificate_Extension::oid_of() const
   {
   return OIDS::lookup(oid_name());
   }

/*************************************************
* Encode an Extensions list                      *
*************************************************/
void Extensions::encode_into(DER_Encoder& to_object) const
   {
   for(u32bit j = 0; j != extensions.size(); ++j)
      {
      const Certificate_Extension* ext = extensions[j];

      std::string setting;

      if(ext->config_id() != "")
         setting = global_config().option("x509/exts/" + ext->config_id());

      if(setting == "")
         setting = "yes";

      if(setting != "yes" && setting != "no" && setting != "critical")
         throw Invalid_Argument("X509_CA:: Invalid value for option "
                                "x509/exts/" + ext->config_id() + " of " +
                                setting);

      bool is_critical = (setting == "critical");
      bool should_encode = ext->should_encode() && (setting != "no");

      if(should_encode)
         {
         to_object.start_cons(SEQUENCE)
               .encode(ext->oid_of())
               .encode_optional(is_critical, false)
               .encode(ext->encode_inner(), OCTET_STRING)
            .end_cons();
         }
      }
   }

/*************************************************
* Decode a list of Extensions                    *
*************************************************/
void Extensions::decode_from(BER_Decoder& from_source)
   {
   for(u32bit j = 0; j != extensions.size(); ++j)
      delete extensions[j];
   extensions.clear();

   BER_Decoder sequence = from_source.start_cons(SEQUENCE);
   while(sequence.more_items())
      {
      OID oid;
      MemoryVector<byte> value;
      bool critical;

      sequence.start_cons(SEQUENCE)
            .decode(oid)
            .decode_optional(critical, BOOLEAN, UNIVERSAL, false)
            .decode(value, OCTET_STRING)
            .verify_end()
         .end_cons();

      Certificate_Extension* ext =
         global_state().x509_state().get_extension(oid);

      if(!ext)
         {
         if(!critical || !should_throw)
            continue;

         throw Decoding_Error("Encountered unknown X.509 extension marked "
                              "as critical; OID = " + oid.as_string());
         }

      ext->decode_inner(value);

      extensions.push_back(ext);
      }
   sequence.verify_end();
   }

/*************************************************
* Write the extensions to an info store          *
*************************************************/
void Extensions::contents_to(Data_Store& subject_info,
                             Data_Store& issuer_info) const
   {
   for(u32bit j = 0; j != extensions.size(); ++j)
      extensions[j]->contents_to(subject_info, issuer_info);
   }

/*************************************************
* Copy another extensions list                   *
*************************************************/
Extensions& Extensions::copy_this(const Extensions& other)
   {
   for(u32bit j = 0; j != extensions.size(); ++j)
      delete extensions[j];
   extensions.clear();

   for(u32bit j = 0; j != other.extensions.size(); ++j)
      extensions.push_back(other.extensions[j]->copy());

   return (*this);
   }

/*************************************************
* Delete an Extensions list                      *
*************************************************/
Extensions::~Extensions()
   {
   for(u32bit j = 0; j != extensions.size(); ++j)
      delete extensions[j];
   }

namespace Cert_Extension {

/*************************************************
* Checked accessor for the path_limit member     *
*************************************************/
bool Basic_Constraints::get_path_limit() const
   {
   if(!is_ca)
      throw Invalid_State("Basic_Constraints::get_path_limit: Not a CA");
   return path_limit;
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> Basic_Constraints::encode_inner() const
   {
   return DER_Encoder()
      .start_cons(SEQUENCE)
      .encode_if(is_ca,
                 DER_Encoder()
                    .encode(is_ca)
                    .encode_optional(path_limit, NO_CERT_PATH_LIMIT)
         )
      .end_cons()
   .get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void Basic_Constraints::decode_inner(const MemoryRegion<byte>& in)
   {
   BER_Decoder(in)
      .start_cons(SEQUENCE)
         .decode_optional(is_ca, BOOLEAN, UNIVERSAL, false)
         .decode_optional(path_limit, INTEGER, UNIVERSAL, NO_CERT_PATH_LIMIT)
         .verify_end()
      .end_cons();

   if(is_ca == false)
      path_limit = 0;
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void Basic_Constraints::contents_to(Data_Store& subject, Data_Store&) const
   {
   subject.add("X509v3.BasicConstraints.is_ca", (is_ca ? 1 : 0));
   subject.add("X509v3.BasicConstraints.path_constraint", path_limit);
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> Key_Usage::encode_inner() const
   {
   if(constraints == NO_CONSTRAINTS)
      throw Encoding_Error("Cannot encode zero usage constraints");

   const u32bit unused_bits = low_bit(constraints) - 1;

   SecureVector<byte> der;
   der.append(BIT_STRING);
   der.append(2 + ((unused_bits < 8) ? 1 : 0));
   der.append(unused_bits % 8);
   der.append((constraints >> 8) & 0xFF);
   if(constraints & 0xFF)
      der.append(constraints & 0xFF);

   return der;
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void Key_Usage::decode_inner(const MemoryRegion<byte>& in)
   {
   BER_Decoder ber(in);

   BER_Object obj = ber.get_next_object();

   if(obj.type_tag != BIT_STRING || obj.class_tag != UNIVERSAL)
      throw BER_Bad_Tag("Bad tag for usage constraint",
                        obj.type_tag, obj.class_tag);

   if(obj.value.size() != 2 && obj.value.size() != 3)
      throw BER_Decoding_Error("Bad size for BITSTRING in usage constraint");

   if(obj.value[0] >= 8)
      throw BER_Decoding_Error("Invalid unused bits in usage constraint");

   obj.value[obj.value.size()-1] &= (0xFF << obj.value[0]);

   u16bit usage = 0;
   for(u32bit j = 1; j != obj.value.size(); ++j)
      usage = (obj.value[j] << 8) | usage;

   constraints = Key_Constraints(usage);
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void Key_Usage::contents_to(Data_Store& subject, Data_Store&) const
   {
   subject.add("X509v3.KeyUsage", constraints);
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> Subject_Key_ID::encode_inner() const
   {
   return DER_Encoder().encode(key_id, OCTET_STRING).get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void Subject_Key_ID::decode_inner(const MemoryRegion<byte>& in)
   {
   BER_Decoder(in).decode(key_id, OCTET_STRING).verify_end();
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void Subject_Key_ID::contents_to(Data_Store& subject, Data_Store&) const
   {
   subject.add("X509v3.SubjectKeyIdentifier", key_id);
   }

/*************************************************
* Subject_Key_ID Constructor                     *
*************************************************/
Subject_Key_ID::Subject_Key_ID(const MemoryRegion<byte>& pub_key)
   {
   std::auto_ptr<HashFunction> hash(get_hash("SHA-1"));
   key_id = hash->process(pub_key);
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> Authority_Key_ID::encode_inner() const
   {
   return DER_Encoder()
         .start_cons(SEQUENCE)
            .encode(key_id, OCTET_STRING, ASN1_Tag(0), CONTEXT_SPECIFIC)
         .end_cons()
      .get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void Authority_Key_ID::decode_inner(const MemoryRegion<byte>& in)
   {
   BER_Decoder(in)
      .start_cons(SEQUENCE)
      .decode_optional_string(key_id, OCTET_STRING, 0);
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void Authority_Key_ID::contents_to(Data_Store&, Data_Store& issuer) const
   {
   if(key_id.size())
      issuer.add("X509v3.AuthorityKeyIdentifier", key_id);
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> Alternative_Name::encode_inner() const
   {
   return DER_Encoder().encode(alt_name).get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void Alternative_Name::decode_inner(const MemoryRegion<byte>& in)
   {
   BER_Decoder(in).decode(alt_name);
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void Alternative_Name::contents_to(Data_Store& subject_info,
                                   Data_Store& issuer_info) const
   {
   std::multimap<std::string, std::string> contents =
      get_alt_name().contents();

   if(oid_name_str == "X509v3.SubjectAlternativeName")
      subject_info.add(contents);
   else if(oid_name_str == "X509v3.IssuerAlternativeName")
      issuer_info.add(contents);
   else
      throw Internal_Error("In Alternative_Name, unknown type " +
                           oid_name_str);
   }

/*************************************************
* Alternative_Name Constructor                   *
*************************************************/
Alternative_Name::Alternative_Name(const AlternativeName& alt_name,
                                   const std::string& oid_name_str,
                                   const std::string& config_name_str)
   {
   this->alt_name = alt_name;
   this->oid_name_str = oid_name_str;
   this->config_name_str = config_name_str;
   }

/*************************************************
* Subject_Alternative_Name Constructor           *
*************************************************/
Subject_Alternative_Name::Subject_Alternative_Name(
   const AlternativeName& name) :

   Alternative_Name(name, "X509v3.SubjectAlternativeName",
                    "subject_alternative_name")
   {
   }

/*************************************************
* Issuer_Alternative_Name Constructor           *
*************************************************/
Issuer_Alternative_Name::Issuer_Alternative_Name(const AlternativeName& name) :
   Alternative_Name(name, "X509v3.IssuerAlternativeName",
                    "issuer_alternative_name")
   {
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> Extended_Key_Usage::encode_inner() const
   {
   return DER_Encoder()
      .start_cons(SEQUENCE)
         .encode_list(oids)
      .end_cons()
   .get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void Extended_Key_Usage::decode_inner(const MemoryRegion<byte>& in)
   {
   BER_Decoder(in)
      .start_cons(SEQUENCE)
         .decode_list(oids)
      .end_cons();
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void Extended_Key_Usage::contents_to(Data_Store& subject, Data_Store&) const
   {
   for(u32bit j = 0; j != oids.size(); ++j)
      subject.add("X509v3.ExtendedKeyUsage", oids[j].as_string());
   }

namespace {

/*************************************************
* A policy specifier                             *
*************************************************/
class Policy_Information : public ASN1_Object
   {
   public:
      OID oid;

      void encode_into(DER_Encoder& codec) const
         {
         codec.start_cons(SEQUENCE)
            .encode(oid)
            .end_cons();
         }

      void decode_from(BER_Decoder& codec)
         {
         codec.start_cons(SEQUENCE)
            .decode(oid)
            .discard_remaining()
            .end_cons();
         }
   };

}

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> Certificate_Policies::encode_inner() const
   {
   throw Exception("Certificate_Policies::encode_inner: Bugged");

   std::vector<Policy_Information> policies;

   return DER_Encoder()
      .start_cons(SEQUENCE)
         .encode_list(policies)
      .end_cons()
   .get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void Certificate_Policies::decode_inner(const MemoryRegion<byte>& in)
   {
   std::vector<Policy_Information> policies;

   BER_Decoder(in)
      .start_cons(SEQUENCE)
         .decode_list(policies)
      .end_cons();
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void Certificate_Policies::contents_to(Data_Store& info, Data_Store&) const
   {
   for(u32bit j = 0; j != oids.size(); ++j)
      info.add("X509v3.ExtendedKeyUsage", oids[j].as_string());
   }

/*************************************************
* Checked accessor for the crl_number member     *
*************************************************/
u32bit CRL_Number::get_crl_number() const
   {
   if(!has_value)
      throw Invalid_State("CRL_Number::get_crl_number: Not set");
   return crl_number;
   }

/*************************************************
* Copy a CRL_Number extension                    *
*************************************************/
CRL_Number* CRL_Number::copy() const
   {
   if(!has_value)
      throw Invalid_State("CRL_Number::copy: Not set");
   return new CRL_Number(crl_number);
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> CRL_Number::encode_inner() const
   {
   return DER_Encoder().encode(crl_number).get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void CRL_Number::decode_inner(const MemoryRegion<byte>& in)
   {
   BER_Decoder(in).decode(crl_number);
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void CRL_Number::contents_to(Data_Store& info, Data_Store&) const
   {
   info.add("X509v3.CRLNumber", crl_number);
   }

/*************************************************
* Encode the extension                           *
*************************************************/
MemoryVector<byte> CRL_ReasonCode::encode_inner() const
   {
   return DER_Encoder()
      .encode((u32bit)reason, ENUMERATED, UNIVERSAL)
   .get_contents();
   }

/*************************************************
* Decode the extension                           *
*************************************************/
void CRL_ReasonCode::decode_inner(const MemoryRegion<byte>& in)
   {
   u32bit reason_code = 0;
   BER_Decoder(in).decode(reason_code, ENUMERATED, UNIVERSAL);
   reason = (CRL_Code)reason_code;
   }

/*************************************************
* Return a textual representation                *
*************************************************/
void CRL_ReasonCode::contents_to(Data_Store& info, Data_Store&) const
   {
   info.add("X509v3.CRLReasonCode", reason);
   }

}

}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit (ITK)
  Module:
  Language:  C++
  Date:
  Version:

Copyright (c) 2000 National Library of Medicine
All rights reserved.

See COPYRIGHT.txt for copyright details.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>
// This file has been generated by BuildHeaderTest.tcl
// Test to include each header file for Insight

#include "itkAnalyzeDbh.h"
#include "itkAnalyzeImageIO.h"
#include "itkAnalyzeImageIOFactory.h"
#include "itkBrains2HeaderBase.h"
#include "itkBrains2HeaderFactory.h"
#include "itkBrains2IPLHeaderInfo.h"
#include "itkBrains2MaskHeaderInfo.h"
#include "itkBrains2MaskImageIO.h"
#include "itkBrains2MaskImageIOFactory.h"
#include "itkConvertPixelBuffer.txx"
#include "itkDICOMImageIO2.h"
#include "itkDICOMImageIO2Factory.h"
#include "itkDICOMSeriesFileNames.h"
#include "itkDefaultConvertPixelTraits.h"
#include "itkDicomImageIO.h"
#include "itkDicomImageIOFactory.h"
#include "itkFileIteratorBase.h"
#include "itkGE4ImageIO.h"
#include "itkGE4ImageIOFactory.h"
#include "itkGE5ImageIO.h"
#include "itkGE5ImageIOFactory.h"
#include "itkGEAdwImageIO.h"
#include "itkGEAdwImageIOFactory.h"
#include "itkGEImageHeader.h"
#include "itkGiplImageIO.h"
#include "itkGiplImageIOFactory.h"
#include "itkIOCommon.h"
#include "itkIPLCommonImageIO.h"
#include "itkImageFileReader.txx"
#include "itkImageFileWriter.txx"
#include "itkImageIOBase.h"
#include "itkImageIOFactory.h"
#include "itkImageIORegion.h"
#include "itkImageSeriesReader.txx"
#include "itkImageSeriesWriter.txx"
#include "itkImageWriter.txx"
#include "itkMetaImageIO.h"
#include "itkMetaImageIOFactory.h"
#include "itkMvtSunf.h"
#include "itkNumericSeriesFileNames.h"
#include "itkPNGImageIO.h"
#include "itkPNGImageIOFactory.h"
#include "itkPixelData.h"
#include "itkPolygonGroupSpatialObjectXMLFile.h"
#include "itkRawImageIO.txx"
#include "itkRawImageWriter.txx"
#include "itkRegularExpressionSeriesFileNames.h"
#include "itkSiemensVisionImageIO.h"
#include "itkSiemensVisionImageIOFactory.h"
#include "itkStimulateImageIO.h"
#include "itkStimulateImageIOFactory.h"
#include "itkVOLImageIO.h"
#include "itkVOLImageIOFactory.h"
#include "itkVTKImageIO.h"
#include "itkVTKImageIOFactory.h"
#include "itkWriter.h"
#include "itkXMLFile.h"

int main ( int , char*  )
{

  return 0;
}

<commit_msg>FIX: ImageWriter class was removed.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit (ITK)
  Module:
  Language:  C++
  Date:
  Version:

Copyright (c) 2000 National Library of Medicine
All rights reserved.

See COPYRIGHT.txt for copyright details.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>
// This file has been generated by BuildHeaderTest.tcl
// Test to include each header file for Insight

#include "itkAnalyzeDbh.h"
#include "itkAnalyzeImageIO.h"
#include "itkAnalyzeImageIOFactory.h"
#include "itkBrains2HeaderBase.h"
#include "itkBrains2HeaderFactory.h"
#include "itkBrains2IPLHeaderInfo.h"
#include "itkBrains2MaskHeaderInfo.h"
#include "itkBrains2MaskImageIO.h"
#include "itkBrains2MaskImageIOFactory.h"
#include "itkConvertPixelBuffer.txx"
#include "itkDICOMImageIO2.h"
#include "itkDICOMImageIO2Factory.h"
#include "itkDICOMSeriesFileNames.h"
#include "itkDefaultConvertPixelTraits.h"
#include "itkDicomImageIO.h"
#include "itkDicomImageIOFactory.h"
#include "itkFileIteratorBase.h"
#include "itkGE4ImageIO.h"
#include "itkGE4ImageIOFactory.h"
#include "itkGE5ImageIO.h"
#include "itkGE5ImageIOFactory.h"
#include "itkGEAdwImageIO.h"
#include "itkGEAdwImageIOFactory.h"
#include "itkGEImageHeader.h"
#include "itkGiplImageIO.h"
#include "itkGiplImageIOFactory.h"
#include "itkIOCommon.h"
#include "itkIPLCommonImageIO.h"
#include "itkImageFileReader.txx"
#include "itkImageFileWriter.txx"
#include "itkImageIOBase.h"
#include "itkImageIOFactory.h"
#include "itkImageIORegion.h"
#include "itkImageSeriesReader.txx"
#include "itkImageSeriesWriter.txx"
#include "itkMetaImageIO.h"
#include "itkMetaImageIOFactory.h"
#include "itkMvtSunf.h"
#include "itkNumericSeriesFileNames.h"
#include "itkPNGImageIO.h"
#include "itkPNGImageIOFactory.h"
#include "itkPixelData.h"
#include "itkPolygonGroupSpatialObjectXMLFile.h"
#include "itkRawImageIO.txx"
#include "itkRawImageWriter.txx"
#include "itkRegularExpressionSeriesFileNames.h"
#include "itkSiemensVisionImageIO.h"
#include "itkSiemensVisionImageIOFactory.h"
#include "itkStimulateImageIO.h"
#include "itkStimulateImageIOFactory.h"
#include "itkVOLImageIO.h"
#include "itkVOLImageIOFactory.h"
#include "itkVTKImageIO.h"
#include "itkVTKImageIOFactory.h"
#include "itkWriter.h"
#include "itkXMLFile.h"

int main ( int , char*  )
{

  return 0;
}

<|endoftext|>


<commit_before>//
//  xptimers.cpp
//  xlua
//
//  Created by Benjamin Supnik on 4/13/16.
//
//	Copyright 2016, Laminar Research
//	This source code is licensed under the MIT open source license.
//	See LICENSE.txt for the full terms of the license.

#include "xptimers.h"
#include <stdlib.h>
#include <stdio.h>
#include <XPLMProcessing.h>

struct xlua_timer {
	xlua_timer *		m_next;
	xlua_timer_f 	m_func;
	void *			m_ref;

	double			m_next_fire_time;
	double			m_repeat_interval;	// -1 to stop after 1

};

static xlua_timer * s_timers;

xlua_timer * xlua_create_timer(xlua_timer_f func, void * ref)
{
	for(xlua_timer * t = s_timers; t; t = t->m_next)
	if(t->m_func == func && t->m_ref == ref)
	{
		printf("ERROR: timer already exists.");
		return NULL;
	}

	xlua_timer * nt = new xlua_timer;
	nt->m_next = s_timers;
	s_timers = nt;
	nt->m_next_fire_time = -1.0;
	nt->m_repeat_interval = -1.0;
	nt->m_func = func;
	nt->m_ref = ref;
	return nt;
}

void xlua_run_timer(xlua_timer * t, double delay, double repeat)
{
	t->m_repeat_interval = repeat;
	if(delay == -1.0)
		t->m_next_fire_time = delay;
	else
		t->m_next_fire_time = XPLMGetElapsedTime() + delay;
}

int xlua_is_timer_scheduled(xlua_timer * t)
{
	if(t == NULL)
		return 0;
	if(t->m_next_fire_time == -1.0)
		return 0;
	return 1;
}

void xlua_do_timers_for_time(double now)
{
	for(xlua_timer * t = s_timers; t; t = t->m_next)
	if(t->m_next_fire_time != -1.0 && t->m_next_fire_time <= now)
	{
		t->m_func(t->m_ref);
		if(t->m_repeat_interval == -1.0)
			t->m_next_fire_time = -1.0;
		else
			t->m_next_fire_time += t->m_repeat_interval;
	}
}

void xlua_timer_cleanup()
{
	while(s_timers)
	{
		xlua_timer * k = s_timers;
		s_timers = s_timers->m_next;
		delete k;
	}
}
<commit_msg>includes fixed for building on Ubuntu 14.04<commit_after>//
//  xptimers.cpp
//  xlua
//
//  Created by Benjamin Supnik on 4/13/16.
//
//	Copyright 2016, Laminar Research
//	This source code is licensed under the MIT open source license.
//	See LICENSE.txt for the full terms of the license.

#include <cstdio>
#include "xptimers.h"
#include <stdlib.h>
#include <stdio.h>
#include <XPLMProcessing.h>

struct xlua_timer {
	xlua_timer *		m_next;
	xlua_timer_f 	m_func;
	void *			m_ref;

	double			m_next_fire_time;
	double			m_repeat_interval;	// -1 to stop after 1

};

static xlua_timer * s_timers;

xlua_timer * xlua_create_timer(xlua_timer_f func, void * ref)
{
	for(xlua_timer * t = s_timers; t; t = t->m_next)
	if(t->m_func == func && t->m_ref == ref)
	{
		printf("ERROR: timer already exists.");
		return NULL;
	}

	xlua_timer * nt = new xlua_timer;
	nt->m_next = s_timers;
	s_timers = nt;
	nt->m_next_fire_time = -1.0;
	nt->m_repeat_interval = -1.0;
	nt->m_func = func;
	nt->m_ref = ref;
	return nt;
}

void xlua_run_timer(xlua_timer * t, double delay, double repeat)
{
	t->m_repeat_interval = repeat;
	if(delay == -1.0)
		t->m_next_fire_time = delay;
	else
		t->m_next_fire_time = XPLMGetElapsedTime() + delay;
}

int xlua_is_timer_scheduled(xlua_timer * t)
{
	if(t == NULL)
		return 0;
	if(t->m_next_fire_time == -1.0)
		return 0;
	return 1;
}

void xlua_do_timers_for_time(double now)
{
	for(xlua_timer * t = s_timers; t; t = t->m_next)
	if(t->m_next_fire_time != -1.0 && t->m_next_fire_time <= now)
	{
		t->m_func(t->m_ref);
		if(t->m_repeat_interval == -1.0)
			t->m_next_fire_time = -1.0;
		else
			t->m_next_fire_time += t->m_repeat_interval;
	}
}

void xlua_timer_cleanup()
{
	while(s_timers)
	{
		xlua_timer * k = s_timers;
		s_timers = s_timers->m_next;
		delete k;
	}
}
<|endoftext|>


<commit_before>//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "Backend.h"

NativeCodeGenerator *
NewNativeCodeGenerator(Js::ScriptContext * scriptContext)
{
    return HeapNew(NativeCodeGenerator, scriptContext);
}

void
DeleteNativeCodeGenerator(NativeCodeGenerator * nativeCodeGen)
{
    HeapDelete(nativeCodeGen);
}

void
CloseNativeCodeGenerator(NativeCodeGenerator * nativeCodeGen)
{
    nativeCodeGen->Close();
}

bool
IsClosedNativeCodeGenerator(NativeCodeGenerator * nativeCodeGen)
{
    return nativeCodeGen->IsClosed();
}

void SetProfileModeNativeCodeGen(NativeCodeGenerator *pNativeCodeGen, BOOL fSet)
{
    pNativeCodeGen->SetProfileMode(fSet);
}

void UpdateNativeCodeGeneratorForDebugMode(NativeCodeGenerator* nativeCodeGen)
{
    nativeCodeGen->UpdateQueueForDebugMode();
}

CriticalSection *GetNativeCodeGenCriticalSection(NativeCodeGenerator *pNativeCodeGen)
{
    return pNativeCodeGen->Processor()->GetCriticalSection();
}

///----------------------------------------------------------------------------
///
/// GenerateFunction
///
///     This is the main entry point for the runtime to call the native code
///     generator for js function.
///
///----------------------------------------------------------------------------

void
GenerateFunction(NativeCodeGenerator * nativeCodeGen, Js::FunctionBody * fn, Js::ScriptFunction * function)
{
    nativeCodeGen->GenerateFunction(fn, function);
}
InProcCodeGenAllocators* GetForegroundAllocator(NativeCodeGenerator * nativeCodeGen, PageAllocator* pageallocator)
{
    return nativeCodeGen->GetCodeGenAllocator(pageallocator);
}
#ifdef ENABLE_PREJIT
void
GenerateAllFunctions(NativeCodeGenerator * nativeCodeGen, Js::FunctionBody *fn)
{
    nativeCodeGen->GenerateAllFunctions(fn);
}
#endif
#ifdef IR_VIEWER
Js::Var
RejitIRViewerFunction(NativeCodeGenerator *nativeCodeGen, Js::FunctionBody *fn, Js::ScriptContext *scriptContext)
{
    return nativeCodeGen->RejitIRViewerFunction(fn, scriptContext);
}
#endif

void
GenerateLoopBody(NativeCodeGenerator *nativeCodeGen, Js::FunctionBody *fn, Js::LoopHeader * loopHeader, Js::EntryPointInfo* info, uint localCount, Js::Var localSlots[])
{
    nativeCodeGen->GenerateLoopBody(fn, loopHeader, info, localCount, localSlots);
}

void
NativeCodeGenEnterScriptStart(NativeCodeGenerator * nativeCodeGen)
{
    if (nativeCodeGen)
    {
        nativeCodeGen->EnterScriptStart();
    }
}

BOOL IsIntermediateCodeGenThunk(Js::JavascriptMethod codeAddress)
{
    return NativeCodeGenerator::IsThunk(codeAddress);
}

BOOL IsAsmJsCodeGenThunk(Js::JavascriptMethod codeAddress)
{
    return NativeCodeGenerator::IsAsmJsCodeGenThunk(codeAddress);
}

CheckCodeGenFunction GetCheckCodeGenFunction(Js::JavascriptMethod codeAddress)
{
    return NativeCodeGenerator::GetCheckCodeGenFunction(codeAddress);
}

Js::JavascriptMethod GetCheckCodeGenThunk()
{
    return NativeCodeGenerator::CheckCodeGenThunk;
}

#ifdef ASMJS_PLAT
Js::JavascriptMethod GetCheckAsmJsCodeGenThunk()
{
    return NativeCodeGenerator::CheckAsmJsCodeGenThunk;
}
#endif

uint GetBailOutRegisterSaveSlotCount()
{
    // REVIEW: not all registers are used, we are allocating more space then necessary.
    return LinearScanMD::GetRegisterSaveSlotCount();
}

uint
GetBailOutReserveSlotCount()
{
    return 1; //For arguments id
}

#if DBG
void CheckIsExecutable(Js::RecyclableObject * function, Js::JavascriptMethod entrypoint)
{
    Js::ScriptContext * scriptContext = function->GetScriptContext();
    // it's easy to call the default entry point from RecyclableObject.
    AssertMsg((Js::JavascriptFunction::Is(function) && Js::JavascriptFunction::FromVar(function)->IsExternalFunction())
        || Js::CrossSite::IsThunk(entrypoint) || !scriptContext->IsActuallyClosed() ||
        (scriptContext->GetThreadContext()->IsScriptActive() && !Js::JavascriptConversion::IsCallable(function)),
        "Can't call function when the script context is closed");

    if (scriptContext->GetThreadContext()->IsScriptActive())
    {
        return;
    }
    if (function->IsExternal())
    {
        return;
    }

    Js::TypeId typeId = Js::JavascriptOperators::GetTypeId(function);
    if (typeId == Js::TypeIds_HostDispatch)
    {
        AssertMsg(false, "Has to go through CallRootFunction to start calling Javascript function");
    }
    else if (typeId == Js::TypeId::TypeIds_Function)
    {
        if (((Js::JavascriptFunction*)function)->IsExternalFunction())
        {
            return;
        }
        else if (((Js::JavascriptFunction*)function)->IsWinRTFunction())
        {
            return;
        }
        else
        {
            AssertMsg(false, "Has to go through CallRootFunction to start calling Javascript function");
        }
    }
    else
    {
        AssertMsg(false, "Has to go through CallRootFunction to start calling Javascript function");
    }
}
#endif

#ifdef PROFILE_EXEC
void
CreateProfilerNativeCodeGen(NativeCodeGenerator * nativeCodeGen, Js::ScriptContextProfiler * profiler)
{
    nativeCodeGen->CreateProfiler(profiler);
}

void
ProfilePrintNativeCodeGen(NativeCodeGenerator * nativeCodeGen)
{
    nativeCodeGen->ProfilePrint();
}

void
SetProfilerFromNativeCodeGen(NativeCodeGenerator * toNativeCodeGen, NativeCodeGenerator * fromNativeCodeGen)
{
    toNativeCodeGen->SetProfilerFromNativeCodeGen(fromNativeCodeGen);
}
#endif

void DeleteNativeCodeData(NativeCodeData * data)
{
    if (data)
    {
        HeapDelete(data);
    }
}
<commit_msg>[MERGE #4297 @tcare] Relax noisy CheckIsExecutable assert<commit_after>//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "Backend.h"

NativeCodeGenerator *
NewNativeCodeGenerator(Js::ScriptContext * scriptContext)
{
    return HeapNew(NativeCodeGenerator, scriptContext);
}

void
DeleteNativeCodeGenerator(NativeCodeGenerator * nativeCodeGen)
{
    HeapDelete(nativeCodeGen);
}

void
CloseNativeCodeGenerator(NativeCodeGenerator * nativeCodeGen)
{
    nativeCodeGen->Close();
}

bool
IsClosedNativeCodeGenerator(NativeCodeGenerator * nativeCodeGen)
{
    return nativeCodeGen->IsClosed();
}

void SetProfileModeNativeCodeGen(NativeCodeGenerator *pNativeCodeGen, BOOL fSet)
{
    pNativeCodeGen->SetProfileMode(fSet);
}

void UpdateNativeCodeGeneratorForDebugMode(NativeCodeGenerator* nativeCodeGen)
{
    nativeCodeGen->UpdateQueueForDebugMode();
}

CriticalSection *GetNativeCodeGenCriticalSection(NativeCodeGenerator *pNativeCodeGen)
{
    return pNativeCodeGen->Processor()->GetCriticalSection();
}

///----------------------------------------------------------------------------
///
/// GenerateFunction
///
///     This is the main entry point for the runtime to call the native code
///     generator for js function.
///
///----------------------------------------------------------------------------

void
GenerateFunction(NativeCodeGenerator * nativeCodeGen, Js::FunctionBody * fn, Js::ScriptFunction * function)
{
    nativeCodeGen->GenerateFunction(fn, function);
}
InProcCodeGenAllocators* GetForegroundAllocator(NativeCodeGenerator * nativeCodeGen, PageAllocator* pageallocator)
{
    return nativeCodeGen->GetCodeGenAllocator(pageallocator);
}
#ifdef ENABLE_PREJIT
void
GenerateAllFunctions(NativeCodeGenerator * nativeCodeGen, Js::FunctionBody *fn)
{
    nativeCodeGen->GenerateAllFunctions(fn);
}
#endif
#ifdef IR_VIEWER
Js::Var
RejitIRViewerFunction(NativeCodeGenerator *nativeCodeGen, Js::FunctionBody *fn, Js::ScriptContext *scriptContext)
{
    return nativeCodeGen->RejitIRViewerFunction(fn, scriptContext);
}
#endif

void
GenerateLoopBody(NativeCodeGenerator *nativeCodeGen, Js::FunctionBody *fn, Js::LoopHeader * loopHeader, Js::EntryPointInfo* info, uint localCount, Js::Var localSlots[])
{
    nativeCodeGen->GenerateLoopBody(fn, loopHeader, info, localCount, localSlots);
}

void
NativeCodeGenEnterScriptStart(NativeCodeGenerator * nativeCodeGen)
{
    if (nativeCodeGen)
    {
        nativeCodeGen->EnterScriptStart();
    }
}

BOOL IsIntermediateCodeGenThunk(Js::JavascriptMethod codeAddress)
{
    return NativeCodeGenerator::IsThunk(codeAddress);
}

BOOL IsAsmJsCodeGenThunk(Js::JavascriptMethod codeAddress)
{
    return NativeCodeGenerator::IsAsmJsCodeGenThunk(codeAddress);
}

CheckCodeGenFunction GetCheckCodeGenFunction(Js::JavascriptMethod codeAddress)
{
    return NativeCodeGenerator::GetCheckCodeGenFunction(codeAddress);
}

Js::JavascriptMethod GetCheckCodeGenThunk()
{
    return NativeCodeGenerator::CheckCodeGenThunk;
}

#ifdef ASMJS_PLAT
Js::JavascriptMethod GetCheckAsmJsCodeGenThunk()
{
    return NativeCodeGenerator::CheckAsmJsCodeGenThunk;
}
#endif

uint GetBailOutRegisterSaveSlotCount()
{
    // REVIEW: not all registers are used, we are allocating more space then necessary.
    return LinearScanMD::GetRegisterSaveSlotCount();
}

uint
GetBailOutReserveSlotCount()
{
    return 1; //For arguments id
}

#if DBG
void CheckIsExecutable(Js::RecyclableObject * function, Js::JavascriptMethod entrypoint)
{
    Js::ScriptContext * scriptContext = function->GetScriptContext();
    // it's easy to call the default entry point from RecyclableObject.
    AssertMsg((Js::JavascriptFunction::Is(function) && Js::JavascriptFunction::FromVar(function)->IsExternalFunction())
        || Js::CrossSite::IsThunk(entrypoint)
        // External object with entrypoint
        || (!Js::JavascriptFunction::Is(function)
            && function->IsExternal()
            && Js::JavascriptConversion::IsCallable(function))
        || !scriptContext->IsActuallyClosed()
        || (scriptContext->GetThreadContext()->IsScriptActive() && !Js::JavascriptConversion::IsCallable(function)),
        "Can't call function when the script context is closed");

    if (scriptContext->GetThreadContext()->IsScriptActive())
    {
        return;
    }
    if (function->IsExternal())
    {
        return;
    }

    Js::TypeId typeId = Js::JavascriptOperators::GetTypeId(function);
    if (typeId == Js::TypeIds_HostDispatch)
    {
        AssertMsg(false, "Has to go through CallRootFunction to start calling Javascript function");
    }
    else if (typeId == Js::TypeId::TypeIds_Function)
    {
        if (((Js::JavascriptFunction*)function)->IsExternalFunction())
        {
            return;
        }
        else if (((Js::JavascriptFunction*)function)->IsWinRTFunction())
        {
            return;
        }
        else
        {
            AssertMsg(false, "Has to go through CallRootFunction to start calling Javascript function");
        }
    }
    else
    {
        AssertMsg(false, "Has to go through CallRootFunction to start calling Javascript function");
    }
}
#endif

#ifdef PROFILE_EXEC
void
CreateProfilerNativeCodeGen(NativeCodeGenerator * nativeCodeGen, Js::ScriptContextProfiler * profiler)
{
    nativeCodeGen->CreateProfiler(profiler);
}

void
ProfilePrintNativeCodeGen(NativeCodeGenerator * nativeCodeGen)
{
    nativeCodeGen->ProfilePrint();
}

void
SetProfilerFromNativeCodeGen(NativeCodeGenerator * toNativeCodeGen, NativeCodeGenerator * fromNativeCodeGen)
{
    toNativeCodeGen->SetProfilerFromNativeCodeGen(fromNativeCodeGen);
}
#endif

void DeleteNativeCodeData(NativeCodeData * data)
{
    if (data)
    {
        HeapDelete(data);
    }
}
<|endoftext|>


<commit_before>/**
 * Copyright 2015 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.
 */

#include "jvm_class_metadata_reader.h"

#include <algorithm>
#include "jni_utils.h"
#include "jvm_instance_field_reader.h"
#include "jvm_static_field_reader.h"
#include "jvmti_buffer.h"
#include "jni_proxy_object.h"

namespace devtools {
namespace cdbg {

static void ReleaseEntryRefs(jobject cls, ClassMetadataReader::Entry* entry) {
  for (auto& static_field_reader : entry->static_fields) {
    static_field_reader->ReleaseRef();
  }
}

JvmClassMetadataReader::JvmClassMetadataReader(
    DataVisibilityPolicy* data_visibility_policy)
    : data_visibility_policy_(data_visibility_policy),
      cls_cache_(ReleaseEntryRefs) {
}

JvmClassMetadataReader::~JvmClassMetadataReader() {
}

const ClassMetadataReader::Entry&
JvmClassMetadataReader::GetClassMetadata(jclass cls) {
  // Safeguard against null references.
  DCHECK(cls != nullptr);
  if (cls == nullptr) {
    static Entry empty_class_metadata;
    return empty_class_metadata;
  }

  // Case 1: the class information is cached.
  {
    MutexLock reader_lock(&mu_);

    const Entry* metadata = cls_cache_.Find(cls);
    if (metadata != nullptr) {
      // It is safe to return reference to "jobject_map" entry. "jobject_map"
      // guarantees that the elements are not moved when data structure is
      // expanded or contracted.
      return *metadata;
    }
  }

  // Case 2: we need to load the class information.
  {
    Entry metadata;
    LoadClassMetadata(cls, &metadata);

    {
      MutexLock writer_lock(&mu_);

      cls_cache_.Insert(cls, std::move(metadata));

      // Return currently or previously inserted entry. Returning reference to
      // "jobject_map" entry as in case 1.
      return *cls_cache_.Find(cls);
    }
  }
}

void JvmClassMetadataReader::LoadClassMetadata(jclass cls, Entry* metadata) {
  string signature = GetClassSignature(cls);
  if (signature.empty()) {
    return;
  }

  metadata->signature = JSignatureFromSignature(signature);

  // Start from the current class and go down the inheritance chain.
  JniLocalRef current_class_ref = JniNewLocalRef(cls);

  // Maintain set of methods we discovered in superclasses to ignore those
  // in base classes. The pair stores method name and signature.
  std::set<std::pair<string, string>> registered_methods;

  while (current_class_ref != nullptr) {
    LoadSingleClassMetadata(
        static_cast<jclass>(current_class_ref.get()),
        &registered_methods,
        metadata);

    LoadImplementedInterfacesMetadata(
        static_cast<jclass>(current_class_ref.get()),
        &registered_methods,
        metadata);

    // Free the current local reference and allocate a new local reference
    // corresponding to the superclass of "current_class_ref".
    JniLocalRef next(
        jni()->GetSuperclass(static_cast<jclass>(current_class_ref.get())));

    // Don't skip "java.lang.Object" even if "cls" is an interface.
    if ((next == nullptr) &&
        !jni()->IsSameObject(current_class_ref.get(),
                             jniproxy::Object()->GetClass())) {
      LoadSingleClassMetadata(
          jniproxy::Object()->GetClass(),
          &registered_methods,
          metadata);
    }

    current_class_ref = std::move(next);
  }

  // Reverse the the lists to accomodate for LoadFieldInfo appending new
  // elements to the end of the list.
  std::reverse(
      metadata->instance_fields.begin(),
      metadata->instance_fields.end());
  std::reverse(
      metadata->static_fields.begin(),
      metadata->static_fields.end());
}

void JvmClassMetadataReader::LoadImplementedInterfacesMetadata(
    jclass parent,
    std::set<std::pair<string, string>>* registered_methods,
    Entry* metadata) {
  jvmtiError err = JVMTI_ERROR_NONE;

  jint count = 0;
  JvmtiBuffer<jclass> interfaces;
  err = jvmti()->GetImplementedInterfaces(parent, &count, interfaces.ref());
  if (err != JVMTI_ERROR_NONE) {
    LOG(ERROR) << "GetImplementedInterfaces failed, error: " << err;
    return;
  }

  for (int i = 0; i < count; ++i) {
    jclass interface = interfaces.get()[i];
    LoadSingleClassMetadata(interface, registered_methods, metadata);
    LoadImplementedInterfacesMetadata(interface, registered_methods, metadata);
  }
}

void JvmClassMetadataReader::LoadSingleClassMetadata(
    jclass cls,
    std::set<std::pair<string, string>>* registered_methods,
    Entry* metadata) {
  jvmtiError err = JVMTI_ERROR_NONE;

  string class_signature = GetClassSignature(cls);
  if (class_signature.empty()) {
    return;
  }

  // Get the visibility policy for the current class.
  std::unique_ptr<DataVisibilityPolicy::Class> class_visibility =
      data_visibility_policy_->GetClassVisibility(cls);

  // Load list of all the fields of the class. This includes both member
  // and static fields.
  jint cls_fields_count = 0;
  JvmtiBuffer<jfieldID> cls_fields;
  err = jvmti()->GetClassFields(cls, &cls_fields_count, cls_fields.ref());
  if (err != JVMTI_ERROR_NONE) {
    LOG(ERROR) << "GetClassFields failed, error: " << err;
  } else {
    // Walk fields in reverse order so that the fields from the base class
    // show up before the fields from the subclass.
    for (int i = cls_fields_count - 1; i >= 0; --i) {
      LoadFieldInfo(
          cls,
          class_signature,
          cls_fields.get()[i],
          class_visibility.get(),
          metadata);
    }
  }

  // Load list of all the methods of the class.
  jint methods_count = 0;
  JvmtiBuffer<jmethodID> methods;
  err = jvmti()->GetClassMethods(
      cls,
      &methods_count,
      methods.ref());
  if (err != JVMTI_ERROR_NONE) {
    LOG(ERROR) << "GetClassMethods failed, error: " << err;
  } else {
    // Load metadata of each method. We don't care about the order of methods
    // in the list.
    for (int i = 0; i < methods_count; ++i) {
      Method method_metadata = LoadMethodInfo(
          cls,
          class_signature,
          methods.get()[i],
          class_visibility.get());

      if (method_metadata.name.empty()) {
        continue;
      }

      // If two instance methods have the same arguments, the one in the
      // superclass overrides the one in the base class. This will be true
      // even if return types are difference (this is called covariance).
      std::pair<string, string> key;
      if (method_metadata.is_static()) {
        key = {
          method_metadata.name,
          method_metadata.signature
        };
      } else {
        key = {
          method_metadata.name,
          TrimReturnType(method_metadata.signature)
        };
      }

      // Skip base class methods that the inherited classes overwrote.
      if (registered_methods->find(key) != registered_methods->end()) {
        continue;
      }

      // Add the method to the registry.
      registered_methods->insert(std::move(key));
      metadata->methods.push_back(std::move(method_metadata));
    }
  }
}

void JvmClassMetadataReader::LoadFieldInfo(
    jclass cls,
    const string& class_signature,
    jfieldID field_id,
    DataVisibilityPolicy::Class* class_visibility,
    Entry* metadata) {
  int err = JVMTI_ERROR_NONE;

  jint field_modifiers = 0;
  err = jvmti()->GetFieldModifiers(cls, field_id, &field_modifiers);
  if (err != JVMTI_ERROR_NONE) {
    LOG(ERROR) << "GetFieldModifiers failed, error: " << err;
    return;
  }

  JvmtiBuffer<char> field_name_buffer;
  JvmtiBuffer<char> field_signature_buffer;
  err = jvmti()->GetFieldName(
      cls,
      field_id,
      field_name_buffer.ref(),
      field_signature_buffer.ref(),
      nullptr);
  if (err != JVMTI_ERROR_NONE) {
    LOG(ERROR) << "GetFieldName failed, error: " << err;
    return;
  }

  if ((field_signature_buffer.get() == nullptr) ||
      (field_signature_buffer.get()[0] == '\0')) {
    LOG(ERROR) << "Empty field signature is unexpected";
    return;
  }

  string field_name = field_name_buffer.get();
  string field_signature = field_signature_buffer.get();

  if ((class_visibility != nullptr) &&
      !class_visibility->IsFieldVisible(field_name, field_modifiers)) {
    if ((field_modifiers & JVM_ACC_STATIC) == 0) {
      metadata->instance_fields_omitted = true;
    }
    return;  // Field is invisible.
  }

  if ((field_modifiers & JVM_ACC_STATIC) == 0) {
    // Instance field.
    std::unique_ptr<InstanceFieldReader> reader(
        new JvmInstanceFieldReader(
            field_name,
            field_id,
            JSignatureFromSignature(field_signature)));
    metadata->instance_fields.push_back(std::move(reader));
  } else {
    // Static field.
    std::unique_ptr<StaticFieldReader> reader(
        new JvmStaticFieldReader(
            cls,
            field_name,
            field_id,
            JSignatureFromSignature(field_signature)));
    metadata->static_fields.push_back(std::move(reader));
  }
}

JvmClassMetadataReader::Method JvmClassMetadataReader::LoadMethodInfo(
    jclass cls,
    const string& class_signature,
    jmethodID method_id,
    DataVisibilityPolicy::Class* class_visibility) {
  int err = JVMTI_ERROR_NONE;

  JvmtiBuffer<char> method_name;
  JvmtiBuffer<char> method_signature;
  err = jvmti()->GetMethodName(
      method_id,
      method_name.ref(),
      method_signature.ref(),
      nullptr);
  if (err != JVMTI_ERROR_NONE) {
    LOG(ERROR) << "GetMethodName failed, error: " << err;
    return Method();
  }

  jint method_modifiers = 0;
  err = jvmti()->GetMethodModifiers(method_id, &method_modifiers);
  if (err != JVMTI_ERROR_NONE) {
    LOG(ERROR) << "GetMethodModifiers failed, error: " << err;
    return Method();
  }

  Method method;
  method.class_signature = JSignatureFromSignature(class_signature);
  method.name = method_name.get();
  method.signature = method_signature.get();
  method.modifiers = method_modifiers;

  if ((class_visibility != nullptr) &&
      !class_visibility->IsMethodVisible(
          method.name,
          method.signature,
          method_modifiers)) {
    return Method();  // Method is invisible.
  }

  return method;
}

}  // namespace cdbg
}  // namespace devtools

<commit_msg>Remove the "val$" prefix from all object fields. The "val$" prefix is used for auto-generated variables, and users should be able to see/use them without the "val$" prefix.<commit_after>/**
 * Copyright 2015 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.
 */

#include "jvm_class_metadata_reader.h"

#include <algorithm>
#include "jni_utils.h"
#include "jvm_instance_field_reader.h"
#include "jvm_static_field_reader.h"
#include "jvmti_buffer.h"
#include "jni_proxy_object.h"

namespace devtools {
namespace cdbg {

static void ReleaseEntryRefs(jobject cls, ClassMetadataReader::Entry* entry) {
  for (auto& static_field_reader : entry->static_fields) {
    static_field_reader->ReleaseRef();
  }
}

// Adjusts the names of auto-generated fields by removing the "val$" prefix.
//
// The most important use case is when a local variable "foo" in an outer scope
// is captured in an inner scope. When using Java 8, the variable is added to
// the inner class as a "val$foo" field, but the user expects to see/use it as
// "foo". Therefore, we remove the "val$" prefix. In Java 7, the debugger
// doesn't know about foo at all, so we cannot do anything about it.
//
// Example:
//    String foo;
//    new SomeClass() {
//      @Override
//      String getFoo () {
//        return foo;  // In Java 8, variable foo becomes SomeClass.this.val$foo
//                     // but here we convert it to SomeClass.this.foo
//      }
//    }
static string ProcessFieldName(string name) {
  constexpr char kPrefix[] = "val$";
  constexpr int kPrefixLength = sizeof(kPrefix) / sizeof(kPrefix[0]) - 1;

  if (name.compare(0, kPrefixLength, kPrefix) == 0) {
    return name.substr(kPrefixLength);
  }

  return name;
}

JvmClassMetadataReader::JvmClassMetadataReader(
    DataVisibilityPolicy* data_visibility_policy)
    : data_visibility_policy_(data_visibility_policy),
      cls_cache_(ReleaseEntryRefs) {
}

JvmClassMetadataReader::~JvmClassMetadataReader() {
}

const ClassMetadataReader::Entry&
JvmClassMetadataReader::GetClassMetadata(jclass cls) {
  // Safeguard against null references.
  DCHECK(cls != nullptr);
  if (cls == nullptr) {
    static Entry empty_class_metadata;
    return empty_class_metadata;
  }

  // Case 1: the class information is cached.
  {
    MutexLock reader_lock(&mu_);

    const Entry* metadata = cls_cache_.Find(cls);
    if (metadata != nullptr) {
      // It is safe to return reference to "jobject_map" entry. "jobject_map"
      // guarantees that the elements are not moved when data structure is
      // expanded or contracted.
      return *metadata;
    }
  }

  // Case 2: we need to load the class information.
  {
    Entry metadata;
    LoadClassMetadata(cls, &metadata);

    {
      MutexLock writer_lock(&mu_);

      cls_cache_.Insert(cls, std::move(metadata));

      // Return currently or previously inserted entry. Returning reference to
      // "jobject_map" entry as in case 1.
      return *cls_cache_.Find(cls);
    }
  }
}

void JvmClassMetadataReader::LoadClassMetadata(jclass cls, Entry* metadata) {
  string signature = GetClassSignature(cls);
  if (signature.empty()) {
    return;
  }

  metadata->signature = JSignatureFromSignature(signature);

  // Start from the current class and go down the inheritance chain.
  JniLocalRef current_class_ref = JniNewLocalRef(cls);

  // Maintain set of methods we discovered in superclasses to ignore those
  // in base classes. The pair stores method name and signature.
  std::set<std::pair<string, string>> registered_methods;

  while (current_class_ref != nullptr) {
    LoadSingleClassMetadata(
        static_cast<jclass>(current_class_ref.get()),
        &registered_methods,
        metadata);

    LoadImplementedInterfacesMetadata(
        static_cast<jclass>(current_class_ref.get()),
        &registered_methods,
        metadata);

    // Free the current local reference and allocate a new local reference
    // corresponding to the superclass of "current_class_ref".
    JniLocalRef next(
        jni()->GetSuperclass(static_cast<jclass>(current_class_ref.get())));

    // Don't skip "java.lang.Object" even if "cls" is an interface.
    if ((next == nullptr) &&
        !jni()->IsSameObject(current_class_ref.get(),
                             jniproxy::Object()->GetClass())) {
      LoadSingleClassMetadata(
          jniproxy::Object()->GetClass(),
          &registered_methods,
          metadata);
    }

    current_class_ref = std::move(next);
  }

  // Reverse the lists to accomodate for LoadFieldInfo appending new elements to
  // the end of the list.
  std::reverse(
      metadata->instance_fields.begin(),
      metadata->instance_fields.end());
  std::reverse(
      metadata->static_fields.begin(),
      metadata->static_fields.end());
}

void JvmClassMetadataReader::LoadImplementedInterfacesMetadata(
    jclass parent,
    std::set<std::pair<string, string>>* registered_methods,
    Entry* metadata) {
  jvmtiError err = JVMTI_ERROR_NONE;

  jint count = 0;
  JvmtiBuffer<jclass> interfaces;
  err = jvmti()->GetImplementedInterfaces(parent, &count, interfaces.ref());
  if (err != JVMTI_ERROR_NONE) {
    LOG(ERROR) << "GetImplementedInterfaces failed, error: " << err;
    return;
  }

  for (int i = 0; i < count; ++i) {
    jclass interface = interfaces.get()[i];
    LoadSingleClassMetadata(interface, registered_methods, metadata);
    LoadImplementedInterfacesMetadata(interface, registered_methods, metadata);
  }
}

void JvmClassMetadataReader::LoadSingleClassMetadata(
    jclass cls,
    std::set<std::pair<string, string>>* registered_methods,
    Entry* metadata) {
  jvmtiError err = JVMTI_ERROR_NONE;

  string class_signature = GetClassSignature(cls);
  if (class_signature.empty()) {
    return;
  }

  // Get the visibility policy for the current class.
  std::unique_ptr<DataVisibilityPolicy::Class> class_visibility =
      data_visibility_policy_->GetClassVisibility(cls);

  // Load list of all the fields of the class. This includes both member
  // and static fields.
  jint cls_fields_count = 0;
  JvmtiBuffer<jfieldID> cls_fields;
  err = jvmti()->GetClassFields(cls, &cls_fields_count, cls_fields.ref());
  if (err != JVMTI_ERROR_NONE) {
    LOG(ERROR) << "GetClassFields failed, error: " << err;
  } else {
    // Walk fields in reverse order so that the fields from the base class
    // show up before the fields from the subclass.
    for (int i = cls_fields_count - 1; i >= 0; --i) {
      LoadFieldInfo(
          cls,
          class_signature,
          cls_fields.get()[i],
          class_visibility.get(),
          metadata);
    }
  }

  // Load list of all the methods of the class.
  jint methods_count = 0;
  JvmtiBuffer<jmethodID> methods;
  err = jvmti()->GetClassMethods(
      cls,
      &methods_count,
      methods.ref());
  if (err != JVMTI_ERROR_NONE) {
    LOG(ERROR) << "GetClassMethods failed, error: " << err;
  } else {
    // Load metadata of each method. We don't care about the order of methods
    // in the list.
    for (int i = 0; i < methods_count; ++i) {
      Method method_metadata = LoadMethodInfo(
          cls,
          class_signature,
          methods.get()[i],
          class_visibility.get());

      if (method_metadata.name.empty()) {
        continue;
      }

      // If two instance methods have the same arguments, the one in the
      // superclass overrides the one in the base class. This will be true
      // even if return types are difference (this is called covariance).
      std::pair<string, string> key;
      if (method_metadata.is_static()) {
        key = {
          method_metadata.name,
          method_metadata.signature
        };
      } else {
        key = {
          method_metadata.name,
          TrimReturnType(method_metadata.signature)
        };
      }

      // Skip base class methods that the inherited classes overwrote.
      if (registered_methods->find(key) != registered_methods->end()) {
        continue;
      }

      // Add the method to the registry.
      registered_methods->insert(std::move(key));
      metadata->methods.push_back(std::move(method_metadata));
    }
  }
}

void JvmClassMetadataReader::LoadFieldInfo(
    jclass cls,
    const string& class_signature,
    jfieldID field_id,
    DataVisibilityPolicy::Class* class_visibility,
    Entry* metadata) {
  int err = JVMTI_ERROR_NONE;

  jint field_modifiers = 0;
  err = jvmti()->GetFieldModifiers(cls, field_id, &field_modifiers);
  if (err != JVMTI_ERROR_NONE) {
    LOG(ERROR) << "GetFieldModifiers failed, error: " << err;
    return;
  }

  JvmtiBuffer<char> field_name_buffer;
  JvmtiBuffer<char> field_signature_buffer;
  err = jvmti()->GetFieldName(
      cls,
      field_id,
      field_name_buffer.ref(),
      field_signature_buffer.ref(),
      nullptr);
  if (err != JVMTI_ERROR_NONE) {
    LOG(ERROR) << "GetFieldName failed, error: " << err;
    return;
  }

  if ((field_signature_buffer.get() == nullptr) ||
      (field_signature_buffer.get()[0] == '\0')) {
    LOG(ERROR) << "Empty field signature is unexpected";
    return;
  }

  string field_name = ProcessFieldName(field_name_buffer.get());
  string field_signature = field_signature_buffer.get();

  if ((class_visibility != nullptr) &&
      !class_visibility->IsFieldVisible(field_name, field_modifiers)) {
    if ((field_modifiers & JVM_ACC_STATIC) == 0) {
      metadata->instance_fields_omitted = true;
    }
    return;  // Field is invisible.
  }

  if ((field_modifiers & JVM_ACC_STATIC) == 0) {
    // Instance field.
    std::unique_ptr<InstanceFieldReader> reader(
        new JvmInstanceFieldReader(
            field_name,
            field_id,
            JSignatureFromSignature(field_signature)));
    metadata->instance_fields.push_back(std::move(reader));
  } else {
    // Static field.
    std::unique_ptr<StaticFieldReader> reader(
        new JvmStaticFieldReader(
            cls,
            field_name,
            field_id,
            JSignatureFromSignature(field_signature)));
    metadata->static_fields.push_back(std::move(reader));
  }
}

JvmClassMetadataReader::Method JvmClassMetadataReader::LoadMethodInfo(
    jclass cls,
    const string& class_signature,
    jmethodID method_id,
    DataVisibilityPolicy::Class* class_visibility) {
  int err = JVMTI_ERROR_NONE;

  JvmtiBuffer<char> method_name;
  JvmtiBuffer<char> method_signature;
  err = jvmti()->GetMethodName(
      method_id,
      method_name.ref(),
      method_signature.ref(),
      nullptr);
  if (err != JVMTI_ERROR_NONE) {
    LOG(ERROR) << "GetMethodName failed, error: " << err;
    return Method();
  }

  jint method_modifiers = 0;
  err = jvmti()->GetMethodModifiers(method_id, &method_modifiers);
  if (err != JVMTI_ERROR_NONE) {
    LOG(ERROR) << "GetMethodModifiers failed, error: " << err;
    return Method();
  }

  Method method;
  method.class_signature = JSignatureFromSignature(class_signature);
  method.name = method_name.get();
  method.signature = method_signature.get();
  method.modifiers = method_modifiers;

  if ((class_visibility != nullptr) &&
      !class_visibility->IsMethodVisible(
          method.name,
          method.signature,
          method_modifiers)) {
    return Method();  // Method is invisible.
  }

  return method;
}

}  // namespace cdbg
}  // namespace devtools

<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "qtlogtarget.h"

// appleseed.studio headers.
#include "mainwindow/logwidget.h"

// appleseed.foundation headers.
#include "foundation/utility/foreach.h"
#include "foundation/utility/string.h"

// Standard headers.
#include <cassert>
#include <string>
#include <vector>

using namespace foundation;
using namespace std;

namespace appleseed {
namespace studio {

//
// QtLogTarget class implementation.
//

QtLogTarget::QtLogTarget(LogWidget* log_widget)
{
    connect(
        this, SIGNAL(signal_append_item(const QColor&, const QString&)),
        log_widget, SLOT(slot_append_item(const QColor&, const QString&)));
}

void QtLogTarget::release()
{
    delete this;
}

namespace
{
    QColor get_text_color_for_category(
        const LogMessage::Category  category)
    {
        switch (category)
        {
          default:
          case LogMessage::Info:
            return QColor("lightgray");

          case LogMessage::Debug:
            return QColor("lime");

          case LogMessage::Warning:
            return QColor("fuchsia");

          case LogMessage::Error:
          case LogMessage::Fatal:
            return QColor("red");
        }
    }
}

void QtLogTarget::write(
    const LogMessage::Category  category,
    const char*                 file,
    const size_t                line_number,
    const char*                 header,
    const char*                 message)
{
    const QColor color = get_text_color_for_category(category);

    vector<string> lines;
    split(message, "\n", lines);

    for (const_each<vector<string> > i = lines; i; ++i)
    {
        const QString line = QString(header) + QString::fromStdString(*i);
        emit signal_append_item(color, line);
    }
}

}   // namespace studio
}   // namespace appleseed
<commit_msg>minor code tweaks.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "qtlogtarget.h"

// appleseed.studio headers.
#include "mainwindow/logwidget.h"

// appleseed.foundation headers.
#include "foundation/utility/foreach.h"
#include "foundation/utility/string.h"

// Standard headers.
#include <string>
#include <vector>

using namespace foundation;
using namespace std;

namespace appleseed {
namespace studio {

//
// QtLogTarget class implementation.
//

QtLogTarget::QtLogTarget(LogWidget* log_widget)
{
    connect(
        this, SIGNAL(signal_append_item(const QColor&, const QString&)),
        log_widget, SLOT(slot_append_item(const QColor&, const QString&)));
}

void QtLogTarget::release()
{
    delete this;
}

namespace
{
    QColor get_text_color_for_category(const LogMessage::Category category)
    {
        switch (category)
        {
          default:
          case LogMessage::Info:
            return QColor("lightgray");

          case LogMessage::Debug:
            return QColor("lime");

          case LogMessage::Warning:
            return QColor("fuchsia");

          case LogMessage::Error:
          case LogMessage::Fatal:
            return QColor("red");
        }
    }
}

void QtLogTarget::write(
    const LogMessage::Category  category,
    const char*                 file,
    const size_t                line_number,
    const char*                 header,
    const char*                 message)
{
    const QColor color = get_text_color_for_category(category);

    vector<string> lines;
    split(message, "\n", lines);

    for (const_each<vector<string> > i = lines; i; ++i)
    {
        const QString line = QString(header) + QString::fromStdString(*i);
        emit signal_append_item(color, line);
    }
}

}   // namespace studio
}   // namespace appleseed
<|endoftext|>