<commit_before>/*
 * loader.cpp
 *
 * Copyright (c) 2001, 2002, 2003 Frerich Raabe <raabe@kde.org>
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. For licensing and distribution details, check the
 * accompanying file 'COPYING'.
 */
#include "loader.h"
#include "document.h"

#include <kio/job.h>
#include <kprocess.h>
#include <kurl.h>
#include <kdebug.h>

#include <qdom.h>
#include <qbuffer.h>
#include <qregexp.h>
#include <qstringlist.h>
#include <qtimer.h>

using namespace RSS;

DataRetriever::DataRetriever()
{
}

DataRetriever::~DataRetriever()
{
}

struct FileRetriever::Private
{
   Private()
      : buffer(NULL),
        lastError(0), job(NULL)
   {
   }

   ~Private()
   {
      delete buffer;
   }

   QBuffer *buffer;
   int lastError;
   KIO::Job *job;
};

FileRetriever::FileRetriever()
   : d(new Private)
{
}

FileRetriever::~FileRetriever()
{
   delete d;
}

bool FileRetriever::m_useCache = true;

void FileRetriever::setUseCache(bool enabled)
{
    m_useCache = enabled;
}

void FileRetriever::retrieveData(const KURL &url)
{
   if (d->buffer)
      return;

   d->buffer = new QBuffer;
   d->buffer->open(IO_WriteOnly);

   KURL u=url;

   if (u.protocol()=="feed")
       u.setProtocol("http");

   d->job = KIO::get(u, !m_useCache, false);

   QTimer::singleShot(1000*90, this, SLOT(slotTimeout()));

   connect(d->job, SIGNAL(data(KIO::Job *, const QByteArray &)),
                SLOT(slotData(KIO::Job *, const QByteArray &)));
   connect(d->job, SIGNAL(result(KIO::Job *)), SLOT(slotResult(KIO::Job *)));
   connect(d->job, SIGNAL(permanentRedirection(KIO::Job *, const KURL &, const KURL &)),
                SLOT(slotPermanentRedirection(KIO::Job *, const KURL &, const KURL &)));
}

void FileRetriever::slotTimeout()
{
    abort();

    delete d->buffer;
    d->buffer = NULL;

    d->lastError = KIO::ERR_SERVER_TIMEOUT;

    emit dataRetrieved(QByteArray(), false);
}

int FileRetriever::errorCode() const
{
   return d->lastError;
}

void FileRetriever::slotData(KIO::Job *, const QByteArray &data)
{
   d->buffer->writeBlock(data.data(), data.size());
}

void FileRetriever::slotResult(KIO::Job *job)
{
   QByteArray data = d->buffer->buffer();
   data.detach();

   delete d->buffer;
   d->buffer = NULL;

   d->lastError = job->error();
   emit dataRetrieved(data, d->lastError == 0);
}

void FileRetriever::slotPermanentRedirection(KIO::Job *, const KURL &, const KURL &newUrl)
{
   emit permanentRedirection(newUrl);
}

void FileRetriever::abort()
{
	if (d->job)
	{
		d->job->kill(true);
		d->job = NULL;
	}
}

struct OutputRetriever::Private
{
   Private() : process(NULL),
      buffer(NULL),
      lastError(0)
   {
   }

   ~Private()
   {
      delete process;
      delete buffer;
   }

   KShellProcess *process;
   QBuffer *buffer;
   int lastError;
};

OutputRetriever::OutputRetriever() :
   d(new Private)
{
}

OutputRetriever::~OutputRetriever()
{
   delete d;
}

void OutputRetriever::retrieveData(const KURL &url)
{
   // Ignore subsequent calls if we didn't finish the previous job yet.
   if (d->buffer || d->process)
      return;

   d->buffer = new QBuffer;
   d->buffer->open(IO_WriteOnly);

   d->process = new KShellProcess();
   connect(d->process, SIGNAL(processExited(KProcess *)),
                       SLOT(slotExited(KProcess *)));
   connect(d->process, SIGNAL(receivedStdout(KProcess *, char *, int)),
                       SLOT(slotOutput(KProcess *, char *, int)));
   *d->process << url.path();
   d->process->start(KProcess::NotifyOnExit, KProcess::Stdout);
}

int OutputRetriever::errorCode() const
{
   return d->lastError;
}

void OutputRetriever::slotOutput(KProcess *, char *data, int length)
{
   d->buffer->writeBlock(data, length);
}

void OutputRetriever::slotExited(KProcess *p)
{
   if (!p->normalExit())
      d->lastError = p->exitStatus();

   QByteArray data = d->buffer->buffer();
   data.detach();

   delete d->buffer;
   d->buffer = NULL;

   delete d->process;
   d->process = NULL;

   emit dataRetrieved(data, p->normalExit() && p->exitStatus() == 0);
}

struct Loader::Private
{
   Private() : retriever(NULL),
      lastError(0)
   {
   }

   ~Private()
   {
      delete retriever;
   }

   DataRetriever *retriever;
   int lastError;
   KURL discoveredFeedURL;
   KURL url;
};

Loader *Loader::create()
{
   return new Loader;
}

Loader *Loader::create(QObject *object, const char *slot)
{
   Loader *loader = create();
   connect(loader, SIGNAL(loadingComplete(Loader *, Document, Status)),
           object, slot);
   return loader;
}

Loader::Loader() : d(new Private)
{
}

Loader::~Loader()
{
    delete d;
}

void Loader::loadFrom(const KURL &url, DataRetriever *retriever)
{
   if (d->retriever != NULL)
      return;

   d->url=url;
   d->retriever = retriever;

   connect(d->retriever, SIGNAL(dataRetrieved(const QByteArray &, bool)),
           this, SLOT(slotRetrieverDone(const QByteArray &, bool)));

   d->retriever->retrieveData(url);
}

int Loader::errorCode() const
{
   return d->lastError;
}

void Loader::abort()
{
	if (d && d->retriever)
	{
		d->retriever->abort();
        delete d->retriever;
		d->retriever=NULL;
	}
    emit loadingComplete(this, QDomDocument(), Aborted);
    delete this;
}

const KURL &Loader::discoveredFeedURL() const
{
   return d->discoveredFeedURL;
}

#include <kdebug.h>

void Loader::slotRetrieverDone(const QByteArray &data, bool success)
{
   d->lastError = d->retriever->errorCode();

   delete d->retriever;
   d->retriever = NULL;

   Document rssDoc;
   Status status = Success;

   if (success) {
      QDomDocument doc;

      /* Some servers insert whitespace before the <?xml...?> declaration.
       * QDom doesn't tolerate that (and it's right, that's invalid XML),
       * so we strip that.
       */

      const char *charData = data.data();
      int len = data.count();

      while (len && QChar(*charData).isSpace()) {
         --len;
         ++charData;
      }

      if ( len > 3 && QChar(*charData) == QChar(0357) ) { // 0357 0273 0277
			  len -= 3;
			  charData += 3;
	  }
      QByteArray tmpData;
      tmpData.setRawData(charData, len);

      if (doc.setContent(tmpData))
      {
         rssDoc = Document(doc);
         if (!rssDoc.isValid())
         {
            discoverFeeds(tmpData);
            status = ParseError;
         }
      }
      else
      {
         discoverFeeds(tmpData);
         status = ParseError;
      }

      tmpData.resetRawData(charData, len);
   } else
      status = RetrieveError;

   emit loadingComplete(this, rssDoc, status);

   delete this;
}

void Loader::discoverFeeds(const QByteArray &data)
{
    QString str = QString(data).simplifyWhiteSpace();
    QString s2;
    //QTextStream ts( &str, IO_WriteOnly );
    //ts << data.data();

    // "<[\\s]link[^>]*rel[\\s]=[\\s]\\\"[\\s]alternate[\\s]\\\"[^>]*>"
    // "type[\\s]=[\\s]\\\"application/rss+xml\\\""
    // "href[\\s]=[\\s]\\\"application/rss+xml\\\""
    QRegExp rx( "(?:REL)[^=]*=[^sAa]*(?:service.feed|ALTERNATE)[\\s]*[^s][^s](?:[^>]*)(?:HREF)[^=]*=[^A-Z0-9-_~,./$]*([^'\">\\s]*)", false);
    if (rx.search(str)!=-1)
        s2=rx.cap(1);
    else{
    // does not support Atom/RSS autodiscovery.. try finding feeds by brute force....
        int pos=0;
        QStringList feeds;
        QString host=d->url.host();
        rx.setPattern("(?:<A )[^H]*(?:HREF)[^=]*=[^A-Z0-9-_~,./]*([^'\">\\s]*)");
        while ( pos >= 0 ) {
            pos = rx.search( str, pos );
            s2=rx.cap(1);
            if (s2.endsWith(".rdf")|s2.endsWith(".rss")|s2.endsWith(".xml"))
                    feeds.append(s2);
            if ( pos >= 0 ) {
                pos += rx.matchedLength();
            }
        }

        s2=feeds.first();
        KURL testURL;
        // loop through, prefer feeds on same host
        for ( QStringList::Iterator it = feeds.begin(); it != feeds.end(); ++it ) {
            testURL=*it;
            if (testURL.host()==host)
            {
                s2=*it;
                break;
            }
        }
    }

    if (s2.isNull()) {
        kdDebug() << "No feed found for a site" << endl;
        return;
    }

    if (KURL::isRelativeURL(s2))
    {
        if (s2.startsWith("//"))
        {
            s2=s2.prepend(d->url.protocol()+":");
            d->discoveredFeedURL=s2;
        }
        else if (s2.startsWith("/"))
        {
            d->discoveredFeedURL=d->url;
            d->discoveredFeedURL.setPath(s2);
        }
        else
        {
            d->discoveredFeedURL=d->url;
            d->discoveredFeedURL.addPath(s2);
        }
        d->discoveredFeedURL.cleanPath();
    }
    else
        d->discoveredFeedURL=s2;

    d->discoveredFeedURL.cleanPath();
}

#include "loader.moc"
// vim:noet:ts=4
<commit_msg>comment out useless debug message<commit_after>/*
 * loader.cpp
 *
 * Copyright (c) 2001, 2002, 2003 Frerich Raabe <raabe@kde.org>
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. For licensing and distribution details, check the
 * accompanying file 'COPYING'.
 */
#include "loader.h"
#include "document.h"

#include <kio/job.h>
#include <kprocess.h>
#include <kurl.h>
#include <kdebug.h>

#include <qdom.h>
#include <qbuffer.h>
#include <qregexp.h>
#include <qstringlist.h>
#include <qtimer.h>

using namespace RSS;

DataRetriever::DataRetriever()
{
}

DataRetriever::~DataRetriever()
{
}

struct FileRetriever::Private
{
   Private()
      : buffer(NULL),
        lastError(0), job(NULL)
   {
   }

   ~Private()
   {
      delete buffer;
   }

   QBuffer *buffer;
   int lastError;
   KIO::Job *job;
};

FileRetriever::FileRetriever()
   : d(new Private)
{
}

FileRetriever::~FileRetriever()
{
   delete d;
}

bool FileRetriever::m_useCache = true;

void FileRetriever::setUseCache(bool enabled)
{
    m_useCache = enabled;
}

void FileRetriever::retrieveData(const KURL &url)
{
   if (d->buffer)
      return;

   d->buffer = new QBuffer;
   d->buffer->open(IO_WriteOnly);

   KURL u=url;

   if (u.protocol()=="feed")
       u.setProtocol("http");

   d->job = KIO::get(u, !m_useCache, false);

   QTimer::singleShot(1000*90, this, SLOT(slotTimeout()));

   connect(d->job, SIGNAL(data(KIO::Job *, const QByteArray &)),
                SLOT(slotData(KIO::Job *, const QByteArray &)));
   connect(d->job, SIGNAL(result(KIO::Job *)), SLOT(slotResult(KIO::Job *)));
   connect(d->job, SIGNAL(permanentRedirection(KIO::Job *, const KURL &, const KURL &)),
                SLOT(slotPermanentRedirection(KIO::Job *, const KURL &, const KURL &)));
}

void FileRetriever::slotTimeout()
{
    abort();

    delete d->buffer;
    d->buffer = NULL;

    d->lastError = KIO::ERR_SERVER_TIMEOUT;

    emit dataRetrieved(QByteArray(), false);
}

int FileRetriever::errorCode() const
{
   return d->lastError;
}

void FileRetriever::slotData(KIO::Job *, const QByteArray &data)
{
   d->buffer->writeBlock(data.data(), data.size());
}

void FileRetriever::slotResult(KIO::Job *job)
{
   QByteArray data = d->buffer->buffer();
   data.detach();

   delete d->buffer;
   d->buffer = NULL;

   d->lastError = job->error();
   emit dataRetrieved(data, d->lastError == 0);
}

void FileRetriever::slotPermanentRedirection(KIO::Job *, const KURL &, const KURL &newUrl)
{
   emit permanentRedirection(newUrl);
}

void FileRetriever::abort()
{
	if (d->job)
	{
		d->job->kill(true);
		d->job = NULL;
	}
}

struct OutputRetriever::Private
{
   Private() : process(NULL),
      buffer(NULL),
      lastError(0)
   {
   }

   ~Private()
   {
      delete process;
      delete buffer;
   }

   KShellProcess *process;
   QBuffer *buffer;
   int lastError;
};

OutputRetriever::OutputRetriever() :
   d(new Private)
{
}

OutputRetriever::~OutputRetriever()
{
   delete d;
}

void OutputRetriever::retrieveData(const KURL &url)
{
   // Ignore subsequent calls if we didn't finish the previous job yet.
   if (d->buffer || d->process)
      return;

   d->buffer = new QBuffer;
   d->buffer->open(IO_WriteOnly);

   d->process = new KShellProcess();
   connect(d->process, SIGNAL(processExited(KProcess *)),
                       SLOT(slotExited(KProcess *)));
   connect(d->process, SIGNAL(receivedStdout(KProcess *, char *, int)),
                       SLOT(slotOutput(KProcess *, char *, int)));
   *d->process << url.path();
   d->process->start(KProcess::NotifyOnExit, KProcess::Stdout);
}

int OutputRetriever::errorCode() const
{
   return d->lastError;
}

void OutputRetriever::slotOutput(KProcess *, char *data, int length)
{
   d->buffer->writeBlock(data, length);
}

void OutputRetriever::slotExited(KProcess *p)
{
   if (!p->normalExit())
      d->lastError = p->exitStatus();

   QByteArray data = d->buffer->buffer();
   data.detach();

   delete d->buffer;
   d->buffer = NULL;

   delete d->process;
   d->process = NULL;

   emit dataRetrieved(data, p->normalExit() && p->exitStatus() == 0);
}

struct Loader::Private
{
   Private() : retriever(NULL),
      lastError(0)
   {
   }

   ~Private()
   {
      delete retriever;
   }

   DataRetriever *retriever;
   int lastError;
   KURL discoveredFeedURL;
   KURL url;
};

Loader *Loader::create()
{
   return new Loader;
}

Loader *Loader::create(QObject *object, const char *slot)
{
   Loader *loader = create();
   connect(loader, SIGNAL(loadingComplete(Loader *, Document, Status)),
           object, slot);
   return loader;
}

Loader::Loader() : d(new Private)
{
}

Loader::~Loader()
{
    delete d;
}

void Loader::loadFrom(const KURL &url, DataRetriever *retriever)
{
   if (d->retriever != NULL)
      return;

   d->url=url;
   d->retriever = retriever;

   connect(d->retriever, SIGNAL(dataRetrieved(const QByteArray &, bool)),
           this, SLOT(slotRetrieverDone(const QByteArray &, bool)));

   d->retriever->retrieveData(url);
}

int Loader::errorCode() const
{
   return d->lastError;
}

void Loader::abort()
{
	if (d && d->retriever)
	{
		d->retriever->abort();
        delete d->retriever;
		d->retriever=NULL;
	}
    emit loadingComplete(this, QDomDocument(), Aborted);
    delete this;
}

const KURL &Loader::discoveredFeedURL() const
{
   return d->discoveredFeedURL;
}

#include <kdebug.h>

void Loader::slotRetrieverDone(const QByteArray &data, bool success)
{
   d->lastError = d->retriever->errorCode();

   delete d->retriever;
   d->retriever = NULL;

   Document rssDoc;
   Status status = Success;

   if (success) {
      QDomDocument doc;

      /* Some servers insert whitespace before the <?xml...?> declaration.
       * QDom doesn't tolerate that (and it's right, that's invalid XML),
       * so we strip that.
       */

      const char *charData = data.data();
      int len = data.count();

      while (len && QChar(*charData).isSpace()) {
         --len;
         ++charData;
      }

      if ( len > 3 && QChar(*charData) == QChar(0357) ) { // 0357 0273 0277
			  len -= 3;
			  charData += 3;
	  }
      QByteArray tmpData;
      tmpData.setRawData(charData, len);

      if (doc.setContent(tmpData))
      {
         rssDoc = Document(doc);
         if (!rssDoc.isValid())
         {
            discoverFeeds(tmpData);
            status = ParseError;
         }
      }
      else
      {
         discoverFeeds(tmpData);
         status = ParseError;
      }

      tmpData.resetRawData(charData, len);
   } else
      status = RetrieveError;

   emit loadingComplete(this, rssDoc, status);

   delete this;
}

void Loader::discoverFeeds(const QByteArray &data)
{
    QString str = QString(data).simplifyWhiteSpace();
    QString s2;
    //QTextStream ts( &str, IO_WriteOnly );
    //ts << data.data();

    // "<[\\s]link[^>]*rel[\\s]=[\\s]\\\"[\\s]alternate[\\s]\\\"[^>]*>"
    // "type[\\s]=[\\s]\\\"application/rss+xml\\\""
    // "href[\\s]=[\\s]\\\"application/rss+xml\\\""
    QRegExp rx( "(?:REL)[^=]*=[^sAa]*(?:service.feed|ALTERNATE)[\\s]*[^s][^s](?:[^>]*)(?:HREF)[^=]*=[^A-Z0-9-_~,./$]*([^'\">\\s]*)", false);
    if (rx.search(str)!=-1)
        s2=rx.cap(1);
    else{
    // does not support Atom/RSS autodiscovery.. try finding feeds by brute force....
        int pos=0;
        QStringList feeds;
        QString host=d->url.host();
        rx.setPattern("(?:<A )[^H]*(?:HREF)[^=]*=[^A-Z0-9-_~,./]*([^'\">\\s]*)");
        while ( pos >= 0 ) {
            pos = rx.search( str, pos );
            s2=rx.cap(1);
            if (s2.endsWith(".rdf")|s2.endsWith(".rss")|s2.endsWith(".xml"))
                    feeds.append(s2);
            if ( pos >= 0 ) {
                pos += rx.matchedLength();
            }
        }

        s2=feeds.first();
        KURL testURL;
        // loop through, prefer feeds on same host
        for ( QStringList::Iterator it = feeds.begin(); it != feeds.end(); ++it ) {
            testURL=*it;
            if (testURL.host()==host)
            {
                s2=*it;
                break;
            }
        }
    }

    if (s2.isNull()) {
        //kdDebug() << "No feed found for a site" << endl;
        return;
    }

    if (KURL::isRelativeURL(s2))
    {
        if (s2.startsWith("//"))
        {
            s2=s2.prepend(d->url.protocol()+":");
            d->discoveredFeedURL=s2;
        }
        else if (s2.startsWith("/"))
        {
            d->discoveredFeedURL=d->url;
            d->discoveredFeedURL.setPath(s2);
        }
        else
        {
            d->discoveredFeedURL=d->url;
            d->discoveredFeedURL.addPath(s2);
        }
        d->discoveredFeedURL.cleanPath();
    }
    else
        d->discoveredFeedURL=s2;

    d->discoveredFeedURL.cleanPath();
}

#include "loader.moc"
// vim:noet:ts=4
<|endoftext|>


<commit_before>/* Copyright (c) 2008, Avian Contributors

   Permission to use, copy, modify, and/or distribute this software
   for any purpose with or without fee is hereby granted, provided
   that the above copyright notice and this permission notice appear
   in all copies.

   There is NO WARRANTY for this software.  See license.txt for
   details. */

#include "bootimage.h"
#include "heapwalk.h"
#include "common.h"
#include "machine.h"
#include "util.h"
#include "assembler.h"

// since we aren't linking against libstdc++, we must implement this
// ourselves:
extern "C" void __cxa_pure_virtual(void) { abort(); }

using namespace vm;

namespace {

bool
endsWith(const char* suffix, const char* s, unsigned length)
{
  unsigned suffixLength = strlen(suffix);
  return length >= suffixLength
    and memcmp(suffix, s + (length - suffixLength), suffixLength) == 0;
}

object
makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
              unsigned capacity, uintptr_t* codeMap)
{
  unsigned size = 0;
  t->m->processor->compileThunks(t, image, code, &size, capacity);

  object constants = 0;
  PROTECT(t, constants);

  object calls = 0;
  PROTECT(t, calls);

  DelayedPromise* addresses = 0;

  for (Finder::Iterator it(t->m->finder); it.hasMore();) {
    unsigned nameSize = 0;
    const char* name = it.next(&nameSize);

    if (endsWith(".class", name, nameSize)) {
      //fprintf(stderr, "%.*s\n", nameSize - 6, name);
      object c = resolveClass
        (t, makeByteArray(t, "%.*s", nameSize - 6, name));
      PROTECT(t, c);

      if (classMethodTable(t, c)) {
        for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
          object method = arrayBody(t, classMethodTable(t, c), i);
          if (methodCode(t, method) or (methodFlags(t, method) & ACC_NATIVE)) {
            t->m->processor->compileMethod
              (t, zone, code, &size, capacity, &constants, &calls, &addresses,
               method);
          }
        }
      }
    }
  }

  for (; calls; calls = tripleThird(t, calls)) {
    object method = tripleFirst(t, calls);
    uintptr_t address;
    if (methodFlags(t, method) & ACC_NATIVE) {
      address = reinterpret_cast<uintptr_t>(code + image->nativeThunk);
    } else {
      address = methodCompiled(t, method);
    }

    static_cast<ListenPromise*>(pointerValue(t, tripleSecond(t, calls)))
      ->listener->resolve(address);
  }

  for (; addresses; addresses = addresses->next) {
    uint8_t* value = reinterpret_cast<uint8_t*>(addresses->basis->value());
    assert(t, value >= code);

    void* dst = addresses->listener->resolve
      ((value - code) | (1 << BootShift));
    assert(t, reinterpret_cast<intptr_t>(dst)
           >= reinterpret_cast<intptr_t>(code));

    markBit(codeMap, reinterpret_cast<intptr_t>(dst)
            - reinterpret_cast<intptr_t>(code));
  }

  image->codeSize = size;

  return constants;
}

unsigned
objectSize(Thread* t, object o)
{
  assert(t, not objectExtended(t, o));

  return baseSize(t, o, objectClass(t, o));
}

void
visitRoots(Thread* t, BootImage* image, HeapWalker* w, object constants)
{
  Machine* m = t->m;

  for (HashMapIterator it(t, m->classMap); it.hasMore();) {
    w->visitRoot(tripleSecond(t, it.next()));
  }

  image->loader = w->visitRoot(m->loader);
  image->types = w->visitRoot(m->types);

  m->processor->visitRoots(image, w);

  for (; constants; constants = tripleThird(t, constants)) {
    w->visitRoot(tripleFirst(t, constants));
  }
}

HeapWalker*
makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
              unsigned capacity, object constants)
{
  class Visitor: public HeapVisitor {
   public:
    Visitor(Thread* t, uintptr_t* heap, uintptr_t* map, unsigned capacity):
      t(t), currentObject(0), currentNumber(0), currentOffset(0), heap(heap),
      map(map), position(0), capacity(capacity)
    { }

    void visit(unsigned number) {
      if (currentObject) {
        unsigned offset = currentNumber - 1 + currentOffset;
        unsigned mark = heap[offset] & (~PointerMask);
        unsigned value = number | (mark << BootShift);

        if (value) markBit(map, offset);

        heap[offset] = value;
      }
    }

    virtual void root() {
      currentObject = 0;
    }

    virtual unsigned visitNew(object p) {
      if (p) {
        unsigned size = objectSize(t, p);

        unsigned number;
        if (currentObject
            and (currentOffset * BytesPerWord) == ClassStaticTable)
        {
          FixedAllocator allocator
            (t, reinterpret_cast<uint8_t*>(heap + position),
             (capacity - position) * BytesPerWord);

          unsigned totalInBytes;
          uintptr_t* dst = static_cast<uintptr_t*>
            (t->m->heap->allocateImmortalFixed
             (&allocator, size, true, &totalInBytes));

          memcpy(dst, p, size * BytesPerWord);

          dst[0] |= FixedMark;

          number = (dst - heap) + 1;
          position += ceiling(totalInBytes, BytesPerWord);
        } else {
          assert(t, position + size < capacity);
          memcpy(heap + position, p, size * BytesPerWord);

          number = position + 1;
          position += size;
        }

        visit(number);

        return number;
      } else {
        return 0;
      }
    }

    virtual void visitOld(object, unsigned number) {
      visit(number);
    }

    virtual void push(object object, unsigned number, unsigned offset) {
      currentObject = object;
      currentNumber = number;
      currentOffset = offset;
    }

    virtual void pop() {
      currentObject = 0;
    }

    Thread* t;
    object currentObject;
    unsigned currentNumber;
    unsigned currentOffset;
    uintptr_t* heap;
    uintptr_t* map;
    unsigned position;
    unsigned capacity;
  } visitor(t, heap, map, capacity / BytesPerWord);

  HeapWalker* w = makeHeapWalker(t, &visitor);
  visitRoots(t, image, w, constants);

  image->heapSize = visitor.position * BytesPerWord;

  return w;
}

void
updateConstants(Thread* t, object constants, uint8_t* code, uintptr_t* codeMap,
                HeapMap* heapTable)
{
  for (; constants; constants = tripleThird(t, constants)) {
    unsigned target = heapTable->find(tripleFirst(t, constants));
    assert(t, target > 0);

    for (Promise::Listener* pl = static_cast<ListenPromise*>
           (pointerValue(t, tripleSecond(t, constants)))->listener;
         pl; pl = pl->next)
    {
      void* dst = pl->resolve(target);

      assert(t, reinterpret_cast<intptr_t>(dst)
             >= reinterpret_cast<intptr_t>(code));

      markBit(codeMap, reinterpret_cast<intptr_t>(dst)
              - reinterpret_cast<intptr_t>(code));
    }
  }
}

unsigned
offset(object a, uintptr_t* b)
{
  return reinterpret_cast<uintptr_t>(b) - reinterpret_cast<uintptr_t>(a);
}

void
writeBootImage(Thread* t, FILE* out)
{
  Zone zone(t->m->system, t->m->heap, 64 * 1024);
  BootImage image;

  const unsigned CodeCapacity = 32 * 1024 * 1024;
  uint8_t* code = static_cast<uint8_t*>(t->m->heap->allocate(CodeCapacity));
  uintptr_t* codeMap = static_cast<uintptr_t*>
    (t->m->heap->allocate(codeMapSize(CodeCapacity)));
  memset(codeMap, 0, codeMapSize(CodeCapacity));

  object constants = makeCodeImage
    (t, &zone, &image, code, CodeCapacity, codeMap);
  PROTECT(t, constants);

  const unsigned HeapCapacity = 32 * 1024 * 1024;
  uintptr_t* heap = static_cast<uintptr_t*>
    (t->m->heap->allocate(HeapCapacity));
  uintptr_t* heapMap = static_cast<uintptr_t*>
    (t->m->heap->allocate(heapMapSize(HeapCapacity)));
  memset(heapMap, 0, heapMapSize(HeapCapacity));

  collect(t, Heap::MajorCollection);

  HeapWalker* heapWalker = makeHeapImage
    (t, &image, heap, heapMap, HeapCapacity, constants);

  updateConstants(t, constants, code, codeMap, heapWalker->map());

  image.classCount = hashMapSize(t, t->m->classMap);
  unsigned* classTable = static_cast<unsigned*>
    (t->m->heap->allocate(image.classCount * sizeof(unsigned)));

  { unsigned i = 0;
    for (HashMapIterator it(t, t->m->classMap); it.hasMore();) {
      classTable[i++] = heapWalker->map()->find(tripleSecond(t, it.next()));
    }
  }

  image.stringCount = hashMapSize(t, t->m->stringMap);
  unsigned* stringTable = static_cast<unsigned*>
    (t->m->heap->allocate(image.stringCount * sizeof(unsigned)));

  { unsigned i = 0;
    for (HashMapIterator it(t, t->m->stringMap); it.hasMore();) {
      stringTable[i++] = heapWalker->map()->find
        (jreferenceTarget(t, tripleFirst(t, it.next())));
    }
  }

  unsigned* callTable = t->m->processor->makeCallTable
    (t, &image, heapWalker, code);

  heapWalker->dispose();

  image.magic = BootImage::Magic;
  image.codeBase = reinterpret_cast<uintptr_t>(code);

  fprintf(stderr, "class count %d string count %d call count %d\n"
          "heap size %d code size %d\n",
          image.classCount, image.stringCount, image.callCount, image.heapSize,
          image.codeSize);

  if (true) {
    fwrite(&image, sizeof(BootImage), 1, out);

    fwrite(classTable, image.classCount * sizeof(unsigned), 1, out);
    fwrite(stringTable, image.stringCount * sizeof(unsigned), 1, out);
    fwrite(callTable, image.callCount * sizeof(unsigned) * 2, 1, out);

    unsigned offset = (image.classCount * sizeof(unsigned))
      + (image.stringCount * sizeof(unsigned))
      + (image.callCount * sizeof(unsigned) * 2);

    while (offset % BytesPerWord) {
      uint8_t c = 0;
      fwrite(&c, 1, 1, out);
      ++ offset;
    }

    fwrite(heapMap, pad(heapMapSize(image.heapSize)), 1, out);
    fwrite(heap, pad(image.heapSize), 1, out);

    fwrite(codeMap, pad(codeMapSize(image.codeSize)), 1, out);
    fwrite(code, pad(image.codeSize), 1, out);
  }
}

} // namespace

int
main(int ac, const char** av)
{
  if (ac != 2) {
    fprintf(stderr, "usage: %s <classpath>\n", av[0]);
    return -1;
  }

  System* s = makeSystem(0);
  Heap* h = makeHeap(s, 128 * 1024 * 1024);
  Finder* f = makeFinder(s, av[1], 0);
  Processor* p = makeProcessor(s, h);
  Machine* m = new (h->allocate(sizeof(Machine))) Machine(s, h, f, p, 0, 0);
  Thread* t = p->makeThread(m, 0, 0);

  enter(t, Thread::ActiveState);
  enter(t, Thread::IdleState);

  writeBootImage(t, stdout);

  return 0;
}
<commit_msg>support filtering based on class name, method name, and method spec in bootimage.cpp<commit_after>/* Copyright (c) 2008, Avian Contributors

   Permission to use, copy, modify, and/or distribute this software
   for any purpose with or without fee is hereby granted, provided
   that the above copyright notice and this permission notice appear
   in all copies.

   There is NO WARRANTY for this software.  See license.txt for
   details. */

#include "bootimage.h"
#include "heapwalk.h"
#include "common.h"
#include "machine.h"
#include "util.h"
#include "assembler.h"

// since we aren't linking against libstdc++, we must implement this
// ourselves:
extern "C" void __cxa_pure_virtual(void) { abort(); }

using namespace vm;

namespace {

bool
endsWith(const char* suffix, const char* s, unsigned length)
{
  unsigned suffixLength = strlen(suffix);
  return length >= suffixLength
    and memcmp(suffix, s + (length - suffixLength), suffixLength) == 0;
}

object
makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
              unsigned capacity, uintptr_t* codeMap, const char* className,
              const char* methodName, const char* methodSpec)
{
  unsigned size = 0;
  t->m->processor->compileThunks(t, image, code, &size, capacity);

  object constants = 0;
  PROTECT(t, constants);

  object calls = 0;
  PROTECT(t, calls);

  DelayedPromise* addresses = 0;

  for (Finder::Iterator it(t->m->finder); it.hasMore();) {
    unsigned nameSize = 0;
    const char* name = it.next(&nameSize);

    if (endsWith(".class", name, nameSize)
        and (className == 0 or strncmp(name, className, nameSize - 6) == 0))
    {
      //fprintf(stderr, "%.*s\n", nameSize - 6, name);
      object c = resolveClass
        (t, makeByteArray(t, "%.*s", nameSize - 6, name));
      PROTECT(t, c);

      if (classMethodTable(t, c)) {
        for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
          object method = arrayBody(t, classMethodTable(t, c), i);
          if ((methodCode(t, method) or (methodFlags(t, method) & ACC_NATIVE))
              and ((methodName == 0
                    or strcmp
                    (reinterpret_cast<char*>
                     (&byteArrayBody
                      (t, vm::methodName(t, method), 0)), methodName) == 0)
                   and (methodSpec == 0
                        or strcmp
                        (reinterpret_cast<char*>
                         (&byteArrayBody
                          (t, vm::methodSpec(t, method), 0)), methodSpec)
                        == 0)))
          {
            t->m->processor->compileMethod
              (t, zone, code, &size, capacity, &constants, &calls, &addresses,
               method);
          }
        }
      }
    }
  }

  for (; calls; calls = tripleThird(t, calls)) {
    object method = tripleFirst(t, calls);
    uintptr_t address;
    if (methodFlags(t, method) & ACC_NATIVE) {
      address = reinterpret_cast<uintptr_t>(code + image->nativeThunk);
    } else {
      address = methodCompiled(t, method);
    }

    static_cast<ListenPromise*>(pointerValue(t, tripleSecond(t, calls)))
      ->listener->resolve(address);
  }

  for (; addresses; addresses = addresses->next) {
    uint8_t* value = reinterpret_cast<uint8_t*>(addresses->basis->value());
    assert(t, value >= code);

    void* dst = addresses->listener->resolve
      ((value - code) | (1 << BootShift));
    assert(t, reinterpret_cast<intptr_t>(dst)
           >= reinterpret_cast<intptr_t>(code));

    markBit(codeMap, reinterpret_cast<intptr_t>(dst)
            - reinterpret_cast<intptr_t>(code));
  }

  image->codeSize = size;

  return constants;
}

unsigned
objectSize(Thread* t, object o)
{
  assert(t, not objectExtended(t, o));

  return baseSize(t, o, objectClass(t, o));
}

void
visitRoots(Thread* t, BootImage* image, HeapWalker* w, object constants)
{
  Machine* m = t->m;

  for (HashMapIterator it(t, m->classMap); it.hasMore();) {
    w->visitRoot(tripleSecond(t, it.next()));
  }

  image->loader = w->visitRoot(m->loader);
  image->types = w->visitRoot(m->types);

  m->processor->visitRoots(image, w);

  for (; constants; constants = tripleThird(t, constants)) {
    w->visitRoot(tripleFirst(t, constants));
  }
}

HeapWalker*
makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
              unsigned capacity, object constants)
{
  class Visitor: public HeapVisitor {
   public:
    Visitor(Thread* t, uintptr_t* heap, uintptr_t* map, unsigned capacity):
      t(t), currentObject(0), currentNumber(0), currentOffset(0), heap(heap),
      map(map), position(0), capacity(capacity)
    { }

    void visit(unsigned number) {
      if (currentObject) {
        unsigned offset = currentNumber - 1 + currentOffset;
        unsigned mark = heap[offset] & (~PointerMask);
        unsigned value = number | (mark << BootShift);

        if (value) markBit(map, offset);

        heap[offset] = value;
      }
    }

    virtual void root() {
      currentObject = 0;
    }

    virtual unsigned visitNew(object p) {
      if (p) {
        unsigned size = objectSize(t, p);

        unsigned number;
        if (currentObject
            and (currentOffset * BytesPerWord) == ClassStaticTable)
        {
          FixedAllocator allocator
            (t, reinterpret_cast<uint8_t*>(heap + position),
             (capacity - position) * BytesPerWord);

          unsigned totalInBytes;
          uintptr_t* dst = static_cast<uintptr_t*>
            (t->m->heap->allocateImmortalFixed
             (&allocator, size, true, &totalInBytes));

          memcpy(dst, p, size * BytesPerWord);

          dst[0] |= FixedMark;

          number = (dst - heap) + 1;
          position += ceiling(totalInBytes, BytesPerWord);
        } else {
          assert(t, position + size < capacity);
          memcpy(heap + position, p, size * BytesPerWord);

          number = position + 1;
          position += size;
        }

        visit(number);

        return number;
      } else {
        return 0;
      }
    }

    virtual void visitOld(object, unsigned number) {
      visit(number);
    }

    virtual void push(object object, unsigned number, unsigned offset) {
      currentObject = object;
      currentNumber = number;
      currentOffset = offset;
    }

    virtual void pop() {
      currentObject = 0;
    }

    Thread* t;
    object currentObject;
    unsigned currentNumber;
    unsigned currentOffset;
    uintptr_t* heap;
    uintptr_t* map;
    unsigned position;
    unsigned capacity;
  } visitor(t, heap, map, capacity / BytesPerWord);

  HeapWalker* w = makeHeapWalker(t, &visitor);
  visitRoots(t, image, w, constants);

  image->heapSize = visitor.position * BytesPerWord;

  return w;
}

void
updateConstants(Thread* t, object constants, uint8_t* code, uintptr_t* codeMap,
                HeapMap* heapTable)
{
  for (; constants; constants = tripleThird(t, constants)) {
    unsigned target = heapTable->find(tripleFirst(t, constants));
    assert(t, target > 0);

    for (Promise::Listener* pl = static_cast<ListenPromise*>
           (pointerValue(t, tripleSecond(t, constants)))->listener;
         pl; pl = pl->next)
    {
      void* dst = pl->resolve(target);

      assert(t, reinterpret_cast<intptr_t>(dst)
             >= reinterpret_cast<intptr_t>(code));

      markBit(codeMap, reinterpret_cast<intptr_t>(dst)
              - reinterpret_cast<intptr_t>(code));
    }
  }
}

unsigned
offset(object a, uintptr_t* b)
{
  return reinterpret_cast<uintptr_t>(b) - reinterpret_cast<uintptr_t>(a);
}

void
writeBootImage(Thread* t, FILE* out, const char* className,
               const char* methodName, const char* methodSpec)
{
  Zone zone(t->m->system, t->m->heap, 64 * 1024);
  BootImage image;

  const unsigned CodeCapacity = 32 * 1024 * 1024;
  uint8_t* code = static_cast<uint8_t*>(t->m->heap->allocate(CodeCapacity));
  uintptr_t* codeMap = static_cast<uintptr_t*>
    (t->m->heap->allocate(codeMapSize(CodeCapacity)));
  memset(codeMap, 0, codeMapSize(CodeCapacity));

  object constants = makeCodeImage
    (t, &zone, &image, code, CodeCapacity, codeMap, className, methodName,
     methodSpec);
  PROTECT(t, constants);

  const unsigned HeapCapacity = 32 * 1024 * 1024;
  uintptr_t* heap = static_cast<uintptr_t*>
    (t->m->heap->allocate(HeapCapacity));
  uintptr_t* heapMap = static_cast<uintptr_t*>
    (t->m->heap->allocate(heapMapSize(HeapCapacity)));
  memset(heapMap, 0, heapMapSize(HeapCapacity));

  collect(t, Heap::MajorCollection);

  HeapWalker* heapWalker = makeHeapImage
    (t, &image, heap, heapMap, HeapCapacity, constants);

  updateConstants(t, constants, code, codeMap, heapWalker->map());

  image.classCount = hashMapSize(t, t->m->classMap);
  unsigned* classTable = static_cast<unsigned*>
    (t->m->heap->allocate(image.classCount * sizeof(unsigned)));

  { unsigned i = 0;
    for (HashMapIterator it(t, t->m->classMap); it.hasMore();) {
      classTable[i++] = heapWalker->map()->find(tripleSecond(t, it.next()));
    }
  }

  image.stringCount = hashMapSize(t, t->m->stringMap);
  unsigned* stringTable = static_cast<unsigned*>
    (t->m->heap->allocate(image.stringCount * sizeof(unsigned)));

  { unsigned i = 0;
    for (HashMapIterator it(t, t->m->stringMap); it.hasMore();) {
      stringTable[i++] = heapWalker->map()->find
        (jreferenceTarget(t, tripleFirst(t, it.next())));
    }
  }

  unsigned* callTable = t->m->processor->makeCallTable
    (t, &image, heapWalker, code);

  heapWalker->dispose();

  image.magic = BootImage::Magic;
  image.codeBase = reinterpret_cast<uintptr_t>(code);

  fprintf(stderr, "class count %d string count %d call count %d\n"
          "heap size %d code size %d\n",
          image.classCount, image.stringCount, image.callCount, image.heapSize,
          image.codeSize);

  if (true) {
    fwrite(&image, sizeof(BootImage), 1, out);

    fwrite(classTable, image.classCount * sizeof(unsigned), 1, out);
    fwrite(stringTable, image.stringCount * sizeof(unsigned), 1, out);
    fwrite(callTable, image.callCount * sizeof(unsigned) * 2, 1, out);

    unsigned offset = (image.classCount * sizeof(unsigned))
      + (image.stringCount * sizeof(unsigned))
      + (image.callCount * sizeof(unsigned) * 2);

    while (offset % BytesPerWord) {
      uint8_t c = 0;
      fwrite(&c, 1, 1, out);
      ++ offset;
    }

    fwrite(heapMap, pad(heapMapSize(image.heapSize)), 1, out);
    fwrite(heap, pad(image.heapSize), 1, out);

    fwrite(codeMap, pad(codeMapSize(image.codeSize)), 1, out);
    fwrite(code, pad(image.codeSize), 1, out);
  }
}

} // namespace

int
main(int ac, const char** av)
{
  if (ac < 2 or ac > 5) {
    fprintf(stderr, "usage: %s <classpath> "
            "[<class name> [<method name> [<method spec>]]]\n", av[0]);
    return -1;
  }

  System* s = makeSystem(0);
  Heap* h = makeHeap(s, 128 * 1024 * 1024);
  Finder* f = makeFinder(s, av[1], 0);
  Processor* p = makeProcessor(s, h);
  Machine* m = new (h->allocate(sizeof(Machine))) Machine(s, h, f, p, 0, 0);
  Thread* t = p->makeThread(m, 0, 0);

  enter(t, Thread::ActiveState);
  enter(t, Thread::IdleState);

  writeBootImage
    (t, stdout, (ac > 2 ? av[2] : 0), (ac > 3 ? av[3] : 0),
     (ac > 4 ? av[4] : 0));

  return 0;
}
<|endoftext|>


<commit_before><commit_msg>Enable the _set_new_mode() call so that calls to malloc behave like calls to new, and will go through the std_new_handler on crash.  For chrome, this means that all out of memory conditions, be they malloc induced or new induced will cause the process to  abort.<commit_after><|endoftext|>


<commit_before>#define SECURITY_WIN32 1

#include <node.h>
#include <nan.h>
#include <v8.h>

#ifdef _WIN32
#include <Windows.h>
#include <Sddl.h>
#endif

namespace {

#ifdef _WIN32
    std::string utf8_encode(const std::wstring &wstr) {
        if (wstr.empty()) return std::string();
        int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int) wstr.size(), NULL, 0, NULL, NULL);
        std::string strTo(size_needed, 0);
        WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int) wstr.size(), &strTo[0], size_needed, NULL, NULL);
        return strTo;
    }

    std::string GetLastErrorAsString() {
        DWORD errorMessageID = ::GetLastError();
        if (errorMessageID == 0)
            return std::string();

        DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
        DWORD languageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
        LPSTR messageBuffer = NULL;
        size_t size = FormatMessageA(flags, NULL, errorMessageID, languageId, (LPSTR)&messageBuffer, 0, NULL);

        std::string message(messageBuffer, size);
        LocalFree(messageBuffer);
        return message;
    }

    std::string getSidTypeString(SID_NAME_USE snu) {
        switch(snu) {
            case SidTypeUser:
                return "User";
            case SidTypeGroup:
                return "Group";
            case SidTypeDomain:
                return "Domain";
            case SidTypeAlias:
                return "Alias";
            case SidTypeWellKnownGroup:
                return "WellKnownGroup";
            case SidTypeDeletedAccount:
                return "DeletedAccount";
            case SidTypeInvalid:
                return "Invalid";
            case SidTypeUnknown:
                return "Unknown";
            case SidTypeComputer:
                return "Computer";
            case SidTypeLabel:
                return "Label";
            default:
                return "Unknown";
        }
    }

#endif

    class GetSidForUser : public Nan::AsyncWorker {
    public:
        GetSidForUser(Nan::Callback *callback, const std::string &user)
                : Nan::AsyncWorker(callback), user(user), sid("") { }

        ~GetSidForUser() { }

        virtual void Execute() {
#ifdef _WIN32
            LPCWSTR lpSystemName = NULL;

            std::wstring swUser = std::wstring(user.begin(), user.end());
            LPCWSTR lpAccountName = swUser.c_str();

            DWORD cbSid = 256;
            BYTE pSid[256];

            DWORD cbDomain = 256 / sizeof(WCHAR);
            WCHAR Domain[256];

            SID_NAME_USE snu;

            if (!LookupAccountNameW(lpSystemName, lpAccountName, pSid, &cbSid, Domain, &cbDomain, &snu)) {
                SetErrorMessage(GetLastErrorAsString().c_str());
                return;
            }

            if (IsValidSid(pSid) == FALSE) {
                std::string msg = "No SID found for user \"" + user + "\".";
                SetErrorMessage(msg.c_str());
                return;
            }

            if (snu != SidTypeUser) {
                std::string msg = "The provided name must belong to a User, but the according SID is of type \"" + getSidTypeString(snu) + "\".";
                SetErrorMessage(msg.c_str());
                return;
            }

            LPTSTR sidStr;
            if (ConvertSidToStringSid(pSid, &sidStr) == FALSE) {
                SetErrorMessage(GetLastErrorAsString().c_str());
                return;
            }

            sid = utf8_encode(sidStr);
#else
            SetErrorMessage("Your operating system is not supported.");
#endif
        }

        void HandleErrorCallback() {
            Nan::HandleScope scope;
            v8::Local <v8::Value> argv[] = { Nan::Error(ErrorMessage() )};
            callback->Call(1, argv);
        }

        void HandleOKCallback() {
            Nan::HandleScope scope;
            v8::Local <v8::Value> returnValue = Nan::New<v8::String>((char *) sid.data(), sid.size()).ToLocalChecked();
            v8::Local <v8::Value> argv[] = { Nan::Null(), returnValue };
            callback->Call(2, argv);
        }

    private:
        std::string user;
        std::string sid;
    };

    NAN_METHOD(getSidForUser) {
        Nan::Utf8String user(info[0]->ToString());
        Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());
        Nan::AsyncQueueWorker(new GetSidForUser(callback, *user));
    }

    NAN_MODULE_INIT(init) {
        Nan::HandleScope scope;
        Nan::SetMethod(target, "getSidForUser", getSidForUser);
    }

    NODE_MODULE(windows_sid, init)

} // anonymous namespace
<commit_msg>Fix Node.js 12 compiler errors<commit_after>#define SECURITY_WIN32 1

#include <node.h>
#include <nan.h>
#include <v8.h>

#ifdef _WIN32
#include <Windows.h>
#include <Sddl.h>
#endif

namespace {

#ifdef _WIN32
    std::string utf8_encode(const std::wstring &wstr) {
        if (wstr.empty()) return std::string();
        int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int) wstr.size(), NULL, 0, NULL, NULL);
        std::string strTo(size_needed, 0);
        WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int) wstr.size(), &strTo[0], size_needed, NULL, NULL);
        return strTo;
    }

    std::string GetLastErrorAsString() {
        DWORD errorMessageID = ::GetLastError();
        if (errorMessageID == 0)
            return std::string();

        DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
        DWORD languageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
        LPSTR messageBuffer = NULL;
        size_t size = FormatMessageA(flags, NULL, errorMessageID, languageId, (LPSTR)&messageBuffer, 0, NULL);

        std::string message(messageBuffer, size);
        LocalFree(messageBuffer);
        return message;
    }

    std::string getSidTypeString(SID_NAME_USE snu) {
        switch(snu) {
            case SidTypeUser:
                return "User";
            case SidTypeGroup:
                return "Group";
            case SidTypeDomain:
                return "Domain";
            case SidTypeAlias:
                return "Alias";
            case SidTypeWellKnownGroup:
                return "WellKnownGroup";
            case SidTypeDeletedAccount:
                return "DeletedAccount";
            case SidTypeInvalid:
                return "Invalid";
            case SidTypeUnknown:
                return "Unknown";
            case SidTypeComputer:
                return "Computer";
            case SidTypeLabel:
                return "Label";
            default:
                return "Unknown";
        }
    }

#endif

    class GetSidForUser : public Nan::AsyncWorker {
    public:
        GetSidForUser(Nan::Callback *callback, const std::string &user)
                : Nan::AsyncWorker(callback), user(user), sid("") { }

        ~GetSidForUser() { }

        virtual void Execute() {
#ifdef _WIN32
            LPCWSTR lpSystemName = NULL;

            std::wstring swUser = std::wstring(user.begin(), user.end());
            LPCWSTR lpAccountName = swUser.c_str();

            DWORD cbSid = 256;
            BYTE pSid[256];

            DWORD cbDomain = 256 / sizeof(WCHAR);
            WCHAR Domain[256];

            SID_NAME_USE snu;

            if (!LookupAccountNameW(lpSystemName, lpAccountName, pSid, &cbSid, Domain, &cbDomain, &snu)) {
                SetErrorMessage(GetLastErrorAsString().c_str());
                return;
            }

            if (IsValidSid(pSid) == FALSE) {
                std::string msg = "No SID found for user \"" + user + "\".";
                SetErrorMessage(msg.c_str());
                return;
            }

            if (snu != SidTypeUser) {
                std::string msg = "The provided name must belong to a User, but the according SID is of type \"" + getSidTypeString(snu) + "\".";
                SetErrorMessage(msg.c_str());
                return;
            }

            LPTSTR sidStr;
            if (ConvertSidToStringSid(pSid, &sidStr) == FALSE) {
                SetErrorMessage(GetLastErrorAsString().c_str());
                return;
            }

            sid = utf8_encode(sidStr);
#else
            SetErrorMessage("Your operating system is not supported.");
#endif
        }

        void HandleErrorCallback() {
            Nan::HandleScope scope;
            v8::Local <v8::Value> argv[] = { Nan::Error(ErrorMessage() )};
            callback->Call(Nan::GetCurrentContext()->Global(), 1, argv, async_resource);
        }

        void HandleOKCallback() {
            Nan::HandleScope scope;
            v8::Local <v8::Value> returnValue = Nan::New<v8::String>((char *) sid.data(), sid.size()).ToLocalChecked();
            v8::Local <v8::Value> argv[] = { Nan::Null(), returnValue };
            callback->Call(Nan::GetCurrentContext()->Global(), 2, argv, async_resource);
        }

    private:
        std::string user;
        std::string sid;
    };

    NAN_METHOD(getSidForUser) {
        Nan::Utf8String user(info[0]);
        Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());
        Nan::AsyncQueueWorker(new GetSidForUser(callback, *user));
    }

    NAN_MODULE_INIT(init) {
        Nan::HandleScope scope;
        Nan::SetMethod(target, "getSidForUser", getSidForUser);
    }

    NODE_MODULE(windows_sid, init)

} // anonymous namespace
<|endoftext|>


<commit_before><commit_msg>linux: show the manpage on -h or --help<commit_after><|endoftext|>


<commit_before><commit_msg>posix: restore permissions on incorrectly-permissioned user data dirs.<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/url_fetcher.h"

#include "base/string_util.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/net/dns_master.h"
#include "googleurl/src/gurl.h"
#include "net/base/load_flags.h"

URLFetcher::URLFetcher(const GURL& url,
                       RequestType request_type,
                       Delegate* d)
#pragma warning(suppress: 4355)  // Okay to pass "this" here.
  : core_(new Core(this, url, request_type, d)) {
}

URLFetcher::~URLFetcher() {
  core_->Stop();
}

URLFetcher::Core::Core(URLFetcher* fetcher,
                       const GURL& original_url,
                       RequestType request_type,
                       URLFetcher::Delegate* d)
    : fetcher_(fetcher),
      original_url_(original_url),
      request_type_(request_type),
      delegate_(d),
      delegate_loop_(MessageLoop::current()),
      io_loop_(ChromeThread::GetMessageLoop(ChromeThread::IO)),
      request_(NULL),
      response_code_(-1),
      load_flags_(net::LOAD_NORMAL),
      protect_entry_(URLFetcherProtectManager::GetInstance()->Register(
          original_url_.host())),
      num_retries_(0) {
}

void URLFetcher::Core::Start() {
  DCHECK(delegate_loop_);
  DCHECK(io_loop_);
  DCHECK(request_context_) << "We need an URLRequestContext!";
  io_loop_->PostDelayedTask(FROM_HERE, NewRunnableMethod(
          this, &Core::StartURLRequest),
      protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SEND));
}

void URLFetcher::Core::Stop() {
  DCHECK_EQ(MessageLoop::current(), delegate_loop_);
  delegate_ = NULL;
  io_loop_->PostTask(FROM_HERE, NewRunnableMethod(
      this, &Core::CancelURLRequest));
}

void URLFetcher::Core::OnResponseStarted(URLRequest* request) {
  DCHECK(request == request_);
  DCHECK(MessageLoop::current() == io_loop_);
  if (request_->status().is_success()) {
    response_code_ = request_->GetResponseCode();
    response_headers_ = request_->response_headers();
  }

  int bytes_read = 0;
  // Some servers may treat HEAD requests as GET requests.  To free up the
  // network connection as soon as possible, signal that the request has
  // completed immediately, without trying to read any data back (all we care
  // about is the response code and headers, which we already have).
  if (request_->status().is_success() && (request_type_ != HEAD))
    request_->Read(buffer_, sizeof(buffer_), &bytes_read);
  OnReadCompleted(request_, bytes_read);
}

void URLFetcher::Core::OnReadCompleted(URLRequest* request, int bytes_read) {
  DCHECK(request == request_);
  DCHECK(MessageLoop::current() == io_loop_);

  url_ = request->url();

  do {
    if (!request_->status().is_success() || bytes_read <= 0)
      break;
    data_.append(buffer_, bytes_read);
  } while (request_->Read(buffer_, sizeof(buffer_), &bytes_read));

  if (request_->status().is_success())
    request_->GetResponseCookies(&cookies_);

  // See comments re: HEAD requests in OnResponseStarted().
  if (!request_->status().is_io_pending() || (request_type_ == HEAD)) {
    delegate_loop_->PostTask(FROM_HERE, NewRunnableMethod(
        this, &Core::OnCompletedURLRequest, request_->status()));
    delete request_;
    request_ = NULL;
  }
}

void URLFetcher::Core::StartURLRequest() {
  DCHECK(MessageLoop::current() == io_loop_);
  DCHECK(!request_);

  request_ = new URLRequest(original_url_, this);
  request_->set_load_flags(
      request_->load_flags() | net::LOAD_DISABLE_INTERCEPT | load_flags_);
  request_->set_context(request_context_.get());

  switch (request_type_) {
    case GET:
      break;

    case POST:
      DCHECK(!upload_content_.empty());
      DCHECK(!upload_content_type_.empty());

      request_->set_method("POST");
      if (!extra_request_headers_.empty())
        extra_request_headers_ += "\r\n";
      StringAppendF(&extra_request_headers_,
                    "Content-Length: %d\r\nContent-Type: %s",
                    upload_content_.size(), upload_content_type_.c_str());
      request_->AppendBytesToUpload(upload_content_.data(),
                                    static_cast<int>(upload_content_.size()));
      break;

    case HEAD:
      request_->set_method("HEAD");
      break;

    default:
      NOTREACHED();
  }

  if (!extra_request_headers_.empty())
    request_->SetExtraRequestHeaders(extra_request_headers_);

  request_->Start();
}

void URLFetcher::Core::CancelURLRequest() {
  DCHECK(MessageLoop::current() == io_loop_);
  if (request_) {
    request_->Cancel();
    delete request_;
    request_ = NULL;
  }
  // Release the reference to the request context. There could be multiple
  // references to URLFetcher::Core at this point so it may take a while to
  // delete the object, but we cannot delay the destruction of the request
  // context.
  request_context_ = NULL;
}

void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) {
  DCHECK(MessageLoop::current() == delegate_loop_);

  // Checks the response from server.
  if (response_code_ >= 500) {
    // When encountering a server error, we will send the request again
    // after backoff time.
    const int wait =
        protect_entry_->UpdateBackoff(URLFetcherProtectEntry::FAILURE);
    ++num_retries_;
    // Restarts the request if we still need to notify the delegate.
    if (delegate_) {
      if (num_retries_ <= protect_entry_->max_retries()) {
        io_loop_->PostDelayedTask(FROM_HERE, NewRunnableMethod(
            this, &Core::StartURLRequest), wait);
      } else {
        delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
                                      cookies_, data_);
      }
    }
  } else {
    protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SUCCESS);
    if (delegate_)
      delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
                                    cookies_, data_);
  }
}
<commit_msg>Do not add the Content-Length header in the URLFetcher, since that header will be added later in HttpNetworkTransaction::BuildRequestHeaders.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/url_fetcher.h"

#include "base/string_util.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/net/dns_master.h"
#include "googleurl/src/gurl.h"
#include "net/base/load_flags.h"

URLFetcher::URLFetcher(const GURL& url,
                       RequestType request_type,
                       Delegate* d)
#pragma warning(suppress: 4355)  // Okay to pass "this" here.
  : core_(new Core(this, url, request_type, d)) {
}

URLFetcher::~URLFetcher() {
  core_->Stop();
}

URLFetcher::Core::Core(URLFetcher* fetcher,
                       const GURL& original_url,
                       RequestType request_type,
                       URLFetcher::Delegate* d)
    : fetcher_(fetcher),
      original_url_(original_url),
      request_type_(request_type),
      delegate_(d),
      delegate_loop_(MessageLoop::current()),
      io_loop_(ChromeThread::GetMessageLoop(ChromeThread::IO)),
      request_(NULL),
      response_code_(-1),
      load_flags_(net::LOAD_NORMAL),
      protect_entry_(URLFetcherProtectManager::GetInstance()->Register(
          original_url_.host())),
      num_retries_(0) {
}

void URLFetcher::Core::Start() {
  DCHECK(delegate_loop_);
  DCHECK(io_loop_);
  DCHECK(request_context_) << "We need an URLRequestContext!";
  io_loop_->PostDelayedTask(FROM_HERE, NewRunnableMethod(
          this, &Core::StartURLRequest),
      protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SEND));
}

void URLFetcher::Core::Stop() {
  DCHECK_EQ(MessageLoop::current(), delegate_loop_);
  delegate_ = NULL;
  io_loop_->PostTask(FROM_HERE, NewRunnableMethod(
      this, &Core::CancelURLRequest));
}

void URLFetcher::Core::OnResponseStarted(URLRequest* request) {
  DCHECK(request == request_);
  DCHECK(MessageLoop::current() == io_loop_);
  if (request_->status().is_success()) {
    response_code_ = request_->GetResponseCode();
    response_headers_ = request_->response_headers();
  }

  int bytes_read = 0;
  // Some servers may treat HEAD requests as GET requests.  To free up the
  // network connection as soon as possible, signal that the request has
  // completed immediately, without trying to read any data back (all we care
  // about is the response code and headers, which we already have).
  if (request_->status().is_success() && (request_type_ != HEAD))
    request_->Read(buffer_, sizeof(buffer_), &bytes_read);
  OnReadCompleted(request_, bytes_read);
}

void URLFetcher::Core::OnReadCompleted(URLRequest* request, int bytes_read) {
  DCHECK(request == request_);
  DCHECK(MessageLoop::current() == io_loop_);

  url_ = request->url();

  do {
    if (!request_->status().is_success() || bytes_read <= 0)
      break;
    data_.append(buffer_, bytes_read);
  } while (request_->Read(buffer_, sizeof(buffer_), &bytes_read));

  if (request_->status().is_success())
    request_->GetResponseCookies(&cookies_);

  // See comments re: HEAD requests in OnResponseStarted().
  if (!request_->status().is_io_pending() || (request_type_ == HEAD)) {
    delegate_loop_->PostTask(FROM_HERE, NewRunnableMethod(
        this, &Core::OnCompletedURLRequest, request_->status()));
    delete request_;
    request_ = NULL;
  }
}

void URLFetcher::Core::StartURLRequest() {
  DCHECK(MessageLoop::current() == io_loop_);
  DCHECK(!request_);

  request_ = new URLRequest(original_url_, this);
  request_->set_load_flags(
      request_->load_flags() | net::LOAD_DISABLE_INTERCEPT | load_flags_);
  request_->set_context(request_context_.get());

  switch (request_type_) {
    case GET:
      break;

    case POST:
      DCHECK(!upload_content_.empty());
      DCHECK(!upload_content_type_.empty());

      request_->set_method("POST");
      if (!extra_request_headers_.empty())
        extra_request_headers_ += "\r\n";
      StringAppendF(&extra_request_headers_,
                    "Content-Type: %s", upload_content_type_.c_str());
      request_->AppendBytesToUpload(upload_content_.data(),
                                    static_cast<int>(upload_content_.size()));
      break;

    case HEAD:
      request_->set_method("HEAD");
      break;

    default:
      NOTREACHED();
  }

  if (!extra_request_headers_.empty())
    request_->SetExtraRequestHeaders(extra_request_headers_);

  request_->Start();
}

void URLFetcher::Core::CancelURLRequest() {
  DCHECK(MessageLoop::current() == io_loop_);
  if (request_) {
    request_->Cancel();
    delete request_;
    request_ = NULL;
  }
  // Release the reference to the request context. There could be multiple
  // references to URLFetcher::Core at this point so it may take a while to
  // delete the object, but we cannot delay the destruction of the request
  // context.
  request_context_ = NULL;
}

void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) {
  DCHECK(MessageLoop::current() == delegate_loop_);

  // Checks the response from server.
  if (response_code_ >= 500) {
    // When encountering a server error, we will send the request again
    // after backoff time.
    const int wait =
        protect_entry_->UpdateBackoff(URLFetcherProtectEntry::FAILURE);
    ++num_retries_;
    // Restarts the request if we still need to notify the delegate.
    if (delegate_) {
      if (num_retries_ <= protect_entry_->max_retries()) {
        io_loop_->PostDelayedTask(FROM_HERE, NewRunnableMethod(
            this, &Core::StartURLRequest), wait);
      } else {
        delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
                                      cookies_, data_);
      }
    }
  } else {
    protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SUCCESS);
    if (delegate_)
      delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
                                    cookies_, data_);
  }
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2015 Couchbase, Inc
 *
 *   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.
 */

/*
 * Checksum abstraction functions.
 *
 * ForestDB evolved to support a software CRC and platform's CRC32-C.
 * This module provides an API for checking and creating checksums
 * utilising the correct method based upon the callers crc_mode.
 */

#include <stdlib.h>
#include <assert.h>
#ifdef _CRC32C
// Linking with platform for crc32c
# include <platform/crc32c.h>
#else
#include <stdint.h>
// Define a crc32c which does nothing but assert.
uint32_t crc32c(const uint8_t* buf,
                size_t buf_len,
                uint32_t pre) {
    // Non couchbase builds are configured to never turn on crc32c.
    assert(false);
    return 0;
}
#endif
# include "checksum.h"
#include "crc32.h"

/*
 * Get a checksum of buf for buf_len bytes.
 *
 * mode = UNKNOWN is an invalid input (triggers assert).
 */
uint32_t get_checksum(const uint8_t* buf,
                      size_t buf_len,
                      uint32_t pre,
                      crc_mode_e mode) {
    if (mode == CRC32C) {
        return crc32c(buf, buf_len, pre);
    } else {
        assert(mode == CRC32);
        return crc32_8(buf, buf_len, pre);
    }
}

/*
 * Get a checksum of buf for buf_len bytes.
 *
 * The pre value is set to 0.
 *
 * mode = UNKNOWN is an invalid input (triggers assert).
 */
uint32_t get_checksum(const uint8_t* buf,
                      size_t buf_len,
                      crc_mode_e mode) {
    return get_checksum(buf, buf_len, 0, mode);
}

/*
 * Perform an integrity check of buf for buf_len bytes.
 *
 * A checksum of buf is created and compared against checksum argument.
 *
 * mode = UNKNOWN is an acceptable input. All modes are tried before failing.
 *
 *
 * Returns true success (checksums match), false for failure.
 */
bool perform_integrity_check(const uint8_t* buf,
                            size_t buf_len,
                            uint32_t checksum,
                            crc_mode_e mode) {
    bool success = false;
#ifdef _CRC32C
    if (mode == CRC_UNKNOWN || mode == CRC32C) {
        success = checksum == crc32c(buf, buf_len, 0);
        if (!success && mode == CRC_UNKNOWN) {
            success = checksum == crc32_8(buf, buf_len, 0);
        }
    } else
#endif
    {
        success = checksum == crc32_8(buf, buf_len, 0);
    }
    return success;
}

/*
 * Detect the CRC mode by performing an integrity check against the
 * two CRC functions ForestDB files could be written with.
 *
 * Returns true if a match is found and sets mode to the correct mode.
 * Returns false if no match and sets mode to CRC_UNKNOWN.
 */
bool detect_and_check_crc(const uint8_t* buf,
                          size_t buf_len,
                          uint32_t checksum,
                          crc_mode_e* mode) {
    *mode = CRC_UNKNOWN;
#ifdef _CRC32C
    if (perform_integrity_check(buf, buf_len, checksum, CRC32C)) {
        *mode = CRC32C;
        return true;
    } else
#endif
    if (perform_integrity_check(buf, buf_len, checksum, CRC32)) {
        *mode = CRC32;
        return true;
    }

    return false;
}
<commit_msg>Fix warning message about conversion from 'const void*' to 'void *'<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2015 Couchbase, Inc
 *
 *   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.
 */

/*
 * Checksum abstraction functions.
 *
 * ForestDB evolved to support a software CRC and platform's CRC32-C.
 * This module provides an API for checking and creating checksums
 * utilising the correct method based upon the callers crc_mode.
 */

#include <stdlib.h>
#include <assert.h>
#ifdef _CRC32C
// Linking with platform for crc32c
# include <platform/crc32c.h>
#else
#include <stdint.h>
// Define a crc32c which does nothing but assert.
uint32_t crc32c(const uint8_t* buf,
                size_t buf_len,
                uint32_t pre) {
    // Non couchbase builds are configured to never turn on crc32c.
    assert(false);
    return 0;
}
#endif
# include "checksum.h"
#include "crc32.h"

/*
 * Get a checksum of buf for buf_len bytes.
 *
 * mode = UNKNOWN is an invalid input (triggers assert).
 */
uint32_t get_checksum(const uint8_t* buf,
                      size_t buf_len,
                      uint32_t pre,
                      crc_mode_e mode) {
    if (mode == CRC32C) {
        return crc32c(buf, buf_len, pre);
    } else {
        assert(mode == CRC32);
        return crc32_8((void *)buf, buf_len, pre);
    }
}

/*
 * Get a checksum of buf for buf_len bytes.
 *
 * The pre value is set to 0.
 *
 * mode = UNKNOWN is an invalid input (triggers assert).
 */
uint32_t get_checksum(const uint8_t* buf,
                      size_t buf_len,
                      crc_mode_e mode) {
    return get_checksum(buf, buf_len, 0, mode);
}

/*
 * Perform an integrity check of buf for buf_len bytes.
 *
 * A checksum of buf is created and compared against checksum argument.
 *
 * mode = UNKNOWN is an acceptable input. All modes are tried before failing.
 *
 *
 * Returns true success (checksums match), false for failure.
 */
bool perform_integrity_check(const uint8_t* buf,
                            size_t buf_len,
                            uint32_t checksum,
                            crc_mode_e mode) {
    bool success = false;
#ifdef _CRC32C
    if (mode == CRC_UNKNOWN || mode == CRC32C) {
        success = checksum == crc32c(buf, buf_len, 0);
        if (!success && mode == CRC_UNKNOWN) {
            success = checksum == crc32_8((void *)buf, buf_len, 0);
        }
    } else
#endif
    {
        success = checksum == crc32_8((void *)buf, buf_len, 0);
    }
    return success;
}

/*
 * Detect the CRC mode by performing an integrity check against the
 * two CRC functions ForestDB files could be written with.
 *
 * Returns true if a match is found and sets mode to the correct mode.
 * Returns false if no match and sets mode to CRC_UNKNOWN.
 */
bool detect_and_check_crc(const uint8_t* buf,
                          size_t buf_len,
                          uint32_t checksum,
                          crc_mode_e* mode) {
    *mode = CRC_UNKNOWN;
#ifdef _CRC32C
    if (perform_integrity_check(buf, buf_len, checksum, CRC32C)) {
        *mode = CRC32C;
        return true;
    } else
#endif
    if (perform_integrity_check(buf, buf_len, checksum, CRC32)) {
        *mode = CRC32;
        return true;
    }

    return false;
}
<|endoftext|>


<commit_before><commit_msg>No gears.dll on non-Windows systems.<commit_after><|endoftext|>


<commit_before>#include "common.hpp"

#include <iostream>
#include <fstream>
#include <cmath>

// some util global variables (lookup tables, constants, ...)
double* power4_lookup = NULL; // contains 4^{-(m-s)} for s=0,...,m

void initUtil() {

  int m = Options::opts.m;
  power4_lookup = new double[m+1];
  for (int s = 0; s <= m; ++s) {
    power4_lookup[s] = pow(4, s-m);
  }
}

void clearUtil() {
  delete[] power4_lookup;
  power4_lookup = NULL;
}

double** initDoubleMatrix(size_t n, size_t m) {
  double** matrix = new double*[n];
  for (size_t i = 0; i < n; ++i) {
    matrix[i] = new double[m];
    for (size_t j = 0; j < m; ++j) {
      matrix[i][j] = 0.0;
    }
  }
    return matrix;
}

void clearDoubleMatrix(double** matrix, size_t n, size_t m) {
  for (size_t i = 0; i < n; ++i) {
    delete[] matrix[i];
  }
  delete[] matrix;
}

double elementsSumDoubleMatrix(double** matrix, size_t n, size_t m) {
  double sum = 0.0;
  for (size_t i  = 0; i < n; ++i) {
    for (size_t j = 0; j < m; ++j) {
      sum += matrix[i][j];
    }
  }
  return sum;
}

void printString(char* s, size_t n) {
  for (int i = 0; i < n; ++i) {
    std::cout << s[i];
  }
}

void printDoubleMatrix(double** M, size_t n, size_t m) {
  for (size_t i = 0; i < n; ++i) {
    for (size_t j = 0; j < n; ++j) {
      std::cout << M[i][j] << '\t';
    }
    std::cout << '\n';
  }
}

// FUNCTIONS FOR 2-BITS ENCODING CONVERSION
uint64_t string2Encode(const std::string&s) {
  size_t n = MAX(32, s.size());
  uint64_t mask = 0;
  uint64_t enc = 0;
  for (int i = 0; i < n; ++i) {
    uint64_t b = revBases[s[i]];
    enc = enc | ( (b & 0x3) << 2*i );
    mask = mask | (0x3 << 2*i);
  }
  //  std::cout << "\n++ " << enc << '\t' << mask << '\t' << (enc & mask) << '\n';
  return (enc & mask);// ( ((uint64_t)-1) >> (64 - 2*n));
}

std::string encoding2String(uint64_t e, size_t n) {
  std::string s;
  for (int i = 0; i < n; ++i) {
    s += bases[e & 0x03];
    e = e >> 2;
  }
  return s;
}

size_t hammingDistance(const char* s1, const char* s2, size_t m) {
  size_t d = 0;
  for (int i = 0; i < m; ++i) {
    if (s1[i] != s2[i]) {
      ++d;
    }
  }
  return d;
}

size_t hammingDistance(const std::string& s1, const std::string& s2, size_t m) {
  return hammingDistance(s1.c_str(), s2.c_str(), m);
}

// Calculates Hamming distance between k suffix of s1 and k prefix of s2
size_t prefixSuffixHammingDistance(const std::string& s1, const std::string& s2, size_t k) {
  size_t d = 0;
  size_t md = s2.length() - k;
  for (int i = 0; i < k; ++i, ++md) {
    if (s2[i] != s1[md]) {
      d++;
    }
  }
  return d;
}

size_t bestHammingOverlap(const std::string& s1, const std::string& s2) {
  size_t m = s1.length();
  for (size_t i = m; i >= 1; --i) {
    size_t d_i = prefixSuffixHammingDistance(s2, s1, i);
    if (d_i == 0) {
      return i;
    }
  }
  return 0;
}

// Edit distance functions

size_t
editDistance(const std::string& s1, const std::string& s2) {
  size_t n = s1.size();
  size_t m = s2.size();
  size_t** dpMatrix = new size_t*[n+1];
  for (size_t i = 0; i < n+1; ++i) {
    dpMatrix[i] = new size_t[m+1];
  }

  // initialization of first row and column
  for (size_t i = 0; i < n+1; ++i) {
    dpMatrix[i][0] = i;
  }
  for (size_t j = 0; j < m+1; ++j) {
    dpMatrix[0][j] = j;
  }

  for (int i = 1; i < n+1; ++i) {
    for(int j = 1; j < m+1; ++j) {
      size_t delta = (s1[i-1] == s2[j-1]) ? 0 : 1;
      dpMatrix[i][j] = MIN( MIN(dpMatrix[i-1][j]+1, dpMatrix[i][j-1]+1) , dpMatrix[i-1][j-1] + delta ) ;
    }
  }
  size_t dist = dpMatrix[n][m];
  for (int i = 0; i < n+1; ++i) {
    delete[] dpMatrix[i];
  }
  delete[] dpMatrix;
  return dist;
}

// returns the edit distance between strings encoded in two bits form on the 64
// for bits input integers (strings can't be longer than 32 characters). The
// actual lengths of the strings are given as parameters
size_t
editDistanceEncoded(uint64_t s1, size_t n1, uint64_t s2, size_t n2, size_t** dpMatrix) {

  for (int i = 1; i < n1+1; ++i) {
    for(int j = 1; j < n2+1; ++j) {
      uint64_t x = ( s1 >> 2*(i-1) ) & 0x3; // pre compute matrix {A,C,G,T} x [1...n]
      uint64_t y = ( s2 >> 2*(j-1) ) & 0x3;
      size_t delta = (x == y) ? 0 : 1; // try to find an alternative not involving if

      dpMatrix[i][j] = MIN( MIN(dpMatrix[i-1][j]+1, dpMatrix[i][j-1]+1) , dpMatrix[i-1][j-1] + delta ) ;
    }
  }
  return dpMatrix[n1][n2];
}

// Most of these function are used for debug and dev purpose, but they can be
// useful in other situations (perhaps in the future development of simulator)

Read randomRead(size_t m) {
  char * tmp = new char[m];
  generateIIDGenome(m,tmp);
  Read r(std::string(tmp), 0);
  delete[] tmp;
}

// Error

void
fatal_error(const std::string &msg, int exit_code)
{
  std::cerr << "[ERROR]  " + msg << std::endl;
  exit(exit_code);
}
<commit_msg>Started linear space edit distance<commit_after>#include "common.hpp"

#include <iostream>
#include <fstream>
#include <cmath>

// some util global variables (lookup tables, constants, ...)
double* power4_lookup = NULL; // contains 4^{-(m-s)} for s=0,...,m

void initUtil() {

  int m = Options::opts.m;
  power4_lookup = new double[m+1];
  for (int s = 0; s <= m; ++s) {
    power4_lookup[s] = pow(4, s-m);
  }
}

void clearUtil() {
  delete[] power4_lookup;
  power4_lookup = NULL;
}

double** initDoubleMatrix(size_t n, size_t m) {
  double** matrix = new double*[n];
  for (size_t i = 0; i < n; ++i) {
    matrix[i] = new double[m];
    for (size_t j = 0; j < m; ++j) {
      matrix[i][j] = 0.0;
    }
  }
    return matrix;
}

void clearDoubleMatrix(double** matrix, size_t n, size_t m) {
  for (size_t i = 0; i < n; ++i) {
    delete[] matrix[i];
  }
  delete[] matrix;
}

double elementsSumDoubleMatrix(double** matrix, size_t n, size_t m) {
  double sum = 0.0;
  for (size_t i  = 0; i < n; ++i) {
    for (size_t j = 0; j < m; ++j) {
      sum += matrix[i][j];
    }
  }
  return sum;
}

void printString(char* s, size_t n) {
  for (int i = 0; i < n; ++i) {
    std::cout << s[i];
  }
}

void printDoubleMatrix(double** M, size_t n, size_t m) {
  for (size_t i = 0; i < n; ++i) {
    for (size_t j = 0; j < n; ++j) {
      std::cout << M[i][j] << '\t';
    }
    std::cout << '\n';
  }
}

// FUNCTIONS FOR 2-BITS ENCODING CONVERSION
uint64_t string2Encode(const std::string&s) {
  size_t n = MAX(32, s.size());
  uint64_t mask = 0;
  uint64_t enc = 0;
  for (int i = 0; i < n; ++i) {
    uint64_t b = revBases[s[i]];
    enc = enc | ( (b & 0x3) << 2*i );
    mask = mask | (0x3 << 2*i);
  }
  //  std::cout << "\n++ " << enc << '\t' << mask << '\t' << (enc & mask) << '\n';
  return (enc & mask);// ( ((uint64_t)-1) >> (64 - 2*n));
}

std::string encoding2String(uint64_t e, size_t n) {
  std::string s;
  for (int i = 0; i < n; ++i) {
    s += bases[e & 0x03];
    e = e >> 2;
  }
  return s;
}

size_t hammingDistance(const char* s1, const char* s2, size_t m) {
  size_t d = 0;
  for (int i = 0; i < m; ++i) {
    if (s1[i] != s2[i]) {
      ++d;
    }
  }
  return d;
}

size_t hammingDistance(const std::string& s1, const std::string& s2, size_t m) {
  return hammingDistance(s1.c_str(), s2.c_str(), m);
}

// Calculates Hamming distance between k suffix of s1 and k prefix of s2
size_t prefixSuffixHammingDistance(const std::string& s1, const std::string& s2, size_t k) {
  size_t d = 0;
  size_t md = s2.length() - k;
  for (int i = 0; i < k; ++i, ++md) {
    if (s2[i] != s1[md]) {
      d++;
    }
  }
  return d;
}

size_t bestHammingOverlap(const std::string& s1, const std::string& s2) {
  size_t m = s1.length();
  for (size_t i = m; i >= 1; --i) {
    size_t d_i = prefixSuffixHammingDistance(s2, s1, i);
    if (d_i == 0) {
      return i;
    }
  }
  return 0;
}

// Edit distance functions

/*
 * FUTURE WORK: This should choose the proper algorithm for calculation
 * of the edit distance.
 */
size_t editDistanceAdpative(const std::string& s1, const std::string& s2) {
  rturn editDistance(s1,s2);
}

size_t
editDistance(const std::string& s1, const std::string& s2) {
  size_t n = s1.size();
  size_t m = s2.size();
  size_t** dpMatrix = new size_t*[n+1];
  for (size_t i = 0; i < n+1; ++i) {
    dpMatrix[i] = new size_t[m+1];
  }

  // initialization of first row and column
  for (size_t i = 0; i < n+1; ++i) {
    dpMatrix[i][0] = i;
  }
  for (size_t j = 0; j < m+1; ++j) {
    dpMatrix[0][j] = j;
  }

  for (int i = 1; i < n+1; ++i) {
    for(int j = 1; j < m+1; ++j) {
      size_t delta = (s1[i-1] == s2[j-1]) ? 0 : 1;
      dpMatrix[i][j] = MIN( MIN(dpMatrix[i-1][j]+1, dpMatrix[i][j-1]+1) , dpMatrix[i-1][j-1] + delta ) ;
    }
  }
  size_t dist = dpMatrix[n][m];
  for (int i = 0; i < n+1; ++i) {
    delete[] dpMatrix[i];
  }
  delete[] dpMatrix;
  return dist;
}

/**
 * \brief Conputes the edit distance between strings s1 and s2 using only
 * linear space (the vecotors passed as parameters)
 */
size_t
editDistanceLinSpace(const std::string& s1, const std::string& s2, size_t* v1, size_t* v2) {
  size_t n1 = s1.size();
  size_t n2 = s2.size();
  //  for (size_t

}

// returns the edit distance between strings encoded in two bits form on the 64
// for bits input integers (strings can't be longer than 32 characters). The
// actual lengths of the strings are given as parameters
size_t
editDistanceEncoded(uint64_t s1, size_t n1, uint64_t s2, size_t n2, size_t** dpMatrix) {

  for (int i = 1; i < n1+1; ++i) {
    for(int j = 1; j < n2+1; ++j) {
      uint64_t x = ( s1 >> 2*(i-1) ) & 0x3; // pre compute matrix {A,C,G,T} x [1...n]
      uint64_t y = ( s2 >> 2*(j-1) ) & 0x3;
      size_t delta = (x == y) ? 0 : 1; // try to find an alternative not involving if

      dpMatrix[i][j] = MIN( MIN(dpMatrix[i-1][j]+1, dpMatrix[i][j-1]+1) , dpMatrix[i-1][j-1] + delta ) ;
    }
  }
  return dpMatrix[n1][n2];
}

// Most of these function are used for debug and dev purpose, but they can be
// useful in other situations (perhaps in the future development of simulator)

Read randomRead(size_t m) {
  char * tmp = new char[m];
  generateIIDGenome(m,tmp);
  Read r(std::string(tmp), 0);
  delete[] tmp;
}

// Error

void
fatal_error(const std::string &msg, int exit_code)
{
  std::cerr << "[ERROR]  " + msg << std::endl;
  exit(exit_code);
}
<|endoftext|>


<commit_before><commit_msg>Fix error [FATAL:at_exit.cc(40)] Check failed: false. Tried to RegisterCallback without an AtExitManager in (possibly unused) binary perf_tests<commit_after><|endoftext|>


<commit_before>/*
 *  ssfpbands_main.cpp
 *
 *  Created by Tobias Wood on 14/03/2014.
 *  Copyright (c) 2014 Tobias Wood.
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

#include <time.h>
#include <getopt.h>
#include <iostream>
#include <atomic>
#include <Eigen/Dense>

#include "Nifti/Nifti.h"
#include "Nifti/Volume.h"
#include "ThreadPool.h"
#include "DESPOT.h"

#ifdef AGILENT
#include "procpar.h"
using namespace Agilent;
#endif

using namespace std;
using namespace Eigen;

//******************************************************************************
// Arguments / Usage
//******************************************************************************
const string usage {
"Usage is: ssfpbands [options] input1 [input2] \n\
\
Options:\n\
	--help, -h        : Print this message\n\
	--verbose, -v     : Print more information\n\
	--out, -o path    : Add a prefix to the output filenames\n\
	--mask, -m file   : Mask input with specified file\n\
	--type, -t p      : Input is magnitude and phase (default)\n\
	           i      : Input is real/imaginary\n\
			   c      : Input is complex\n"
};

enum class Type { Phase, Imag, Complex };
static bool verbose = false;
static string outPrefix;
static Type inputType = Type::Phase;
static struct option long_options[] =
{
	{"help", no_argument, 0, 'h'},
	{"verbose", no_argument, 0, 'v'},
	{"out", required_argument, 0, 'o'},
	{"mask", required_argument, 0, 'm'},
	{"type", required_argument, 0, 't'},
	{0, 0, 0, 0}
};
//******************************************************************************
// Main
//******************************************************************************
int main(int argc, char **argv)
{
	//**************************************************************************
	// Argument Processing
	//**************************************************************************
	cout << version << endl << credit_me << endl;
	Nifti maskFile;
	Volume<bool> maskVol;

	int indexptr = 0, c;
	while ((c = getopt_long(argc, argv, "hvo:m:t:", long_options, &indexptr)) != -1) {
		switch (c) {
			case 'v': verbose = true; break;
			case 'm':
				cout << "Reading mask file " << optarg << endl;
				maskFile.open(optarg, Nifti::Mode::Read);
				maskVol.readFrom(maskFile);
				break;
			case 'o':
				outPrefix = optarg;
				cout << "Output prefix will be: " << outPrefix << endl;
				break;
			case 'i':
				switch (*optarg) {
					case 'p': inputType = Type::Phase;  cout << "Input is magnitude and phase." << endl; break;
					case 'i': inputType = Type::Imag; cout << "Input is real and imaginary." << endl; break;
					case 'c': inputType = Type::Complex; cout << "Input is complex." << endl; break;
					default:
						cout << "Unknown input type " << optarg << endl;
						exit(EXIT_FAILURE);
						break;
				} break;
			case 'h':
			case '?': // getopt will print an error message
				exit(EXIT_FAILURE);
		}
	}
	//**************************************************************************
	#pragma mark Gather data
	//**************************************************************************
	cout << "Opening input file: " << argv[optind] << endl;
	Nifti inputFile;
	inputFile.open(argv[optind++], Nifti::Mode::Read);
	if (maskFile.isOpen() && !maskFile.matchesSpace(inputFile)) {
		cerr << "Mask does not match input file." << endl;
		exit(EXIT_FAILURE);
	}
	Nifti templateFile(inputFile, 1);
	if ((inputFile.rank() < 4) || ((inputFile.dim(4) % 4) != 0)) {
		cout << "Input must contain 4 phase-cycles (0, 90, 180, 270)." << endl;
		exit(EXIT_FAILURE);
	}
	size_t nFlip = inputFile.dim(4) / 4;

	VolumeSeries<float> input1, input2;
	VolumeSeries<complex<float>> inputC;
	if (inputType != Type::Complex) {
		input1.readFrom(inputFile);
		inputFile.close();
		inputFile.open(argv[optind++], Nifti::Mode::Read);
		if (!inputFile.matchesSpace(templateFile)) {
			cerr << "Input files do not match." << endl;
			exit(EXIT_FAILURE);
		}
		input2.readFrom(inputFile);
		inputFile.close();
	} else {
		inputC.readFrom(inputFile);
		inputFile.close();
	}
	if ((argc - optind) != 0) {
		cout << "Incorrect number of arguments." << endl << usage << endl;
		exit(EXIT_FAILURE);
	}
	// Results storage
	VolumeSeries<float> noBands(input1.dims().head(3), nFlip);
	//**************************************************************************
	// Do the fitting
	//**************************************************************************
	ThreadPool pool;
	for (size_t k = 0; k < templateFile.dim(3); k++) {
		clock_t loopStart;
		// Read in data
		if (verbose)
			cout << "Starting slice " << k << "..." << flush;
		loopStart = clock();
		atomic<int> voxCount{0};

		for (size_t j = 0; j < templateFile.dim(2); j++) {
			function<void (const size_t)> processVox = [&] (const size_t i) {
				const typename Volume<float>::IndexArray vox{i, j, k};
				if (!maskFile.isOpen() || (maskVol[vox])) {
					voxCount++;

					ArrayXcd I1(nFlip), I2(nFlip), I3(nFlip), I4(nFlip);
					switch (inputType) {
						case (Type::Phase): {
							ArrayXd mag = input1.series(vox).cast<double>();
							ArrayXd ph  = input2.series(vox).cast<double>();

							I1.real() = mag.head(nFlip) * ph.head(nFlip).cos();
							I1.imag() = mag.head(nFlip) * ph.head(nFlip).sin();
							I2.real() = mag.segment(nFlip, nFlip) * ph.segment(nFlip, nFlip).cos();
							I2.imag() = mag.segment(nFlip, nFlip) * ph.segment(nFlip, nFlip).sin();
							I3.real() = mag.segment(2*nFlip, nFlip) * ph.segment(2*nFlip, nFlip).cos();
							I3.imag() = mag.segment(2*nFlip, nFlip) * ph.segment(2*nFlip, nFlip).sin();
							I4.real() = mag.tail(nFlip) * ph.tail(nFlip).cos();
							I4.imag() = mag.tail(nFlip) * ph.tail(nFlip).sin();
						}	break;
						case (Type::Imag): {
							ArrayXd re = input1.series(vox).cast<double>();
							ArrayXd im = input2.series(vox).cast<double>();

							I1.real() = re.head(nFlip);
							I1.imag() = im.head(nFlip);
							I2.real() = re.segment(nFlip, nFlip);
							I2.imag() = im.segment(nFlip, nFlip);
							I3.real() = re.segment(2*nFlip, nFlip);
							I3.imag() = im.segment(2*nFlip, nFlip);
							I4.real() = re.tail(nFlip);
							I4.imag() = im.tail(nFlip);
						 }	break;
						case (Type::Complex): {
							ArrayXcd input = inputC.series(vox).cast<complex<double>>();
							I1 = input.head(nFlip);
							I2 = input.segment(nFlip, nFlip);
							I3 = input.segment(2*nFlip, nFlip);
							I4 = input.tail(nFlip);
						}	break;
					}

					ArrayXcd crossPoint = (I1.real()*I3.imag() - I3.real()*I1.imag())*(I2 - I4) - (I2.real()*I4.imag() - I4.real()*I2.imag())*(I1 - I3) /
					                      ((I1.real() - I3.real())*(I2.imag() - I4.imag()) + (I2.real() - I4.real())*(I3.imag() - I1.imag()));
					noBands.series(vox) = crossPoint.abs().cast<float>();
				}
			};

			pool.for_loop(processVox, templateFile.dim(1));
		}

		if (verbose) {
			clock_t loopEnd = clock();
			if (voxCount > 0)
				cout << voxCount << " unmasked voxels, CPU time per voxel was "
				          << ((loopEnd - loopStart) / ((float)voxCount * CLOCKS_PER_SEC)) << " s, ";
			cout << "finished." << endl;
		}
	}

	if (verbose)
		cout << "Writing results." << endl;
	templateFile.setDim(4, nFlip);
	templateFile.open("no_bands.nii.gz", Nifti::Mode::Write);
	noBands.writeTo(templateFile);
	templateFile.close();
	cout << "All done." << endl;
	exit(EXIT_SUCCESS);
}
<commit_msg>Fixed some missing parentheses.<commit_after>/*
 *  ssfpbands_main.cpp
 *
 *  Created by Tobias Wood on 14/03/2014.
 *  Copyright (c) 2014 Tobias Wood.
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

#include <time.h>
#include <getopt.h>
#include <iostream>
#include <atomic>
#include <Eigen/Dense>

#include "Nifti/Nifti.h"
#include "Nifti/Volume.h"
#include "ThreadPool.h"
#include "DESPOT.h"

#ifdef AGILENT
#include "procpar.h"
using namespace Agilent;
#endif

using namespace std;
using namespace Eigen;

//******************************************************************************
// Arguments / Usage
//******************************************************************************
const string usage {
"Usage is: ssfpbands [options] input1 [input2] \n\
\
Options:\n\
	--help, -h        : Print this message\n\
	--verbose, -v     : Print more information\n\
	--out, -o path    : Add a prefix to the output filenames\n\
	--mask, -m file   : Mask input with specified file\n\
	--type, -t p      : Input is magnitude and phase (default)\n\
	           i      : Input is real/imaginary\n\
			   c      : Input is complex\n"
};

enum class Type { Phase, Imag, Complex };
static bool verbose = false;
static string outPrefix;
static Type inputType = Type::Phase;
static struct option long_options[] =
{
	{"help", no_argument, 0, 'h'},
	{"verbose", no_argument, 0, 'v'},
	{"out", required_argument, 0, 'o'},
	{"mask", required_argument, 0, 'm'},
	{"type", required_argument, 0, 't'},
	{0, 0, 0, 0}
};
//******************************************************************************
// Main
//******************************************************************************
int main(int argc, char **argv)
{
	//**************************************************************************
	// Argument Processing
	//**************************************************************************
	cout << version << endl << credit_me << endl;
	Nifti maskFile;
	Volume<bool> maskVol;

	int indexptr = 0, c;
	while ((c = getopt_long(argc, argv, "hvo:m:t:", long_options, &indexptr)) != -1) {
		switch (c) {
			case 'v': verbose = true; break;
			case 'm':
				cout << "Reading mask file " << optarg << endl;
				maskFile.open(optarg, Nifti::Mode::Read);
				maskVol.readFrom(maskFile);
				break;
			case 'o':
				outPrefix = optarg;
				cout << "Output prefix will be: " << outPrefix << endl;
				break;
			case 'i':
				switch (*optarg) {
					case 'p': inputType = Type::Phase;  cout << "Input is magnitude and phase." << endl; break;
					case 'i': inputType = Type::Imag; cout << "Input is real and imaginary." << endl; break;
					case 'c': inputType = Type::Complex; cout << "Input is complex." << endl; break;
					default:
						cout << "Unknown input type " << optarg << endl;
						exit(EXIT_FAILURE);
						break;
				} break;
			case 'h':
			case '?': // getopt will print an error message
				exit(EXIT_FAILURE);
		}
	}
	//**************************************************************************
	#pragma mark Gather data
	//**************************************************************************
	cout << "Opening input file: " << argv[optind] << endl;
	Nifti inputFile;
	inputFile.open(argv[optind++], Nifti::Mode::Read);
	if (maskFile.isOpen() && !maskFile.matchesSpace(inputFile)) {
		cerr << "Mask does not match input file." << endl;
		exit(EXIT_FAILURE);
	}
	Nifti templateFile(inputFile, 1);
	if ((inputFile.rank() < 4) || ((inputFile.dim(4) % 4) != 0)) {
		cout << "Input must contain 4 phase-cycles (0, 90, 180, 270)." << endl;
		exit(EXIT_FAILURE);
	}
	size_t nFlip = inputFile.dim(4) / 4;

	VolumeSeries<float> input1, input2;
	VolumeSeries<complex<float>> inputC;
	if (inputType != Type::Complex) {
		input1.readFrom(inputFile);
		inputFile.close();
		inputFile.open(argv[optind++], Nifti::Mode::Read);
		if (!inputFile.matchesSpace(templateFile)) {
			cerr << "Input files do not match." << endl;
			exit(EXIT_FAILURE);
		}
		input2.readFrom(inputFile);
		inputFile.close();
	} else {
		inputC.readFrom(inputFile);
		inputFile.close();
	}
	if ((argc - optind) != 0) {
		cout << "Incorrect number of arguments." << endl << usage << endl;
		exit(EXIT_FAILURE);
	}
	// Results storage
	VolumeSeries<float> noBands(input1.dims().head(3), nFlip);
	//**************************************************************************
	// Do the fitting
	//**************************************************************************
	ThreadPool pool;
	for (size_t k = 0; k < templateFile.dim(3); k++) {
		clock_t loopStart;
		// Read in data
		if (verbose)
			cout << "Starting slice " << k << "..." << flush;
		loopStart = clock();
		atomic<int> voxCount{0};

		for (size_t j = 0; j < templateFile.dim(2); j++) {
			function<void (const size_t)> processVox = [&] (const size_t i) {
				const typename Volume<float>::IndexArray vox{i, j, k};
				if (!maskFile.isOpen() || (maskVol[vox])) {
					voxCount++;

					ArrayXcd I1(nFlip), I2(nFlip), I3(nFlip), I4(nFlip);
					switch (inputType) {
						case (Type::Phase): {
							ArrayXd mag = input1.series(vox).cast<double>();
							ArrayXd ph  = input2.series(vox).cast<double>();

							I1.real() = mag.head(nFlip) * ph.head(nFlip).cos();
							I1.imag() = mag.head(nFlip) * ph.head(nFlip).sin();
							I2.real() = mag.segment(nFlip, nFlip) * ph.segment(nFlip, nFlip).cos();
							I2.imag() = mag.segment(nFlip, nFlip) * ph.segment(nFlip, nFlip).sin();
							I3.real() = mag.segment(2*nFlip, nFlip) * ph.segment(2*nFlip, nFlip).cos();
							I3.imag() = mag.segment(2*nFlip, nFlip) * ph.segment(2*nFlip, nFlip).sin();
							I4.real() = mag.tail(nFlip) * ph.tail(nFlip).cos();
							I4.imag() = mag.tail(nFlip) * ph.tail(nFlip).sin();
						}	break;
						case (Type::Imag): {
							ArrayXd re = input1.series(vox).cast<double>();
							ArrayXd im = input2.series(vox).cast<double>();

							I1.real() = re.head(nFlip);
							I1.imag() = im.head(nFlip);
							I2.real() = re.segment(nFlip, nFlip);
							I2.imag() = im.segment(nFlip, nFlip);
							I3.real() = re.segment(2*nFlip, nFlip);
							I3.imag() = im.segment(2*nFlip, nFlip);
							I4.real() = re.tail(nFlip);
							I4.imag() = im.tail(nFlip);
						 }	break;
						case (Type::Complex): {
							ArrayXcd input = inputC.series(vox).cast<complex<double>>();
							I1 = input.head(nFlip);
							I2 = input.segment(nFlip, nFlip);
							I3 = input.segment(2*nFlip, nFlip);
							I4 = input.tail(nFlip);
						}	break;
					}

					ArrayXcd crossPoint = ((I1.real()*I3.imag() - I3.real()*I1.imag())*(I2 - I4) - (I2.real()*I4.imag() - I4.real()*I2.imag())*(I1 - I3)) /
					                      ((I1.real() - I3.real())*(I2.imag() - I4.imag()) + (I2.real() - I4.real())*(I3.imag() - I1.imag()));
					noBands.series(vox) = crossPoint.abs().cast<float>();
				}
			};

			pool.for_loop(processVox, templateFile.dim(1));
		}

		if (verbose) {
			clock_t loopEnd = clock();
			if (voxCount > 0)
				cout << voxCount << " unmasked voxels, CPU time per voxel was "
				          << ((loopEnd - loopStart) / ((float)voxCount * CLOCKS_PER_SEC)) << " s, ";
			cout << "finished." << endl;
		}
	}

	if (verbose)
		cout << "Writing results." << endl;
	templateFile.setDim(4, nFlip);
	templateFile.open("no_bands.nii.gz", Nifti::Mode::Write);
	noBands.writeTo(templateFile);
	templateFile.close();
	cout << "All done." << endl;
	exit(EXIT_SUCCESS);
}
<|endoftext|>