# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at sergio.garcia.murillo@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]

[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

{'repo_name': 'medooze/media-server-node', 'stars': '405', 'repo_language': 'C++', 'file_name': 'mirrored.js', 'mime_type': 'text/plain', 'hash': -8509021940439699634, 'source_dataset': 'data'}


// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Author: anuraag@google.com (Anuraag Agrawal)
// Author: tibell@google.com (Johan Tibell)

#include <google/protobuf/pyext/repeated_scalar_container.h>

#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif

#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/message.h>
#include <google/protobuf/pyext/descriptor.h>
#include <google/protobuf/pyext/message.h>
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>

#if PY_MAJOR_VERSION >= 3
  #define PyInt_FromLong PyLong_FromLong
  #if PY_VERSION_HEX < 0x03030000
    #error "Python 3.0 - 3.2 are not supported."
  #else
  #define PyString_AsString(ob) \
    (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AS_STRING(ob))
  #endif
#endif

namespace google {
namespace protobuf {
namespace python {

extern google::protobuf::DynamicMessageFactory* global_message_factory;

namespace repeated_scalar_container {

static int InternalAssignRepeatedField(
    RepeatedScalarContainer* self, PyObject* list) {
  self->message->GetReflection()->ClearField(self->message,
                                             self->parent_field->descriptor);
  for (Py_ssize_t i = 0; i < PyList_GET_SIZE(list); ++i) {
    PyObject* value = PyList_GET_ITEM(list, i);
    if (Append(self, value) == NULL) {
      return -1;
    }
  }
  return 0;
}

static Py_ssize_t Len(RepeatedScalarContainer* self) {
  google::protobuf::Message* message = self->message;
  return message->GetReflection()->FieldSize(*message,
                                             self->parent_field->descriptor);
}

static int AssignItem(RepeatedScalarContainer* self,
                      Py_ssize_t index,
                      PyObject* arg) {
  cmessage::AssureWritable(self->parent);
  google::protobuf::Message* message = self->message;
  const google::protobuf::FieldDescriptor* field_descriptor =
      self->parent_field->descriptor;
  if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) {
    PyErr_SetString(
        PyExc_KeyError, "Field does not belong to message!");
    return -1;
  }

  const google::protobuf::Reflection* reflection = message->GetReflection();
  int field_size = reflection->FieldSize(*message, field_descriptor);
  if (index < 0) {
    index = field_size + index;
  }
  if (index < 0 || index >= field_size) {
    PyErr_Format(PyExc_IndexError,
                 "list assignment index (%d) out of range",
                 static_cast<int>(index));
    return -1;
  }

  if (arg == NULL) {
    ScopedPyObjectPtr py_index(PyLong_FromLong(index));
    return cmessage::InternalDeleteRepeatedField(message, field_descriptor,
                                                 py_index, NULL);
  }

  if (PySequence_Check(arg) && !(PyBytes_Check(arg) || PyUnicode_Check(arg))) {
    PyErr_SetString(PyExc_TypeError, "Value must be scalar");
    return -1;
  }

  switch (field_descriptor->cpp_type()) {
    case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
      GOOGLE_CHECK_GET_INT32(arg, value, -1);
      reflection->SetRepeatedInt32(message, field_descriptor, index, value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
      GOOGLE_CHECK_GET_INT64(arg, value, -1);
      reflection->SetRepeatedInt64(message, field_descriptor, index, value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
      GOOGLE_CHECK_GET_UINT32(arg, value, -1);
      reflection->SetRepeatedUInt32(message, field_descriptor, index, value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
      GOOGLE_CHECK_GET_UINT64(arg, value, -1);
      reflection->SetRepeatedUInt64(message, field_descriptor, index, value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
      GOOGLE_CHECK_GET_FLOAT(arg, value, -1);
      reflection->SetRepeatedFloat(message, field_descriptor, index, value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
      GOOGLE_CHECK_GET_DOUBLE(arg, value, -1);
      reflection->SetRepeatedDouble(message, field_descriptor, index, value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
      GOOGLE_CHECK_GET_BOOL(arg, value, -1);
      reflection->SetRepeatedBool(message, field_descriptor, index, value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
      if (!CheckAndSetString(
          arg, message, field_descriptor, reflection, false, index)) {
        return -1;
      }
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
      GOOGLE_CHECK_GET_INT32(arg, value, -1);
      const google::protobuf::EnumDescriptor* enum_descriptor =
          field_descriptor->enum_type();
      const google::protobuf::EnumValueDescriptor* enum_value =
          enum_descriptor->FindValueByNumber(value);
      if (enum_value != NULL) {
        reflection->SetRepeatedEnum(message, field_descriptor, index,
                                    enum_value);
      } else {
        ScopedPyObjectPtr s(PyObject_Str(arg));
        if (s != NULL) {
          PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
                       PyString_AsString(s.get()));
        }
        return -1;
      }
      break;
    }
    default:
      PyErr_Format(
          PyExc_SystemError, "Adding value to a field of unknown type %d",
          field_descriptor->cpp_type());
      return -1;
  }
  return 0;
}

static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) {
  google::protobuf::Message* message = self->message;
  const google::protobuf::FieldDescriptor* field_descriptor =
      self->parent_field->descriptor;
  const google::protobuf::Reflection* reflection = message->GetReflection();

  int field_size = reflection->FieldSize(*message, field_descriptor);
  if (index < 0) {
    index = field_size + index;
  }
  if (index < 0 || index >= field_size) {
    PyErr_Format(PyExc_IndexError,
                 "list assignment index (%d) out of range",
                 static_cast<int>(index));
    return NULL;
  }

  PyObject* result = NULL;
  switch (field_descriptor->cpp_type()) {
    case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
      int32 value = reflection->GetRepeatedInt32(
          *message, field_descriptor, index);
      result = PyInt_FromLong(value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
      int64 value = reflection->GetRepeatedInt64(
          *message, field_descriptor, index);
      result = PyLong_FromLongLong(value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
      uint32 value = reflection->GetRepeatedUInt32(
          *message, field_descriptor, index);
      result = PyLong_FromLongLong(value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
      uint64 value = reflection->GetRepeatedUInt64(
          *message, field_descriptor, index);
      result = PyLong_FromUnsignedLongLong(value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
      float value = reflection->GetRepeatedFloat(
          *message, field_descriptor, index);
      result = PyFloat_FromDouble(value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
      double value = reflection->GetRepeatedDouble(
          *message, field_descriptor, index);
      result = PyFloat_FromDouble(value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
      bool value = reflection->GetRepeatedBool(
          *message, field_descriptor, index);
      result = PyBool_FromLong(value ? 1 : 0);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
      const google::protobuf::EnumValueDescriptor* enum_value =
          message->GetReflection()->GetRepeatedEnum(
              *message, field_descriptor, index);
      result = PyInt_FromLong(enum_value->number());
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
      string value = reflection->GetRepeatedString(
          *message, field_descriptor, index);
      result = ToStringObject(field_descriptor, value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
      PyObject* py_cmsg = PyObject_CallObject(reinterpret_cast<PyObject*>(
          &CMessage_Type), NULL);
      if (py_cmsg == NULL) {
        return NULL;
      }
      CMessage* cmsg = reinterpret_cast<CMessage*>(py_cmsg);
      const google::protobuf::Message& msg = reflection->GetRepeatedMessage(
          *message, field_descriptor, index);
      cmsg->owner = self->owner;
      cmsg->parent = self->parent;
      cmsg->message = const_cast<google::protobuf::Message*>(&msg);
      cmsg->read_only = false;
      result = reinterpret_cast<PyObject*>(py_cmsg);
      break;
    }
    default:
      PyErr_Format(
          PyExc_SystemError,
          "Getting value from a repeated field of unknown type %d",
          field_descriptor->cpp_type());
  }

  return result;
}

static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) {
  Py_ssize_t from;
  Py_ssize_t to;
  Py_ssize_t step;
  Py_ssize_t length;
  Py_ssize_t slicelength;
  bool return_list = false;
#if PY_MAJOR_VERSION < 3
  if (PyInt_Check(slice)) {
    from = to = PyInt_AsLong(slice);
  } else  // NOLINT
#endif
  if (PyLong_Check(slice)) {
    from = to = PyLong_AsLong(slice);
  } else if (PySlice_Check(slice)) {
    length = Len(self);
#if PY_MAJOR_VERSION >= 3
    if (PySlice_GetIndicesEx(slice,
#else
    if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice),
#endif
                             length, &from, &to, &step, &slicelength) == -1) {
      return NULL;
    }
    return_list = true;
  } else {
    PyErr_SetString(PyExc_TypeError, "list indices must be integers");
    return NULL;
  }

  if (!return_list) {
    return Item(self, from);
  }

  PyObject* list = PyList_New(0);
  if (list == NULL) {
    return NULL;
  }
  if (from <= to) {
    if (step < 0) {
      return list;
    }
    for (Py_ssize_t index = from; index < to; index += step) {
      if (index < 0 || index >= length) {
        break;
      }
      ScopedPyObjectPtr s(Item(self, index));
      PyList_Append(list, s);
    }
  } else {
    if (step > 0) {
      return list;
    }
    for (Py_ssize_t index = from; index > to; index += step) {
      if (index < 0 || index >= length) {
        break;
      }
      ScopedPyObjectPtr s(Item(self, index));
      PyList_Append(list, s);
    }
  }
  return list;
}

PyObject* Append(RepeatedScalarContainer* self, PyObject* item) {
  cmessage::AssureWritable(self->parent);
  google::protobuf::Message* message = self->message;
  const google::protobuf::FieldDescriptor* field_descriptor =
      self->parent_field->descriptor;

  if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) {
    PyErr_SetString(
        PyExc_KeyError, "Field does not belong to message!");
    return NULL;
  }

  const google::protobuf::Reflection* reflection = message->GetReflection();
  switch (field_descriptor->cpp_type()) {
    case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
      GOOGLE_CHECK_GET_INT32(item, value, NULL);
      reflection->AddInt32(message, field_descriptor, value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
      GOOGLE_CHECK_GET_INT64(item, value, NULL);
      reflection->AddInt64(message, field_descriptor, value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
      GOOGLE_CHECK_GET_UINT32(item, value, NULL);
      reflection->AddUInt32(message, field_descriptor, value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
      GOOGLE_CHECK_GET_UINT64(item, value, NULL);
      reflection->AddUInt64(message, field_descriptor, value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
      GOOGLE_CHECK_GET_FLOAT(item, value, NULL);
      reflection->AddFloat(message, field_descriptor, value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
      GOOGLE_CHECK_GET_DOUBLE(item, value, NULL);
      reflection->AddDouble(message, field_descriptor, value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
      GOOGLE_CHECK_GET_BOOL(item, value, NULL);
      reflection->AddBool(message, field_descriptor, value);
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
      if (!CheckAndSetString(
          item, message, field_descriptor, reflection, true, -1)) {
        return NULL;
      }
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
      GOOGLE_CHECK_GET_INT32(item, value, NULL);
      const google::protobuf::EnumDescriptor* enum_descriptor =
          field_descriptor->enum_type();
      const google::protobuf::EnumValueDescriptor* enum_value =
          enum_descriptor->FindValueByNumber(value);
      if (enum_value != NULL) {
        reflection->AddEnum(message, field_descriptor, enum_value);
      } else {
        ScopedPyObjectPtr s(PyObject_Str(item));
        if (s != NULL) {
          PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
                       PyString_AsString(s.get()));
        }
        return NULL;
      }
      break;
    }
    default:
      PyErr_Format(
          PyExc_SystemError, "Adding value to a field of unknown type %d",
          field_descriptor->cpp_type());
      return NULL;
  }

  Py_RETURN_NONE;
}

static int AssSubscript(RepeatedScalarContainer* self,
                        PyObject* slice,
                        PyObject* value) {
  Py_ssize_t from;
  Py_ssize_t to;
  Py_ssize_t step;
  Py_ssize_t length;
  Py_ssize_t slicelength;
  bool create_list = false;

  cmessage::AssureWritable(self->parent);
  google::protobuf::Message* message = self->message;
  const google::protobuf::FieldDescriptor* field_descriptor =
      self->parent_field->descriptor;

#if PY_MAJOR_VERSION < 3
  if (PyInt_Check(slice)) {
    from = to = PyInt_AsLong(slice);
  } else
#endif
  if (PyLong_Check(slice)) {
    from = to = PyLong_AsLong(slice);
  } else if (PySlice_Check(slice)) {
    const google::protobuf::Reflection* reflection = message->GetReflection();
    length = reflection->FieldSize(*message, field_descriptor);
#if PY_MAJOR_VERSION >= 3
    if (PySlice_GetIndicesEx(slice,
#else
    if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice),
#endif
                             length, &from, &to, &step, &slicelength) == -1) {
      return -1;
    }
    create_list = true;
  } else {
    PyErr_SetString(PyExc_TypeError, "list indices must be integers");
    return -1;
  }

  if (value == NULL) {
    return cmessage::InternalDeleteRepeatedField(
        message, field_descriptor, slice, NULL);
  }

  if (!create_list) {
    return AssignItem(self, from, value);
  }

  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
  if (full_slice == NULL) {
    return -1;
  }
  ScopedPyObjectPtr new_list(Subscript(self, full_slice));
  if (new_list == NULL) {
    return -1;
  }
  if (PySequence_SetSlice(new_list, from, to, value) < 0) {
    return -1;
  }

  return InternalAssignRepeatedField(self, new_list);
}

PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) {
  cmessage::AssureWritable(self->parent);
  if (PyObject_Not(value)) {
    Py_RETURN_NONE;
  }
  ScopedPyObjectPtr iter(PyObject_GetIter(value));
  if (iter == NULL) {
    PyErr_SetString(PyExc_TypeError, "Value must be iterable");
    return NULL;
  }
  ScopedPyObjectPtr next;
  while ((next.reset(PyIter_Next(iter))) != NULL) {
    if (Append(self, next) == NULL) {
      return NULL;
    }
  }
  if (PyErr_Occurred()) {
    return NULL;
  }
  Py_RETURN_NONE;
}

static PyObject* Insert(RepeatedScalarContainer* self, PyObject* args) {
  Py_ssize_t index;
  PyObject* value;
  if (!PyArg_ParseTuple(args, "lO", &index, &value)) {
    return NULL;
  }
  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
  ScopedPyObjectPtr new_list(Subscript(self, full_slice));
  if (PyList_Insert(new_list, index, value) < 0) {
    return NULL;
  }
  int ret = InternalAssignRepeatedField(self, new_list);
  if (ret < 0) {
    return NULL;
  }
  Py_RETURN_NONE;
}

static PyObject* Remove(RepeatedScalarContainer* self, PyObject* value) {
  Py_ssize_t match_index = -1;
  for (Py_ssize_t i = 0; i < Len(self); ++i) {
    ScopedPyObjectPtr elem(Item(self, i));
    if (PyObject_RichCompareBool(elem, value, Py_EQ)) {
      match_index = i;
      break;
    }
  }
  if (match_index == -1) {
    PyErr_SetString(PyExc_ValueError, "remove(x): x not in container");
    return NULL;
  }
  if (AssignItem(self, match_index, NULL) < 0) {
    return NULL;
  }
  Py_RETURN_NONE;
}

static PyObject* RichCompare(RepeatedScalarContainer* self,
                             PyObject* other,
                             int opid) {
  if (opid != Py_EQ && opid != Py_NE) {
    Py_INCREF(Py_NotImplemented);
    return Py_NotImplemented;
  }

  // Copy the contents of this repeated scalar container, and other if it is
  // also a repeated scalar container, into Python lists so we can delegate
  // to the list's compare method.

  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
  if (full_slice == NULL) {
    return NULL;
  }

  ScopedPyObjectPtr other_list_deleter;
  if (PyObject_TypeCheck(other, &RepeatedScalarContainer_Type)) {
    other_list_deleter.reset(Subscript(
        reinterpret_cast<RepeatedScalarContainer*>(other), full_slice));
    other = other_list_deleter.get();
  }

  ScopedPyObjectPtr list(Subscript(self, full_slice));
  if (list == NULL) {
    return NULL;
  }
  return PyObject_RichCompare(list, other, opid);
}

PyObject* Reduce(RepeatedScalarContainer* unused_self) {
  PyErr_Format(
      PickleError_class,
      "can't pickle repeated message fields, convert to list first");
  return NULL;
}

static PyObject* Sort(RepeatedScalarContainer* self,
                      PyObject* args,
                      PyObject* kwds) {
  // Support the old sort_function argument for backwards
  // compatibility.
  if (kwds != NULL) {
    PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function");
    if (sort_func != NULL) {
      // Must set before deleting as sort_func is a borrowed reference
      // and kwds might be the only thing keeping it alive.
      if (PyDict_SetItemString(kwds, "cmp", sort_func) == -1)
        return NULL;
      if (PyDict_DelItemString(kwds, "sort_function") == -1)
        return NULL;
    }
  }

  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
  if (full_slice == NULL) {
    return NULL;
  }
  ScopedPyObjectPtr list(Subscript(self, full_slice));
  if (list == NULL) {
    return NULL;
  }
  ScopedPyObjectPtr m(PyObject_GetAttrString(list, "sort"));
  if (m == NULL) {
    return NULL;
  }
  ScopedPyObjectPtr res(PyObject_Call(m, args, kwds));
  if (res == NULL) {
    return NULL;
  }
  int ret = InternalAssignRepeatedField(self, list);
  if (ret < 0) {
    return NULL;
  }
  Py_RETURN_NONE;
}

static int Init(RepeatedScalarContainer* self,
                PyObject* args,
                PyObject* kwargs) {
  PyObject* py_parent;
  PyObject* py_parent_field;
  if (!PyArg_UnpackTuple(args, "__init__()", 2, 2, &py_parent,
                         &py_parent_field)) {
    return -1;
  }

  if (!PyObject_TypeCheck(py_parent, &CMessage_Type)) {
    PyErr_Format(PyExc_TypeError,
                 "expect %s, but got %s",
                 CMessage_Type.tp_name,
                 Py_TYPE(py_parent)->tp_name);
    return -1;
  }

  if (!PyObject_TypeCheck(py_parent_field, &CFieldDescriptor_Type)) {
    PyErr_Format(PyExc_TypeError,
                 "expect %s, but got %s",
                 CFieldDescriptor_Type.tp_name,
                 Py_TYPE(py_parent_field)->tp_name);
    return -1;
  }

  CMessage* cmessage = reinterpret_cast<CMessage*>(py_parent);
  CFieldDescriptor* cdescriptor = reinterpret_cast<CFieldDescriptor*>(
      py_parent_field);

  if (!FIELD_BELONGS_TO_MESSAGE(cdescriptor->descriptor, cmessage->message)) {
    PyErr_SetString(
        PyExc_KeyError, "Field does not belong to message!");
    return -1;
  }

  self->message = cmessage->message;
  self->parent = cmessage;
  self->parent_field = cdescriptor;
  self->owner = cmessage->owner;
  return 0;
}

// Initializes the underlying Message object of "to" so it becomes a new parent
// repeated scalar, and copies all the values from "from" to it. A child scalar
// container can be released by passing it as both from and to (e.g. making it
// the recipient of the new parent message and copying the values from itself).
static int InitializeAndCopyToParentContainer(
    RepeatedScalarContainer* from,
    RepeatedScalarContainer* to) {
  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
  if (full_slice == NULL) {
    return -1;
  }
  ScopedPyObjectPtr values(Subscript(from, full_slice));
  if (values == NULL) {
    return -1;
  }
  google::protobuf::Message* new_message = global_message_factory->GetPrototype(
      from->message->GetDescriptor())->New();
  to->parent = NULL;
  // TODO(anuraag): Document why it's OK to hang on to parent_field,
  //     even though it's a weak reference. It ought to be enough to
  //     hold on to the FieldDescriptor only.
  to->parent_field = from->parent_field;
  to->message = new_message;
  to->owner.reset(new_message);
  if (InternalAssignRepeatedField(to, values) < 0) {
    return -1;
  }
  return 0;
}

int Release(RepeatedScalarContainer* self) {
  return InitializeAndCopyToParentContainer(self, self);
}

PyObject* DeepCopy(RepeatedScalarContainer* self, PyObject* arg) {
  ScopedPyObjectPtr init_args(
      PyTuple_Pack(2, self->parent, self->parent_field));
  PyObject* clone = PyObject_CallObject(
      reinterpret_cast<PyObject*>(&RepeatedScalarContainer_Type), init_args);
  if (clone == NULL) {
    return NULL;
  }
  if (!PyObject_TypeCheck(clone, &RepeatedScalarContainer_Type)) {
    Py_DECREF(clone);
    return NULL;
  }
  if (InitializeAndCopyToParentContainer(
          self, reinterpret_cast<RepeatedScalarContainer*>(clone)) < 0) {
    Py_DECREF(clone);
    return NULL;
  }
  return clone;
}

static void Dealloc(RepeatedScalarContainer* self) {
  self->owner.reset();
  Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
}

void SetOwner(RepeatedScalarContainer* self,
              const shared_ptr<Message>& new_owner) {
  self->owner = new_owner;
}

static PySequenceMethods SqMethods = {
  (lenfunc)Len,           /* sq_length */
  0, /* sq_concat */
  0, /* sq_repeat */
  (ssizeargfunc)Item, /* sq_item */
  0, /* sq_slice */
  (ssizeobjargproc)AssignItem /* sq_ass_item */
};

static PyMappingMethods MpMethods = {
  (lenfunc)Len,               /* mp_length */
  (binaryfunc)Subscript,      /* mp_subscript */
  (objobjargproc)AssSubscript, /* mp_ass_subscript */
};

static PyMethodDef Methods[] = {
  { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
    "Makes a deep copy of the class." },
  { "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
    "Outputs picklable representation of the repeated field." },
  { "append", (PyCFunction)Append, METH_O,
    "Appends an object to the repeated container." },
  { "extend", (PyCFunction)Extend, METH_O,
    "Appends objects to the repeated container." },
  { "insert", (PyCFunction)Insert, METH_VARARGS,
    "Appends objects to the repeated container." },
  { "remove", (PyCFunction)Remove, METH_O,
    "Removes an object from the repeated container." },
  { "sort", (PyCFunction)Sort, METH_VARARGS | METH_KEYWORDS,
    "Sorts the repeated container."},
  { NULL, NULL }
};

}  // namespace repeated_scalar_container

PyTypeObject RepeatedScalarContainer_Type = {
  PyVarObject_HEAD_INIT(&PyType_Type, 0)
  "google.protobuf.internal."
  "cpp._message.RepeatedScalarContainer",  // tp_name
  sizeof(RepeatedScalarContainer),     // tp_basicsize
  0,                                   //  tp_itemsize
  (destructor)repeated_scalar_container::Dealloc,  //  tp_dealloc
  0,                                   //  tp_print
  0,                                   //  tp_getattr
  0,                                   //  tp_setattr
  0,                                   //  tp_compare
  0,                                   //  tp_repr
  0,                                   //  tp_as_number
  &repeated_scalar_container::SqMethods,   //  tp_as_sequence
  &repeated_scalar_container::MpMethods,   //  tp_as_mapping
  0,                                   //  tp_hash
  0,                                   //  tp_call
  0,                                   //  tp_str
  0,                                   //  tp_getattro
  0,                                   //  tp_setattro
  0,                                   //  tp_as_buffer
  Py_TPFLAGS_DEFAULT,                  //  tp_flags
  "A Repeated scalar container",       //  tp_doc
  0,                                   //  tp_traverse
  0,                                   //  tp_clear
  (richcmpfunc)repeated_scalar_container::RichCompare,  //  tp_richcompare
  0,                                   //  tp_weaklistoffset
  0,                                   //  tp_iter
  0,                                   //  tp_iternext
  repeated_scalar_container::Methods,      //  tp_methods
  0,                                   //  tp_members
  0,                                   //  tp_getset
  0,                                   //  tp_base
  0,                                   //  tp_dict
  0,                                   //  tp_descr_get
  0,                                   //  tp_descr_set
  0,                                   //  tp_dictoffset
  (initproc)repeated_scalar_container::Init,  //  tp_init
};

}  // namespace python
}  // namespace protobuf
}  // namespace google

{'repo_name': 'xtreemfs/xtreemfs', 'stars': '293', 'repo_language': 'Java', 'file_name': 'PBRPC.proto', 'mime_type': 'text/x-java', 'hash': 691286992343340419, 'source_dataset': 'data'}


import numpy as np

from distutils.spawn import find_executable
from string import Template

import tempfile
import subprocess
import collections

from .. import util
from .. import visual
from .. import grouping
from .. import resources

from ..geometry import triangulate_quads
from ..constants import log

# from ply specification, and additional dtypes found in the wild
dtypes = {
    'char': 'i1',
    'uchar': 'u1',
    'short': 'i2',
    'ushort': 'u2',
    'int': 'i4',
    'int8': 'i1',
    'int16': 'i2',
    'int32': 'i4',
    'int64': 'i8',
    'uint': 'u4',
    'uint8': 'u1',
    'uint16': 'u2',
    'uint32': 'u4',
    'uint64': 'u8',
    'float': 'f4',
    'float16': 'f2',
    'float32': 'f4',
    'float64': 'f8',
    'double': 'f8'}

# Inverse of the above dict, collisions on numpy type were removed
inverse_dtypes = {
    'i1': 'char',
    'u1': 'uchar',
    'i2': 'short',
    'u2': 'ushort',
    'i4': 'int',
    'i8': 'int64',
    'u4': 'uint',
    'u8': 'uint64',
    'f4': 'float',
    'f2': 'float16',
    'f8': 'double'}

def numpy_type_to_ply_type(numpy_type):
    """
    Returns the closest ply equivalent of a numpy type

    Parameters
    ---------
    numpy_type : a numpy datatype

    Returns
    ---------
    ply_type : string
    """
    return inverse_dtypes[numpy_type.str[1:]]

def load_ply(file_obj,
             resolver=None,
             fix_texture=True,
             prefer_color=None,
             *args,
             **kwargs):
    """
    Load a PLY file from an open file object.

    Parameters
    ---------
    file_obj : an open file- like object
      Source data, ASCII or binary PLY
    resolver : trimesh.visual.resolvers.Resolver
      Object which can resolve assets
    fix_texture : bool
      If True, will re- index vertices and faces
      so vertices with different UV coordinates
      are disconnected.
    prefer_color : None, 'vertex', or 'face'
      Which kind of color to prefer if both defined

    Returns
    ---------
    mesh_kwargs : dict
      Data which can be passed to
      Trimesh constructor, eg: a = Trimesh(**mesh_kwargs)
    """

    # OrderedDict which is populated from the header
    elements, is_ascii, image_name = parse_header(file_obj)

    # functions will fill in elements from file_obj
    if is_ascii:
        ply_ascii(elements, file_obj)
    else:
        ply_binary(elements, file_obj)

    # try to load the referenced image
    image = None
    try:
        # soft dependency
        import PIL.Image
        # if an image name is passed try to load it
        if image_name is not None:
            data = resolver.get(image_name)
            image = PIL.Image.open(util.wrap_as_stream(data))
    except BaseException:
        log.warning(
            'unable to load image!', exc_info=True)

    # translate loaded PLY elements to kwargs
    kwargs = elements_to_kwargs(
        image=image,
        elements=elements,
        fix_texture=fix_texture,
        prefer_color=prefer_color)

    return kwargs

def add_attributes_to_dtype(dtype, attributes):
    """
    Parses attribute datatype to populate a numpy dtype list

    Parameters
    ----------
    dtype : list of numpy datatypes
      operated on in place
    attributes : dict
      contains all the attributes to parse

    Returns
    ----------
    dtype : list of numpy datatypes
    """
    for name, data in attributes.items():
        if data.ndim == 1:
            dtype.append((name, data.dtype))
        else:
            attribute_dtype = data.dtype if len(data.dtype) == 0 else data.dtype[0]
            dtype.append(('{}_count'.format(name), 'u1'))
            dtype.append((name, numpy_type_to_ply_type(attribute_dtype), data.shape[1]))
    return dtype

def add_attributes_to_header(header, attributes):
    """
    Parses attributes in to ply header entries

    Parameters
    ----------
    header : list of ply header entries
      operated on in place
    attributes : dict
      contains all the attributes to parse

    Returns
    ----------
    header : list
      Contains ply header entries
    """
    for name, data in attributes.items():
        if data.ndim == 1:
            header.append(
                'property {} {}\n'.format(
                    numpy_type_to_ply_type(data.dtype), name))
        else:
            header.append(
                'property list uchar {} {}\n'.format(
                    numpy_type_to_ply_type(data.dtype), name))
    return header

def add_attributes_to_data_array(data_array, attributes):
    """
    Parses attribute data in to a custom array, assumes datatype has been defined
    appropriately

    Parameters
    ----------
    data_array : numpy array with custom datatype
      datatype reflects all the data to be stored for a given ply element
    attributes : dict
      contains all the attributes to parse

    Returns
    ----------
    data_array : numpy array with custom datatype
    """
    for name, data in attributes.items():
        if data.ndim > 1:
            data_array['{}_count'.format(name)] = data.shape[1] * np.ones(data.shape[0])
        data_array[name] = data
    return data_array

def assert_attributes_valid(attributes):
    """
    Asserts that a set of attributes is valid for PLY export.

    Parameters
    ----------
    attributes : dict
      Contains the attributes to validate

    Raises
    --------
    ValueError
      If passed attributes aren't valid.
    """
    for data in attributes.values():
        if data.ndim not in [1, 2]:
            raise ValueError('PLY attributes are limited to 1 or 2 dimensions')
        # Inelegant test for structured arrays, reference:
        # https://numpy.org/doc/stable/user/basics.rec.html
        if data.dtype.names is not None:
            raise ValueError('PLY attributes must be of a single datatype')

def export_ply(mesh,
               encoding='binary',
               vertex_normal=None,
               include_attributes=True):
    """
    Export a mesh in the PLY format.

    Parameters
    ----------
    mesh : trimesh.Trimesh
      Mesh to export.
    encoding : str
      PLY encoding: 'ascii' or 'binary_little_endian'
    vertex_normal : None or include vertex normals

    Returns
    ----------
    export : bytes of result
    """
    # evaluate input args
    # allow a shortcut for binary
    if encoding == 'binary':
        encoding = 'binary_little_endian'
    elif encoding not in ['binary_little_endian', 'ascii']:
        raise ValueError('encoding must be binary or ascii')
    # if vertex normals aren't specifically asked for
    # only export them if they are stored in cache
    if vertex_normal is None:
        vertex_normal = 'vertex_normal' in mesh._cache

    # if we want to include mesh attributes in the export
    if include_attributes:
        if hasattr(mesh, 'vertex_attributes'):
            assert_attributes_valid(mesh.vertex_attributes)
        if hasattr(mesh, 'face_attributes'):
            assert_attributes_valid(mesh.face_attributes)

    # custom numpy dtypes for exporting
    dtype_face = [('count', '<u1'),
                  ('index', '<i4', (3))]
    dtype_vertex = [('vertex', '<f4', (3))]
    # will be appended to main dtype if needed
    dtype_vertex_normal = ('normals', '<f4', (3))
    dtype_color = ('rgba', '<u1', (4))

    # get template strings in dict
    templates = resources.get('ply.template', decode_json=True)
    # start collecting elements into a string for the header
    header = [templates['intro']]
    header.append(templates['vertex'])

    # if we're exporting vertex normals add them
    # to the header and dtype
    if vertex_normal:
        header.append(templates['vertex_normal'])
        dtype_vertex.append(dtype_vertex_normal)

    # if mesh has a vertex coloradd it to the header
    if mesh.visual.kind == 'vertex' and encoding != 'ascii':
        header.append(templates['color'])
        dtype_vertex.append(dtype_color)

    if include_attributes and hasattr(mesh, 'vertex_attributes'):
        add_attributes_to_header(header, mesh.vertex_attributes)
        add_attributes_to_dtype(dtype_vertex, mesh.vertex_attributes)

    # create and populate the custom dtype for vertices
    vertex = np.zeros(len(mesh.vertices),
                      dtype=dtype_vertex)
    vertex['vertex'] = mesh.vertices
    if vertex_normal:
        vertex['normals'] = mesh.vertex_normals
    if mesh.visual.kind == 'vertex':
        vertex['rgba'] = mesh.visual.vertex_colors

    if include_attributes and hasattr(mesh, 'vertex_attributes'):
        add_attributes_to_data_array(vertex, mesh.vertex_attributes)

    header_params = {'vertex_count': len(mesh.vertices),
                     'encoding': encoding}

    if hasattr(mesh, 'faces'):
        header.append(templates['face'])
        if mesh.visual.kind == 'face' and encoding != 'ascii':
            header.append(templates['color'])
            dtype_face.append(dtype_color)

        if include_attributes and hasattr(mesh, 'face_attributes'):
            add_attributes_to_header(header, mesh.face_attributes)
            add_attributes_to_dtype(dtype_face, mesh.face_attributes)

        # put mesh face data into custom dtype to export
        faces = np.zeros(len(mesh.faces), dtype=dtype_face)
        faces['count'] = 3
        faces['index'] = mesh.faces
        if mesh.visual.kind == 'face' and encoding != 'ascii':
            faces['rgba'] = mesh.visual.face_colors
        header_params['face_count'] = len(mesh.faces)

        if include_attributes and hasattr(mesh, 'face_attributes'):
            add_attributes_to_data_array(faces, mesh.face_attributes)

    header.append(templates['outro'])
    export = Template(''.join(header)).substitute(
        header_params).encode('utf-8')

    if encoding == 'binary_little_endian':
        export += vertex.tobytes()
        if hasattr(mesh, 'faces'):
            export += faces.tobytes()
    elif encoding == 'ascii':
        if hasattr(mesh, 'faces'):
            # ply format is: (face count, v0, v1, v2)
            fstack = np.column_stack(
                (np.ones(len(mesh.faces), dtype=np.int64) * 3,
                 mesh.faces))
        else:
            fstack = []

        # if we're exporting vertex normals they get stacked
        if vertex_normal:
            vstack = np.column_stack((mesh.vertices,
                                      mesh.vertex_normals))
        else:
            vstack = mesh.vertices

        # add the string formatted vertices and faces
        export += (util.array_to_string(vstack,
                                        col_delim=' ',
                                        row_delim='\n') +
                   '\n' +
                   util.array_to_string(fstack,
                                        col_delim=' ',
                                        row_delim='\n')).encode('utf-8')
    else:
        raise ValueError('encoding must be ascii or binary!')

    return export

def parse_header(file_obj):
    """
    Read the ASCII header of a PLY file, and leave the file object
    at the position of the start of data but past the header.

    Parameters
    -----------
    file_obj : open file object
      Positioned at the start of the file

    Returns
    -----------
    elements : collections.OrderedDict
      Fields and data types populated
    is_ascii : bool
      Whether the data is ASCII or binary
    image_name : None or str
      File name of TextureFile
    """

    if 'ply' not in str(file_obj.readline()).lower():
        raise ValueError('Not a ply file!')

    # collect the encoding: binary or ASCII
    encoding = file_obj.readline().decode('utf-8').strip().lower()
    is_ascii = 'ascii' in encoding

    # big or little endian
    endian = ['<', '>'][int('big' in encoding)]
    elements = collections.OrderedDict()

    # store file name of TextureFiles in the header
    image_name = None

    while True:
        line = file_obj.readline()
        if line is None:
            raise ValueError("Header not terminated properly!")
        line = line.decode('utf-8').strip().split()

        # we're done
        if 'end_header' in line:
            break

        # elements are groups of properties
        if 'element' in line[0]:
            # we got a new element so add it
            name, length = line[1:]
            elements[name] = {
                'length': int(length),
                'properties': collections.OrderedDict()}
        # a property is a member of an element
        elif 'property' in line[0]:
            # is the property a simple single value, like:
            # `propert float x`
            if len(line) == 3:
                dtype, field = line[1:]
                elements[name]['properties'][
                    str(field)] = endian + dtypes[dtype]
            # is the property a painful list, like:
            # `property list uchar int vertex_indices`
            elif 'list' in line[1]:
                dtype_count, dtype, field = line[2:]
                elements[name]['properties'][
                    str(field)] = (
                    endian +
                    dtypes[dtype_count] +
                    ', ($LIST,)' +
                    endian +
                    dtypes[dtype])
        # referenced as a file name
        elif 'TextureFile' in line:
            # textures come listed like:
            # `comment TextureFile fuze_uv.jpg`
            index = line.index('TextureFile') + 1
            if index < len(line):
                image_name = line[index]

    return elements, is_ascii, image_name

def elements_to_kwargs(elements,
                       fix_texture,
                       image,
                       prefer_color=None):
    """
    Given an elements data structure, extract the keyword
    arguments that a Trimesh object constructor will expect.

    Parameters
    ------------
    elements : OrderedDict object
      With fields and data loaded
    fix_texture : bool
      If True, will re- index vertices and faces
      so vertices with different UV coordinates
      are disconnected.
    image : PIL.Image
      Image to be viewed
    prefer_color : None, 'vertex', or 'face'
      Which kind of color to prefer if both defined

    Returns
    -----------
    kwargs : dict
      Keyword arguments for Trimesh constructor
    """

    kwargs = {'metadata': {'ply_raw': elements}}

    vertices = np.column_stack([elements['vertex']['data'][i]
                                for i in 'xyz'])

    if not util.is_shape(vertices, (-1, 3)):
        raise ValueError('Vertices were not (n,3)!')

    try:
        face_data = elements['face']['data']
    except (KeyError, ValueError):
        # some PLY files only include vertices
        face_data = None
        faces = None

    # what keys do in-the-wild exporters use for vertices
    index_names = ['vertex_index',
                   'vertex_indices']
    texcoord = None

    if util.is_shape(face_data, (-1, (3, 4))):
        faces = face_data
    elif isinstance(face_data, dict):
        # get vertex indexes
        for i in index_names:
            if i in face_data:
                faces = face_data[i]
                break
        # if faces have UV coordinates defined use them
        if 'texcoord' in face_data:
            texcoord = face_data['texcoord']

    elif isinstance(face_data, np.ndarray):
        face_blob = elements['face']['data']
        # some exporters set this name to 'vertex_index'
        # and some others use 'vertex_indices' but we really
        # don't care about the name unless there are multiple
        if len(face_blob.dtype.names) == 1:
            name = face_blob.dtype.names[0]
        elif len(face_blob.dtype.names) > 1:
            # loop through options
            for i in face_blob.dtype.names:
                if i in index_names:
                    name = i
                    break
        # get faces
        faces = face_blob[name]['f1']

        try:
            texcoord = face_blob['texcoord']['f1']
        except (ValueError, KeyError):
            # accessing numpy arrays with named fields
            # incorrectly is a ValueError
            pass

    if faces is not None:
        shape = np.shape(faces)
        if len(shape) != 2:
            # we may have mixed quads and triangles
            tris = np.array([i for i in faces if len(i) == 3])
            quads = np.array([i for i in faces if len(i) == 4])
            # combine triangulated quads with triangles
            faces = util.vstack_empty([
                tris,
                triangulate_quads(quads)])

        # PLY stores texture coordinates per-face which is
        # slightly annoying, as we have to then figure out
        # which vertices have the same position but different UV
        if (image is not None and
            texcoord is not None and
            len(shape) == 2 and
                texcoord.shape == (faces.shape[0], faces.shape[1] * 2)):

            # vertices with the same position but different
            # UV coordinates can't be merged without it
            # looking like it went through a woodchipper
            # in- the- wild PLY comes with things merged that
            # probably shouldn't be so disconnect vertices
            if fix_texture:
                # do import here
                from ..visual.texture import unmerge_faces

                # reshape to correspond with flattened faces
                uv_all = texcoord.reshape((-1, 2))
                # UV coordinates defined for every triangle have
                # duplicates which can be merged so figure out
                # which UV coordinates are the same here
                unique, inverse = grouping.unique_rows(uv_all)

                # use the indices of faces and face textures
                # to only merge vertices where the position
                # AND uv coordinate are the same
                faces, mask_v, mask_vt = unmerge_faces(
                    faces, inverse.reshape(faces.shape))
                # apply the mask to get resulting vertices
                vertices = vertices[mask_v]
                # apply the mask to get UV coordinates
                uv = uv_all[unique][mask_vt]
            else:
                # don't alter vertices, UV will look like crap
                # if it was exported with vertices merged
                uv = np.zeros((len(vertices), 2))
                uv[faces.reshape(-1)] = texcoord.reshape((-1, 2))

            # create the visuals object for the texture
            kwargs['visual'] = visual.texture.TextureVisuals(
                uv=uv, image=image)
        # faces were not none so assign them
        kwargs['faces'] = faces
    # kwargs for Trimesh or PointCloud
    kwargs['vertices'] = vertices

    # if both vertex and face color are defined pick the one
    # with the most "signal," i.e. which one is not all zeros
    colors = []
    signal = []
    if faces is not None:
        # extract face colors or None
        f_color, f_signal = element_colors(elements['face'])
        colors.append({'face_colors': f_color})
        signal.append(f_signal)
        # extract vertex colors or None
        v_color, v_signal = element_colors(elements['vertex'])
        colors.append({'vertex_colors': v_color})
        signal.append(v_signal)

        if prefer_color is None:
            # if we are in "auto-pick" mode take the one with the
            # largest  standard deviation of colors
            kwargs.update(colors[np.argmax(signal)])
        elif 'vert' in prefer_color and v_color is not None:
            # vertex colors are preferred and defined
            kwargs['vertex_colors'] = v_color
        elif 'face' in prefer_color and f_color is not None:
            # face colors are preferred and defined
            kwargs['face_colors'] = f_color
    else:
        kwargs['colors'] = element_colors(elements['vertex'])[0]

    return kwargs

def element_colors(element):
    """
    Given an element, try to extract RGBA color from
    properties and return them as an (n,3|4) array.

    Parameters
    -------------
    element : dict
      Containing color keys

    Returns
    ------------
    colors : (n, 3) or (n, 4) float
      Colors extracted from the element
    signal : float
      Estimate of range
    """
    keys = ['red', 'green', 'blue', 'alpha']
    candidate_colors = [element['data'][i]
                        for i in keys if i in element['properties']]

    if len(candidate_colors) >= 3:
        colors = np.column_stack(candidate_colors)
        signal = colors.std(axis=0).sum()
        return colors, signal

    return None, 0.0

def load_element_different(properties, data):
    """
    Load elements which include lists of different lengths
    based on the element's property-definitions.

    Parameters
    ------------
    properties : dict
      Property definitions encoded in a dict where the property name is the key
      and the property data type the value.
    data : array
      Data rows for this element.
    """
    element_data = {k: [] for k in properties.keys()}
    for row in data:
        start = 0
        for name, dt in properties.items():
            length = 1
            if '$LIST' in dt:
                dt = dt.split('($LIST,)')[-1]
                # the first entry in a list-property is the number of elements in the list
                length = int(row[start])
                # skip the first entry (the length), when reading the data
                start += 1
            end = start + length
            element_data[name].append(row[start:end].astype(dt))
            # start next property at the end of this one
            start = end

    # convert all property lists to numpy arrays
    for name in element_data.keys():
        element_data[name] = np.array(element_data[name]).squeeze()

    return element_data

def load_element_single(properties, data):
    """
    Load element data with lists of a single length
    based on the element's property-definitions.

    Parameters
    ------------
    properties : dict
      Property definitions encoded in a dict where the property name is the key
      and the property data type the value.
    data : array
      Data rows for this element. If the data contains list-properties,
      all lists belonging to one property must have the same length.
    """
    col_ranges = []
    start = 0
    row0 = data[0]
    for name, dt in properties.items():
        length = 1
        if '$LIST' in dt:
            # the first entry in a list-property is the number of elements in the list
            length = int(row0[start])
            # skip the first entry (the length), when reading the data
            start += 1
        end = start + length
        col_ranges.append((start, end))
        # start next property at the end of this one
        start = end

    return {n: data[:, c[0]:c[1]].astype(dt.split('($LIST,)')[-1])
            for c, (n, dt) in zip(col_ranges, properties.items())}

def ply_ascii(elements, file_obj):
    """
    Load data from an ASCII PLY file into an existing elements data structure.

    Parameters
    ------------
    elements : OrderedDict
      Populated from the file header, data will
      be added in-place to this object
    file_obj : file-like-object
      Current position at the start
      of the data section (past the header).
    """

    # get the file contents as a string
    text = str(file_obj.read().decode('utf-8'))
    # split by newlines
    lines = str.splitlines(text)
    # get each line as an array split by whitespace
    array = [np.fromstring(i, sep=' ') for i in lines]
    # store the line position in the file
    row_pos = 0

    # loop through data we need
    for key, values in elements.items():
        # if the element is empty ignore it
        if 'length' not in values or values['length'] == 0:
            continue
        data = array[row_pos:row_pos + values['length']]
        row_pos += values['length']
        # try stacking the data, which simplifies column-wise access. this is only
        # possible, if all rows have the same length.
        try:
            data = np.vstack(data)
            col_count_equal = True
        except ValueError:
            col_count_equal = False

        # number of list properties in this element
        list_count = sum(1 for dt in values['properties'].values() if '$LIST' in dt)
        if col_count_equal and list_count <= 1:
            # all rows have the same length and we only have at most one list
            # property where all entries have the same length. this means we can
            # use the quick numpy-based loading.
            element_data = load_element_single(
                values['properties'], data)
        else:
            # there are lists of differing lengths. we need to fall back to loading
            # the data by iterating all rows and checking for list-lengths. this is
            # slower than the variant above.
            element_data = load_element_different(
                values['properties'], data)

        elements[key]['data'] = element_data

def ply_binary(elements, file_obj):
    """
    Load the data from a binary PLY file into the elements data structure.

    Parameters
    ------------
    elements : OrderedDict
      Populated from the file header.
      Object will be modified to add data by this function.
    file_obj : open file object
      With current position at the start
      of the data section (past the header)
    """

    def populate_listsize(file_obj, elements):
        """
        Given a set of elements populated from the header if there are any
        list properties seek in the file the length of the list.

        Note that if you have a list where each instance is different length
        (if for example you mixed triangles and quads) this won't work at all
        """
        p_start = file_obj.tell()
        p_current = file_obj.tell()
        elem_pop = []
        for element_key, element in elements.items():
            props = element['properties']
            prior_data = ''
            for k, dtype in props.items():
                prop_pop = []
                if '$LIST' in dtype:
                    # every list field has two data types:
                    # the list length (single value), and the list data (multiple)
                    # here we are only reading the single value for list length
                    field_dtype = np.dtype(dtype.split(',')[0])
                    if len(prior_data) == 0:
                        offset = 0
                    else:
                        offset = np.dtype(prior_data).itemsize
                    file_obj.seek(p_current + offset)
                    blob = file_obj.read(field_dtype.itemsize)
                    if len(blob) == 0:
                        # no data was read for property
                        prop_pop.append(k)
                        break
                    size = np.frombuffer(blob, dtype=field_dtype)[0]
                    props[k] = props[k].replace('$LIST', str(size))
                prior_data += props[k] + ','
            if len(prop_pop) > 0:
                # if a property was empty remove it
                for pop in prop_pop:
                    props.pop(pop)
                # if we've removed all properties from
                # an element remove the element later
                if len(props) == 0:
                    elem_pop.append(element_key)
                    continue
            # get the size of the items in bytes
            itemsize = np.dtype(', '.join(props.values())).itemsize
            # offset the file based on read size
            p_current += element['length'] * itemsize
        # move the file back to where we found it
        file_obj.seek(p_start)
        # if there were elements without properties remove them
        for pop in elem_pop:
            elements.pop(pop)

    def populate_data(file_obj, elements):
        """
        Given the data type and field information from the header,
        read the data and add it to a 'data' field in the element.
        """
        for key in elements.keys():
            items = list(elements[key]['properties'].items())
            dtype = np.dtype(items)
            data = file_obj.read(elements[key]['length'] * dtype.itemsize)
            try:
                elements[key]['data'] = np.frombuffer(
                    data, dtype=dtype)
            except BaseException:
                log.warning('PLY failed to populate: {}'.format(key))
                elements[key]['data'] = None
        return elements

    def elements_size(elements):
        """
        Given an elements data structure populated from the header,
        calculate how long the file should be if it is intact.
        """
        size = 0
        for element in elements.values():
            dtype = np.dtype(','.join(element['properties'].values()))
            size += element['length'] * dtype.itemsize
        return size

    # some elements are passed where the list dimensions
    # are not included in the header, so this function goes
    # into the meat of the file and grabs the list dimensions
    # before we to the main data read as a single operation
    populate_listsize(file_obj, elements)

    # how many bytes are left in the file
    size_file = util.distance_to_end(file_obj)
    # how many bytes should the data structure described by
    # the header take up
    size_elements = elements_size(elements)

    # if the number of bytes is not the same the file is probably corrupt
    if size_file != size_elements:
        raise ValueError('File is unexpected length!')

    # with everything populated and a reasonable confidence the file
    # is intact, read the data fields described by the header
    populate_data(file_obj, elements)

def export_draco(mesh, bits=28):
    """
    Export a mesh using Google's Draco compressed format.

    Only works if draco_encoder is in your PATH:
    https://github.com/google/draco

    Parameters
    ----------
    mesh : Trimesh object
      Mesh to export
    bits : int
      Bits of quantization for position
      tol.merge=1e-8 is roughly 25 bits

    Returns
    ----------
    data : str or bytes
      DRC file bytes
    """
    with tempfile.NamedTemporaryFile(suffix='.ply') as temp_ply:
        temp_ply.write(export_ply(mesh))
        temp_ply.flush()
        with tempfile.NamedTemporaryFile(suffix='.drc') as encoded:
            subprocess.check_output([draco_encoder,
                                     '-qp',
                                     str(int(bits)),
                                     '-i',
                                     temp_ply.name,
                                     '-o',
                                     encoded.name])
            encoded.seek(0)
            data = encoded.read()
    return data

def load_draco(file_obj, **kwargs):
    """
    Load a mesh from Google's Draco format.

    Parameters
    ----------
    file_obj : file- like object
      Contains data

    Returns
    ----------
    kwargs : dict
      Keyword arguments to construct a Trimesh object
    """

    with tempfile.NamedTemporaryFile(suffix='.drc') as temp_drc:
        temp_drc.write(file_obj.read())
        temp_drc.flush()

        with tempfile.NamedTemporaryFile(suffix='.ply') as temp_ply:
            subprocess.check_output(
                [draco_decoder, '-i', temp_drc.name, '-o', temp_ply.name])
            temp_ply.seek(0)
            kwargs = load_ply(temp_ply)
    return kwargs

_ply_loaders = {'ply': load_ply}
_ply_exporters = {'ply': export_ply}
draco_encoder = find_executable('draco_encoder')
draco_decoder = find_executable('draco_decoder')

if draco_decoder is not None:
    _ply_loaders['drc'] = load_draco
if draco_encoder is not None:
    _ply_exporters['drc'] = export_draco

{'repo_name': 'mikedh/trimesh', 'stars': '959', 'repo_language': 'Python', 'file_name': 'base_interface_AP214.STEP', 'mime_type': 'text/plain', 'hash': 4777869437586385963, 'source_dataset': 'data'}


"""(Experimental) replacement for import/export functionality.

This module contains the `Document` class, a container for a DOM-style
document (e.g. svg, html, xml, etc.) designed to replace and improve
upon the IO functionality of svgpathtools (i.e. the svg2paths and
disvg/wsvg functions).

An Historic Note:
     The functionality in this module is meant to replace and improve
     upon the IO functionality previously provided by the the
     `svg2paths` and `disvg`/`wsvg` functions.

Example:
    Typical usage looks something like the following.

        >> from svgpathtools import *
        >> doc = Document('my_file.html')
        >> for path in doc.paths():
        >>     # Do something with the transformed Path object.
        >>     foo(path)
        >>     # Inspect the raw SVG element, e.g. change its attributes
        >>     foo(path.element)
        >>     transform = result.transform
        >>     # Use the transform that was applied to the path.
        >>     foo(path.transform)
        >> foo(doc.tree)  # do stuff using ElementTree's functionality
        >> doc.display()  # display doc in OS's default application
        >> doc.save('my_new_file.html')

A Big Problem:
    Derivatives and other functions may be messed up by
    transforms unless transforms are flattened (and not included in
    css)
"""

# External dependencies
from __future__ import division, absolute_import, print_function
import os
import collections
import xml.etree.ElementTree as etree
from xml.etree.ElementTree import Element, SubElement, register_namespace
from xml.dom.minidom import parseString
import warnings
from tempfile import gettempdir
from time import time

# Internal dependencies
from .parser import parse_path
from .parser import parse_transform
from .svg_to_paths import (path2pathd, ellipse2pathd, line2pathd,
                           polyline2pathd, polygon2pathd, rect2pathd)
from .misctools import open_in_browser
from .path import *

# To maintain forward/backward compatibility
try:
    str = basestring
except NameError:
    pass

# Let xml.etree.ElementTree know about the SVG namespace
SVG_NAMESPACE = {'svg': 'http://www.w3.org/2000/svg'}
register_namespace('svg', 'http://www.w3.org/2000/svg')

# THESE MUST BE WRAPPED TO OUTPUT ElementTree.element objects
CONVERSIONS = {'path': path2pathd,
               'circle': ellipse2pathd,
               'ellipse': ellipse2pathd,
               'line': line2pathd,
               'polyline': polyline2pathd,
               'polygon': polygon2pathd,
               'rect': rect2pathd}

CONVERT_ONLY_PATHS = {'path': path2pathd}

SVG_GROUP_TAG = 'svg:g'

def flattened_paths(group, group_filter=lambda x: True,
                    path_filter=lambda x: True, path_conversions=CONVERSIONS,
                    group_search_xpath=SVG_GROUP_TAG):
    """Returns the paths inside a group (recursively), expressing the
    paths in the base coordinates.

    Note that if the group being passed in is nested inside some parent
    group(s), we cannot take the parent group(s) into account, because
    xml.etree.Element has no pointer to its parent. You should use
    Document.flattened_paths_from_group(group) to flatten a specific nested group into
    the root coordinates.

    Args:
        group is an Element
        path_conversions (dict):
            A dictionary to convert from an SVG element to a path data
            string. Any element tags that are not included in this
            dictionary will be ignored (including the `path` tag). To
            only convert explicit path elements, pass in
            `path_conversions=CONVERT_ONLY_PATHS`.
    """
    if not isinstance(group, Element):
        raise TypeError('Must provide an xml.etree.Element object. '
                        'Instead you provided {0}'.format(type(group)))

    # Stop right away if the group_selector rejects this group
    if not group_filter(group):
        warnings.warn('The input group [{}] (id attribute: {}) was rejected by the group filter'
                      .format(group, group.get('id')))
        return []

    # To handle the transforms efficiently, we'll traverse the tree of
    # groups depth-first using a stack of tuples.
    # The first entry in the tuple is a group element and the second
    # entry is its transform. As we pop each entry in the stack, we
    # will add all its child group elements to the stack.
    StackElement = collections.namedtuple('StackElement',
                                          ['group', 'transform'])

    def new_stack_element(element, last_tf):
        return StackElement(element, last_tf.dot(
            parse_transform(element.get('transform'))))

    def get_relevant_children(parent, last_tf):
        children = []
        for elem in filter(group_filter,
                           parent.iterfind(group_search_xpath, SVG_NAMESPACE)):
            children.append(new_stack_element(elem, last_tf))
        return children

    stack = [new_stack_element(group, np.identity(3))]

    paths = []
    while stack:
        top = stack.pop()

        # For each element type that we know how to convert into path
        # data, parse the element after confirming that the path_filter
        # accepts it.
        for key, converter in path_conversions.items():
            for path_elem in filter(path_filter, top.group.iterfind(
                    'svg:'+key, SVG_NAMESPACE)):
                path_tf = top.transform.dot(
                    parse_transform(path_elem.get('transform')))
                path = transform(parse_path(converter(path_elem)), path_tf)
                path.element = path_elem
                path.transform = path_tf
                paths.append(path)

        stack.extend(get_relevant_children(top.group, top.transform))

    return paths

def flattened_paths_from_group(group_to_flatten, root, recursive=True,
                               group_filter=lambda x: True,
                               path_filter=lambda x: True,
                               path_conversions=CONVERSIONS,
                               group_search_xpath=SVG_GROUP_TAG):
    """Flatten all the paths in a specific group.

    The paths will be flattened into the 'root' frame. Note that root
    needs to be an ancestor of the group that is being flattened.
    Otherwise, no paths will be returned."""

    if not any(group_to_flatten is descendant for descendant in root.iter()):
        warnings.warn('The requested group_to_flatten is not a '
                      'descendant of root')
        # We will shortcut here, because it is impossible for any paths
        # to be returned anyhow.
        return []

    # We create a set of the unique IDs of each element that we wish to
    # flatten, if those elements are groups. Any groups outside of this
    # set will be skipped while we flatten the paths.
    desired_groups = set()
    if recursive:
        for group in group_to_flatten.iter():
            desired_groups.add(id(group))
    else:
        desired_groups.add(id(group_to_flatten))

    ignore_paths = set()
    # Use breadth-first search to find the path to the group that we care about
    if root is not group_to_flatten:
        search = [[root]]
        route = None
        while search:
            top = search.pop(0)
            frontier = top[-1]
            for child in frontier.iterfind(group_search_xpath, SVG_NAMESPACE):
                if child is group_to_flatten:
                    route = top
                    break
                future_top = list(top)
                future_top.append(child)
                search.append(future_top)

            if route is not None:
                for group in route:
                    # Add each group from the root to the parent of the desired group
                    # to the list of groups that we should traverse. This makes sure
                    # that paths will not stop before reaching the desired
                    # group.
                    desired_groups.add(id(group))
                    for key in path_conversions.keys():
                        for path_elem in group.iterfind('svg:'+key, SVG_NAMESPACE):
                            # Add each path in the parent groups to the list of paths
                            # that should be ignored. The user has not requested to
                            # flatten the paths of the parent groups, so we should not
                            # include any of these in the result.
                            ignore_paths.add(id(path_elem))
                break

        if route is None:
            raise ValueError('The group_to_flatten is not a descendant of the root!')

    def desired_group_filter(x):
        return (id(x) in desired_groups) and group_filter(x)

    def desired_path_filter(x):
        return (id(x) not in ignore_paths) and path_filter(x)

    return flattened_paths(root, desired_group_filter, desired_path_filter,
                           path_conversions, group_search_xpath)

class Document:
    def __init__(self, filepath=None):
        """A container for a DOM-style SVG document.

        The `Document` class provides a simple interface to modify and analyze
        the path elements in a DOM-style document.  The DOM-style document is
        parsed into an ElementTree object (stored in the `tree` attribute).

        This class provides functions for extracting SVG data into Path objects.
        The output Path objects will be transformed based on their parent groups.

        Args:
            filepath (str): The filepath of the DOM-style object.
        """

        # remember location of original svg file
        self.original_filepath = filepath
        if filepath is not None and os.path.dirname(filepath) == '':
            self.original_filepath = os.path.join(os.getcwd(), filepath)

        if filepath is None:
            self.tree = etree.ElementTree(Element('svg'))
        else:
            # parse svg to ElementTree object
            self.tree = etree.parse(filepath)

        self.root = self.tree.getroot()

    def paths(self, group_filter=lambda x: True,
              path_filter=lambda x: True, path_conversions=CONVERSIONS):
        """Returns a list of all paths in the document.

        Note that any transform attributes are applied before returning
        the paths.
        """
        return flattened_paths(self.tree.getroot(), group_filter,
                               path_filter, path_conversions)

    def paths_from_group(self, group, recursive=True, group_filter=lambda x: True,
                         path_filter=lambda x: True, path_conversions=CONVERSIONS):
        if all(isinstance(s, str) for s in group):
            # If we're given a list of strings, assume it represents a
            # nested sequence
            group = self.get_group(group)
        elif not isinstance(group, Element):
            raise TypeError(
                'Must provide a list of strings that represent a nested '
                'group name, or provide an xml.etree.Element object. '
                'Instead you provided {0}'.format(group))

        if group is None:
            warnings.warn("Could not find the requested group!")
            return []

        return flattened_paths_from_group(group, self.tree.getroot(), recursive,
                                          group_filter, path_filter, path_conversions)

    def add_path(self, path, attribs=None, group=None):
        """Add a new path to the SVG."""

        # If not given a parent, assume that the path does not have a group
        if group is None:
            group = self.tree.getroot()

        # If given a list of strings (one or more), assume it represents
        # a sequence of nested group names
        elif all(isinstance(elem, str) for elem in group):
            group = self.get_or_add_group(group)

        elif not isinstance(group, Element):
            raise TypeError(
                'Must provide a list of strings or an xml.etree.Element '
                'object. Instead you provided {0}'.format(group))

        else:
            # Make sure that the group belongs to this Document object
            if not self.contains_group(group):
                warnings.warn('The requested group does not belong to '
                              'this Document')

        # TODO: It might be better to use duck-typing here with a try-except
        if isinstance(path, Path):
            path_svg = path.d()
        elif is_path_segment(path):
            path_svg = Path(path).d()
        elif isinstance(path, str):
            # Assume this is a valid d-string.
            # TODO: Should we sanity check the input string?
            path_svg = path
        else:
            raise TypeError(
                'Must provide a Path, a path segment type, or a valid '
                'SVG path d-string. Instead you provided {0}'.format(path))

        if attribs is None:
            attribs = {}
        else:
            attribs = attribs.copy()

        attribs['d'] = path_svg

        return SubElement(group, 'path', attribs)

    def contains_group(self, group):
        return any(group is owned for owned in self.tree.iter())

    def get_group(self, nested_names, name_attr='id'):
        """Get a group from the tree, or None if the requested group
        does not exist. Use get_or_add_group(~) if you want a new group
        to be created if it did not already exist.

        `nested_names` is a list of strings which represent group names.
        Each group name will be nested inside of the previous group name.

        `name_attr` is the group attribute that is being used to
        represent the group's name. Default is 'id', but some SVGs may
        contain custom name labels, like 'inkscape:label'.

        Returns the request group. If the requested group did not
        exist, this function will return a None value.
        """
        group = self.tree.getroot()
        # Drill down through the names until we find the desired group
        while len(nested_names):
            prev_group = group
            next_name = nested_names.pop(0)
            for elem in group.iterfind(SVG_GROUP_TAG, SVG_NAMESPACE):
                if elem.get(name_attr) == next_name:
                    group = elem
                    break

            if prev_group is group:
                # The nested group could not be found, so we return None
                return None

        return group

    def get_or_add_group(self, nested_names, name_attr='id'):
        """Get a group from the tree, or add a new one with the given
        name structure.

        `nested_names` is a list of strings which represent group names.
        Each group name will be nested inside of the previous group name.

        `name_attr` is the group attribute that is being used to
        represent the group's name. Default is 'id', but some SVGs may
        contain custom name labels, like 'inkscape:label'.

        Returns the requested group. If the requested group did not
        exist, this function will create it, as well as all parent
        groups that it requires. All created groups will be left with
        blank attributes.

        """
        group = self.tree.getroot()
        # Drill down through the names until we find the desired group
        while len(nested_names):
            prev_group = group
            next_name = nested_names.pop(0)
            for elem in group.iterfind(SVG_GROUP_TAG, SVG_NAMESPACE):
                if elem.get(name_attr) == next_name:
                    group = elem
                    break

            if prev_group is group:
                # The group we're looking for does not exist, so let's
                # create the group structure
                nested_names.insert(0, next_name)

                while nested_names:
                    next_name = nested_names.pop(0)
                    group = self.add_group({'id': next_name}, group)
                # Now nested_names will be empty, so the topmost
                # while-loop will end
        return group

    def add_group(self, group_attribs=None, parent=None):
        """Add an empty group element to the SVG."""
        if parent is None:
            parent = self.tree.getroot()
        elif not self.contains_group(parent):
            warnings.warn('The requested group {0} does not belong to '
                          'this Document'.format(parent))

        if group_attribs is None:
            group_attribs = {}
        else:
            group_attribs = group_attribs.copy()

        return SubElement(parent, '{{{0}}}g'.format(
            SVG_NAMESPACE['svg']), group_attribs)

    def __repr__(self):
        return etree.tostring(self.tree.getroot()).decode()

    def pretty(self, **kwargs):
        return parseString(repr(self)).toprettyxml(**kwargs)

    def save(self, filepath, prettify=False, **kwargs):
        with open(filepath, 'w+') as output_svg:
            if prettify:
                output_svg.write(self.pretty(**kwargs))
            else:
                output_svg.write(repr(self))

    def display(self, filepath=None):
        """Displays/opens the doc using the OS's default application."""

        if filepath is None:
            if self.original_filepath is None: # created from empty Document
                orig_name, ext = 'unnamed', '.svg'
            else:
                orig_name, ext = \
                    os.path.splitext(os.path.basename(self.original_filepath))
            tmp_name = orig_name + '_' + str(time()).replace('.', '-') + ext
            filepath = os.path.join(gettempdir(), tmp_name)

        # write to a (by default temporary) file
        with open(filepath, 'w') as output_svg:
            output_svg.write(repr(self))

        open_in_browser(filepath)

{'repo_name': 'mathandy/svgpathtools', 'stars': '207', 'repo_language': 'Python', 'file_name': 'svg_to_paths.py', 'mime_type': 'text/x-python', 'hash': -6780337339190641823, 'source_dataset': 'data'}


<?xml version="1.0" encoding="UTF-8"?>
<report xmlns="http://www.eclipse.org/birt/2005/design" version="3.2.23" id="1">
    <list-property name="libraries">
        <structure>
            <property name="fileName">Library_1.xml</property>
            <property name="namespace">Lib1</property>
        </structure>
    </list-property>
    <page-setup>
        <graphic-master-page name="My Page" id="2"/>
    </page-setup>
    <list-property name="images">
        <structure>
            <property name="name">image1</property>
            <property name="libReference">Lib1.image1</property>
        </structure>
    </list-property>
</report>

{'repo_name': 'eclipse/birt', 'stars': '201', 'repo_language': 'Java', 'file_name': 'Messages.properties', 'mime_type': 'text/plain', 'hash': -6946268324668667951, 'source_dataset': 'data'}


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Uses of Class javax.mail.Message (Java(TM) EE 8 Specification APIs)</title>
<meta name="date" content="2017-09-06">
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">

JavaScript is disabled on your browser.

Skip navigation links

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev

Next

Frames

No Frames

All Classes

Uses of Class
javax.mail.Message

Packages that use Message

Package
Description

javax.mail

The JavaMailTM API
provides classes that model a mail system.

javax.mail.event

Listeners and events for the JavaMail API.

javax.mail.internet

Classes specific to Internet mail systems.

javax.mail.search

Message search terms for the JavaMail API.

Uses of Message in javax.mail

Methods in javax.mail that return Message

Modifier and Type
Method and Description

abstract Message[]
Folder.expunge()

Expunge (permanently remove) messages marked DELETED.

Message
MessageContext.getMessage()

Return the Message that contains the content.

abstract Message
Folder.getMessage(int msgnum)

Get the Message object corresponding to the given message
 number.

Message
UIDFolder.getMessageByUID(long uid)

Get the Message corresponding to the given UID.

Message[]
Folder.getMessages()

Get all Message objects from this Folder.

Message[]
Folder.getMessages(int[] msgnums)

Get the Message objects for message numbers specified in
 the array.

Message[]
Folder.getMessages(int start,
           int end)

Get the Message objects for message numbers ranging from start
 through end, both start and end inclusive.

Message[]
UIDFolder.getMessagesByUID(long[] uids)

Get the Messages specified by the given array of UIDs.

Message[]
UIDFolder.getMessagesByUID(long start,
                long end)

Get the Messages specified by the given range.

abstract Message
Message.reply(boolean replyToAll)

Get a new Message suitable for a reply to this message.

Message[]
Folder.search(SearchTerm term)

Search this Folder for messages matching the specified
 search criterion.

Message[]
Folder.search(SearchTerm term,
      Message[] msgs)

Search the given array of messages for those that match the
 specified search criterion.

Methods in javax.mail with parameters of type Message

Modifier and Type
Method and Description

abstract void
Folder.appendMessages(Message[] msgs)

Append given Messages to this folder.

void
Folder.copyMessages(Message[] msgs,
            Folder folder)

Copy the specified Messages from this Folder into another
 Folder.

void
Folder.fetch(Message[] msgs,
     FetchProfile fp)

Prefetch the items specified in the FetchProfile for the
 given Messages.

long
UIDFolder.getUID(Message message)

Get the UID for the specified message.

protected void
Folder.notifyMessageAddedListeners(Message[] msgs)

Notify all MessageCountListeners about the addition of messages
 into this folder.

protected void
Folder.notifyMessageChangedListeners(int type,
                             Message msg)

Notify all MessageChangedListeners.

protected void
Folder.notifyMessageRemovedListeners(boolean removed,
                             Message[] msgs)

Notify all MessageCountListeners about the removal of messages
 from this Folder.

protected void
Transport.notifyTransportListeners(int type,
                        Address[] validSent,
                        Address[] validUnsent,
                        Address[] invalid,
                        Message msg)

Notify all TransportListeners.

Message[]
Folder.search(SearchTerm term,
      Message[] msgs)

Search the given array of messages for those that match the
 specified search criterion.

static void
Transport.send(Message msg)

Send a message.

static void
Transport.send(Message msg,
    Address[] addresses)

Send the message to the specified addresses, ignoring any
 recipients specified in the message itself.

static void
Transport.send(Message msg,
    Address[] addresses,
    String user,
    String password)

Send the message to the specified addresses, ignoring any
 recipients specified in the message itself.

static void
Transport.send(Message msg,
    String user,
    String password)

Send a message.

abstract void
Transport.sendMessage(Message msg,
           Address[] addresses)

Send the Message to the specified list of addresses.

void
Folder.setFlags(Message[] msgs,
        Flags flag,
        boolean value)

Set the specified flags on the messages specified in the array.

Uses of Message in javax.mail.event

Fields in javax.mail.event declared as Message

Modifier and Type
Field and Description

protected Message
TransportEvent.msg

The Message to which this event applies.

protected Message
MessageChangedEvent.msg

The message that changed.

protected Message[]
MessageCountEvent.msgs

The messages.

Methods in javax.mail.event that return Message

Modifier and Type
Method and Description

Message
TransportEvent.getMessage()

Get the Message object associated with this Transport Event.

Message
MessageChangedEvent.getMessage()

Return the changed Message.

Message[]
MessageCountEvent.getMessages()

Return the array of messages added or removed.

Constructors in javax.mail.event with parameters of type Message

Constructor and Description

MessageChangedEvent(Object source,
                   int type,
                   Message msg)

Constructor.

MessageCountEvent(Folder folder,
                 int type,
                 boolean removed,
                 Message[] msgs)

Constructor.

TransportEvent(Transport transport,
              int type,
              Address[] validSent,
              Address[] validUnsent,
              Address[] invalid,
              Message msg)

Constructor.

Uses of Message in javax.mail.internet

Subclasses of Message in javax.mail.internet

Modifier and Type
Class and Description

class
MimeMessage

This class represents a MIME style email message.

Methods in javax.mail.internet that return Message

Modifier and Type
Method and Description

Message
MimeMessage.reply(boolean replyToAll)

Get a new Message suitable for a reply to this message.

Message
MimeMessage.reply(boolean replyToAll,
     boolean setAnswered)

Get a new Message suitable for a reply to this message.

Uses of Message in javax.mail.search

Methods in javax.mail.search with parameters of type Message

Modifier and Type
Method and Description

boolean
SubjectTerm.match(Message msg)

The match method.

boolean
SizeTerm.match(Message msg)

The match method.

boolean
SentDateTerm.match(Message msg)

The match method.

abstract boolean
SearchTerm.match(Message msg)

This method applies a specific match criterion to the given
 message and returns the result.

boolean
RecipientTerm.match(Message msg)

The match method.

boolean
RecipientStringTerm.match(Message msg)

Check whether the address specified in the constructor is
 a substring of the recipient address of this Message.

boolean
ReceivedDateTerm.match(Message msg)

The match method.

boolean
OrTerm.match(Message msg)

The OR operation.

boolean
NotTerm.match(Message msg)

boolean
MessageNumberTerm.match(Message msg)

The match method.

boolean
MessageIDTerm.match(Message msg)

The match method.

boolean
HeaderTerm.match(Message msg)

The header match method.

boolean
FromTerm.match(Message msg)

The address comparator.

boolean
FromStringTerm.match(Message msg)

Check whether the address string specified in the constructor is
 a substring of the From address of this Message.

boolean
FlagTerm.match(Message msg)

The comparison method.

boolean
BodyTerm.match(Message msg)

The match method.

boolean
AndTerm.match(Message msg)

The AND operation.

Skip navigation links

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev

Next

Frames

No Frames

All Classes

Copyright © 1996-2017,     Oracle     and/or its affiliates. All Rights Reserved.     Use is subject to     license terms.

{'repo_name': 'javaee/javaee-spec', 'stars': '388', 'repo_language': 'HTML', 'file_name': 'default.html', 'mime_type': 'text/html', 'hash': 3708323261905907133, 'source_dataset': 'data'}


'use strict';
// 21.1.3.25 String.prototype.trim()
require('./_string-trim')('trim', function ($trim) {
  return function trim() {
    return $trim(this, 3);
  };
});

{'repo_name': 'arschles/go-in-5-minutes', 'stars': '1199', 'repo_language': 'JavaScript', 'file_name': 'plugin.js', 'mime_type': 'text/plain', 'hash': -1932547919453075963, 'source_dataset': 'data'}


---
title: Función EndMethodEnumeration (Referencia de API no administrada)
description: La función EndMethodEnumeration finaliza una secuencia de enumeración de método.
ms.date: 11/06/2017
api_name:
- EndMethodEnumeration
api_location:
- WMINet_Utils.dll
api_type:
- DLLExport
f1_keywords:
- EndMethodEnumeration
helpviewer_keywords:
- EndMethodEnumeration function [.NET WMI and performance counters]
topic_type:
- Reference
ms.openlocfilehash: 63667d0668f905ded2aedd961be0d1831faf838c
ms.sourcegitcommit: 7588136e355e10cbc2582f389c90c127363c02a5
ms.translationtype: MT
ms.contentlocale: es-ES
ms.lasthandoff: 03/12/2020
ms.locfileid: "79175010"
---
# Función EndMethodEnumeration
Termina una secuencia de enumeración iniciada con una llamada a la [función BeginMethodEnumeration](beginmethodenumeration.md).

[!INCLUDE[internalonly-unmanaged](../../../../includes/internalonly-unmanaged.md)]

## Sintaxis

```cpp
HRESULT EndMethodEnumeration (
   [in] int               vFunc,
   [in] IWbemClassObject* ptr
);
```

## Parámetros

`vFunc`
[en] Este parámetro no se utiliza.

`ptr`
[en] Puntero a una instancia de [IWbemClassObject.](/windows/desktop/api/wbemcli/nn-wbemcli-iwbemclassobject)

## Valor devuelto

Los siguientes valores devueltos por esta función se definen en el archivo de encabezado *WbemCli.h,* o puede definirlos como constantes en el código:

|Constante  |Value  |Descripción  |
|---------|---------|---------|
|`WBEM_E_UNEXPECTED` | 0x8004101d | Error interno. |
|`WBEM_S_NO_ERROR` | 0 | La llamada de función se realizó correctamente.  |

## Observaciones

Esta función ajusta una llamada a la [IWbemClassObject::EndMethodEnumeration](/windows/desktop/api/wbemcli/nf-wbemcli-iwbemclassobject-endmethodenumeration) método.

El llamador comienza la secuencia de enumeración mediante [beginMethodEnumeration función](beginmethodenumeration.md)y, a continuación, llama a la [NextMethod función](nextmethod.md )hasta que el método devuelve `WBEM_S_NO_MORE_DATA`. El autor de la llamada `EndMethodEnumeration`finaliza opcionalmente la secuencia llamando a . El llamador puede terminar `EndMethodEnumeration` la enumeración antes de tiempo llamando en cualquier momento.

## Requisitos
 **Plataformas:** Vea [Requisitos de sistema](../../get-started/system-requirements.md).

 **Encabezado:** WMINet_Utils.idl

 **Versiones de .NET Framework:** [!INCLUDE[net_current_v472plus](../../../../includes/net-current-v472plus.md)]

## Consulte también

- [WMI y contadores de rendimiento (referencia de API no administrada)](index.md)

{'repo_name': 'dotnet/docs.es-es', 'stars': '120', 'repo_language': 'PowerShell', 'file_name': 'index.md', 'mime_type': 'text/plain', 'hash': -2285743645862880811, 'source_dataset': 'data'}


package constants

type ExpressionType int

const (
	XtNull         ExpressionType = 0  /* P data: [0] */
	XtInt          ExpressionType = 1  /* P data: [4]int */
	XtDouble       ExpressionType = 2  /* -  data: [8]double */
	XtString       ExpressionType = 3  /* P data: [n]char null-term. strg. */
	XtLang         ExpressionType = 4  /* - */
	XtS4           ExpressionType = 7  /* P data: [0] */
	XtVector       ExpressionType = 16 /* P data: [?]REXP,REXP,.. */
	XtClos         ExpressionType = 18 /* P X formals, X body  (closure; since 0.1-5) */
	XtSymName      ExpressionType = 19 /* s same as XtStr (since 0.5) */
	XtListNoTag    ExpressionType = 20 /* s same as XtVector (since 0.5) */
	XtListTag      ExpressionType = 21 /* P X tag, X val, Y tag, Y val, ... (since 0.5) */
	XtLangNoTag    ExpressionType = 22 /* s same as XtListNoTag (since 0.5) */
	XtLangTag      ExpressionType = 23 /* s same as XtListTag (since 0.5) */
	XtExpVector    ExpressionType = 26 /* s same as XtVector (since 0.5) */
	XtIntArray     ExpressionType = 32 /* P data: [n*4]int,int,.. */
	XtDoubleArray  ExpressionType = 33 /* P data: [n*8]double,double,.. */
	XtStringArray  ExpressionType = 34 /* P data: string,string,.. (string=byte,byte,...,0) padded with '\01' */
	XtBoolArray    ExpressionType = 36 /* P data: int(n),byte,byte,... */
	XtRaw          ExpressionType = 37 /* P data: int(n),byte,byte,... */
	XtComplexArray ExpressionType = 38 /* P data: [n*16]double,double,... (Re,Im,Re,Im,...) */
	XtUnknown      ExpressionType = 48 /* P data: [4]int - SEXP type (as from TYPEOF(x)) */
)

{'repo_name': 'senseyeio/roger', 'stars': '243', 'repo_language': 'Go', 'file_name': 'xt-list-no-tag.go', 'mime_type': 'text/plain', 'hash': -8066869648374410343, 'source_dataset': 'data'}


/**
 * This file is part of the ReTeX library - https://github.com/himamis/ReTeX
 *
 * Copyright (C) 2015 Balazs Bencze
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * A copy of the GNU General Public License can be found in the file
 * LICENSE.txt provided with the source distribution of this program (see
 * the META-INF directory in the source jar). This license can also be
 * found on the GNU website at http://www.gnu.org/licenses/gpl.html.
 *
 * If you did not receive a copy of the GNU General Public License along
 * with this program, contact the lead developer, or write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *
 * Linking this library statically or dynamically with other modules
 * is making a combined work based on this library. Thus, the terms
 * and conditions of the GNU General Public License cover the whole
 * combination.
 *
 * As a special exception, the copyright holders of this library give you
 * permission to link this library with independent modules to produce
 * an executable, regardless of the license terms of these independent
 * modules, and to copy and distribute the resulting executable under terms
 * of your choice, provided that you also meet, for each linked independent
 * module, the terms and conditions of the license of that module.
 * An independent module is a module which is not derived from or based
 * on this library. If you modify this library, you may extend this exception
 * to your version of the library, but you are not obliged to do so.
 * If you do not wish to do so, delete this exception statement from your
 * version.
 *
 */
package com.himamis.retex.renderer.share.platform.graphics;

public class ImageBase64 implements Image {

	private String base64PNG;
	private int width;
	private int height;

	public ImageBase64(String base64PNG, int width, int height) {
		this.base64PNG = base64PNG;
		this.width = width;
		this.height = height;
	}

	@Override
	public int getWidth() {
		return width;
	}

	@Override
	public int getHeight() {
		return height;
	}

	public String getBase64() {
		return base64PNG;
	}

	@Override
	public Graphics2DInterface createGraphics2D() {
		return null;
	}

}

{'repo_name': 'geogebra/geogebra', 'stars': '470', 'repo_language': 'Java', 'file_name': 'HelpDialog.java', 'mime_type': 'text/plain', 'hash': -6516412732716424025, 'source_dataset': 'data'}


Warns about the invalid assignment of the animation trigger. To attach an animation to an element, use
[@triggerName]="expression" or an attribute without a value @triggerName.

{'repo_name': 'JetBrains/intellij-plugins', 'stars': '1534', 'repo_language': 'Java', 'file_name': 'index.js', 'mime_type': 'text/plain', 'hash': 2876596835028826320, 'source_dataset': 'data'}