<commit_before>#include "vtkDICOMMetaData.h"

#include <vtkObjectFactory.h>
#include <vtkMatrix4x4.h>
#include <vtkAbstractArray.h>

#include <assert.h>
#include <vector>
#include <utility>

vtkStandardNewMacro(vtkDICOMMetaData);

// The hash table size, must be a power of two
#define METADATA_HASH_SIZE 512

//----------------------------------------------------------------------------
// For use by methods that must return an invalid value
const vtkDICOMValue vtkDICOMMetaData::InvalidValue;

//----------------------------------------------------------------------------
// Constructor
vtkDICOMMetaData::vtkDICOMMetaData()
{
  this->NumberOfInstances = 1;
  this->NumberOfDataElements = 0;
  this->Table = NULL;
  this->Head.Prev = NULL;
  this->Head.Next = &this->Tail;
  this->Tail.Prev = &this->Head;
  this->Tail.Next = NULL;
}

// Destructor
vtkDICOMMetaData::~vtkDICOMMetaData()
{
  this->Clear();
}

//----------------------------------------------------------------------------
void vtkDICOMMetaData::Clear()
{
  vtkDICOMDataElement **htable = this->Table;

  if (htable)
    {
    for (unsigned int i = 0; i < METADATA_HASH_SIZE; i++)
      {
      delete [] htable[i];
      }
    delete [] htable;
    }

  this->NumberOfInstances = 1;
  this->Table = NULL;
  this->Head.Next = &this->Tail;
  this->Tail.Prev = &this->Head;
}

//----------------------------------------------------------------------------
void vtkDICOMMetaData::SetNumberOfInstances(int n)
{
  if (this->Table != NULL)
    {
    vtkErrorMacro("SetNumberOfInstances: Cannot set NumberOfInstances after "
                  "attributes have been added");
    }
  else
    {
    if (n != this->NumberOfInstances)
      {
      this->Modified();
      }
    this->NumberOfInstances = n;
    }
}

//----------------------------------------------------------------------------
// Erase an element from the hash table
void vtkDICOMMetaData::RemoveAttribute(vtkDICOMTag tag)
{
  unsigned int m = METADATA_HASH_SIZE - 1;
  unsigned int i = (tag.ComputeHash() & m);
  vtkDICOMDataElement **htable = this->Table;
  vtkDICOMDataElement *hptr;

  if (htable && (hptr = htable[i]) != NULL)
    {
    while (hptr->Next != 0)
      {
      if (hptr->Tag == tag)
        {
        // remove from the linked list
        hptr->Next->Prev = hptr->Prev;
        hptr->Prev->Next = hptr->Next;
        // remove from the hash table
        hptr[0] = hptr[1];
        while (hptr->Next != 0)
          {
          // adjust links as necessary
          hptr->Prev->Next = hptr;
          hptr->Next->Prev = hptr;
          hptr++;
          hptr[0] = hptr[1];
          }
        this->NumberOfDataElements--;
        break;
        }
      hptr++;
      }
    }
}

//----------------------------------------------------------------------------
// Get an element from the hash table.
vtkDICOMDataElement *vtkDICOMMetaData::FindDataElement(
  vtkDICOMTag tag)
{
  unsigned int m = METADATA_HASH_SIZE - 1;
  unsigned int i = (tag.ComputeHash() & m);
  vtkDICOMDataElement **htable = this->Table;
  vtkDICOMDataElement *hptr;

  if (htable && (hptr = htable[i]) != NULL)
    {
    while (hptr->Next != 0)
      {
      if (hptr->Tag == tag)
        {
        return hptr;
        }
      hptr++;
      }
    }

  return NULL;
}

//----------------------------------------------------------------------------
bool vtkDICOMMetaData::HasAttribute(vtkDICOMTag tag)
{
  return (this->FindDataElement(tag) != 0);
}

//----------------------------------------------------------------------------
const vtkDICOMValue *vtkDICOMMetaData::FindAttributeValue(
  int idx, vtkDICOMTag tag)
{
  vtkDICOMDataElement *a = this->FindDataElement(tag);
  const vtkDICOMValue *vptr = 0;

  if (a != 0)
    {
    vptr = &a->Value;
    // is this a sequence of values?
    const vtkDICOMValue *sptr = vptr->GetMultiplexData();
    if (sptr)
      {
      assert(idx >= 0 && idx < static_cast<int>(vptr->GetNumberOfValues()));
      vptr = &sptr[idx];
      }
    }

  return vptr;
}

//----------------------------------------------------------------------------
const vtkDICOMValue &vtkDICOMMetaData::GetAttributeValue(vtkDICOMTag tag)
{
  const vtkDICOMValue *vptr = this->FindAttributeValue(0, tag);
  return (vptr ? *vptr : vtkDICOMMetaData::InvalidValue);
}

//----------------------------------------------------------------------------
const vtkDICOMValue &vtkDICOMMetaData::GetAttributeValue(
  int idx, vtkDICOMTag tag)
{
  const vtkDICOMValue *vptr = this->FindAttributeValue(idx, tag);
  return (vptr ? *vptr : vtkDICOMMetaData::InvalidValue);
}

//----------------------------------------------------------------------------
// Return a reference to the element within the hash table, which can
// be used to insert a new value.
vtkDICOMDataElement *vtkDICOMMetaData::FindDataElementOrInsert(
  vtkDICOMTag tag)
{
  unsigned int m = METADATA_HASH_SIZE - 1;
  unsigned int i = (tag.ComputeHash() & m);
  vtkDICOMDataElement **htable = this->Table;
  vtkDICOMDataElement *hptr;

  if (htable == NULL)
    {
    // allocate the hash table
    m = METADATA_HASH_SIZE;
    htable = new vtkDICOMDataElement *[METADATA_HASH_SIZE];
    this->Table = htable;
    do { *htable++ = NULL; } while (--m);
    htable = this->Table;
    }

  hptr = htable[i];

  if (hptr == NULL)
    {
    hptr = new vtkDICOMDataElement[4];
    htable[i] = hptr;
    }
  else if (hptr->Next != 0)
    {
    // see if item is already there
    unsigned int n = 0;
    do
      {
      if (hptr->Tag == tag)
        {
        return hptr;
        }
      n++;
      hptr++;
      }
    while (hptr->Next != 0);

    // if n+1 is a power of two, double allocated space
    if (n > 2 && (n & (n+1)) == 0)
      {
      vtkDICOMDataElement *oldptr = htable[i];
      hptr = new vtkDICOMDataElement[2*(n+1)];
      htable[i] = hptr;
      // copy the old list
      for (unsigned int j = 0; j < n; j++)
        {
        *hptr = oldptr[j];
        // link the new element into the list
        hptr->Next->Prev = hptr;
        hptr->Prev->Next = hptr;
        hptr++;
        }
      delete [] oldptr;
      }
    }

  // insert into the linked list
  vtkDICOMDataElement *tptr = &this->Tail;
  do
    {
    tptr = tptr->Prev;
    }
  while (tag < tptr->GetTag());

  hptr->Prev = tptr;
  hptr->Next = tptr->Next;
  hptr->Prev->Next = hptr;
  hptr->Next->Prev = hptr;
  this->NumberOfDataElements++;

  return hptr;
}

//----------------------------------------------------------------------------
// Insert an attribute into the hash table
void vtkDICOMMetaData::SetAttributeValue(
  vtkDICOMTag tag, const vtkDICOMValue& v)
{
  vtkDICOMDataElement *loc = this->FindDataElementOrInsert(tag);
  if (loc == 0)
    {
    vtkErrorMacro("SetAttributeValue: tag group number must not be zero.");
    return;
    }
  loc->Tag = tag;
  loc->Value = v;
}

template<class T>
void vtkDICOMMetaData::SetAttributeValueT(vtkDICOMTag tag, T v)
{
  vtkDICOMVR vr = this->FindDictVR(0, tag);
  if (vr != vtkDICOMVR::UN)
    {
    this->SetAttributeValue(tag, vtkDICOMValue(vr, v));
    }
}

void vtkDICOMMetaData::SetAttributeValue(vtkDICOMTag tag, double v)
{
  this->SetAttributeValueT(tag, v);
}

void vtkDICOMMetaData::SetAttributeValue(vtkDICOMTag tag, const std::string& v)
{
  this->SetAttributeValueT(tag, v);
}

//----------------------------------------------------------------------------
// Insert an attribute for a particular image
void vtkDICOMMetaData::SetAttributeValue(
  int idx, vtkDICOMTag tag, const vtkDICOMValue& v)
{
  vtkDICOMDataElement *loc = this->FindDataElementOrInsert(tag);
  if (loc == 0)
    {
    vtkErrorMacro("SetAttributeValue: tag group number must not be zero.");
    return;
    }

  loc->Tag = tag;
  vtkDICOMValue *vptr = &loc->Value;

  assert(idx >= 0 && idx < static_cast<int>(vptr->GetNumberOfValues()));

  // first value for this attribute
  if (!vptr->IsValid())
    {
    *vptr = v;
    return;
    }

  // is this a sequence of values?
  vtkDICOMValue *sptr = vptr->GetMultiplexData();
  if (sptr)
    {
    sptr[idx] = v;
    }
  else if (v != *vptr)
    {
    // differs from other instances, must turn value into a list,
    // so create a value that is actually a list of values
    int n = this->NumberOfInstances;
    vtkDICOMValue l;
    sptr = l.AllocateMultiplexData(v.GetVR(), n);
    for (int i = 0; i < n; i++)
      {
      if (i == idx)
        {
        sptr[i] = v;
        }
      else
        {
        sptr[i] = *vptr;
        }
      }
    *vptr = l;
    }
}

template<class T>
void vtkDICOMMetaData::SetAttributeValueT(int idx, vtkDICOMTag tag, T v)
{
  vtkDICOMVR vr = this->FindDictVR(idx, tag);
  if (vr != vtkDICOMVR::UN)
    {
    this->SetAttributeValue(idx, tag, vtkDICOMValue(vr, v));
    }
}

void vtkDICOMMetaData::SetAttributeValue(
  int idx, vtkDICOMTag tag, double v)
{
  this->SetAttributeValueT(idx, tag, v);
}

void vtkDICOMMetaData::SetAttributeValue(
  int idx, vtkDICOMTag tag, const std::string& v)
{
  this->SetAttributeValueT(idx, tag, v);
}

// should only be called from SetAttributeValue
vtkDICOMVR vtkDICOMMetaData::FindDictVR(int idx, vtkDICOMTag tag)
{
  vtkDICOMVR vr = vtkDICOMVR::UN;
  vtkDICOMDictEntry e;

  if (vtkDICOMMetaData::FindDictEntry(tag, e))
    {
    vr = e.GetVR();
    // use the dictionary VR
    if (vr == vtkDICOMVR::XS)
      {
      const vtkDICOMValue &v =
        this->GetAttributeValue(idx, vtkDICOMTag(0x0028,0x0103));
      if (v.IsValid())
        {
        unsigned short r = v.AsUnsignedShort();
        vr = (r == 0 ? vtkDICOMVR::US : vtkDICOMVR::SS);
        }
      else
        {
        vtkErrorMacro("SetAttributeValue: could not look up vr for (" <<
                      tag << ") because PixelRepresentation is not set.");
        }
      }
    else if (vr == vtkDICOMVR::OX)
      {
      if (tag.GetGroup() == 0x5400)
        {
        const vtkDICOMValue &v =
          this->GetAttributeValue(idx, vtkDICOMTag(0x5400,0x1004));
        if (v.IsValid())
          {
          unsigned short s = v.AsUnsignedShort();
          vr = (s > 8 ? vtkDICOMVR::OW : vtkDICOMVR::OB);
          }
        else
          {
          vtkErrorMacro("SetAttributeValue: could not look up vr for (" <<
                        tag << ") because WaveformBitsAllocated is not set.");
          }
        }
      else
        {
        const vtkDICOMValue &v =
          this->GetAttributeValue(idx, vtkDICOMTag(0x0028,0x0100));
        if (v.IsValid())
          {
          unsigned short s = v.AsUnsignedShort();
          vr = (s > 8 ? vtkDICOMVR::OW : vtkDICOMVR::OB);
          }
        else
          {
          vtkErrorMacro("SetAttributeValue: could not look up vr for (" <<
                        tag << ") because BitsAllocated is not set.");
          }
        }
      }
    }
  else
    {
    vtkErrorMacro("SetAttributeValue: could not find tag (" <<
                  tag << ") in the dictionary");
    }

  return vr;
}

//----------------------------------------------------------------------------
void vtkDICOMMetaData::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);

  os << indent << "NumberOfInstances: "
     << this->NumberOfInstances << "\n";
  os << indent << "NumberOfDataElements: "
     << this->NumberOfDataElements << "\n";
}
<commit_msg>BUG: Wrong limit was used in assert statement.<commit_after>#include "vtkDICOMMetaData.h"

#include <vtkObjectFactory.h>
#include <vtkMatrix4x4.h>
#include <vtkAbstractArray.h>

#include <assert.h>
#include <vector>
#include <utility>

vtkStandardNewMacro(vtkDICOMMetaData);

// The hash table size, must be a power of two
#define METADATA_HASH_SIZE 512

//----------------------------------------------------------------------------
// For use by methods that must return an invalid value
const vtkDICOMValue vtkDICOMMetaData::InvalidValue;

//----------------------------------------------------------------------------
// Constructor
vtkDICOMMetaData::vtkDICOMMetaData()
{
  this->NumberOfInstances = 1;
  this->NumberOfDataElements = 0;
  this->Table = NULL;
  this->Head.Prev = NULL;
  this->Head.Next = &this->Tail;
  this->Tail.Prev = &this->Head;
  this->Tail.Next = NULL;
}

// Destructor
vtkDICOMMetaData::~vtkDICOMMetaData()
{
  this->Clear();
}

//----------------------------------------------------------------------------
void vtkDICOMMetaData::Clear()
{
  vtkDICOMDataElement **htable = this->Table;

  if (htable)
    {
    for (unsigned int i = 0; i < METADATA_HASH_SIZE; i++)
      {
      delete [] htable[i];
      }
    delete [] htable;
    }

  this->NumberOfInstances = 1;
  this->Table = NULL;
  this->Head.Next = &this->Tail;
  this->Tail.Prev = &this->Head;
}

//----------------------------------------------------------------------------
void vtkDICOMMetaData::SetNumberOfInstances(int n)
{
  if (this->Table != NULL)
    {
    vtkErrorMacro("SetNumberOfInstances: Cannot set NumberOfInstances after "
                  "attributes have been added");
    }
  else
    {
    if (n != this->NumberOfInstances)
      {
      this->Modified();
      }
    this->NumberOfInstances = n;
    }
}

//----------------------------------------------------------------------------
// Erase an element from the hash table
void vtkDICOMMetaData::RemoveAttribute(vtkDICOMTag tag)
{
  unsigned int m = METADATA_HASH_SIZE - 1;
  unsigned int i = (tag.ComputeHash() & m);
  vtkDICOMDataElement **htable = this->Table;
  vtkDICOMDataElement *hptr;

  if (htable && (hptr = htable[i]) != NULL)
    {
    while (hptr->Next != 0)
      {
      if (hptr->Tag == tag)
        {
        // remove from the linked list
        hptr->Next->Prev = hptr->Prev;
        hptr->Prev->Next = hptr->Next;
        // remove from the hash table
        hptr[0] = hptr[1];
        while (hptr->Next != 0)
          {
          // adjust links as necessary
          hptr->Prev->Next = hptr;
          hptr->Next->Prev = hptr;
          hptr++;
          hptr[0] = hptr[1];
          }
        this->NumberOfDataElements--;
        break;
        }
      hptr++;
      }
    }
}

//----------------------------------------------------------------------------
// Get an element from the hash table.
vtkDICOMDataElement *vtkDICOMMetaData::FindDataElement(
  vtkDICOMTag tag)
{
  unsigned int m = METADATA_HASH_SIZE - 1;
  unsigned int i = (tag.ComputeHash() & m);
  vtkDICOMDataElement **htable = this->Table;
  vtkDICOMDataElement *hptr;

  if (htable && (hptr = htable[i]) != NULL)
    {
    while (hptr->Next != 0)
      {
      if (hptr->Tag == tag)
        {
        return hptr;
        }
      hptr++;
      }
    }

  return NULL;
}

//----------------------------------------------------------------------------
bool vtkDICOMMetaData::HasAttribute(vtkDICOMTag tag)
{
  return (this->FindDataElement(tag) != 0);
}

//----------------------------------------------------------------------------
const vtkDICOMValue *vtkDICOMMetaData::FindAttributeValue(
  int idx, vtkDICOMTag tag)
{
  vtkDICOMDataElement *a = this->FindDataElement(tag);
  const vtkDICOMValue *vptr = 0;

  if (a != 0)
    {
    vptr = &a->Value;
    // is this a sequence of values?
    const vtkDICOMValue *sptr = vptr->GetMultiplexData();
    if (sptr)
      {
      assert(idx >= 0 && idx < static_cast<int>(vptr->GetNumberOfValues()));
      vptr = &sptr[idx];
      }
    }

  return vptr;
}

//----------------------------------------------------------------------------
const vtkDICOMValue &vtkDICOMMetaData::GetAttributeValue(vtkDICOMTag tag)
{
  const vtkDICOMValue *vptr = this->FindAttributeValue(0, tag);
  return (vptr ? *vptr : vtkDICOMMetaData::InvalidValue);
}

//----------------------------------------------------------------------------
const vtkDICOMValue &vtkDICOMMetaData::GetAttributeValue(
  int idx, vtkDICOMTag tag)
{
  const vtkDICOMValue *vptr = this->FindAttributeValue(idx, tag);
  return (vptr ? *vptr : vtkDICOMMetaData::InvalidValue);
}

//----------------------------------------------------------------------------
// Return a reference to the element within the hash table, which can
// be used to insert a new value.
vtkDICOMDataElement *vtkDICOMMetaData::FindDataElementOrInsert(
  vtkDICOMTag tag)
{
  unsigned int m = METADATA_HASH_SIZE - 1;
  unsigned int i = (tag.ComputeHash() & m);
  vtkDICOMDataElement **htable = this->Table;
  vtkDICOMDataElement *hptr;

  if (htable == NULL)
    {
    // allocate the hash table
    m = METADATA_HASH_SIZE;
    htable = new vtkDICOMDataElement *[METADATA_HASH_SIZE];
    this->Table = htable;
    do { *htable++ = NULL; } while (--m);
    htable = this->Table;
    }

  hptr = htable[i];

  if (hptr == NULL)
    {
    hptr = new vtkDICOMDataElement[4];
    htable[i] = hptr;
    }
  else if (hptr->Next != 0)
    {
    // see if item is already there
    unsigned int n = 0;
    do
      {
      if (hptr->Tag == tag)
        {
        return hptr;
        }
      n++;
      hptr++;
      }
    while (hptr->Next != 0);

    // if n+1 is a power of two, double allocated space
    if (n > 2 && (n & (n+1)) == 0)
      {
      vtkDICOMDataElement *oldptr = htable[i];
      hptr = new vtkDICOMDataElement[2*(n+1)];
      htable[i] = hptr;
      // copy the old list
      for (unsigned int j = 0; j < n; j++)
        {
        *hptr = oldptr[j];
        // link the new element into the list
        hptr->Next->Prev = hptr;
        hptr->Prev->Next = hptr;
        hptr++;
        }
      delete [] oldptr;
      }
    }

  // insert into the linked list
  vtkDICOMDataElement *tptr = &this->Tail;
  do
    {
    tptr = tptr->Prev;
    }
  while (tag < tptr->GetTag());

  hptr->Prev = tptr;
  hptr->Next = tptr->Next;
  hptr->Prev->Next = hptr;
  hptr->Next->Prev = hptr;
  this->NumberOfDataElements++;

  return hptr;
}

//----------------------------------------------------------------------------
// Insert an attribute into the hash table
void vtkDICOMMetaData::SetAttributeValue(
  vtkDICOMTag tag, const vtkDICOMValue& v)
{
  vtkDICOMDataElement *loc = this->FindDataElementOrInsert(tag);
  if (loc == 0)
    {
    vtkErrorMacro("SetAttributeValue: tag group number must not be zero.");
    return;
    }
  loc->Tag = tag;
  loc->Value = v;
}

template<class T>
void vtkDICOMMetaData::SetAttributeValueT(vtkDICOMTag tag, T v)
{
  vtkDICOMVR vr = this->FindDictVR(0, tag);
  if (vr != vtkDICOMVR::UN)
    {
    this->SetAttributeValue(tag, vtkDICOMValue(vr, v));
    }
}

void vtkDICOMMetaData::SetAttributeValue(vtkDICOMTag tag, double v)
{
  this->SetAttributeValueT(tag, v);
}

void vtkDICOMMetaData::SetAttributeValue(vtkDICOMTag tag, const std::string& v)
{
  this->SetAttributeValueT(tag, v);
}

//----------------------------------------------------------------------------
// Insert an attribute for a particular image
void vtkDICOMMetaData::SetAttributeValue(
  int idx, vtkDICOMTag tag, const vtkDICOMValue& v)
{
  vtkDICOMDataElement *loc = this->FindDataElementOrInsert(tag);
  if (loc == 0)
    {
    vtkErrorMacro("SetAttributeValue: tag group number must not be zero.");
    return;
    }

  loc->Tag = tag;
  vtkDICOMValue *vptr = &loc->Value;

  assert(idx >= 0 && idx < this->NumberOfInstances);

  // first value for this attribute
  if (!vptr->IsValid())
    {
    *vptr = v;
    return;
    }

  // is this a sequence of values?
  vtkDICOMValue *sptr = vptr->GetMultiplexData();
  if (sptr)
    {
    sptr[idx] = v;
    }
  else if (v != *vptr)
    {
    // differs from other instances, must turn value into a list,
    // so create a value that is actually a list of values
    int n = this->NumberOfInstances;
    vtkDICOMValue l;
    sptr = l.AllocateMultiplexData(v.GetVR(), n);
    for (int i = 0; i < n; i++)
      {
      if (i == idx)
        {
        sptr[i] = v;
        }
      else
        {
        sptr[i] = *vptr;
        }
      }
    *vptr = l;
    }
}

template<class T>
void vtkDICOMMetaData::SetAttributeValueT(int idx, vtkDICOMTag tag, T v)
{
  vtkDICOMVR vr = this->FindDictVR(idx, tag);
  if (vr != vtkDICOMVR::UN)
    {
    this->SetAttributeValue(idx, tag, vtkDICOMValue(vr, v));
    }
}

void vtkDICOMMetaData::SetAttributeValue(
  int idx, vtkDICOMTag tag, double v)
{
  this->SetAttributeValueT(idx, tag, v);
}

void vtkDICOMMetaData::SetAttributeValue(
  int idx, vtkDICOMTag tag, const std::string& v)
{
  this->SetAttributeValueT(idx, tag, v);
}

// should only be called from SetAttributeValue
vtkDICOMVR vtkDICOMMetaData::FindDictVR(int idx, vtkDICOMTag tag)
{
  vtkDICOMVR vr = vtkDICOMVR::UN;
  vtkDICOMDictEntry e;

  if (vtkDICOMMetaData::FindDictEntry(tag, e))
    {
    vr = e.GetVR();
    // use the dictionary VR
    if (vr == vtkDICOMVR::XS)
      {
      const vtkDICOMValue &v =
        this->GetAttributeValue(idx, vtkDICOMTag(0x0028,0x0103));
      if (v.IsValid())
        {
        unsigned short r = v.AsUnsignedShort();
        vr = (r == 0 ? vtkDICOMVR::US : vtkDICOMVR::SS);
        }
      else
        {
        vtkErrorMacro("SetAttributeValue: could not look up vr for (" <<
                      tag << ") because PixelRepresentation is not set.");
        }
      }
    else if (vr == vtkDICOMVR::OX)
      {
      if (tag.GetGroup() == 0x5400)
        {
        const vtkDICOMValue &v =
          this->GetAttributeValue(idx, vtkDICOMTag(0x5400,0x1004));
        if (v.IsValid())
          {
          unsigned short s = v.AsUnsignedShort();
          vr = (s > 8 ? vtkDICOMVR::OW : vtkDICOMVR::OB);
          }
        else
          {
          vtkErrorMacro("SetAttributeValue: could not look up vr for (" <<
                        tag << ") because WaveformBitsAllocated is not set.");
          }
        }
      else
        {
        const vtkDICOMValue &v =
          this->GetAttributeValue(idx, vtkDICOMTag(0x0028,0x0100));
        if (v.IsValid())
          {
          unsigned short s = v.AsUnsignedShort();
          vr = (s > 8 ? vtkDICOMVR::OW : vtkDICOMVR::OB);
          }
        else
          {
          vtkErrorMacro("SetAttributeValue: could not look up vr for (" <<
                        tag << ") because BitsAllocated is not set.");
          }
        }
      }
    }
  else
    {
    vtkErrorMacro("SetAttributeValue: could not find tag (" <<
                  tag << ") in the dictionary");
    }

  return vr;
}

//----------------------------------------------------------------------------
void vtkDICOMMetaData::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);

  os << indent << "NumberOfInstances: "
     << this->NumberOfInstances << "\n";
  os << indent << "NumberOfDataElements: "
     << this->NumberOfDataElements << "\n";
}
<|endoftext|>


<commit_before>/* Copyright (c) 2017-2022 Hans-Kristian Arntzen
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#pragma once

#include "vulkan_common.hpp"
#include "vulkan_headers.hpp"
#include "cookie.hpp"
#include "object_pool.hpp"

namespace Vulkan
{
class Device;

class SemaphoreHolder;
struct SemaphoreHolderDeleter
{
	void operator()(SemaphoreHolder *semaphore);
};

class SemaphoreHolder : public Util::IntrusivePtrEnabled<SemaphoreHolder, SemaphoreHolderDeleter, HandleCounter>,
                        public InternalSyncEnabled
{
public:
	friend struct SemaphoreHolderDeleter;

	~SemaphoreHolder();

	const VkSemaphore &get_semaphore() const
	{
		return semaphore;
	}

	bool is_signalled() const
	{
		return signalled;
	}

	uint64_t get_timeline_value() const
	{
		VK_ASSERT(!owned && semaphore_type == VK_SEMAPHORE_TYPE_TIMELINE_KHR);
		return timeline;
	}

	VkSemaphore consume()
	{
		auto ret = semaphore;
		VK_ASSERT(semaphore);
		VK_ASSERT(signalled);
		semaphore = VK_NULL_HANDLE;
		signalled = false;
		owned = false;
		return ret;
	}

	VkSemaphore release_semaphore()
	{
		auto ret = semaphore;
		semaphore = VK_NULL_HANDLE;
		signalled = false;
		owned = false;
		return ret;
	}

	void wait_external()
	{
		VK_ASSERT(semaphore);
		VK_ASSERT(signalled);
		signalled = false;
	}

	void signal_external()
	{
		VK_ASSERT(!signalled);
		VK_ASSERT(semaphore);
		signalled = true;
	}

	void set_pending_wait()
	{
		pending_wait = true;
	}

	bool is_pending_wait() const
	{
		return pending_wait;
	}

	void set_external_object_compatible(VkExternalSemaphoreHandleTypeFlagBits handle_type,
	                                    VkExternalSemaphoreFeatureFlags features)
	{
		external_compatible_handle_type = handle_type;
		external_compatible_features = features;
	}

	bool is_external_object_compatible() const
	{
		return external_compatible_features != 0;
	}

	VkSemaphoreTypeKHR get_semaphore_type() const
	{
		return semaphore_type;
	}

	bool is_proxy_timeline() const
	{
		return proxy_timeline;
	}

	void set_proxy_timeline()
	{
		proxy_timeline = true;
		signalled = false;
	}

	// If successful, importing takes ownership of the handle/fd.
	// Application can use dup() / DuplicateHandle() to keep a reference.
	// Imported semaphores are assumed to be signalled, or pending to be signalled.
	// All imports are performed with TEMPORARY permanence.
	ExternalHandle export_to_handle();
	bool import_from_handle(ExternalHandle handle);

	SemaphoreHolder &operator=(SemaphoreHolder &&other) noexcept;

private:
	friend class Util::ObjectPool<SemaphoreHolder>;
	SemaphoreHolder(Device *device_, VkSemaphore semaphore_, bool signalled_, bool owned_)
		: device(device_)
		, semaphore(semaphore_)
		, timeline(0)
		, semaphore_type(VK_SEMAPHORE_TYPE_BINARY_KHR)
		, signalled(signalled_)
		, owned(owned_)
	{
	}

	SemaphoreHolder(Device *device_, uint64_t timeline_, VkSemaphore semaphore_, bool owned_)
		: device(device_)
		, semaphore(semaphore_)
		, timeline(timeline_)
		, semaphore_type(VK_SEMAPHORE_TYPE_TIMELINE_KHR)
		, owned(owned_)
	{
		VK_ASSERT((owned && timeline == 0) || (!owned && timeline != 0));
	}

	explicit SemaphoreHolder(Device *device_)
		: device(device_)
	{
	}

	void recycle_semaphore();

	Device *device;
	VkSemaphore semaphore = VK_NULL_HANDLE;
	uint64_t timeline = 0;
	VkSemaphoreTypeKHR semaphore_type = VK_SEMAPHORE_TYPE_BINARY_KHR;
	bool signalled = false;
	bool pending_wait = false;
	bool owned = false;
	bool proxy_timeline = false;
	VkExternalSemaphoreHandleTypeFlagBits external_compatible_handle_type = {};
	VkExternalSemaphoreFeatureFlags external_compatible_features = 0;
};

using Semaphore = Util::IntrusivePtr<SemaphoreHolder>;
}
<commit_msg>Add getter to query external semaphore properties.<commit_after>/* Copyright (c) 2017-2022 Hans-Kristian Arntzen
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#pragma once

#include "vulkan_common.hpp"
#include "vulkan_headers.hpp"
#include "cookie.hpp"
#include "object_pool.hpp"

namespace Vulkan
{
class Device;

class SemaphoreHolder;
struct SemaphoreHolderDeleter
{
	void operator()(SemaphoreHolder *semaphore);
};

class SemaphoreHolder : public Util::IntrusivePtrEnabled<SemaphoreHolder, SemaphoreHolderDeleter, HandleCounter>,
                        public InternalSyncEnabled
{
public:
	friend struct SemaphoreHolderDeleter;

	~SemaphoreHolder();

	const VkSemaphore &get_semaphore() const
	{
		return semaphore;
	}

	bool is_signalled() const
	{
		return signalled;
	}

	uint64_t get_timeline_value() const
	{
		VK_ASSERT(!owned && semaphore_type == VK_SEMAPHORE_TYPE_TIMELINE_KHR);
		return timeline;
	}

	VkSemaphore consume()
	{
		auto ret = semaphore;
		VK_ASSERT(semaphore);
		VK_ASSERT(signalled);
		semaphore = VK_NULL_HANDLE;
		signalled = false;
		owned = false;
		return ret;
	}

	VkSemaphore release_semaphore()
	{
		auto ret = semaphore;
		semaphore = VK_NULL_HANDLE;
		signalled = false;
		owned = false;
		return ret;
	}

	void wait_external()
	{
		VK_ASSERT(semaphore);
		VK_ASSERT(signalled);
		signalled = false;
	}

	void signal_external()
	{
		VK_ASSERT(!signalled);
		VK_ASSERT(semaphore);
		signalled = true;
	}

	void set_pending_wait()
	{
		pending_wait = true;
	}

	bool is_pending_wait() const
	{
		return pending_wait;
	}

	void set_external_object_compatible(VkExternalSemaphoreHandleTypeFlagBits handle_type,
	                                    VkExternalSemaphoreFeatureFlags features)
	{
		external_compatible_handle_type = handle_type;
		external_compatible_features = features;
	}

	bool is_external_object_compatible() const
	{
		return external_compatible_features != 0;
	}

	VkSemaphoreTypeKHR get_semaphore_type() const
	{
		return semaphore_type;
	}

	bool is_proxy_timeline() const
	{
		return proxy_timeline;
	}

	void set_proxy_timeline()
	{
		proxy_timeline = true;
		signalled = false;
	}

	// If successful, importing takes ownership of the handle/fd.
	// Application can use dup() / DuplicateHandle() to keep a reference.
	// Imported semaphores are assumed to be signalled, or pending to be signalled.
	// All imports are performed with TEMPORARY permanence.
	ExternalHandle export_to_handle();
	bool import_from_handle(ExternalHandle handle);

	VkExternalSemaphoreFeatureFlags get_external_features() const
	{
		return external_compatible_features;
	}

	VkExternalSemaphoreHandleTypeFlagBits get_external_handle_type() const
	{
		return external_compatible_handle_type;
	}

	SemaphoreHolder &operator=(SemaphoreHolder &&other) noexcept;

private:
	friend class Util::ObjectPool<SemaphoreHolder>;
	SemaphoreHolder(Device *device_, VkSemaphore semaphore_, bool signalled_, bool owned_)
		: device(device_)
		, semaphore(semaphore_)
		, timeline(0)
		, semaphore_type(VK_SEMAPHORE_TYPE_BINARY_KHR)
		, signalled(signalled_)
		, owned(owned_)
	{
	}

	SemaphoreHolder(Device *device_, uint64_t timeline_, VkSemaphore semaphore_, bool owned_)
		: device(device_)
		, semaphore(semaphore_)
		, timeline(timeline_)
		, semaphore_type(VK_SEMAPHORE_TYPE_TIMELINE_KHR)
		, owned(owned_)
	{
		VK_ASSERT((owned && timeline == 0) || (!owned && timeline != 0));
	}

	explicit SemaphoreHolder(Device *device_)
		: device(device_)
	{
	}

	void recycle_semaphore();

	Device *device;
	VkSemaphore semaphore = VK_NULL_HANDLE;
	uint64_t timeline = 0;
	VkSemaphoreTypeKHR semaphore_type = VK_SEMAPHORE_TYPE_BINARY_KHR;
	bool signalled = false;
	bool pending_wait = false;
	bool owned = false;
	bool proxy_timeline = false;
	VkExternalSemaphoreHandleTypeFlagBits external_compatible_handle_type = {};
	VkExternalSemaphoreFeatureFlags external_compatible_features = 0;
};

using Semaphore = Util::IntrusivePtr<SemaphoreHolder>;
}
<|endoftext|>


<commit_before>#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN

#include <iterator>

#include "doctest/doctest.h"
#include "include/parser.hh"

template<typename T>
int length(T const &x) {
    return std::distance(std::begin(x), std::end(x));
}

TEST_CASE("test parser functionality")
{
    const char * argv[] = {
        "tests",
        "--flag",
        "--only_large",
        "-s",
        "-q", "first_short2",
        "--in-fil-e",
        "-dash",
        "--store_str", "qqqdash",
        "--store_num", "72",
        "--store_multy_s", "str1", "str2", "str3", "str4", "str5",
        "-b",
        "--pp",
        "-singledash", "hellooo"
    };

    int argc = length(argv);

    optionparser::parser p("A test to make sure that this option parser works");

    p.add_option("--flag", "-f") .help("just flag");
    p.add_option("--boolean", "-b") .help("boolean").mode(optionparser::store_true);

    p.add_option("--only_large") .help("set only large opt");
    p.add_option("-singledash") .help("singledash").mode(optionparser::store_value);
    p.add_option("-s") .help("set only small opt");
    p.add_option("-q", "--first_short1") .help("first_short1").mode(optionparser::store_value);
    p.add_option("-w", "--first_short2") .help("first_short2");
    p.add_option("--in-fil-e", "-i").help("dashes in name");
    p.add_option("-dash") .help("only one dash for large opt");
    p.add_option("--store_str", "-v") .help("store single str val").mode(optionparser::store_value).default_value("stor str def1");
    p.add_option("--store_num", "-n") .help("store single num val").mode(optionparser::store_value);
    p.add_option("--store_multy_s", "-m") .help("store multy str val").mode(optionparser::store_mult_values).default_value("def2");
    p.add_option("--pp", "-p") .help("store single str val").mode(optionparser::store_value).default_value("p1");

    p.eat_arguments(argc, argv);

    bool check_is_flag_set = false;
    if (p.get_value("flag"))
    {
      check_is_flag_set = true;
    }
    CHECK(check_is_flag_set == true);
    if (p.get_value("only_large"))
    {
      check_is_flag_set = true;
    }
    CHECK(check_is_flag_set == true);
    if (p.get_value("s_option"))
    {
      check_is_flag_set = true;
    }
    CHECK(check_is_flag_set == true);
     if (p.get_value("first_short1"))
    {
      check_is_flag_set = true;
    }
    CHECK(check_is_flag_set == true);
     if (p.get_value("first_short2"))
    {
      check_is_flag_set = true;
    }
    CHECK(check_is_flag_set == true);
     if (p.get_value("in-fil-e"))
    {
      check_is_flag_set = true;
    }
    CHECK(check_is_flag_set == true);
    if (p.get_value("dash"))
    {
      check_is_flag_set = true;
    }
    CHECK(check_is_flag_set == true);

    if (p.get_value("store_str"))
    {
        auto names = p.get_value<std::vector<std::string>>("store_str");
        CHECK(names[0] == argv[9]);
    }

    if (p.get_value("store_num"))
    {
        CHECK(p.get_value<int>("store_num") == 72);
    }

    if (p.get_value("store_multy_s"))
    {
        auto names = p.get_value<std::vector<std::string>>("store_multy_s");
        CHECK(names[0] == argv[13]);
        CHECK(names[1] == argv[14]);
        CHECK(names[2] == argv[15]);
        CHECK(names[3] == argv[16]);
        CHECK(names[4] == argv[17]);
    }

    if (p.get_value("boolean"))
    {
        CHECK(p.get_value<bool>("boolean") == true);
    }

}

TEST_CASE("test OO functionality")
{
    const char * argv[] = {
        "tests",
        "--flag asdsaflag",
        "bsadsad",
        "bqwewqeq"
    };

    auto argc = length(argv);

    optionparser::parser p("A test to make sure that this option parser works");

    p.add_option("--flag", "-f") .help("just=flag").mode(optionparser::store_mult_values);;
    p.add_option("--boolean", "-b") .help("boolean").mode(optionparser::store_true);

    p.eat_arguments(argc, argv);

    bool check_is_flag_set = false;
    if (p.get_value("flag"))
    {
      check_is_flag_set = true;
      auto names = p.get_value<std::vector<std::string>>("flag");
      CHECK(names[0] == "asdsaflag");
      CHECK(names[1] == "bsadsad");
      CHECK(names[2] == "bqwewqeq");
    }

}

TEST_CASE_TEMPLATE("test typecasting functionality", T, int, double, std::string)
{
    const char * argv[] = {
        "tests",
        "--flag",
        "2.0"
    };

    auto argc = length(argv);

    optionparser::parser p("A test to make sure that this option parser works");

    p.add_option("--flag", "-f") .help("just=flag").mode(optionparser::store_value);

    p.eat_arguments(argc, argv);

    CHECK(p.get_value("flag"));

    auto value = p.get_value<T>("flag");

    CHECK(typeid(value) == typeid(T));
}
<commit_msg>Format tests to Google style<commit_after>#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN

#include <iterator>

#include "doctest/doctest.h"
#include "include/parser.hh"

template <typename T>
int length(T const &x) {
  return std::distance(std::begin(x), std::end(x));
}

TEST_CASE("test parser functionality") {
  const char *argv[] = {"tests",
                        "--flag",
                        "--only_large",
                        "-s",
                        "-q",
                        "first_short2",
                        "--in-fil-e",
                        "-dash",
                        "--store_str",
                        "qqqdash",
                        "--store_num",
                        "72",
                        "--store_multy_s",
                        "str1",
                        "str2",
                        "str3",
                        "str4",
                        "str5",
                        "-b",
                        "--pp",
                        "-singledash",
                        "hellooo"};

  int argc = length(argv);

  optionparser::parser p("A test to make sure that this option parser works");

  p.add_option("--flag", "-f").help("just flag");
  p.add_option("--boolean", "-b")
      .help("boolean")
      .mode(optionparser::store_true);

  p.add_option("--only_large").help("set only large opt");
  p.add_option("-singledash")
      .help("singledash")
      .mode(optionparser::store_value);
  p.add_option("-s").help("set only small opt");
  p.add_option("-q", "--first_short1")
      .help("first_short1")
      .mode(optionparser::store_value);
  p.add_option("-w", "--first_short2").help("first_short2");
  p.add_option("--in-fil-e", "-i").help("dashes in name");
  p.add_option("-dash").help("only one dash for large opt");
  p.add_option("--store_str", "-v")
      .help("store single str val")
      .mode(optionparser::store_value)
      .default_value("stor str def1");
  p.add_option("--store_num", "-n")
      .help("store single num val")
      .mode(optionparser::store_value);
  p.add_option("--store_multy_s", "-m")
      .help("store multy str val")
      .mode(optionparser::store_mult_values)
      .default_value("def2");
  p.add_option("--pp", "-p")
      .help("store single str val")
      .mode(optionparser::store_value)
      .default_value("p1");

  p.eat_arguments(argc, argv);

  bool check_is_flag_set = false;
  if (p.get_value("flag")) {
    check_is_flag_set = true;
  }
  CHECK(check_is_flag_set == true);
  if (p.get_value("only_large")) {
    check_is_flag_set = true;
  }
  CHECK(check_is_flag_set == true);
  if (p.get_value("s_option")) {
    check_is_flag_set = true;
  }
  CHECK(check_is_flag_set == true);
  if (p.get_value("first_short1")) {
    check_is_flag_set = true;
  }
  CHECK(check_is_flag_set == true);
  if (p.get_value("first_short2")) {
    check_is_flag_set = true;
  }
  CHECK(check_is_flag_set == true);
  if (p.get_value("in-fil-e")) {
    check_is_flag_set = true;
  }
  CHECK(check_is_flag_set == true);
  if (p.get_value("dash")) {
    check_is_flag_set = true;
  }
  CHECK(check_is_flag_set == true);

  if (p.get_value("store_str")) {
    auto names = p.get_value<std::vector<std::string>>("store_str");
    CHECK(names[0] == argv[9]);
  }

  if (p.get_value("store_num")) {
    CHECK(p.get_value<int>("store_num") == 72);
  }

  if (p.get_value("store_multy_s")) {
    auto names = p.get_value<std::vector<std::string>>("store_multy_s");
    CHECK(names[0] == argv[13]);
    CHECK(names[1] == argv[14]);
    CHECK(names[2] == argv[15]);
    CHECK(names[3] == argv[16]);
    CHECK(names[4] == argv[17]);
  }

  if (p.get_value("boolean")) {
    CHECK(p.get_value<bool>("boolean") == true);
  }
}

TEST_CASE("test OO functionality") {
  const char *argv[] = {"tests", "--flag asdsaflag", "bsadsad", "bqwewqeq"};

  auto argc = length(argv);

  optionparser::parser p("A test to make sure that this option parser works");

  p.add_option("--flag", "-f")
      .help("just=flag")
      .mode(optionparser::store_mult_values);
  ;
  p.add_option("--boolean", "-b")
      .help("boolean")
      .mode(optionparser::store_true);

  p.eat_arguments(argc, argv);

  bool check_is_flag_set = false;
  if (p.get_value("flag")) {
    check_is_flag_set = true;
    auto names = p.get_value<std::vector<std::string>>("flag");
    CHECK(names[0] == "asdsaflag");
    CHECK(names[1] == "bsadsad");
    CHECK(names[2] == "bqwewqeq");
  }
}

TEST_CASE_TEMPLATE("test typecasting functionality", T, int, double,
                   std::string) {
  const char *argv[] = {"tests", "--flag", "2.0"};

  auto argc = length(argv);

  optionparser::parser p("A test to make sure that this option parser works");

  p.add_option("--flag", "-f")
      .help("just=flag")
      .mode(optionparser::store_value);

  p.eat_arguments(argc, argv);

  CHECK(p.get_value("flag"));

  auto value = p.get_value<T>("flag");

  CHECK(typeid(value) == typeid(T));
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "Startup.h"

#include "MenuCommon/Defines.h"

Startup::Startup()
{
	ZeroMemory(&si, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);
	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
}

Startup::~Startup()
{
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);

	CloseHandle(hJob);
}

BOOL Startup::CreateJob()
{
	// Create a job
	hJob = CreateJobObject(NULL, MT_JOB_NAME);
	if(!hJob)
	{
		return FALSE;
	}

#ifdef _WIN64
#if !MT_DEBUG_ONLY_X64
	// Check if application x64 is running with a job
	BOOL bIsJob;
	if(!IsProcessInJob(GetCurrentProcess(), hJob, &bIsJob))
	{
		return FALSE;
	}

	// Not running inside a job
	if(!bIsJob)
	{
		return FALSE;
	}
#endif
#endif

	// If the job already exists
	if(GetLastError() == ERROR_ALREADY_EXISTS)
	{
#ifdef _WIN64
		// Close the job handle
		CloseHandle(hJob);
		// Don't create child and allow process creation
		return TRUE;
#else
		// Can't run more than one instance
		return FALSE;
#endif
	}

#ifndef _WIN64
#if !MT_DEBUG_ONLY_X86
	// Check if application x86 is running on Windows x64
	BOOL bIsWOW64;
	if(!IsWow64Process(GetCurrentProcess(), &bIsWOW64))
	{
		return FALSE;
	}

	// Create a child to handle x64 processes
	if(bIsWOW64)
	{
		return CreateJobChild();
	}
#endif
#endif

	return TRUE;
}

BOOL Startup::CreateJobChild()
{
	// Causes all processes associated with the job to terminate when the last handle to the job is closed.
	JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0};
	jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
	if(!SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jeli, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)))
	{
		return FALSE;
	}

	// Creates a new process is created in a suspended state
	if(!CreateProcess(MT_EXE_NAME64, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
	{
		return FALSE;
	}

	// Assigns a process to an existing job object
	if(!AssignProcessToJobObject(hJob, pi.hProcess))
	{
		return FALSE;
	}

	// Execution of the thread is resumed
	if(ResumeThread(pi.hThread) == -1)
	{
		return FALSE;
	}

	return TRUE;
}<commit_msg>Fixed bug on startup job in Windows prior to Windows 8.<commit_after>#include "stdafx.h"
#include "Startup.h"

#include "MenuCommon/Defines.h"

Startup::Startup()
{
	ZeroMemory(&si, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);
	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
}

Startup::~Startup()
{
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);

	CloseHandle(hJob);
}

BOOL Startup::CreateJob()
{
	// Create a job
	hJob = CreateJobObject(NULL, MT_JOB_NAME);
	if(!hJob)
	{
		return FALSE;
	}

#ifdef _WIN64
#if !MT_DEBUG_ONLY_X64
	// Check if application x64 is running with a job
	BOOL bIsJob;
	if(!IsProcessInJob(GetCurrentProcess(), hJob, &bIsJob))
	{
		return FALSE;
	}

	// Not running inside a job
	if(!bIsJob)
	{
		return FALSE;
	}
#endif
#endif

	// If the job already exists
	if(GetLastError() == ERROR_ALREADY_EXISTS)
	{
#ifdef _WIN64
		// Close the job handle
		CloseHandle(hJob);
		// Don't create child and allow process creation
		return TRUE;
#else
		// Can't run more than one instance
		return FALSE;
#endif
	}

#ifndef _WIN64
#if !MT_DEBUG_ONLY_X86
	// Check if application x86 is running on Windows x64
	BOOL bIsWOW64;
	if(!IsWow64Process(GetCurrentProcess(), &bIsWOW64))
	{
		return FALSE;
	}

	// Create a child to handle x64 processes
	if(bIsWOW64)
	{
		return CreateJobChild();
	}
#endif
#endif

	return TRUE;
}

BOOL Startup::CreateJobChild()
{
	// Causes all processes associated with the job to terminate when the last handle to the job is closed.
	JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0};
	jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
	if(!SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jeli, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)))
	{
		return FALSE;
	}

	// Creates a new process is created in a suspended state
	if(!CreateProcess(MT_EXE_NAME64, NULL, NULL, NULL, FALSE,
		CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB,
		NULL, NULL, &si, &pi))
	{
		return FALSE;
	}

	// Assigns a process to an existing job object
	if(!AssignProcessToJobObject(hJob, pi.hProcess))
	{
		return FALSE;
	}

	// Execution of the thread is resumed
	if(ResumeThread(pi.hThread) == -1)
	{
		return FALSE;
	}

	return TRUE;
}<|endoftext|>


<commit_before>//===--- ExperimentalDependencies.cpp - Generates swiftdeps files ---------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include <stdio.h>

#include "swift/AST/ExperimentalDependencies.h"

// may not all be needed
#include "swift/Basic/FileSystem.h"
#include "swift/Basic/LLVM.h"
#include "swift/Demangling/Demangle.h"
#include "swift/Frontend/FrontendOptions.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/YAMLParser.h"

// This file holds the definitions for the experimental dependency system
// that are likely to be stable as it moves away from the status quo.
// These include the graph structures common to both programs and also
// the frontend graph, which must be read by the driver.

using namespace swift;
using namespace experimental_dependencies;

//==============================================================================
// MARK: SourceFileDepGraph access
//==============================================================================

SourceFileDepGraphNode *
SourceFileDepGraph::getNode(size_t sequenceNumber) const {
  assert(sequenceNumber < allNodes.size() && "Bad node index");
  SourceFileDepGraphNode *n = allNodes[sequenceNumber];
  assert(n->getSequenceNumber() == sequenceNumber &&
         "Bad sequence number in node or bad entry in allNodes.");
  return n;
}

InterfaceAndImplementationPair<SourceFileDepGraphNode>
SourceFileDepGraph::getSourceFileNodePair() const {
  assert(getNode(0)->getKey().getKind() == NodeKind::sourceFileProvide &&
         "First node must be sourceFileProvide.");
  assert(getNode(1)->getKey().getKind() == NodeKind::sourceFileProvide &&
         "Second node must be sourceFileProvide.");
  return InterfaceAndImplementationPair<SourceFileDepGraphNode>(getNode(0),
                                                                getNode(1));
}

StringRef SourceFileDepGraph::getSwiftDepsFromSourceFileProvide() const {
  return getSourceFileNodePair()
      .getInterface()
      ->getKey()
      .getSwiftDepsFromSourceFileProvide();
}

void SourceFileDepGraph::forEachArc(
    function_ref<void(const SourceFileDepGraphNode *def,
                      const SourceFileDepGraphNode *use)>
        fn) const {
  forEachNode([&](const SourceFileDepGraphNode *useNode) {
    forEachDefDependedUponBy(useNode, [&](SourceFileDepGraphNode *defNode) {
      fn(defNode, useNode);
    });
  });
}

InterfaceAndImplementationPair<SourceFileDepGraphNode>
SourceFileDepGraph::findExistingNodePairOrCreateAndAddIfNew(
    NodeKind k, StringRef context, StringRef name,
    Optional<std::string> fingerprint) {
  InterfaceAndImplementationPair<SourceFileDepGraphNode> nodePair{
      findExistingNodeOrCreateIfNew(
          DependencyKey(k, DeclAspect::interface, context, name), fingerprint,
          true /* = isProvides */),
      findExistingNodeOrCreateIfNew(
          DependencyKey(k, DeclAspect::implementation, context, name),
          fingerprint, true /* = isProvides */)};
  // if interface changes, have to rebuild implementation
  addArc(nodePair.getInterface(), nodePair.getImplementation());
  return nodePair;
}

SourceFileDepGraphNode *SourceFileDepGraph::findExistingNodeOrCreateIfNew(
    DependencyKey key, Optional<std::string> fingerprint,
    const bool isProvides) {
  SourceFileDepGraphNode *result = memoizedNodes.findExistingOrCreateIfNew(
      key, [&](DependencyKey key) -> SourceFileDepGraphNode * {
        SourceFileDepGraphNode *n =
            new SourceFileDepGraphNode(key, fingerprint, isProvides);
        addNode(n);
        return n;
      });
  // If have provides and depends with same key, result is one node that
  // isProvides
  if (isProvides)
    result->setIsProvides();
  assert(result->getKey() == key && "Keys must match.");
  return result;
}

std::string DependencyKey::demangleTypeAsContext(StringRef s) {
  return swift::Demangle::demangleTypeAsString(s.str());
}

//==============================================================================
// MARK: Debugging
//==============================================================================

bool SourceFileDepGraph::verify() const {
  DependencyKey::verifyNodeKindNames();
  DependencyKey::verifyDeclAspectNames();
  // Ensure Keys are unique
  std::unordered_map<DependencyKey, SourceFileDepGraphNode *> nodesSeen;
  // Ensure each node only appears once.
  std::unordered_set<void *> nodes;
  forEachNode([&](SourceFileDepGraphNode *n) {
    n->verify();
    assert(nodes.insert(n).second && "Frontend nodes are identified by "
                                     "sequence number, therefore must be "
                                     "unique.");

    auto iterInserted = nodesSeen.insert(std::make_pair(n->getKey(), n));
    if (!iterInserted.second) {
      llvm::errs() << "Duplicate frontend keys: ";
      iterInserted.first->second->dump();
      llvm::errs() << " and ";
      n->dump();
      llvm::errs() << "\n";
      llvm_unreachable("duplicate frontend keys");
    }

    forEachDefDependedUponBy(n, [&](SourceFileDepGraphNode *def) {
      assert(def != n && "Uses should be irreflexive.");
    });
  });
  return true;
}

bool SourceFileDepGraph::verifyReadsWhatIsWritten(StringRef path) const {
  auto loadedGraph = SourceFileDepGraph::loadFromPath(path);
  assert(loadedGraph.hasValue() &&
         "Should be able to read the exported graph.");
  verifySame(loadedGraph.getValue());
  return true;
}

std::string DependencyKey::humanReadableName() const {
  switch (kind) {
  case NodeKind::member:
    return demangleTypeAsContext(context) + "." + name;
  case NodeKind::externalDepend:
  case NodeKind::sourceFileProvide:
    return llvm::sys::path::filename(name);
  case NodeKind::potentialMember:
    return demangleTypeAsContext(context) + ".*";
  case NodeKind::nominal:
    return demangleTypeAsContext(context);
  case NodeKind::topLevel:
  case NodeKind::dynamicLookup:
    return name;
  default:
    llvm_unreachable("bad kind");
  }
}

std::string DependencyKey::asString() const {
  return NodeKindNames[size_t(kind)] + " " +
         "aspect: " + DeclAspectNames[size_t(aspect)] + ", " +
         humanReadableName();
}

/// Needed for TwoStageMap::verify:
raw_ostream &experimental_dependencies::operator<<(raw_ostream &out,
                                                   const DependencyKey &key) {
  out << key.asString();
  return out;
}

bool DependencyKey::verify() const {
  assert((getKind() != NodeKind::externalDepend || isInterface()) &&
         "All external dependencies must be interfaces.");
  return true;
}

/// Since I don't have Swift enums, ensure name corresspondence here.
void DependencyKey::verifyNodeKindNames() {
  for (size_t i = 0; i < size_t(NodeKind::kindCount); ++i)
    switch (NodeKind(i)) {
#define CHECK_NAME(n)                                                          \
  case NodeKind::n:                                                            \
    assert(#n == NodeKindNames[i]);                                            \
    break;
      CHECK_NAME(topLevel)
      CHECK_NAME(nominal)
      CHECK_NAME(potentialMember)
      CHECK_NAME(member)
      CHECK_NAME(dynamicLookup)
      CHECK_NAME(externalDepend)
      CHECK_NAME(sourceFileProvide)
    case NodeKind::kindCount:
      llvm_unreachable("impossible");
    }
#undef CHECK_NAME
}

/// Since I don't have Swift enums, ensure name corresspondence here.
void DependencyKey::verifyDeclAspectNames() {
  for (size_t i = 0; i < size_t(DeclAspect::aspectCount); ++i)
    switch (DeclAspect(i)) {
#define CHECK_NAME(n)                                                          \
  case DeclAspect::n:                                                          \
    assert(#n == DeclAspectNames[i]);                                          \
    break;
      CHECK_NAME(interface)
      CHECK_NAME(implementation)
    case DeclAspect::aspectCount:
      llvm_unreachable("impossible");
    }
#undef CHECK_NAME
}

void DepGraphNode::dump() const {
  key.dump();
  if (fingerprint.hasValue())
    llvm::errs() << "fingerprint: " << fingerprint.getValue() << "";
  else
    llvm::errs() << "no fingerprint";
}

std::string DepGraphNode::humanReadableName(StringRef where) const {

  return getKey().humanReadableName() +
         (getKey().getKind() == NodeKind::sourceFileProvide || where.empty()
              ? std::string()
              : std::string(" in ") + where.str());
}

void SourceFileDepGraph::verifySame(const SourceFileDepGraph &other) const {
  assert(allNodes.size() == other.allNodes.size() &&
         "Both graphs must have same number of nodes.");
  for (size_t i : indices(allNodes)) {
    assert(*allNodes[i] == *other.allNodes[i] &&
           "Both graphs must have corresponding nodes");
  }
}

//==============================================================================
// MARK: SourceFileDepGraph YAML reading & writing
//==============================================================================

namespace llvm {
namespace yaml {
void ScalarTraits<size_t>::output(const size_t &Val, void *, raw_ostream &out) {
  out << Val;
}
StringRef ScalarTraits<size_t>::input(StringRef scalar, void *ctxt,
                                      size_t &value) {
  return scalar.getAsInteger(10, value) ? "could not parse size_t" : "";
}

void ScalarEnumerationTraits<NodeKind>::enumeration(
    IO &io, swift::experimental_dependencies::NodeKind &value) {
  using NodeKind = swift::experimental_dependencies::NodeKind;
  io.enumCase(value, "topLevel", NodeKind::topLevel);
  io.enumCase(value, "nominal", NodeKind::nominal);
  io.enumCase(value, "potentialMember", NodeKind::potentialMember);
  io.enumCase(value, "member", NodeKind::member);
  io.enumCase(value, "dynamicLookup", NodeKind::dynamicLookup);
  io.enumCase(value, "externalDepend", NodeKind::externalDepend);
  io.enumCase(value, "sourceFileProvide", NodeKind::sourceFileProvide);
}

void ScalarEnumerationTraits<DeclAspect>::enumeration(
    IO &io, swift::experimental_dependencies::DeclAspect &value) {
  using DeclAspect = swift::experimental_dependencies::DeclAspect;
  io.enumCase(value, "interface", DeclAspect::interface);
  io.enumCase(value, "implementation", DeclAspect::implementation);
}

void MappingTraits<DependencyKey>::mapping(
    IO &io, swift::experimental_dependencies::DependencyKey &key) {
  io.mapRequired("kind", key.kind);
  io.mapRequired("aspect", key.aspect);
  io.mapRequired("context", key.context);
  io.mapRequired("name", key.name);
}

void MappingTraits<DepGraphNode>::mapping(
    IO &io, swift::experimental_dependencies::DepGraphNode &node) {
  io.mapRequired("key", node.key);
  io.mapOptional("fingerprint", node.fingerprint);
}

void MappingContextTraits<SourceFileDepGraphNode, SourceFileDepGraph>::mapping(
    IO &io, SourceFileDepGraphNode &node, SourceFileDepGraph &g) {
  MappingTraits<DepGraphNode>::mapping(io, node);
  io.mapRequired("sequenceNumber", node.sequenceNumber);
  std::vector<size_t> defsIDependUponVec(node.defsIDependUpon.begin(),
                                         node.defsIDependUpon.end());
  io.mapRequired("defsIDependUpon", defsIDependUponVec);
  io.mapRequired("isProvides", node.isProvides);
  if (!io.outputting()) {
    for (size_t u : defsIDependUponVec)
      node.defsIDependUpon.insert(u);
  }
  assert(g.getNode(node.sequenceNumber) && "Bad sequence number");
}

size_t SequenceTraits<std::vector<SourceFileDepGraphNode *>>::size(
    IO &, std::vector<SourceFileDepGraphNode *> &vec) {
  return vec.size();
}

SourceFileDepGraphNode &
SequenceTraits<std::vector<SourceFileDepGraphNode *>>::element(
    IO &, std::vector<SourceFileDepGraphNode *> &vec, size_t index) {
  while (vec.size() <= index)
    vec.push_back(new SourceFileDepGraphNode());
  return *vec[index];
}

void MappingTraits<SourceFileDepGraph>::mapping(IO &io, SourceFileDepGraph &g) {
  io.mapRequired("allNodes", g.allNodes, g);
}
} // namespace yaml
} // namespace llvm
<commit_msg>Linux patch<commit_after>//===--- ExperimentalDependencies.cpp - Generates swiftdeps files ---------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include <stdio.h>

#include "swift/AST/ExperimentalDependencies.h"

// may not all be needed
#include "swift/Basic/FileSystem.h"
#include "swift/Basic/LLVM.h"
#include "swift/Demangling/Demangle.h"
#include "swift/Frontend/FrontendOptions.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/YAMLParser.h"

// This file holds the definitions for the experimental dependency system
// that are likely to be stable as it moves away from the status quo.
// These include the graph structures common to both programs and also
// the frontend graph, which must be read by the driver.

using namespace swift;
using namespace experimental_dependencies;

//==============================================================================
// MARK: SourceFileDepGraph access
//==============================================================================

SourceFileDepGraphNode *
SourceFileDepGraph::getNode(size_t sequenceNumber) const {
  assert(sequenceNumber < allNodes.size() && "Bad node index");
  SourceFileDepGraphNode *n = allNodes[sequenceNumber];
  assert(n->getSequenceNumber() == sequenceNumber &&
         "Bad sequence number in node or bad entry in allNodes.");
  return n;
}

InterfaceAndImplementationPair<SourceFileDepGraphNode>
SourceFileDepGraph::getSourceFileNodePair() const {
  assert(getNode(0)->getKey().getKind() == NodeKind::sourceFileProvide &&
         "First node must be sourceFileProvide.");
  assert(getNode(1)->getKey().getKind() == NodeKind::sourceFileProvide &&
         "Second node must be sourceFileProvide.");
  return InterfaceAndImplementationPair<SourceFileDepGraphNode>(getNode(0),
                                                                getNode(1));
}

StringRef SourceFileDepGraph::getSwiftDepsFromSourceFileProvide() const {
  return getSourceFileNodePair()
      .getInterface()
      ->getKey()
      .getSwiftDepsFromSourceFileProvide();
}

void SourceFileDepGraph::forEachArc(
    function_ref<void(const SourceFileDepGraphNode *def,
                      const SourceFileDepGraphNode *use)>
        fn) const {
  forEachNode([&](const SourceFileDepGraphNode *useNode) {
    forEachDefDependedUponBy(useNode, [&](SourceFileDepGraphNode *defNode) {
      fn(defNode, useNode);
    });
  });
}

InterfaceAndImplementationPair<SourceFileDepGraphNode>
SourceFileDepGraph::findExistingNodePairOrCreateAndAddIfNew(
    NodeKind k, StringRef context, StringRef name,
    Optional<std::string> fingerprint) {
  InterfaceAndImplementationPair<SourceFileDepGraphNode> nodePair{
      findExistingNodeOrCreateIfNew(
          DependencyKey(k, DeclAspect::interface, context, name), fingerprint,
          true /* = isProvides */),
      findExistingNodeOrCreateIfNew(
          DependencyKey(k, DeclAspect::implementation, context, name),
          fingerprint, true /* = isProvides */)};
  // if interface changes, have to rebuild implementation
  addArc(nodePair.getInterface(), nodePair.getImplementation());
  return nodePair;
}

SourceFileDepGraphNode *SourceFileDepGraph::findExistingNodeOrCreateIfNew(
    DependencyKey key, Optional<std::string> fingerprint,
    const bool isProvides) {
  SourceFileDepGraphNode *result = memoizedNodes.findExistingOrCreateIfNew(
      key, [&](DependencyKey key) -> SourceFileDepGraphNode * {
        SourceFileDepGraphNode *n =
            new SourceFileDepGraphNode(key, fingerprint, isProvides);
        addNode(n);
        return n;
      });
  // If have provides and depends with same key, result is one node that
  // isProvides
  if (isProvides)
    result->setIsProvides();
  assert(result->getKey() == key && "Keys must match.");
  return result;
}

std::string DependencyKey::demangleTypeAsContext(StringRef s) {
  return swift::Demangle::demangleTypeAsString(s.str());
}

//==============================================================================
// MARK: Debugging
//==============================================================================

bool SourceFileDepGraph::verify() const {
  DependencyKey::verifyNodeKindNames();
  DependencyKey::verifyDeclAspectNames();
  // Ensure Keys are unique
  std::unordered_map<DependencyKey, SourceFileDepGraphNode *> nodesSeen;
  // Ensure each node only appears once.
  std::unordered_set<void *> nodes;
  forEachNode([&](SourceFileDepGraphNode *n) {
    n->verify();
    assert(nodes.insert(n).second && "Frontend nodes are identified by "
                                     "sequence number, therefore must be "
                                     "unique.");

    auto iterInserted = nodesSeen.insert(std::make_pair(n->getKey(), n));
    if (!iterInserted.second) {
      llvm::errs() << "Duplicate frontend keys: ";
      iterInserted.first->second->dump();
      llvm::errs() << " and ";
      n->dump();
      llvm::errs() << "\n";
      llvm_unreachable("duplicate frontend keys");
    }

    forEachDefDependedUponBy(n, [&](SourceFileDepGraphNode *def) {
      assert(def != n && "Uses should be irreflexive.");
    });
  });
  return true;
}

bool SourceFileDepGraph::verifyReadsWhatIsWritten(StringRef path) const {
  auto loadedGraph = SourceFileDepGraph::loadFromPath(path);
  assert(loadedGraph.hasValue() &&
         "Should be able to read the exported graph.");
  verifySame(loadedGraph.getValue());
  return true;
}

std::string DependencyKey::humanReadableName() const {
  switch (kind) {
  case NodeKind::member:
    return demangleTypeAsContext(context) + "." + name;
  case NodeKind::externalDepend:
  case NodeKind::sourceFileProvide:
    return llvm::sys::path::filename(name);
  case NodeKind::potentialMember:
    return demangleTypeAsContext(context) + ".*";
  case NodeKind::nominal:
    return demangleTypeAsContext(context);
  case NodeKind::topLevel:
  case NodeKind::dynamicLookup:
    return name;
  default:
    llvm_unreachable("bad kind");
  }
}

std::string DependencyKey::asString() const {
  return NodeKindNames[size_t(kind)] + " " +
         "aspect: " + DeclAspectNames[size_t(aspect)] + ", " +
         humanReadableName();
}

/// Needed for TwoStageMap::verify:
raw_ostream &experimental_dependencies::operator<<(raw_ostream &out,
                                                   const DependencyKey &key) {
  out << key.asString();
  return out;
}

bool DependencyKey::verify() const {
  assert((getKind() != NodeKind::externalDepend || isInterface()) &&
         "All external dependencies must be interfaces.");
  return true;
}

/// Since I don't have Swift enums, ensure name corresspondence here.
void DependencyKey::verifyNodeKindNames() {
  for (size_t i = 0; i < size_t(NodeKind::kindCount); ++i)
    switch (NodeKind(i)) {
#define CHECK_NAME(n)                                                          \
  case NodeKind::n:                                                            \
    assert(#n == NodeKindNames[i]);                                            \
    break;
      CHECK_NAME(topLevel)
      CHECK_NAME(nominal)
      CHECK_NAME(potentialMember)
      CHECK_NAME(member)
      CHECK_NAME(dynamicLookup)
      CHECK_NAME(externalDepend)
      CHECK_NAME(sourceFileProvide)
    case NodeKind::kindCount:
      llvm_unreachable("impossible");
    }
#undef CHECK_NAME
}

/// Since I don't have Swift enums, ensure name corresspondence here.
void DependencyKey::verifyDeclAspectNames() {
  for (size_t i = 0; i < size_t(DeclAspect::aspectCount); ++i)
    switch (DeclAspect(i)) {
#define CHECK_NAME(n)                                                          \
  case DeclAspect::n:                                                          \
    assert(#n == DeclAspectNames[i]);                                          \
    break;
      CHECK_NAME(interface)
      CHECK_NAME(implementation)
    case DeclAspect::aspectCount:
      llvm_unreachable("impossible");
    }
#undef CHECK_NAME
}

void DepGraphNode::dump() const {
  key.dump();
  if (fingerprint.hasValue())
    llvm::errs() << "fingerprint: " << fingerprint.getValue() << "";
  else
    llvm::errs() << "no fingerprint";
}

std::string DepGraphNode::humanReadableName(StringRef where) const {

  return getKey().humanReadableName() +
         (getKey().getKind() == NodeKind::sourceFileProvide || where.empty()
              ? std::string()
              : std::string(" in ") + where.str());
}

void SourceFileDepGraph::verifySame(const SourceFileDepGraph &other) const {
  assert(allNodes.size() == other.allNodes.size() &&
         "Both graphs must have same number of nodes.");
  for (size_t i : indices(allNodes)) {
    assert(*allNodes[i] == *other.allNodes[i] &&
           "Both graphs must have corresponding nodes");
  }
}

//==============================================================================
// MARK: SourceFileDepGraph YAML reading & writing
//==============================================================================

namespace llvm {
namespace yaml {
// This introduces a redefinition for Linux.
#if !defined(__linux__)
void ScalarTraits<size_t>::output(const size_t &Val, void *, raw_ostream &out) {
  out << Val;
}

StringRef ScalarTraits<size_t>::input(StringRef scalar, void *ctxt,
                                      size_t &value) {
  return scalar.getAsInteger(10, value) ? "could not parse size_t" : "";
}
#endif

void ScalarEnumerationTraits<NodeKind>::enumeration(
    IO &io, swift::experimental_dependencies::NodeKind &value) {
  using NodeKind = swift::experimental_dependencies::NodeKind;
  io.enumCase(value, "topLevel", NodeKind::topLevel);
  io.enumCase(value, "nominal", NodeKind::nominal);
  io.enumCase(value, "potentialMember", NodeKind::potentialMember);
  io.enumCase(value, "member", NodeKind::member);
  io.enumCase(value, "dynamicLookup", NodeKind::dynamicLookup);
  io.enumCase(value, "externalDepend", NodeKind::externalDepend);
  io.enumCase(value, "sourceFileProvide", NodeKind::sourceFileProvide);
}

void ScalarEnumerationTraits<DeclAspect>::enumeration(
    IO &io, swift::experimental_dependencies::DeclAspect &value) {
  using DeclAspect = swift::experimental_dependencies::DeclAspect;
  io.enumCase(value, "interface", DeclAspect::interface);
  io.enumCase(value, "implementation", DeclAspect::implementation);
}

void MappingTraits<DependencyKey>::mapping(
    IO &io, swift::experimental_dependencies::DependencyKey &key) {
  io.mapRequired("kind", key.kind);
  io.mapRequired("aspect", key.aspect);
  io.mapRequired("context", key.context);
  io.mapRequired("name", key.name);
}

void MappingTraits<DepGraphNode>::mapping(
    IO &io, swift::experimental_dependencies::DepGraphNode &node) {
  io.mapRequired("key", node.key);
  io.mapOptional("fingerprint", node.fingerprint);
}

void MappingContextTraits<SourceFileDepGraphNode, SourceFileDepGraph>::mapping(
    IO &io, SourceFileDepGraphNode &node, SourceFileDepGraph &g) {
  MappingTraits<DepGraphNode>::mapping(io, node);
  io.mapRequired("sequenceNumber", node.sequenceNumber);
  std::vector<size_t> defsIDependUponVec(node.defsIDependUpon.begin(),
                                         node.defsIDependUpon.end());
  io.mapRequired("defsIDependUpon", defsIDependUponVec);
  io.mapRequired("isProvides", node.isProvides);
  if (!io.outputting()) {
    for (size_t u : defsIDependUponVec)
      node.defsIDependUpon.insert(u);
  }
  assert(g.getNode(node.sequenceNumber) && "Bad sequence number");
}

size_t SequenceTraits<std::vector<SourceFileDepGraphNode *>>::size(
    IO &, std::vector<SourceFileDepGraphNode *> &vec) {
  return vec.size();
}

SourceFileDepGraphNode &
SequenceTraits<std::vector<SourceFileDepGraphNode *>>::element(
    IO &, std::vector<SourceFileDepGraphNode *> &vec, size_t index) {
  while (vec.size() <= index)
    vec.push_back(new SourceFileDepGraphNode());
  return *vec[index];
}

void MappingTraits<SourceFileDepGraph>::mapping(IO &io, SourceFileDepGraph &g) {
  io.mapRequired("allNodes", g.allNodes, g);
}
} // namespace yaml
} // namespace llvm
<|endoftext|>


<commit_before>//===- ConstructionContext.cpp - CFG constructor information --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the ConstructionContext class and its sub-classes,
// which represent various different ways of constructing C++ objects
// with the additional information the users may want to know about
// the constructor.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/ConstructionContext.h"

using namespace clang;

const ConstructionContextLayer *
ConstructionContextLayer::create(BumpVectorContext &C, TriggerTy Trigger,
                                 const ConstructionContextLayer *Parent) {
  ConstructionContextLayer *CC =
      C.getAllocator().Allocate<ConstructionContextLayer>();
  return new (CC) ConstructionContextLayer(Trigger, Parent);
}

bool ConstructionContextLayer::isStrictlyMoreSpecificThan(
    const ConstructionContextLayer *Other) const {
  const ConstructionContextLayer *Self = this;
  while (true) {
    if (!Other)
      return Self;
    if (!Self || !Self->isSameLayer(Other))
      return false;
    Self = Self->getParent();
    Other = Other->getParent();
  }
  llvm_unreachable("The above loop can only be terminated via return!");
}

const ConstructionContext *ConstructionContext::createFromLayers(
    BumpVectorContext &C, const ConstructionContextLayer *TopLayer) {
  // Before this point all we've had was a stockpile of arbitrary layers.
  // Now validate that it is shaped as one of the finite amount of expected
  // patterns.
  if (const Stmt *S = TopLayer->getTriggerStmt()) {
    if (const auto *DS = dyn_cast<DeclStmt>(S)) {
      assert(TopLayer->isLast());
      return create<SimpleVariableConstructionContext>(C, DS);
    }
    if (const auto *NE = dyn_cast<CXXNewExpr>(S)) {
      assert(TopLayer->isLast());
      return create<NewAllocatedObjectConstructionContext>(C, NE);
    }
    if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(S)) {
      const MaterializeTemporaryExpr *MTE = nullptr;
      assert(BTE->getType().getCanonicalType()
                ->getAsCXXRecordDecl()->hasNonTrivialDestructor());
      // For temporaries with destructors, there may or may not be
      // lifetime extension on the parent layer.
      if (const ConstructionContextLayer *ParentLayer = TopLayer->getParent()) {
        assert(ParentLayer->isLast());
        // C++17 *requires* elision of the constructor at the return site
        // and at variable/member initialization site, while previous standards
        // were allowing an optional elidable constructor.
        // This is the C++17 copy-elided construction into a ctor initializer.
        if (const CXXCtorInitializer *I = ParentLayer->getTriggerInit()) {
          return create<
              CXX17ElidedCopyConstructorInitializerConstructionContext>(C,
                                                                        I, BTE);
        }
        assert(ParentLayer->getTriggerStmt() &&
               "Non-statement-based layers have been handled above!");
        // This is the normal, non-C++17 case: a temporary object which has
        // both destruction and materialization info attached to it in the AST.
        if ((MTE = dyn_cast<MaterializeTemporaryExpr>(
                 ParentLayer->getTriggerStmt()))) {
          return create<TemporaryObjectConstructionContext>(C, BTE, MTE);
        }
        // This is a constructor into a function argument. Not implemented yet.
        if (auto *CE = dyn_cast<CallExpr>(ParentLayer->getTriggerStmt()))
          return nullptr;
        // This is C++17 copy-elided construction into return statement.
        if (auto *RS = dyn_cast<ReturnStmt>(ParentLayer->getTriggerStmt())) {
          assert(!RS->getRetValue()->getType().getCanonicalType()
                    ->getAsCXXRecordDecl()->hasTrivialDestructor());
          return create<CXX17ElidedCopyReturnedValueConstructionContext>(C,
                                                                       RS, BTE);
        }
        // This is C++17 copy-elided construction into a simple variable.
        if (auto *DS = dyn_cast<DeclStmt>(ParentLayer->getTriggerStmt())) {
          assert(!cast<VarDecl>(DS->getSingleDecl())->getType()
                      .getCanonicalType()->getAsCXXRecordDecl()
                      ->hasTrivialDestructor());
          return create<CXX17ElidedCopyVariableConstructionContext>(C, DS, BTE);
        }
        llvm_unreachable("Unexpected construction context with destructor!");
      }
      // A temporary object that doesn't require materialization.
      return create<TemporaryObjectConstructionContext>(C, BTE, /*MTE=*/nullptr);
    }
    if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(S)) {
      // If the object requires destruction and is not lifetime-extended,
      // then it must have a BTE within its MTE.
      // FIXME: This should be an assertion.
      if (!(MTE->getType().getCanonicalType()
                ->getAsCXXRecordDecl()->hasTrivialDestructor() ||
             MTE->getStorageDuration() != SD_FullExpression))
        return nullptr;

      assert(TopLayer->isLast());
      return create<TemporaryObjectConstructionContext>(C, nullptr, MTE);
    }
    if (const auto *RS = dyn_cast<ReturnStmt>(S)) {
      assert(TopLayer->isLast());
      return create<SimpleReturnedValueConstructionContext>(C, RS);
    }
    // This is a constructor into a function argument. Not implemented yet.
    if (auto *CE = dyn_cast<CallExpr>(TopLayer->getTriggerStmt()))
      return nullptr;
    llvm_unreachable("Unexpected construction context with statement!");
  } else if (const CXXCtorInitializer *I = TopLayer->getTriggerInit()) {
    assert(TopLayer->isLast());
    return create<SimpleConstructorInitializerConstructionContext>(C, I);
  }
  llvm_unreachable("Unexpected construction context!");
}
<commit_msg>Fix -Wunused-variable warnings after r330377.<commit_after>//===- ConstructionContext.cpp - CFG constructor information --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the ConstructionContext class and its sub-classes,
// which represent various different ways of constructing C++ objects
// with the additional information the users may want to know about
// the constructor.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/ConstructionContext.h"

using namespace clang;

const ConstructionContextLayer *
ConstructionContextLayer::create(BumpVectorContext &C, TriggerTy Trigger,
                                 const ConstructionContextLayer *Parent) {
  ConstructionContextLayer *CC =
      C.getAllocator().Allocate<ConstructionContextLayer>();
  return new (CC) ConstructionContextLayer(Trigger, Parent);
}

bool ConstructionContextLayer::isStrictlyMoreSpecificThan(
    const ConstructionContextLayer *Other) const {
  const ConstructionContextLayer *Self = this;
  while (true) {
    if (!Other)
      return Self;
    if (!Self || !Self->isSameLayer(Other))
      return false;
    Self = Self->getParent();
    Other = Other->getParent();
  }
  llvm_unreachable("The above loop can only be terminated via return!");
}

const ConstructionContext *ConstructionContext::createFromLayers(
    BumpVectorContext &C, const ConstructionContextLayer *TopLayer) {
  // Before this point all we've had was a stockpile of arbitrary layers.
  // Now validate that it is shaped as one of the finite amount of expected
  // patterns.
  if (const Stmt *S = TopLayer->getTriggerStmt()) {
    if (const auto *DS = dyn_cast<DeclStmt>(S)) {
      assert(TopLayer->isLast());
      return create<SimpleVariableConstructionContext>(C, DS);
    }
    if (const auto *NE = dyn_cast<CXXNewExpr>(S)) {
      assert(TopLayer->isLast());
      return create<NewAllocatedObjectConstructionContext>(C, NE);
    }
    if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(S)) {
      const MaterializeTemporaryExpr *MTE = nullptr;
      assert(BTE->getType().getCanonicalType()
                ->getAsCXXRecordDecl()->hasNonTrivialDestructor());
      // For temporaries with destructors, there may or may not be
      // lifetime extension on the parent layer.
      if (const ConstructionContextLayer *ParentLayer = TopLayer->getParent()) {
        assert(ParentLayer->isLast());
        // C++17 *requires* elision of the constructor at the return site
        // and at variable/member initialization site, while previous standards
        // were allowing an optional elidable constructor.
        // This is the C++17 copy-elided construction into a ctor initializer.
        if (const CXXCtorInitializer *I = ParentLayer->getTriggerInit()) {
          return create<
              CXX17ElidedCopyConstructorInitializerConstructionContext>(C,
                                                                        I, BTE);
        }
        assert(ParentLayer->getTriggerStmt() &&
               "Non-statement-based layers have been handled above!");
        // This is the normal, non-C++17 case: a temporary object which has
        // both destruction and materialization info attached to it in the AST.
        if ((MTE = dyn_cast<MaterializeTemporaryExpr>(
                 ParentLayer->getTriggerStmt()))) {
          return create<TemporaryObjectConstructionContext>(C, BTE, MTE);
        }
        // This is a constructor into a function argument. Not implemented yet.
        if (isa<CallExpr>(ParentLayer->getTriggerStmt()))
          return nullptr;
        // This is C++17 copy-elided construction into return statement.
        if (auto *RS = dyn_cast<ReturnStmt>(ParentLayer->getTriggerStmt())) {
          assert(!RS->getRetValue()->getType().getCanonicalType()
                    ->getAsCXXRecordDecl()->hasTrivialDestructor());
          return create<CXX17ElidedCopyReturnedValueConstructionContext>(C,
                                                                       RS, BTE);
        }
        // This is C++17 copy-elided construction into a simple variable.
        if (auto *DS = dyn_cast<DeclStmt>(ParentLayer->getTriggerStmt())) {
          assert(!cast<VarDecl>(DS->getSingleDecl())->getType()
                      .getCanonicalType()->getAsCXXRecordDecl()
                      ->hasTrivialDestructor());
          return create<CXX17ElidedCopyVariableConstructionContext>(C, DS, BTE);
        }
        llvm_unreachable("Unexpected construction context with destructor!");
      }
      // A temporary object that doesn't require materialization.
      return create<TemporaryObjectConstructionContext>(C, BTE, /*MTE=*/nullptr);
    }
    if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(S)) {
      // If the object requires destruction and is not lifetime-extended,
      // then it must have a BTE within its MTE.
      // FIXME: This should be an assertion.
      if (!(MTE->getType().getCanonicalType()
                ->getAsCXXRecordDecl()->hasTrivialDestructor() ||
             MTE->getStorageDuration() != SD_FullExpression))
        return nullptr;

      assert(TopLayer->isLast());
      return create<TemporaryObjectConstructionContext>(C, nullptr, MTE);
    }
    if (const auto *RS = dyn_cast<ReturnStmt>(S)) {
      assert(TopLayer->isLast());
      return create<SimpleReturnedValueConstructionContext>(C, RS);
    }
    // This is a constructor into a function argument. Not implemented yet.
    if (isa<CallExpr>(TopLayer->getTriggerStmt()))
      return nullptr;
    llvm_unreachable("Unexpected construction context with statement!");
  } else if (const CXXCtorInitializer *I = TopLayer->getTriggerInit()) {
    assert(TopLayer->isLast());
    return create<SimpleConstructorInitializerConstructionContext>(C, I);
  }
  llvm_unreachable("Unexpected construction context!");
}
<|endoftext|>