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

#include "instance_intersector.h"
#include "../common/scene.h"

namespace embree
{
  namespace isa
  {
    void InstanceBoundsFunction(const struct RTCBoundsFunctionArguments* const args)
    {
      const Instance* instance = (const Instance*) args->geometryUserPtr;
      unsigned int itime = args->timeStep;

      assert(itime < instance->numTimeSteps);
      unsigned num_time_segments = instance->numTimeSegments();
      if (num_time_segments == 0) {
        *((BBox3fa*)args->bounds_o) = xfmBounds(instance->local2world[itime],instance->object->bounds.bounds());
      }
      else {
        const float ftime = float(itime) / float(num_time_segments);
        const BBox3fa obounds = instance->object->bounds.interpolate(ftime);
        *((BBox3fa*)args->bounds_o) = xfmBounds(instance->local2world[itime],obounds);
      }
    }

    RTCBoundsFunction InstanceBoundsFunc() {
      return InstanceBoundsFunction;
    }

    __forceinline void FastInstanceIntersectorN::intersect1(const struct RTCIntersectFunctionNArguments* const args)
    {
      const Instance* instance = (const Instance*) args->geometryUserPtr;
      RTCIntersectContext* user_context = args->context;
      Ray& ray = *(Ray*)args->rayhit;

      const AffineSpace3fa world2local =
        likely(instance->numTimeSteps == 1) ? instance->getWorld2Local() : instance->getWorld2Local(ray.time());
      const Vec3fa ray_org = ray.org;
      const Vec3fa ray_dir = ray.dir;
      ray.org = Vec3fa(xfmPoint (world2local,ray_org),ray.tnear());
      ray.dir = Vec3fa(xfmVector(world2local,ray_dir),ray.time());
      user_context->instID[0] = instance->geomID;
      IntersectContext context(instance->object,user_context);
      instance->object->intersectors.intersect((RTCRayHit&)ray,&context);
      user_context->instID[0] = -1;
      ray.org = ray_org;
      ray.dir = ray_dir;
    }

    __forceinline void FastInstanceIntersectorN::occluded1(const struct RTCOccludedFunctionNArguments* const args)
    {
      const Instance* instance = (const Instance*) args->geometryUserPtr;
      RTCIntersectContext* user_context = args->context;
      RayHit& ray = *(RayHit*)args->ray;

      const AffineSpace3fa world2local =
        likely(instance->numTimeSteps == 1) ? instance->getWorld2Local() : instance->getWorld2Local(ray.time());
      const Vec3fa ray_org = ray.org;
      const Vec3fa ray_dir = ray.dir;
      ray.org = Vec3fa(xfmPoint (world2local,ray_org),ray.tnear());
      ray.dir = Vec3fa(xfmVector(world2local,ray_dir),ray.time());
      user_context->instID[0] = instance->geomID;
      IntersectContext context(instance->object,user_context);
      instance->object->intersectors.occluded((RTCRay&)ray,&context);
      user_context->instID[0] = -1;
      ray.org = ray_org;
      ray.dir = ray_dir;
    }

    template<int K>
    __forceinline void intersectObject(vint<K>* valid, Scene* object, IntersectContext* context, RayHitK<K>& ray);
    template<int K>
    __forceinline void occludedObject(vint<K>* valid, Scene* object, IntersectContext* context, RayHitK<K>& ray);

#if defined (__SSE__)
    template<> __forceinline void intersectObject<4>(vint4* valid, Scene* object, IntersectContext* context, RayHit4& ray) { object->intersectors.intersect4(valid,(RTCRayHit4&)ray,context); }
    template<> __forceinline void occludedObject <4>(vint4* valid, Scene* object, IntersectContext* context, RayHit4& ray) { object->intersectors.occluded4 (valid,(RTCRay4&)ray,context); }
#endif
#if defined (__AVX__)
    template<> __forceinline void intersectObject<8>(vint8* valid, Scene* object, IntersectContext* context, RayHit8& ray) { object->intersectors.intersect8(valid,(RTCRayHit8&)ray,context); }
    template<> __forceinline void occludedObject <8>(vint8* valid, Scene* object, IntersectContext* context, RayHit8& ray) { object->intersectors.occluded8 (valid,(RTCRay8&)ray,context); }
#endif
#if defined (__AVX512F__)
    template<> __forceinline void intersectObject<16>(vint16* valid, Scene* object, IntersectContext* context, RayHit16& ray) { object->intersectors.intersect16(valid,(RTCRayHit16&)ray,context); }
    template<> __forceinline void occludedObject <16>(vint16* valid, Scene* object, IntersectContext* context, RayHit16& ray) { object->intersectors.occluded16 (valid,(RTCRay16&)ray,context); }
#endif

    template<int N>
    __noinline void FastInstanceIntersectorN::intersectN(const struct RTCIntersectFunctionNArguments* const args)
    {
      const vint<N>* validi = (const vint<N>*) args->valid;
      const Instance* instance = (const Instance*) args->geometryUserPtr;
      RTCIntersectContext* user_context = args->context;
      RayHitK<N>& ray = *(RayHitK<N>*)args->rayhit;

      AffineSpace3vf<N> world2local;
      const vbool<N> valid = *validi == vint<N>(-1);
      if (likely(instance->numTimeSteps == 1)) world2local = instance->getWorld2Local();
      else                                     world2local = instance->getWorld2Local<N>(valid,ray.time());

      const Vec3vf<N> ray_org = ray.org;
      const Vec3vf<N> ray_dir = ray.dir;
      ray.org = xfmPoint (world2local,ray_org);
      ray.dir = xfmVector(world2local,ray_dir);
      user_context->instID[0] = instance->geomID;
      IntersectContext context(instance->object,user_context);
      intersectObject((vint<N>*)validi,instance->object,&context,ray);
      user_context->instID[0] = -1;
      ray.org = ray_org;
      ray.dir = ray_dir;
    }

    template<int N>
    __noinline void FastInstanceIntersectorN::occludedN(const struct RTCOccludedFunctionNArguments* const args)
    {
      const vint<N>* validi = (const vint<N>*) args->valid;
      const Instance* instance = (const Instance*) args->geometryUserPtr;
      RTCIntersectContext* user_context = args->context;
      RayHitK<N>& ray = *(RayHitK<N>*)args->ray;

      AffineSpace3vf<N> world2local;
      const vbool<N> valid = *validi == vint<N>(-1);
      if (likely(instance->numTimeSteps == 1)) world2local = instance->getWorld2Local();
      else                                     world2local = instance->getWorld2Local<N>(valid,ray.time());

      const Vec3vf<N> ray_org = ray.org;
      const Vec3vf<N> ray_dir = ray.dir;
      ray.org = xfmPoint (world2local,ray_org);
      ray.dir = xfmVector(world2local,ray_dir);
      user_context->instID[0] = instance->geomID;
      IntersectContext context(instance->object,user_context);
      occludedObject((vint<N>*)validi,instance->object,&context,ray);
      user_context->instID[0] = -1;
      ray.org = ray_org;
      ray.dir = ray_dir;
    }

    void FastInstanceIntersectorN::intersect(const struct RTCIntersectFunctionNArguments* const args)
    {
      const unsigned int N = args->N;
      if      (likely(N ==  1)) return intersect1(args);
      else if (likely(N ==  4)) return intersectN<4>(args);
#if defined(__AVX__)
      else if (likely(N ==  8)) return intersectN<8>(args);
#endif
#if defined(__AVX512F__)
      else if (likely(N == 16)) return intersectN<16>(args);
#endif
      assert(false);
    }

    void FastInstanceIntersectorN::occluded(const struct RTCOccludedFunctionNArguments* const args)
    {
      const unsigned int N = args->N;
      if      (likely(N ==  1)) return occluded1(args);
      else if (likely(N ==  4)) return occludedN<4>(args);
#if defined(__AVX__)
      else if (likely(N ==  8)) return occludedN<8>(args);
#endif
#if defined(__AVX512F__)
      else if (likely(N == 16)) return occludedN<16>(args);
#endif
      assert(false);
    }

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

#include "instance_intersector.h"
#include "../common/scene.h"

namespace embree
{
  namespace isa
  {
    void InstanceBoundsFunction(const struct RTCBoundsFunctionArguments* const args)
    {
      const Instance* instance = (const Instance*) args->geometryUserPtr;
      unsigned int itime = args->timeStep;

      assert(itime < instance->numTimeSteps);
      unsigned num_time_segments = instance->numTimeSegments();
      if (num_time_segments == 0) {
        *((BBox3fa*)args->bounds_o) = xfmBounds(instance->local2world[itime],instance->object->bounds.bounds());
      }
      else {
        const float ftime = float(itime) / float(num_time_segments);
        const BBox3fa obounds = instance->object->bounds.interpolate(ftime);
        *((BBox3fa*)args->bounds_o) = xfmBounds(instance->local2world[itime],obounds);
      }
    }

    RTCBoundsFunction InstanceBoundsFunc() {
      return InstanceBoundsFunction;
    }

    __forceinline void FastInstanceIntersectorN::intersect1(const struct RTCIntersectFunctionNArguments* const args)
    {
      const Instance* instance = (const Instance*) args->geometryUserPtr;
      RTCIntersectContext* user_context = args->context;
      Ray& ray = *(Ray*)args->rayhit;

      const AffineSpace3fa world2local =
        likely(instance->numTimeSteps == 1) ? instance->getWorld2Local() : instance->getWorld2Local(ray.time());
      const Vec3fa ray_org = ray.org;
      const Vec3fa ray_dir = ray.dir;
      ray.org = Vec3fa(xfmPoint (world2local,ray_org),ray.tnear());
      ray.dir = Vec3fa(xfmVector(world2local,ray_dir),ray.time());
      user_context->instID[0] = instance->geomID;
      IntersectContext context(instance->object,user_context);
      instance->object->intersectors.intersect((RTCRayHit&)ray,&context);
      user_context->instID[0] = -1;
      ray.org = ray_org;
      ray.dir = ray_dir;
    }

    __forceinline void FastInstanceIntersectorN::occluded1(const struct RTCOccludedFunctionNArguments* const args)
    {
      const Instance* instance = (const Instance*) args->geometryUserPtr;
      RTCIntersectContext* user_context = args->context;
      RayHit& ray = *(RayHit*)args->ray;

      const AffineSpace3fa world2local =
        likely(instance->numTimeSteps == 1) ? instance->getWorld2Local() : instance->getWorld2Local(ray.time());
      const Vec3fa ray_org = ray.org;
      const Vec3fa ray_dir = ray.dir;
      ray.org = Vec3fa(xfmPoint (world2local,ray_org),ray.tnear());
      ray.dir = Vec3fa(xfmVector(world2local,ray_dir),ray.time());
      user_context->instID[0] = instance->geomID;
      IntersectContext context(instance->object,user_context);
      instance->object->intersectors.occluded((RTCRay&)ray,&context);
      user_context->instID[0] = -1;
      ray.org = ray_org;
      ray.dir = ray_dir;
    }

    template<int K>
    __forceinline void intersectObject(vint<K>* valid, Scene* object, IntersectContext* context, RayHitK<K>& ray);
    template<int K>
    __forceinline void occludedObject(vint<K>* valid, Scene* object, IntersectContext* context, RayK<K>& ray);

#if defined (__SSE__)
    template<> __forceinline void intersectObject<4>(vint4* valid, Scene* object, IntersectContext* context, RayHit4& ray) { object->intersectors.intersect4(valid,(RTCRayHit4&)ray,context); }
    template<> __forceinline void occludedObject <4>(vint4* valid, Scene* object, IntersectContext* context, Ray4& ray)    { object->intersectors.occluded4 (valid,(RTCRay4&)ray,context); }
#endif
#if defined (__AVX__)
    template<> __forceinline void intersectObject<8>(vint8* valid, Scene* object, IntersectContext* context, RayHit8& ray) { object->intersectors.intersect8(valid,(RTCRayHit8&)ray,context); }
    template<> __forceinline void occludedObject <8>(vint8* valid, Scene* object, IntersectContext* context, Ray8& ray)    { object->intersectors.occluded8 (valid,(RTCRay8&)ray,context); }
#endif
#if defined (__AVX512F__)
    template<> __forceinline void intersectObject<16>(vint16* valid, Scene* object, IntersectContext* context, RayHit16& ray) { object->intersectors.intersect16(valid,(RTCRayHit16&)ray,context); }
    template<> __forceinline void occludedObject <16>(vint16* valid, Scene* object, IntersectContext* context, Ray16& ray)    { object->intersectors.occluded16 (valid,(RTCRay16&)ray,context); }
#endif

    template<int N>
    __noinline void FastInstanceIntersectorN::intersectN(const struct RTCIntersectFunctionNArguments* const args)
    {
      const vint<N>* validi = (const vint<N>*) args->valid;
      const Instance* instance = (const Instance*) args->geometryUserPtr;
      RTCIntersectContext* user_context = args->context;
      RayHitK<N>& ray = *(RayHitK<N>*)args->rayhit;

      AffineSpace3vf<N> world2local;
      const vbool<N> valid = *validi == vint<N>(-1);
      if (likely(instance->numTimeSteps == 1)) world2local = instance->getWorld2Local();
      else                                     world2local = instance->getWorld2Local<N>(valid,ray.time());

      const Vec3vf<N> ray_org = ray.org;
      const Vec3vf<N> ray_dir = ray.dir;
      ray.org = xfmPoint (world2local,ray_org);
      ray.dir = xfmVector(world2local,ray_dir);
      user_context->instID[0] = instance->geomID;
      IntersectContext context(instance->object,user_context);
      intersectObject((vint<N>*)validi,instance->object,&context,ray);
      user_context->instID[0] = -1;
      ray.org = ray_org;
      ray.dir = ray_dir;
    }

    template<int N>
    __noinline void FastInstanceIntersectorN::occludedN(const struct RTCOccludedFunctionNArguments* const args)
    {
      const vint<N>* validi = (const vint<N>*) args->valid;
      const Instance* instance = (const Instance*) args->geometryUserPtr;
      RTCIntersectContext* user_context = args->context;
      RayK<N>& ray = *(RayK<N>*)args->ray;

      AffineSpace3vf<N> world2local;
      const vbool<N> valid = *validi == vint<N>(-1);
      if (likely(instance->numTimeSteps == 1)) world2local = instance->getWorld2Local();
      else                                     world2local = instance->getWorld2Local<N>(valid,ray.time());

      const Vec3vf<N> ray_org = ray.org;
      const Vec3vf<N> ray_dir = ray.dir;
      ray.org = xfmPoint (world2local,ray_org);
      ray.dir = xfmVector(world2local,ray_dir);
      user_context->instID[0] = instance->geomID;
      IntersectContext context(instance->object,user_context);
      occludedObject((vint<N>*)validi,instance->object,&context,ray);
      user_context->instID[0] = -1;
      ray.org = ray_org;
      ray.dir = ray_dir;
    }

    void FastInstanceIntersectorN::intersect(const struct RTCIntersectFunctionNArguments* const args)
    {
      const unsigned int N = args->N;
      if      (likely(N ==  1)) return intersect1(args);
      else if (likely(N ==  4)) return intersectN<4>(args);
#if defined(__AVX__)
      else if (likely(N ==  8)) return intersectN<8>(args);
#endif
#if defined(__AVX512F__)
      else if (likely(N == 16)) return intersectN<16>(args);
#endif
      assert(false);
    }

    void FastInstanceIntersectorN::occluded(const struct RTCOccludedFunctionNArguments* const args)
    {
      const unsigned int N = args->N;
      if      (likely(N ==  1)) return occluded1(args);
      else if (likely(N ==  4)) return occludedN<4>(args);
#if defined(__AVX__)
      else if (likely(N ==  8)) return occludedN<8>(args);
#endif
#if defined(__AVX512F__)
      else if (likely(N == 16)) return occludedN<16>(args);
#endif
      assert(false);
    }

    DEFINE_SET_INTERSECTORN(InstanceIntersectorN,FastInstanceIntersectorN);
  }
}
<|endoftext|>


<commit_before>/*********************************************************************\
	File name        : ResEdit.cpp
	Description      :
	Created at       : 11.08.01, @ 09:29:23
	Created by       : Thomas Kunert
	Modified by      :
\*********************************************************************/

#include "stdafx.h"
#include "globals.h"
#include "MakeDistriDialog.h"

#if (defined _DEBUG) && (defined USE_CPP_NEW_DELETE)
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

Bool RegisterResEdit(void);
Bool RegisterWizardCommand();
Bool RegisterDiffZipCommand();
void FreeMenuItems();
void WriteDistriPrefs(BaseFile* pFile);
void ReadDistriPrefs(BaseFile* pFile);
void WriteDistriPrefs();
void ReadDistriPrefs();
void FreeDiffZipCommand();

void SaveResEditPrefs()
{
	if (!g_pResEditPrefs)
		return;

	Filename fnPrefs = GeGetC4DPath(C4D_PATH_PREFS) + String("ResEdit.prf");
	AutoAlloc <BaseFile> pf;
	if (pf)
	{
		if (ForceOpenFileWrite(pf, fnPrefs))
		{
			pf->WriteString(g_pResEditPrefs->strOrigPath);
			pf->WriteString(g_pResEditPrefs->strNewPath);
			pf->WriteString(g_pResEditPrefs->strExtractPath);
			pf->WriteString(g_pResEditPrefs->strWizardPath);
			pf->WriteFilename(g_pResEditPrefs->fnNewZip);
			pf->WriteFilename(g_pResEditPrefs->fnDestZip);
			g_pResEditPrefs->arOldFiles.Write(pf, 0);
			pf->WriteBool(g_pResEditPrefs->toolbarIconSize);
			pf->WriteBool(g_pResEditPrefs->toolbarIconOrder);
			pf->WriteBool(g_pResEditPrefs->toolbarIconSingle);
			pf->Close();
		}
	}
	WriteDistriPrefs();
}

static CDynamicFilenameSet *g_pDiffzipFiles = nullptr;
static Filename *g_pfnDiffzipNewSrc;
static Filename *g_pfnDiffzipDest;

/*********************************************************************\
	Function name    : C4D_PlStart
	Description      : start function of the plugin
	Created at       : 11.08.01, @ 09:46:11
	Created by       : Thomas Kunert
	Modified by      :
\*********************************************************************/
Bool PluginStart()
{
#if (defined _DEBUG) && (defined USE_CPP_NEW_DELETE)
	_//CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
	if (!resource.Init()) return false; // don't start plugin without resource

	if (!RegisterResEdit()) return false;
	if (!RegisterWizardCommand()) return false;
	if (!RegisterDiffZipCommand()) return false;

	// load the control images
	g_pControlImages = BaseBitmap::Alloc();
	if (!g_pControlImages)
		return false;
	if (g_pControlImages->Init(GeGetPluginPath() + String("res") + String("images") + String("toolbar.tif")) != IMAGERESULT_OK)
		return false;

	g_pstrFillSave = NewObjClear(String);
	g_pLastOpenFile = NewObjClear(Filename);
	g_pResEditPrefs = NewObjClear(ResEditPrefs);

	Filename fnPrefs = GeGetC4DPath(C4D_PATH_PREFS) + String("ResEdit.prf");
	AutoAlloc <BaseFile> pf;
	if (!pf || !g_pstrFillSave || !g_pLastOpenFile || !g_pResEditPrefs)
		return false;
	if (pf->Open(fnPrefs, FILEOPEN_READ, FILEDIALOG_NONE))
	{
		pf->ReadString(&g_pResEditPrefs->strOrigPath);
		pf->ReadString(&g_pResEditPrefs->strNewPath);
		pf->ReadString(&g_pResEditPrefs->strExtractPath);
		pf->ReadString(&g_pResEditPrefs->strWizardPath);
		pf->ReadFilename(&g_pResEditPrefs->fnNewZip);
		pf->ReadFilename(&g_pResEditPrefs->fnDestZip);
		g_pResEditPrefs->arOldFiles.Read(pf);
		pf->ReadBool(&g_pResEditPrefs->toolbarIconSize);
		pf->ReadBool(&g_pResEditPrefs->toolbarIconOrder);
		pf->ReadBool(&g_pResEditPrefs->toolbarIconSingle);
		pf->Close();
	}
	ReadDistriPrefs();

	*g_pstrFillSave = "";
	g_chFill = ' ';
	g_lFillChars = 2;
	char ch[2];
	ch[0] = g_chFill;
	ch[1] = '\0';
	Int32 a;
	for (a = 0; a < g_lFillChars; a++)
		*g_pstrFillSave += ch;

	*g_pLastOpenFile = GeGetStartupPath();

	GePrint("Loaded ResEdit version 5.00\n");

	return true;
}

volatile const char* pChName = "Resource editor version 5.02 by Thomas Kunert";

void EndActivity()
{
	FreeMenuItems();
	FreeDiffZipCommand();
}

/*********************************************************************\
	Funktionsname    : C4D_PlEnd
	Beschreibung     : bye
	Rckgabewert     : void
	Erstellt am      : 11.08.01, @ 09:46:34
	Argument         : void
\*********************************************************************/
void PluginEnd(void)
{
	DeleteObj(g_pDiffzipFiles);
	DeleteObj(g_pfnDiffzipNewSrc);
	DeleteObj(g_pfnDiffzipDest);

	BaseBitmap::Free(g_pControlImages);
	BaseBitmap::Free(g_pStringCompareIcons);

	SaveResEditPrefs();

	if (g_pResEditPrefs)
	{
		g_pResEditPrefs->arOldFiles.Free();
		DeleteObj(g_pResEditPrefs);
	}

	DeleteObj(g_pstrFillSave);
	DeleteObj(g_pLastOpenFile);

#if (defined _DEBUG) && (defined USE_CPP_NEW_DELETE)
	//_CrtDumpMemoryLeaks();
#endif
}

Bool PluginMessage(Int32 id, void *data)
{
	switch (id)
	{
		case C4DMSG_PRIORITY:
			SetPluginPriority(data, 800);
			return true;

		case C4DPL_COMMANDLINEARGS:
			{
				C4DPL_CommandLineArgs *args = (C4DPL_CommandLineArgs*)data;
				Int32 i;

				for (i=0;i<args->argc;i++)
				{
					if (!args->argv[i]) continue;

					if (!strcmp(args->argv[i],"--help") || !strcmp(args->argv[i],"-help"))
					{
						// do not clear the entry so that other plugins can make their output!!!
						GePrint("\x01-makedistri <distributionname> <build_id> ... starts the makedistri script for the given distribution and buildid");
						GePrint("\x01-diffzips <previous zip files> -diffsrc <new zip file> -diffdest <destination zif diff ... generates a difference zip out of X basezips and one new zip");
						GePrint("\x01  example: -diffzips \"11.513_RC20354.zip\" \"11.514_RC20476.zip\" \"11.516_RC21195.zip\" -diffsrc \"11.517_RC21478.zip\" -diffdest \"11.517_RC21478_diff_test.zip\"");
					}
					else if (!strcmp(args->argv[i],"-makedistri"))
					{
						args->argv[i] = nullptr;

						if (i+1<args->argc && args->argv[i+1] && args->argv[i+1][0]!='-')
						{
							i++;
							const String prffile = args->argv[i];
							args->argv[i] = nullptr;

							if (i+1<args->argc && args->argv[i+1] && args->argv[i+1][0]!='-')
							{
								i++;
								const String buildid = args->argv[i];
								args->argv[i] = nullptr;
								Int32 tt = GeGetTimer();
								MakeDistriCommandLine(prffile,buildid);
								GePrint("Time: " + String::FloatToString((GeGetTimer() - tt) / 1000.0) + " sec.");
							}
							else
								GePrint("\x01-makedistri: missing argument (see --help for help)");
						}
						else
							GePrint("\x01-makedistri: missing argument (see --help for help)");
					}
					else if (!strcmp(args->argv[i],"-diffzips"))
					{
						args->argv[i] = nullptr;

						if (!g_pDiffzipFiles) g_pDiffzipFiles = NewObjClear(CDynamicFilenameSet);
						if (!g_pDiffzipFiles) break;

						for (i++;i<args->argc;i++)
						{
							if (!args->argv[i]) { i--; break; }
							if (args->argv[i][0]=='-') { i--; break; }
							g_pDiffzipFiles->AddFilename(args->argv[i]);
							args->argv[i] = nullptr;
						}
					}
					else if (!strcmp(args->argv[i],"-diffsrc"))
					{
						args->argv[i] = nullptr;

						if (!g_pfnDiffzipNewSrc) g_pfnDiffzipNewSrc = NewObjClear(Filename);
						if (g_pfnDiffzipNewSrc)
						{
							if (i+1<args->argc && args->argv[i+1] && args->argv[i+1][0]!='-')
							{
								i++;
								*g_pfnDiffzipNewSrc = args->argv[i];
								args->argv[i] = nullptr;
							}
						}
					}
					else if (!strcmp(args->argv[i],"-diffdest"))
					{
						args->argv[i] = nullptr;

						GePrint("@Starting ZipDiff");

						if (!g_pfnDiffzipDest) g_pfnDiffzipDest = NewObjClear(Filename);
						if (g_pfnDiffzipDest)
						{
							if (i+1<args->argc && args->argv[i+1] && args->argv[i+1][0]!='-')
							{
								i++;
								*g_pfnDiffzipDest = args->argv[i];
								args->argv[i] = nullptr;

								if (g_pDiffzipFiles && g_pfnDiffzipNewSrc && g_pfnDiffzipDest && g_pDiffzipFiles->GetElementCount()>=1)
								{
									Int32 i;
									Bool DiffZipFiles(const CDynamicFilenameSet &arFiles, const Filename &fnNew, const Filename &fnDestZip, const char* pchPassword);
									GePrint("Base Zips:");
									for (i=0;i<g_pDiffzipFiles->GetElementCount();i++)
									{
										GePrint("  "+(*g_pDiffzipFiles)[i]->GetString());
									}
									GePrint("New Zip: "+(*g_pfnDiffzipNewSrc).GetString());
									GePrint("Difference Zip: "+(*g_pfnDiffzipDest).GetString());
									Bool res = DiffZipFiles(*g_pDiffzipFiles, *g_pfnDiffzipNewSrc, *g_pfnDiffzipDest, nullptr);
									if (res)
										GePrint("ZifDiff successfully finished");
									else
										GePrint("Error: ZifDiff had an error");
								}
								GePrint("@Script End");
								break;
							}
							else
								GePrint("Error: ZifDiff no Input files");
						}
						GePrint("@Script End");
					}
				}
			}
			break;

		case C4DPL_ENDACTIVITY:
			EndActivity();
			break;
	}

	return 0;
}
<commit_msg>Fix bug introduced in bafe933, icon order and size must be saved as ints<commit_after>/*********************************************************************\
	File name        : ResEdit.cpp
	Description      :
	Created at       : 11.08.01, @ 09:29:23
	Created by       : Thomas Kunert
	Modified by      :
\*********************************************************************/

#include "stdafx.h"
#include "globals.h"
#include "MakeDistriDialog.h"

#if (defined _DEBUG) && (defined USE_CPP_NEW_DELETE)
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

Bool RegisterResEdit(void);
Bool RegisterWizardCommand();
Bool RegisterDiffZipCommand();
void FreeMenuItems();
void WriteDistriPrefs(BaseFile* pFile);
void ReadDistriPrefs(BaseFile* pFile);
void WriteDistriPrefs();
void ReadDistriPrefs();
void FreeDiffZipCommand();

void SaveResEditPrefs()
{
	if (!g_pResEditPrefs)
		return;

	Filename fnPrefs = GeGetC4DPath(C4D_PATH_PREFS) + String("ResEdit.prf");
	AutoAlloc <BaseFile> pf;
	if (pf)
	{
		if (ForceOpenFileWrite(pf, fnPrefs))
		{
			pf->WriteString(g_pResEditPrefs->strOrigPath);
			pf->WriteString(g_pResEditPrefs->strNewPath);
			pf->WriteString(g_pResEditPrefs->strExtractPath);
			pf->WriteString(g_pResEditPrefs->strWizardPath);
			pf->WriteFilename(g_pResEditPrefs->fnNewZip);
			pf->WriteFilename(g_pResEditPrefs->fnDestZip);
			g_pResEditPrefs->arOldFiles.Write(pf, 0);
			pf->WriteInt32(g_pResEditPrefs->toolbarIconSize);
			pf->WriteInt32(g_pResEditPrefs->toolbarIconOrder);
			pf->WriteBool(g_pResEditPrefs->toolbarIconSingle);
			pf->Close();
		}
	}
	WriteDistriPrefs();
}

static CDynamicFilenameSet *g_pDiffzipFiles = nullptr;
static Filename *g_pfnDiffzipNewSrc;
static Filename *g_pfnDiffzipDest;

/*********************************************************************\
	Function name    : C4D_PlStart
	Description      : start function of the plugin
	Created at       : 11.08.01, @ 09:46:11
	Created by       : Thomas Kunert
	Modified by      :
\*********************************************************************/
Bool PluginStart()
{
#if (defined _DEBUG) && (defined USE_CPP_NEW_DELETE)
	_//CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
	if (!resource.Init()) return false; // don't start plugin without resource

	if (!RegisterResEdit()) return false;
	if (!RegisterWizardCommand()) return false;
	if (!RegisterDiffZipCommand()) return false;

	// load the control images
	g_pControlImages = BaseBitmap::Alloc();
	if (!g_pControlImages)
		return false;
	if (g_pControlImages->Init(GeGetPluginPath() + String("res") + String("images") + String("toolbar.tif")) != IMAGERESULT_OK)
		return false;

	g_pstrFillSave = NewObjClear(String);
	g_pLastOpenFile = NewObjClear(Filename);
	g_pResEditPrefs = NewObjClear(ResEditPrefs);

	Filename fnPrefs = GeGetC4DPath(C4D_PATH_PREFS) + String("ResEdit.prf");
	AutoAlloc <BaseFile> pf;
	if (!pf || !g_pstrFillSave || !g_pLastOpenFile || !g_pResEditPrefs)
		return false;
	if (pf->Open(fnPrefs, FILEOPEN_READ, FILEDIALOG_NONE))
	{
		pf->ReadString(&g_pResEditPrefs->strOrigPath);
		pf->ReadString(&g_pResEditPrefs->strNewPath);
		pf->ReadString(&g_pResEditPrefs->strExtractPath);
		pf->ReadString(&g_pResEditPrefs->strWizardPath);
		pf->ReadFilename(&g_pResEditPrefs->fnNewZip);
		pf->ReadFilename(&g_pResEditPrefs->fnDestZip);
		g_pResEditPrefs->arOldFiles.Read(pf);
		pf->ReadInt32(&g_pResEditPrefs->toolbarIconSize);
		pf->ReadInt32(&g_pResEditPrefs->toolbarIconOrder);
		pf->ReadBool(&g_pResEditPrefs->toolbarIconSingle);
		pf->Close();
	}
	ReadDistriPrefs();

	*g_pstrFillSave = "";
	g_chFill = ' ';
	g_lFillChars = 2;
	char ch[2];
	ch[0] = g_chFill;
	ch[1] = '\0';
	Int32 a;
	for (a = 0; a < g_lFillChars; a++)
		*g_pstrFillSave += ch;

	*g_pLastOpenFile = GeGetStartupPath();

	GePrint("Loaded ResEdit version 5.00\n");

	return true;
}

volatile const char* pChName = "Resource editor version 5.02 by Thomas Kunert";

void EndActivity()
{
	FreeMenuItems();
	FreeDiffZipCommand();
}

/*********************************************************************\
	Funktionsname    : C4D_PlEnd
	Beschreibung     : bye
	Rckgabewert     : void
	Erstellt am      : 11.08.01, @ 09:46:34
	Argument         : void
\*********************************************************************/
void PluginEnd(void)
{
	DeleteObj(g_pDiffzipFiles);
	DeleteObj(g_pfnDiffzipNewSrc);
	DeleteObj(g_pfnDiffzipDest);

	BaseBitmap::Free(g_pControlImages);
	BaseBitmap::Free(g_pStringCompareIcons);

	SaveResEditPrefs();

	if (g_pResEditPrefs)
	{
		g_pResEditPrefs->arOldFiles.Free();
		DeleteObj(g_pResEditPrefs);
	}

	DeleteObj(g_pstrFillSave);
	DeleteObj(g_pLastOpenFile);

#if (defined _DEBUG) && (defined USE_CPP_NEW_DELETE)
	//_CrtDumpMemoryLeaks();
#endif
}

Bool PluginMessage(Int32 id, void *data)
{
	switch (id)
	{
		case C4DMSG_PRIORITY:
			SetPluginPriority(data, 800);
			return true;

		case C4DPL_COMMANDLINEARGS:
			{
				C4DPL_CommandLineArgs *args = (C4DPL_CommandLineArgs*)data;
				Int32 i;

				for (i=0;i<args->argc;i++)
				{
					if (!args->argv[i]) continue;

					if (!strcmp(args->argv[i],"--help") || !strcmp(args->argv[i],"-help"))
					{
						// do not clear the entry so that other plugins can make their output!!!
						GePrint("\x01-makedistri <distributionname> <build_id> ... starts the makedistri script for the given distribution and buildid");
						GePrint("\x01-diffzips <previous zip files> -diffsrc <new zip file> -diffdest <destination zif diff ... generates a difference zip out of X basezips and one new zip");
						GePrint("\x01  example: -diffzips \"11.513_RC20354.zip\" \"11.514_RC20476.zip\" \"11.516_RC21195.zip\" -diffsrc \"11.517_RC21478.zip\" -diffdest \"11.517_RC21478_diff_test.zip\"");
					}
					else if (!strcmp(args->argv[i],"-makedistri"))
					{
						args->argv[i] = nullptr;

						if (i+1<args->argc && args->argv[i+1] && args->argv[i+1][0]!='-')
						{
							i++;
							const String prffile = args->argv[i];
							args->argv[i] = nullptr;

							if (i+1<args->argc && args->argv[i+1] && args->argv[i+1][0]!='-')
							{
								i++;
								const String buildid = args->argv[i];
								args->argv[i] = nullptr;
								Int32 tt = GeGetTimer();
								MakeDistriCommandLine(prffile,buildid);
								GePrint("Time: " + String::FloatToString((GeGetTimer() - tt) / 1000.0) + " sec.");
							}
							else
								GePrint("\x01-makedistri: missing argument (see --help for help)");
						}
						else
							GePrint("\x01-makedistri: missing argument (see --help for help)");
					}
					else if (!strcmp(args->argv[i],"-diffzips"))
					{
						args->argv[i] = nullptr;

						if (!g_pDiffzipFiles) g_pDiffzipFiles = NewObjClear(CDynamicFilenameSet);
						if (!g_pDiffzipFiles) break;

						for (i++;i<args->argc;i++)
						{
							if (!args->argv[i]) { i--; break; }
							if (args->argv[i][0]=='-') { i--; break; }
							g_pDiffzipFiles->AddFilename(args->argv[i]);
							args->argv[i] = nullptr;
						}
					}
					else if (!strcmp(args->argv[i],"-diffsrc"))
					{
						args->argv[i] = nullptr;

						if (!g_pfnDiffzipNewSrc) g_pfnDiffzipNewSrc = NewObjClear(Filename);
						if (g_pfnDiffzipNewSrc)
						{
							if (i+1<args->argc && args->argv[i+1] && args->argv[i+1][0]!='-')
							{
								i++;
								*g_pfnDiffzipNewSrc = args->argv[i];
								args->argv[i] = nullptr;
							}
						}
					}
					else if (!strcmp(args->argv[i],"-diffdest"))
					{
						args->argv[i] = nullptr;

						GePrint("@Starting ZipDiff");

						if (!g_pfnDiffzipDest) g_pfnDiffzipDest = NewObjClear(Filename);
						if (g_pfnDiffzipDest)
						{
							if (i+1<args->argc && args->argv[i+1] && args->argv[i+1][0]!='-')
							{
								i++;
								*g_pfnDiffzipDest = args->argv[i];
								args->argv[i] = nullptr;

								if (g_pDiffzipFiles && g_pfnDiffzipNewSrc && g_pfnDiffzipDest && g_pDiffzipFiles->GetElementCount()>=1)
								{
									Int32 i;
									Bool DiffZipFiles(const CDynamicFilenameSet &arFiles, const Filename &fnNew, const Filename &fnDestZip, const char* pchPassword);
									GePrint("Base Zips:");
									for (i=0;i<g_pDiffzipFiles->GetElementCount();i++)
									{
										GePrint("  "+(*g_pDiffzipFiles)[i]->GetString());
									}
									GePrint("New Zip: "+(*g_pfnDiffzipNewSrc).GetString());
									GePrint("Difference Zip: "+(*g_pfnDiffzipDest).GetString());
									Bool res = DiffZipFiles(*g_pDiffzipFiles, *g_pfnDiffzipNewSrc, *g_pfnDiffzipDest, nullptr);
									if (res)
										GePrint("ZifDiff successfully finished");
									else
										GePrint("Error: ZifDiff had an error");
								}
								GePrint("@Script End");
								break;
							}
							else
								GePrint("Error: ZifDiff no Input files");
						}
						GePrint("@Script End");
					}
				}
			}
			break;

		case C4DPL_ENDACTIVITY:
			EndActivity();
			break;
	}

	return 0;
}
<|endoftext|>


<commit_before><commit_msg>Fixes compile warning. If you have a better suggestion for this, let me know. Here's the warning I was getting without this:<commit_after><|endoftext|>


<commit_before>/*
 Copyright 2014 Aleix Pol Gonzalez <aleixpol@blue-systems.com>

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library 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
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "alternativesmodel.h"
#include <QMimeType>
#include <QMimeDatabase>
#include <QList>
#include <KPluginLoader>
#include <KPluginMetaData>
#include <KPluginFactory>
#include <QIcon>
#include <QDebug>
#include <QJsonDocument>
#include <QStandardPaths>
#include <QFile>
#include <QJsonArray>
#include <QRegularExpression>

#include "pluginbase.h"
#include "job.h"

using namespace Purpose;

class Purpose::AlternativesModelPrivate
{
public:
    QVector<KPluginMetaData> m_plugins;
    QJsonObject m_inputData;
    QString m_pluginType;
    QJsonObject m_pluginTypeData;

    static void checkJobFinish(Purpose::Job* job)
    {
        QStringList outputArgs = job->property("outputArgs").toStringList();
        QJsonObject output = job->property("outputValues").toJsonObject();

        if (!output.keys().toSet().contains(outputArgs.toSet()) && job->error() == 0) {
            qWarning() << "missing output values for" << job->metaObject()->className()
                       << ". Expected: " << outputArgs.join(QStringLiteral(", "))
                       << ". Got: " << output.keys().join(QStringLiteral(", "));
        }
    }
};

AlternativesModel::AlternativesModel(QObject* parent)
    : QAbstractListModel(parent)
    , d_ptr(new AlternativesModelPrivate)
{
}

AlternativesModel::~AlternativesModel()
{
    Q_D(AlternativesModel);
    delete d;
}

QHash<int,QByteArray> AlternativesModel::roleNames() const
{
    QHash<int,QByteArray> roles = QAbstractListModel::roleNames();
    roles.unite({
        { IconNameRole, "iconName" },
        { PluginIdRole, "pluginId" }
    });
    return roles;
}

void AlternativesModel::setInputData(const QJsonObject &input)
{
    Q_D(AlternativesModel);
    if (input == d->m_inputData)
        return;

    d->m_inputData = input;
    initializeModel();

    Q_EMIT inputDataChanged();
}

void AlternativesModel::setPluginType(const QString& pluginType)
{
    Q_D(AlternativesModel);
    if (pluginType == d->m_pluginType)
        return;

    const QString lookup = QStringLiteral("purpose/types/") + pluginType + QStringLiteral("PluginType.json");
    const QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, lookup);
    if (path.isEmpty()) {
        qWarning() << "Couldn't find" << lookup;
        return;
    }
    QFile typeFile(path);
    if (!typeFile.open(QFile::ReadOnly)) {
        qWarning() << "Couldn't open" << lookup;
        return;
    }

    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(typeFile.readAll(), &error);
    if (error.error) {
        qWarning() << "JSON error in " << path << error.offset << ":" << error.errorString();
        return;
    }

    Q_ASSERT(doc.isObject());
    QJsonObject typeData = doc.object();
    d->m_pluginTypeData = typeData;
    d->m_pluginType = pluginType;
    Q_ASSERT(d->m_pluginTypeData.isEmpty() == d->m_pluginType.isEmpty());

    initializeModel();

    Q_EMIT pluginTypeChanged();
}

QString AlternativesModel::pluginType() const
{
    Q_D(const AlternativesModel);
    return d->m_pluginType;
}

QJsonObject AlternativesModel::inputData() const
{
    Q_D(const AlternativesModel);
    return d->m_inputData;
}

Purpose::Job* AlternativesModel::createJob(int row)
{
    Q_D(AlternativesModel);
    KPluginMetaData pluginData = d->m_plugins.at(row);
    KPluginLoader loader(pluginData.fileName(), this);
    KPluginFactory* factory = loader.factory();
    if (!factory) {
        qWarning() << "Couldn't create job" << pluginData.fileName() << loader.errorString();
        return Q_NULLPTR;
    }
    Purpose::PluginBase* plugin = dynamic_cast<Purpose::PluginBase*>(factory->create<QObject>(this, QVariantList()));

    if (!plugin) {
        qWarning() << "Couldn't load plugin:" << pluginData.fileName() << loader.errorString();
    }

    Purpose::Job* job = plugin->share();
    job->setParent(this);
    job->setData(d->m_inputData);
    job->setConfigurationArguments(d->m_inputData.value(QStringLiteral("X-Purpose-InboundArguments")));
    job->setInboundArguments(pluginData.value(QStringLiteral("X-Purpose-Configuration")));
    job->setProperty("outputArgs", d->m_pluginTypeData.value(QStringLiteral("X-Purpose-OutboundArguments")));

    connect(job, &Purpose::Job::output, job, [job](const QJsonObject& obj){ job->setProperty("outputValues", obj); });
    connect(job, &Purpose::Job::finished, job, [job](){ AlternativesModelPrivate::checkJobFinish(job); });
    return job;
}

int AlternativesModel::rowCount(const QModelIndex& parent) const
{
    Q_D(const AlternativesModel);
    return parent.isValid() ? 0 : d->m_plugins.count();
}

QVariant AlternativesModel::data(const QModelIndex& index, int role) const
{
    Q_D(const AlternativesModel);
    if (!index.isValid() || index.row()>d->m_plugins.count())
        return QVariant();

    KPluginMetaData data = d->m_plugins[index.row()];
    switch (role) {
        case Qt::DisplayRole:
            return data.name();
        case Qt::ToolTip:
            return data.description();
        case IconNameRole:
            return data.iconName();
        case Qt::DecorationRole:
            return QIcon::fromTheme(data.iconName());
        case PluginIdRole:
            return data.pluginId();
    }
    return QVariant();
}

typedef bool (*matchFunction)(const QString& constraint, const QJsonValue& value);

static bool defaultMatch(const QString& constraint, const QJsonValue& value)
{
    return value == QJsonValue(constraint);
}

static bool mimeTypeMatch(const QString& constraint, const QJsonValue& value)
{
    if(value.isArray()) {
        foreach(const QJsonValue& val, value.toArray()) {
            if (mimeTypeMatch(constraint, val))
                return true;
        }
        return false;
    } else if(value.isObject()) {
        foreach(const QJsonValue& val, value.toObject()) {
            if (mimeTypeMatch(constraint, val))
                return true;
        }
        return false;
    } else if(constraint.contains(QLatin1Char('*'))) {
        return QRegExp(constraint, Qt::CaseInsensitive, QRegExp::Wildcard).exactMatch(value.toString());
    } else {
        QMimeDatabase db;
        QMimeType mime = db.mimeTypeForName(value.toString());
        return mime.inherits(constraint);
    }
}

static QMap<QString, matchFunction> s_matchFunctions = {
    { QStringLiteral("mimeType"), mimeTypeMatch }
};

void AlternativesModel::initializeModel()
{
    Q_D(AlternativesModel);
    if (d->m_pluginType.isEmpty()) {
        return;
    }

    const QJsonArray inbound = d->m_pluginTypeData.value(QStringLiteral("X-Purpose-InboundArguments")).toArray();
    foreach(const QJsonValue& arg, inbound) {
        if(!d->m_inputData.contains(arg.toString())) {
            qWarning() << "Cannot initialize model with data" << d->m_inputData << ". missing:" << arg;
            return;
        }
    }

    beginResetModel();
    d->m_plugins = KPluginLoader::findPlugins(QStringLiteral("purpose"), [d](const KPluginMetaData& meta) {
        const QJsonObject obj = meta.rawData();
        if(!obj.value(QStringLiteral("X-Purpose-PluginTypes")).toArray().contains(d->m_pluginType)) {
            qDebug() << "discarding" << meta.name() << meta.value(QStringLiteral("X-Purpose-PluginTypes"));
            return false;
        }

        const QJsonArray constraints = obj.value(QStringLiteral("X-Purpose-Constraints")).toArray();
        const QRegularExpression constraintRx(QStringLiteral("(\\w+):(.*)"));
        for(const QJsonValue& constraint: constraints) {
            Q_ASSERT(constraintRx.isValid());
            QRegularExpressionMatch match = constraintRx.match(constraint.toString());
            if (!match.isValid() || !match.hasMatch()) {
                qWarning() << "wrong constraint" << constraint.toString();
                continue;
            }
            QString propertyName = match.captured(1);
            QString constrainedValue = match.captured(2);
            bool acceptable = s_matchFunctions.value(propertyName, defaultMatch)(constrainedValue, d->m_inputData[propertyName]);
            if (!acceptable) {
//                 qDebug() << "not accepted" << meta.name() << propertyName << constrainedValue << d->m_inputData[propertyName];
                return false;
            }
        }
        return true;
    });
    endResetModel();

}
<commit_msg>Make sure we're fetching the properties from the correct source.<commit_after>/*
 Copyright 2014 Aleix Pol Gonzalez <aleixpol@blue-systems.com>

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library 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
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "alternativesmodel.h"
#include <QMimeType>
#include <QMimeDatabase>
#include <QList>
#include <KPluginLoader>
#include <KPluginMetaData>
#include <KPluginFactory>
#include <QIcon>
#include <QDebug>
#include <QJsonDocument>
#include <QStandardPaths>
#include <QFile>
#include <QJsonArray>
#include <QRegularExpression>

#include "pluginbase.h"
#include "job.h"

using namespace Purpose;

class Purpose::AlternativesModelPrivate
{
public:
    QVector<KPluginMetaData> m_plugins;
    QJsonObject m_inputData;
    QString m_pluginType;
    QJsonObject m_pluginTypeData;

    static void checkJobFinish(Purpose::Job* job)
    {
        QStringList outputArgs = job->property("outputArgs").toStringList();
        QJsonObject output = job->property("outputValues").toJsonObject();

        if (!output.keys().toSet().contains(outputArgs.toSet()) && job->error() == 0) {
            qWarning() << "missing output values for" << job->metaObject()->className()
                       << ". Expected: " << outputArgs.join(QStringLiteral(", "))
                       << ". Got: " << output.keys().join(QStringLiteral(", "));
        }
    }
};

AlternativesModel::AlternativesModel(QObject* parent)
    : QAbstractListModel(parent)
    , d_ptr(new AlternativesModelPrivate)
{
}

AlternativesModel::~AlternativesModel()
{
    Q_D(AlternativesModel);
    delete d;
}

QHash<int,QByteArray> AlternativesModel::roleNames() const
{
    QHash<int,QByteArray> roles = QAbstractListModel::roleNames();
    roles.unite({
        { IconNameRole, "iconName" },
        { PluginIdRole, "pluginId" }
    });
    return roles;
}

void AlternativesModel::setInputData(const QJsonObject &input)
{
    Q_D(AlternativesModel);
    if (input == d->m_inputData)
        return;

    d->m_inputData = input;
    initializeModel();

    Q_EMIT inputDataChanged();
}

void AlternativesModel::setPluginType(const QString& pluginType)
{
    Q_D(AlternativesModel);
    if (pluginType == d->m_pluginType)
        return;

    const QString lookup = QStringLiteral("purpose/types/") + pluginType + QStringLiteral("PluginType.json");
    const QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, lookup);
    if (path.isEmpty()) {
        qWarning() << "Couldn't find" << lookup;
        return;
    }
    QFile typeFile(path);
    if (!typeFile.open(QFile::ReadOnly)) {
        qWarning() << "Couldn't open" << lookup;
        return;
    }

    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(typeFile.readAll(), &error);
    if (error.error) {
        qWarning() << "JSON error in " << path << error.offset << ":" << error.errorString();
        return;
    }

    Q_ASSERT(doc.isObject());
    QJsonObject typeData = doc.object();
    d->m_pluginTypeData = typeData;
    d->m_pluginType = pluginType;
    Q_ASSERT(d->m_pluginTypeData.isEmpty() == d->m_pluginType.isEmpty());

    initializeModel();

    Q_EMIT pluginTypeChanged();
}

QString AlternativesModel::pluginType() const
{
    Q_D(const AlternativesModel);
    return d->m_pluginType;
}

QJsonObject AlternativesModel::inputData() const
{
    Q_D(const AlternativesModel);
    return d->m_inputData;
}

Purpose::Job* AlternativesModel::createJob(int row)
{
    Q_D(AlternativesModel);
    KPluginMetaData pluginData = d->m_plugins.at(row);
    KPluginLoader loader(pluginData.fileName(), this);
    KPluginFactory* factory = loader.factory();
    if (!factory) {
        qWarning() << "Couldn't create job" << pluginData.fileName() << loader.errorString();
        return Q_NULLPTR;
    }
    Purpose::PluginBase* plugin = dynamic_cast<Purpose::PluginBase*>(factory->create<QObject>(this, QVariantList()));

    if (!plugin) {
        qWarning() << "Couldn't load plugin:" << pluginData.fileName() << loader.errorString();
    }

    Purpose::Job* job = plugin->share();
    job->setParent(this);
    job->setData(d->m_inputData);
    job->setConfigurationArguments(d->m_pluginTypeData.value(QStringLiteral("X-Purpose-InboundArguments")));
    job->setInboundArguments(pluginData.rawData().value(QStringLiteral("X-Purpose-Configuration")));
    job->setProperty("outputArgs", d->m_pluginTypeData.value(QStringLiteral("X-Purpose-OutboundArguments")));

    connect(job, &Purpose::Job::output, job, [job](const QJsonObject& obj){ job->setProperty("outputValues", obj); });
    connect(job, &Purpose::Job::finished, job, [job](){ AlternativesModelPrivate::checkJobFinish(job); });
    return job;
}

int AlternativesModel::rowCount(const QModelIndex& parent) const
{
    Q_D(const AlternativesModel);
    return parent.isValid() ? 0 : d->m_plugins.count();
}

QVariant AlternativesModel::data(const QModelIndex& index, int role) const
{
    Q_D(const AlternativesModel);
    if (!index.isValid() || index.row()>d->m_plugins.count())
        return QVariant();

    KPluginMetaData data = d->m_plugins[index.row()];
    switch (role) {
        case Qt::DisplayRole:
            return data.name();
        case Qt::ToolTip:
            return data.description();
        case IconNameRole:
            return data.iconName();
        case Qt::DecorationRole:
            return QIcon::fromTheme(data.iconName());
        case PluginIdRole:
            return data.pluginId();
    }
    return QVariant();
}

typedef bool (*matchFunction)(const QString& constraint, const QJsonValue& value);

static bool defaultMatch(const QString& constraint, const QJsonValue& value)
{
    return value == QJsonValue(constraint);
}

static bool mimeTypeMatch(const QString& constraint, const QJsonValue& value)
{
    if(value.isArray()) {
        foreach(const QJsonValue& val, value.toArray()) {
            if (mimeTypeMatch(constraint, val))
                return true;
        }
        return false;
    } else if(value.isObject()) {
        foreach(const QJsonValue& val, value.toObject()) {
            if (mimeTypeMatch(constraint, val))
                return true;
        }
        return false;
    } else if(constraint.contains(QLatin1Char('*'))) {
        return QRegExp(constraint, Qt::CaseInsensitive, QRegExp::Wildcard).exactMatch(value.toString());
    } else {
        QMimeDatabase db;
        QMimeType mime = db.mimeTypeForName(value.toString());
        return mime.inherits(constraint);
    }
}

static QMap<QString, matchFunction> s_matchFunctions = {
    { QStringLiteral("mimeType"), mimeTypeMatch }
};

void AlternativesModel::initializeModel()
{
    Q_D(AlternativesModel);
    if (d->m_pluginType.isEmpty()) {
        return;
    }

    const QJsonArray inbound = d->m_pluginTypeData.value(QStringLiteral("X-Purpose-InboundArguments")).toArray();
    foreach(const QJsonValue& arg, inbound) {
        if(!d->m_inputData.contains(arg.toString())) {
            qWarning() << "Cannot initialize model with data" << d->m_inputData << ". missing:" << arg;
            return;
        }
    }

    beginResetModel();
    d->m_plugins = KPluginLoader::findPlugins(QStringLiteral("purpose"), [d](const KPluginMetaData& meta) {
        const QJsonObject obj = meta.rawData();
        if(!obj.value(QStringLiteral("X-Purpose-PluginTypes")).toArray().contains(d->m_pluginType)) {
            qDebug() << "discarding" << meta.name() << meta.value(QStringLiteral("X-Purpose-PluginTypes"));
            return false;
        }

        const QJsonArray constraints = obj.value(QStringLiteral("X-Purpose-Constraints")).toArray();
        const QRegularExpression constraintRx(QStringLiteral("(\\w+):(.*)"));
        for(const QJsonValue& constraint: constraints) {
            Q_ASSERT(constraintRx.isValid());
            QRegularExpressionMatch match = constraintRx.match(constraint.toString());
            if (!match.isValid() || !match.hasMatch()) {
                qWarning() << "wrong constraint" << constraint.toString();
                continue;
            }
            QString propertyName = match.captured(1);
            QString constrainedValue = match.captured(2);
            bool acceptable = s_matchFunctions.value(propertyName, defaultMatch)(constrainedValue, d->m_inputData[propertyName]);
            if (!acceptable) {
//                 qDebug() << "not accepted" << meta.name() << propertyName << constrainedValue << d->m_inputData[propertyName];
                return false;
            }
        }
        return true;
    });
    endResetModel();

}
<|endoftext|>


<commit_before>// Copyright(c) 2015-present Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)

#include <mutex>
#include <chrono>

#include "spdlog/common.h"
#include "spdlog/common-inl.h"

#include "spdlog/details/null_mutex.h"

#include "spdlog/logger.h"
#include "spdlog/logger-inl.h"

#include "spdlog/async_logger.h"
#include "spdlog/async_logger-inl.h"

#include "spdlog/details/log_msg.h"
#include "spdlog/details/log_msg-inl.h"

#include "spdlog/sinks/sink.h"
#include "spdlog/sinks/sink-inl.h"

#include "spdlog/sinks/base_sink.h"
#include "spdlog/sinks/base_sink-inl.h"
template class spdlog::sinks::base_sink<std::mutex>;
template class spdlog::sinks::base_sink<spdlog::details::null_mutex>;

#include "spdlog/details/registry.h"
#include "spdlog/details/registry-inl.h"

#include "spdlog/details/os.h"
#include "spdlog/details/os-inl.h"

#include "spdlog/details/periodic_worker.h"
#include "spdlog/details/periodic_worker-inl.h"

#include "spdlog/details/file_helper.h"
#include "spdlog/details/file_helper-inl.h"

#include "spdlog/details/pattern_formatter.h"
#include "spdlog/details/pattern_formatter-inl.h"

#include "spdlog/details/thread_pool.h"
#include "spdlog/details/thread_pool-inl.h"
template class spdlog::details::mpmc_blocking_queue<spdlog::details::async_msg>;

#include "spdlog/sinks/ansicolor_sink.h"
#include "spdlog/sinks/ansicolor_sink-inl.h"
template class spdlog::sinks::ansicolor_sink<spdlog::details::console_stdout, spdlog::details::console_mutex>;
template class spdlog::sinks::ansicolor_sink<spdlog::details::console_stdout, spdlog::details::console_nullmutex>;
template class spdlog::sinks::ansicolor_sink<spdlog::details::console_stderr, spdlog::details::console_mutex>;
template class spdlog::sinks::ansicolor_sink<spdlog::details::console_stderr, spdlog::details::console_nullmutex>;

// fmt_helper templates
#include "spdlog/details/fmt_helper.h"
template void spdlog::details::fmt_helper::append_string_view(spdlog::string_view_t view, fmt::memory_buffer &dest);
template spdlog::string_view_t spdlog::details::fmt_helper::to_string_view(const fmt::memory_buffer &buf) SPDLOG_NOEXCEPT;

// Slightly modified version of fmt lib's format.cc source file.
// Copyright (c) 2012 - 2016, Victor Zverovich
// All rights reserved.

#if !defined(SPDLOG_FMT_EXTERNAL)
#include "spdlog/fmt/bundled/format-inl.h"

FMT_BEGIN_NAMESPACE
template struct internal::basic_data<void>;
template FMT_API internal::locale_ref::locale_ref(const std::locale &loc);
template FMT_API std::locale internal::locale_ref::get<std::locale>() const;

// Explicit instantiations for char.

template FMT_API char internal::thousands_sep_impl(locale_ref);

template FMT_API void internal::basic_buffer<char>::append(const char *, const char *);

template FMT_API void internal::arg_map<format_context>::init(const basic_format_args<format_context> &args);

template FMT_API int internal::char_traits<char>::format_float(char *, std::size_t, const char *, int, double);

template FMT_API int internal::char_traits<char>::format_float(char *, std::size_t, const char *, int, long double);

template FMT_API std::string internal::vformat<char>(string_view, basic_format_args<format_context>);

template FMT_API format_context::iterator internal::vformat_to(internal::buffer &, string_view, basic_format_args<format_context>);

template FMT_API void internal::sprintf_format(double, internal::buffer &, core_format_specs);
template FMT_API void internal::sprintf_format(long double, internal::buffer &, core_format_specs);

// Explicit instantiations for wchar_t.

template FMT_API wchar_t internal::thousands_sep_impl(locale_ref);

template FMT_API void internal::basic_buffer<wchar_t>::append(const wchar_t *, const wchar_t *);

template FMT_API void internal::arg_map<wformat_context>::init(const basic_format_args<wformat_context> &);

template FMT_API int internal::char_traits<wchar_t>::format_float(wchar_t *, std::size_t, const wchar_t *, int, double);

template FMT_API int internal::char_traits<wchar_t>::format_float(wchar_t *, std::size_t, const wchar_t *, int, long double);

template FMT_API std::wstring internal::vformat<wchar_t>(wstring_view, basic_format_args<wformat_context>);
FMT_END_NAMESPACE

#endif<commit_msg>Warn if compiling spdlog.cpp under header only configuration<commit_after>// Copyright(c) 2015-present Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#ifndef SPDLOG_STATIC_LIB
#warning spdlog is in header only configuration. please define SPDLOG_STATIC_LIB
#endif

#include <mutex>
#include <chrono>

#include "spdlog/common.h"

#include "spdlog/common-inl.h"

#include "spdlog/details/null_mutex.h"

#include "spdlog/logger.h"
#include "spdlog/logger-inl.h"

#include "spdlog/async_logger.h"
#include "spdlog/async_logger-inl.h"

#include "spdlog/details/log_msg.h"
#include "spdlog/details/log_msg-inl.h"

#include "spdlog/sinks/sink.h"
#include "spdlog/sinks/sink-inl.h"

#include "spdlog/sinks/base_sink.h"
#include "spdlog/sinks/base_sink-inl.h"
template class spdlog::sinks::base_sink<std::mutex>;
template class spdlog::sinks::base_sink<spdlog::details::null_mutex>;

#include "spdlog/details/registry.h"
#include "spdlog/details/registry-inl.h"

#include "spdlog/details/os.h"
#include "spdlog/details/os-inl.h"

#include "spdlog/details/periodic_worker.h"
#include "spdlog/details/periodic_worker-inl.h"

#include "spdlog/details/file_helper.h"
#include "spdlog/details/file_helper-inl.h"

#include "spdlog/details/pattern_formatter.h"
#include "spdlog/details/pattern_formatter-inl.h"

#include "spdlog/details/thread_pool.h"
#include "spdlog/details/thread_pool-inl.h"
template class spdlog::details::mpmc_blocking_queue<spdlog::details::async_msg>;

#include "spdlog/sinks/ansicolor_sink.h"
#include "spdlog/sinks/ansicolor_sink-inl.h"
template class spdlog::sinks::ansicolor_sink<spdlog::details::console_stdout, spdlog::details::console_mutex>;
template class spdlog::sinks::ansicolor_sink<spdlog::details::console_stdout, spdlog::details::console_nullmutex>;
template class spdlog::sinks::ansicolor_sink<spdlog::details::console_stderr, spdlog::details::console_mutex>;
template class spdlog::sinks::ansicolor_sink<spdlog::details::console_stderr, spdlog::details::console_nullmutex>;

// fmt_helper templates
#include "spdlog/details/fmt_helper.h"
template void spdlog::details::fmt_helper::append_string_view(spdlog::string_view_t view, fmt::memory_buffer &dest);
template spdlog::string_view_t spdlog::details::fmt_helper::to_string_view(const fmt::memory_buffer &buf) SPDLOG_NOEXCEPT;

// Slightly modified version of fmt lib's format.cc source file.
// Copyright (c) 2012 - 2016, Victor Zverovich
// All rights reserved.

#if !defined(SPDLOG_FMT_EXTERNAL)
#include "spdlog/fmt/bundled/format-inl.h"

FMT_BEGIN_NAMESPACE
template struct internal::basic_data<void>;
template FMT_API internal::locale_ref::locale_ref(const std::locale &loc);
template FMT_API std::locale internal::locale_ref::get<std::locale>() const;

// Explicit instantiations for char.

template FMT_API char internal::thousands_sep_impl(locale_ref);

template FMT_API void internal::basic_buffer<char>::append(const char *, const char *);

template FMT_API void internal::arg_map<format_context>::init(const basic_format_args<format_context> &args);

template FMT_API int internal::char_traits<char>::format_float(char *, std::size_t, const char *, int, double);

template FMT_API int internal::char_traits<char>::format_float(char *, std::size_t, const char *, int, long double);

template FMT_API std::string internal::vformat<char>(string_view, basic_format_args<format_context>);

template FMT_API format_context::iterator internal::vformat_to(internal::buffer &, string_view, basic_format_args<format_context>);

template FMT_API void internal::sprintf_format(double, internal::buffer &, core_format_specs);
template FMT_API void internal::sprintf_format(long double, internal::buffer &, core_format_specs);

// Explicit instantiations for wchar_t.

template FMT_API wchar_t internal::thousands_sep_impl(locale_ref);

template FMT_API void internal::basic_buffer<wchar_t>::append(const wchar_t *, const wchar_t *);

template FMT_API void internal::arg_map<wformat_context>::init(const basic_format_args<wformat_context> &);

template FMT_API int internal::char_traits<wchar_t>::format_float(wchar_t *, std::size_t, const wchar_t *, int, double);

template FMT_API int internal::char_traits<wchar_t>::format_float(wchar_t *, std::size_t, const wchar_t *, int, long double);

template FMT_API std::wstring internal::vformat<wchar_t>(wstring_view, basic_format_args<wformat_context>);
FMT_END_NAMESPACE

#endif<|endoftext|>


<commit_before>#include <cstring>
#include <cassert>
#include <cstdio>
#include <sstream>

#include "hit.h"
#include "config.h"

hit::hit(int32_t p)
{
	bam1_core_t::pos = p;
	strand = '.';
	xs = '.';
}

hit::hit(const hit &h)
	:bam1_core_t(h)
{
	rpos = h.rpos;
	qname = h.qname;
	strand = h.strand;
	xs = h.xs;
	for(int i = 0; i < MAX_NUM_CIGAR; i++)
	{
		cigar[i] = h.cigar[i];
	}
}

hit::hit(bam1_t *b)
	:bam1_core_t(b->core)
{
	// fetch query name
	char buf[1024];
	memcpy(buf, bam_get_qname(b), l_qname);
	buf[l_qname] = '\0';
	qname = string(buf);

	// compute rpos
	rpos = pos + (int32_t)bam_cigar2rlen(n_cigar, bam_get_cigar(b));

	// copy cigar
	assert(n_cigar <= MAX_NUM_CIGAR);
	assert(n_cigar >= 1);
	memcpy(cigar, bam_get_cigar(b), 4 * n_cigar);

	// get strandness
	/*
	if(bam_is_rev(b) == true) strand = '-';
	else strand = '+';
	*/

	strand = '.';
	if((flag & 0x10) <= 0 && (flag & 0x20) >= 1 && (flag & 0x40) >= 1 && (flag & 0x80) <= 0) strand = '+';
	if((flag & 0x10) <= 0 && (flag & 0x20) >= 1 && (flag & 0x40) <= 0 && (flag & 0x80) >= 1) strand = '-';
	if((flag & 0x10) >= 1 && (flag & 0x20) <= 0 && (flag & 0x40) <= 0 && (flag & 0x80) >= 1) strand = '+';
	if((flag & 0x10) >= 1 && (flag & 0x20) <= 0 && (flag & 0x40) >= 1 && (flag & 0x80) <= 0) strand = '-';

	if(strand_reverse == true && strand == '+') strand = '-';
	else if(strand_reverse == true && strand == '-') strand = '+';

	xs = '.';
	uint8_t *p = bam_aux_get(b, "XS");
	if(p && (*p) == 'A') xs = bam_aux2A(p);
	if(xs == '-' || xs == '+') strand = xs;

	/*
	if((flag & 0x10) <= 0 && (flag & 0x20) >= 1 && (flag & 0x40) >= 1 && (flag & 0x80) <= 0) strand = '-';
	if((flag & 0x10) >= 1 && (flag & 0x20) <= 0 && (flag & 0x40) <= 0 && (flag & 0x80) >= 1) strand = '-';
	if((flag & 0x10) <= 0 && (flag & 0x20) >= 1 && (flag & 0x40) <= 0 && (flag & 0x80) >= 1) strand = '+';
	if((flag & 0x10) >= 1 && (flag & 0x20) <= 0 && (flag & 0x40) >= 1 && (flag & 0x80) <= 0) strand = '+';
	*/
}

hit::~hit()
{
}

bool hit::operator<(const hit &h) const
{
	if(pos < h.pos) return true;
	else return false;
}

int hit::print() const
{
	// get cigar string
	ostringstream sstr;
	for(int i = 0; i < n_cigar; i++)
	{
		sstr << bam_cigar_opchr(cigar[i]) << bam_cigar_oplen(cigar[i]);
		//printf("cigar %d: op = %c, length = %3d\n", i, bam_cigar_opchr(cigar[i]), bam_cigar_oplen(cigar[i]));
	}

	// print basic information
	printf("Hit %s: [%d-%d), mpos = %d, cigar = %s, flag = %d, quality = %d, strand = %c\n",
			qname.c_str(), pos, rpos, mpos, sstr.str().c_str(), flag, qual, strand);

	return 0;
}

int hit::get_splice_positions(vector<int64_t> &v) const
{
	v.clear();
	int32_t p = pos;
    for(int k = 0; k < n_cigar; k++)
	{
		if (bam_cigar_type(bam_cigar_op(cigar[k]))&2)
			p += bam_cigar_oplen(cigar[k]);

		if(k == 0 || k == n_cigar - 1) continue;
		if(bam_cigar_op(cigar[k]) != BAM_CREF_SKIP) continue;
		if(bam_cigar_op(cigar[k-1]) != BAM_CMATCH) continue;
		if(bam_cigar_op(cigar[k+1]) != BAM_CMATCH) continue;
		if(bam_cigar_oplen(cigar[k-1]) < min_flank_length) continue;
		if(bam_cigar_oplen(cigar[k+1]) < min_flank_length) continue;

		int32_t s = p - bam_cigar_oplen(cigar[k]);
		v.push_back(pack(s, p));
	}
    return 0;
}

int hit::get_mid_intervals(vector<int64_t> &vm, vector<int64_t> &vi, vector<int64_t> &vd) const
{
	vm.clear();
	vi.clear();
	vd.clear();
	int32_t p = pos;
    for(int k = 0; k < n_cigar; k++)
	{
		if (bam_cigar_type(bam_cigar_op(cigar[k]))&2)
		{
			p += bam_cigar_oplen(cigar[k]);
		}

		if(bam_cigar_op(cigar[k]) == BAM_CMATCH)
		{
			int32_t s = p - bam_cigar_oplen(cigar[k]);
			vm.push_back(pack(s, p));
		}

		if(bam_cigar_op(cigar[k]) == BAM_CINS)
		{
			vi.push_back(pack(p - 1, p + 1));
		}

		if(bam_cigar_op(cigar[k]) == BAM_CDEL)
		{
			int32_t s = p - bam_cigar_oplen(cigar[k]);
			vd.push_back(pack(s, p));
		}
	}
    return 0;
}

int hit::get_matched_intervals(vector<int64_t> &v) const
{
	vector<int64_t> vi, vd;
	return get_mid_intervals(v, vi, vd);
}

/*
inline bool hit_compare_left(const hit &x, const hit &y)
{
	if(x.pos < y.pos) return true;
	else return false;
}

inline bool hit_compare_right(const hit &x, const hit &y)
{
	if(x.rpos < y.rpos) return true;
	return false;
}
*/
<commit_msg>change back the strand method<commit_after>#include <cstring>
#include <cassert>
#include <cstdio>
#include <sstream>

#include "hit.h"
#include "config.h"

hit::hit(int32_t p)
{
	bam1_core_t::pos = p;
	strand = '.';
	xs = '.';
}

hit::hit(const hit &h)
	:bam1_core_t(h)
{
	rpos = h.rpos;
	qname = h.qname;
	strand = h.strand;
	xs = h.xs;
	for(int i = 0; i < MAX_NUM_CIGAR; i++)
	{
		cigar[i] = h.cigar[i];
	}
}

hit::hit(bam1_t *b)
	:bam1_core_t(b->core)
{
	// fetch query name
	char buf[1024];
	memcpy(buf, bam_get_qname(b), l_qname);
	buf[l_qname] = '\0';
	qname = string(buf);

	// compute rpos
	rpos = pos + (int32_t)bam_cigar2rlen(n_cigar, bam_get_cigar(b));

	// copy cigar
	assert(n_cigar <= MAX_NUM_CIGAR);
	assert(n_cigar >= 1);
	memcpy(cigar, bam_get_cigar(b), 4 * n_cigar);

	// get strandness
	/*
	if(bam_is_rev(b) == true) strand = '-';
	else strand = '+';
	*/

	strand = '.';
	if((flag & 0x10) <= 0 && (flag & 0x20) >= 1 && (flag & 0x40) >= 1 && (flag & 0x80) <= 0) strand = '+';
	if((flag & 0x10) <= 0 && (flag & 0x20) >= 1 && (flag & 0x40) <= 0 && (flag & 0x80) >= 1) strand = '-';
	if((flag & 0x10) >= 1 && (flag & 0x20) <= 0 && (flag & 0x40) <= 0 && (flag & 0x80) >= 1) strand = '+';
	if((flag & 0x10) >= 1 && (flag & 0x20) <= 0 && (flag & 0x40) >= 1 && (flag & 0x80) <= 0) strand = '-';

	if(strand_reverse == true && strand == '+') strand = '-';
	else if(strand_reverse == true && strand == '-') strand = '+';

	xs = '.';
	uint8_t *p = bam_aux_get(b, "XS");
	if(p && (*p) == 'A') xs = bam_aux2A(p);
	//if(xs == '-' || xs == '+') strand = xs;

	/*
	if((flag & 0x10) <= 0 && (flag & 0x20) >= 1 && (flag & 0x40) >= 1 && (flag & 0x80) <= 0) strand = '-';
	if((flag & 0x10) >= 1 && (flag & 0x20) <= 0 && (flag & 0x40) <= 0 && (flag & 0x80) >= 1) strand = '-';
	if((flag & 0x10) <= 0 && (flag & 0x20) >= 1 && (flag & 0x40) <= 0 && (flag & 0x80) >= 1) strand = '+';
	if((flag & 0x10) >= 1 && (flag & 0x20) <= 0 && (flag & 0x40) >= 1 && (flag & 0x80) <= 0) strand = '+';
	*/
}

hit::~hit()
{
}

bool hit::operator<(const hit &h) const
{
	if(pos < h.pos) return true;
	else return false;
}

int hit::print() const
{
	// get cigar string
	ostringstream sstr;
	for(int i = 0; i < n_cigar; i++)
	{
		sstr << bam_cigar_opchr(cigar[i]) << bam_cigar_oplen(cigar[i]);
		//printf("cigar %d: op = %c, length = %3d\n", i, bam_cigar_opchr(cigar[i]), bam_cigar_oplen(cigar[i]));
	}

	// print basic information
	printf("Hit %s: [%d-%d), mpos = %d, cigar = %s, flag = %d, quality = %d, strand = %c\n",
			qname.c_str(), pos, rpos, mpos, sstr.str().c_str(), flag, qual, strand);

	return 0;
}

int hit::get_splice_positions(vector<int64_t> &v) const
{
	v.clear();
	int32_t p = pos;
    for(int k = 0; k < n_cigar; k++)
	{
		if (bam_cigar_type(bam_cigar_op(cigar[k]))&2)
			p += bam_cigar_oplen(cigar[k]);

		if(k == 0 || k == n_cigar - 1) continue;
		if(bam_cigar_op(cigar[k]) != BAM_CREF_SKIP) continue;
		if(bam_cigar_op(cigar[k-1]) != BAM_CMATCH) continue;
		if(bam_cigar_op(cigar[k+1]) != BAM_CMATCH) continue;
		if(bam_cigar_oplen(cigar[k-1]) < min_flank_length) continue;
		if(bam_cigar_oplen(cigar[k+1]) < min_flank_length) continue;

		int32_t s = p - bam_cigar_oplen(cigar[k]);
		v.push_back(pack(s, p));
	}
    return 0;
}

int hit::get_mid_intervals(vector<int64_t> &vm, vector<int64_t> &vi, vector<int64_t> &vd) const
{
	vm.clear();
	vi.clear();
	vd.clear();
	int32_t p = pos;
    for(int k = 0; k < n_cigar; k++)
	{
		if (bam_cigar_type(bam_cigar_op(cigar[k]))&2)
		{
			p += bam_cigar_oplen(cigar[k]);
		}

		if(bam_cigar_op(cigar[k]) == BAM_CMATCH)
		{
			int32_t s = p - bam_cigar_oplen(cigar[k]);
			vm.push_back(pack(s, p));
		}

		if(bam_cigar_op(cigar[k]) == BAM_CINS)
		{
			vi.push_back(pack(p - 1, p + 1));
		}

		if(bam_cigar_op(cigar[k]) == BAM_CDEL)
		{
			int32_t s = p - bam_cigar_oplen(cigar[k]);
			vd.push_back(pack(s, p));
		}
	}
    return 0;
}

int hit::get_matched_intervals(vector<int64_t> &v) const
{
	vector<int64_t> vi, vd;
	return get_mid_intervals(v, vi, vd);
}

/*
inline bool hit_compare_left(const hit &x, const hit &y)
{
	if(x.pos < y.pos) return true;
	else return false;
}

inline bool hit_compare_right(const hit &x, const hit &y)
{
	if(x.rpos < y.rpos) return true;
	return false;
}
*/
<|endoftext|>


<commit_before>//===- PDB.cpp ------------------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "PDB.h"
#include "Chunks.h"
#include "Config.h"
#include "Error.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/MSF/ByteStream.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
#include "llvm/DebugInfo/PDB/Native/StringTableBuilder.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/ScopedPrinter.h"
#include <memory>

using namespace lld;
using namespace lld::coff;
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::support;
using namespace llvm::support::endian;

using llvm::object::coff_section;

static ExitOnError ExitOnErr;

// Returns a list of all SectionChunks.
static std::vector<coff_section> getInputSections(SymbolTable *Symtab) {
  std::vector<coff_section> V;
  for (Chunk *C : Symtab->getChunks())
    if (auto *SC = dyn_cast<SectionChunk>(C))
      V.push_back(*SC->Header);
  return V;
}

static SectionChunk *findByName(std::vector<SectionChunk *> &Sections,
                                StringRef Name) {
  for (SectionChunk *C : Sections)
    if (C->getSectionName() == Name)
      return C;
  return nullptr;
}

static ArrayRef<uint8_t> getDebugSection(ObjectFile *File, StringRef SecName) {
  SectionChunk *Sec = findByName(File->getDebugChunks(), SecName);
  if (!Sec)
    return {};

  // First 4 bytes are section magic.
  ArrayRef<uint8_t> Data = Sec->getContents();
  if (Data.size() < 4)
    fatal(SecName + " too short");
  if (read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC)
    fatal(SecName + " has an invalid magic");
  return Data.slice(4);
}

// Merge .debug$T sections and returns it.
static std::vector<uint8_t> mergeDebugT(SymbolTable *Symtab) {
  ScopedPrinter W(outs());

  // Visit all .debug$T sections to add them to Builder.
  codeview::TypeTableBuilder Builder(BAlloc);
  for (ObjectFile *File : Symtab->ObjectFiles) {
    ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
    if (Data.empty())
      continue;

    msf::ByteStream Stream(Data);
    codeview::CVTypeArray Types;
    msf::StreamReader Reader(Stream);
    if (auto EC = Reader.readArray(Types, Reader.getLength()))
      fatal(EC, "Reader::readArray failed");
    if (auto Err = codeview::mergeTypeStreams(Builder, Types))
      fatal(Err, "codeview::mergeTypeStreams failed");
  }

  // Construct section contents.
  std::vector<uint8_t> V;
  Builder.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Rec) {
    V.insert(V.end(), Rec.begin(), Rec.end());
  });
  return V;
}

static void dumpDebugT(ScopedPrinter &W, ObjectFile *File) {
  ListScope LS(W, "DebugT");
  ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
  if (Data.empty())
    return;

  TypeDatabase TDB;
  TypeDumpVisitor TDV(TDB, &W, false);
  CVTypeDumper TypeDumper(TDB);
  if (auto EC = TypeDumper.dump(Data, TDV))
    fatal(EC, "CVTypeDumper::dump failed");
}

static void dumpDebugS(ScopedPrinter &W, ObjectFile *File) {
  ListScope LS(W, "DebugS");
  ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$S");
  if (Data.empty())
    return;

  msf::ByteStream Stream(Data);
  CVSymbolArray Symbols;
  msf::StreamReader Reader(Stream);
  if (auto EC = Reader.readArray(Symbols, Reader.getLength()))
    fatal(EC, "StreamReader.readArray<CVSymbolArray> failed");

  TypeDatabase TDB;
  CVSymbolDumper SymbolDumper(W, TDB, nullptr, false);
  if (auto EC = SymbolDumper.dump(Symbols))
    fatal(EC, "CVSymbolDumper::dump failed");
}

// Dump CodeView debug info. This is for debugging.
static void dumpCodeView(SymbolTable *Symtab) {
  ScopedPrinter W(outs());

  for (ObjectFile *File : Symtab->ObjectFiles) {
    dumpDebugT(W, File);
    dumpDebugS(W, File);
  }
}

static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
                        ArrayRef<uint8_t> Data) {
  msf::ByteStream Stream(Data);
  codeview::CVTypeArray Records;
  msf::StreamReader Reader(Stream);
  if (auto EC = Reader.readArray(Records, Reader.getLength()))
    fatal(EC, "Reader.readArray failed");
  for (const codeview::CVType &Rec : Records)
    TpiBuilder.addTypeRecord(Rec);
}

// Creates a PDB file.
void coff::createPDB(StringRef Path, SymbolTable *Symtab,
                     ArrayRef<uint8_t> SectionTable,
                     const llvm::codeview::DebugInfo *DI) {
  if (Config->DumpPdb)
    dumpCodeView(Symtab);

  BumpPtrAllocator Alloc;
  pdb::PDBFileBuilder Builder(Alloc);
  ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize

  // Create streams in MSF for predefined streams, namely
  // PDB, TPI, DBI and IPI.
  for (int I = 0; I < (int)pdb::kSpecialStreamCount; ++I)
    ExitOnErr(Builder.getMsfBuilder().addStream(0));

  // Add an Info stream.
  auto &InfoBuilder = Builder.getInfoBuilder();
  InfoBuilder.setAge(DI ? DI->PDB70.Age : 0);

  pdb::PDB_UniqueId uuid{};
  if (DI)
    memcpy(&uuid, &DI->PDB70.Signature, sizeof(uuid));
  InfoBuilder.setGuid(uuid);
  // Should be the current time, but set 0 for reproducibilty.
  InfoBuilder.setSignature(0);
  InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);

  // Add an empty DPI stream.
  auto &DbiBuilder = Builder.getDbiBuilder();
  DbiBuilder.setVersionHeader(pdb::PdbDbiV110);

  // Add an empty TPI stream.
  auto &TpiBuilder = Builder.getTpiBuilder();
  TpiBuilder.setVersionHeader(pdb::PdbTpiV80);
  std::vector<uint8_t> TpiData;
  if (Config->DebugPdb) {
    TpiData = mergeDebugT(Symtab);
    addTypeInfo(TpiBuilder, TpiData);
  }

  // Add an empty IPI stream.
  auto &IpiBuilder = Builder.getIpiBuilder();
  IpiBuilder.setVersionHeader(pdb::PdbTpiV80);

  // Add Section Contributions.
  std::vector<pdb::SectionContrib> Contribs =
      pdb::DbiStreamBuilder::createSectionContribs(getInputSections(Symtab));
  DbiBuilder.setSectionContribs(Contribs);

  // Add Section Map stream.
  ArrayRef<object::coff_section> Sections = {
      (const object::coff_section *)SectionTable.data(),
      SectionTable.size() / sizeof(object::coff_section)};
  std::vector<pdb::SecMapEntry> SectionMap =
      pdb::DbiStreamBuilder::createSectionMap(Sections);
  DbiBuilder.setSectionMap(SectionMap);

  ExitOnErr(DbiBuilder.addModuleInfo("", "* Linker *"));

  // Add COFF section header stream.
  ExitOnErr(
      DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable));

  // Write to a file.
  ExitOnErr(Builder.commit(Path));
}
<commit_msg>[pdb] Add the ability to resolve TypeServer PDBs.<commit_after>//===- PDB.cpp ------------------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "PDB.h"
#include "Chunks.h"
#include "Config.h"
#include "Error.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/MSF/ByteStream.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
#include "llvm/DebugInfo/PDB/Native/StringTableBuilder.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
#include <memory>

using namespace lld;
using namespace lld::coff;
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::support;
using namespace llvm::support::endian;

using llvm::object::coff_section;

static ExitOnError ExitOnErr;

// Returns a list of all SectionChunks.
static std::vector<coff_section> getInputSections(SymbolTable *Symtab) {
  std::vector<coff_section> V;
  for (Chunk *C : Symtab->getChunks())
    if (auto *SC = dyn_cast<SectionChunk>(C))
      V.push_back(*SC->Header);
  return V;
}

static SectionChunk *findByName(std::vector<SectionChunk *> &Sections,
                                StringRef Name) {
  for (SectionChunk *C : Sections)
    if (C->getSectionName() == Name)
      return C;
  return nullptr;
}

static ArrayRef<uint8_t> getDebugSection(ObjectFile *File, StringRef SecName) {
  SectionChunk *Sec = findByName(File->getDebugChunks(), SecName);
  if (!Sec)
    return {};

  // First 4 bytes are section magic.
  ArrayRef<uint8_t> Data = Sec->getContents();
  if (Data.size() < 4)
    fatal(SecName + " too short");
  if (read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC)
    fatal(SecName + " has an invalid magic");
  return Data.slice(4);
}

// Merge .debug$T sections and returns it.
static std::vector<uint8_t> mergeDebugT(SymbolTable *Symtab) {
  ScopedPrinter W(outs());

  // Visit all .debug$T sections to add them to Builder.
  codeview::TypeTableBuilder Builder(BAlloc);
  for (ObjectFile *File : Symtab->ObjectFiles) {
    ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
    if (Data.empty())
      continue;

    msf::ByteStream Stream(Data);
    codeview::CVTypeArray Types;
    msf::StreamReader Reader(Stream);
    // Follow type servers.  If the same type server is encountered more than
    // once for this instance of `PDBTypeServerHandler` (for example if many
    // object files reference the same TypeServer), the types from the
    // TypeServer will only be visited once.
    pdb::PDBTypeServerHandler Handler;
    Handler.addSearchPath(llvm::sys::path::parent_path(File->getName()));
    if (auto EC = Reader.readArray(Types, Reader.getLength()))
      fatal(EC, "Reader::readArray failed");
    if (auto Err = codeview::mergeTypeStreams(Builder, &Handler, Types))
      fatal(Err, "codeview::mergeTypeStreams failed");
  }

  // Construct section contents.
  std::vector<uint8_t> V;
  Builder.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Rec) {
    V.insert(V.end(), Rec.begin(), Rec.end());
  });
  return V;
}

static void dumpDebugT(ScopedPrinter &W, ObjectFile *File) {
  ListScope LS(W, "DebugT");
  ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
  if (Data.empty())
    return;

  TypeDatabase TDB;
  TypeDumpVisitor TDV(TDB, &W, false);
  // Use a default implementation that does not follow type servers and instead
  // just dumps the contents of the TypeServer2 record.
  CVTypeDumper TypeDumper(TDB);
  if (auto EC = TypeDumper.dump(Data, TDV))
    fatal(EC, "CVTypeDumper::dump failed");
}

static void dumpDebugS(ScopedPrinter &W, ObjectFile *File) {
  ListScope LS(W, "DebugS");
  ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$S");
  if (Data.empty())
    return;

  msf::ByteStream Stream(Data);
  CVSymbolArray Symbols;
  msf::StreamReader Reader(Stream);
  if (auto EC = Reader.readArray(Symbols, Reader.getLength()))
    fatal(EC, "StreamReader.readArray<CVSymbolArray> failed");

  TypeDatabase TDB;
  CVSymbolDumper SymbolDumper(W, TDB, nullptr, false);
  if (auto EC = SymbolDumper.dump(Symbols))
    fatal(EC, "CVSymbolDumper::dump failed");
}

// Dump CodeView debug info. This is for debugging.
static void dumpCodeView(SymbolTable *Symtab) {
  ScopedPrinter W(outs());

  for (ObjectFile *File : Symtab->ObjectFiles) {
    dumpDebugT(W, File);
    dumpDebugS(W, File);
  }
}

static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
                        ArrayRef<uint8_t> Data) {
  msf::ByteStream Stream(Data);
  codeview::CVTypeArray Records;
  msf::StreamReader Reader(Stream);
  if (auto EC = Reader.readArray(Records, Reader.getLength()))
    fatal(EC, "Reader.readArray failed");
  for (const codeview::CVType &Rec : Records)
    TpiBuilder.addTypeRecord(Rec);
}

// Creates a PDB file.
void coff::createPDB(StringRef Path, SymbolTable *Symtab,
                     ArrayRef<uint8_t> SectionTable,
                     const llvm::codeview::DebugInfo *DI) {
  if (Config->DumpPdb)
    dumpCodeView(Symtab);

  BumpPtrAllocator Alloc;
  pdb::PDBFileBuilder Builder(Alloc);
  ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize

  // Create streams in MSF for predefined streams, namely
  // PDB, TPI, DBI and IPI.
  for (int I = 0; I < (int)pdb::kSpecialStreamCount; ++I)
    ExitOnErr(Builder.getMsfBuilder().addStream(0));

  // Add an Info stream.
  auto &InfoBuilder = Builder.getInfoBuilder();
  InfoBuilder.setAge(DI ? DI->PDB70.Age : 0);

  pdb::PDB_UniqueId uuid{};
  if (DI)
    memcpy(&uuid, &DI->PDB70.Signature, sizeof(uuid));
  InfoBuilder.setGuid(uuid);
  // Should be the current time, but set 0 for reproducibilty.
  InfoBuilder.setSignature(0);
  InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);

  // Add an empty DPI stream.
  auto &DbiBuilder = Builder.getDbiBuilder();
  DbiBuilder.setVersionHeader(pdb::PdbDbiV110);

  // Add an empty TPI stream.
  auto &TpiBuilder = Builder.getTpiBuilder();
  TpiBuilder.setVersionHeader(pdb::PdbTpiV80);
  std::vector<uint8_t> TpiData;
  if (Config->DebugPdb) {
    TpiData = mergeDebugT(Symtab);
    addTypeInfo(TpiBuilder, TpiData);
  }

  // Add an empty IPI stream.
  auto &IpiBuilder = Builder.getIpiBuilder();
  IpiBuilder.setVersionHeader(pdb::PdbTpiV80);

  // Add Section Contributions.
  std::vector<pdb::SectionContrib> Contribs =
      pdb::DbiStreamBuilder::createSectionContribs(getInputSections(Symtab));
  DbiBuilder.setSectionContribs(Contribs);

  // Add Section Map stream.
  ArrayRef<object::coff_section> Sections = {
      (const object::coff_section *)SectionTable.data(),
      SectionTable.size() / sizeof(object::coff_section)};
  std::vector<pdb::SecMapEntry> SectionMap =
      pdb::DbiStreamBuilder::createSectionMap(Sections);
  DbiBuilder.setSectionMap(SectionMap);

  ExitOnErr(DbiBuilder.addModuleInfo("", "* Linker *"));

  // Add COFF section header stream.
  ExitOnErr(
      DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable));

  // Write to a file.
  ExitOnErr(Builder.commit(Path));
}
<|endoftext|>